Coverage for website/members/api/calendarjs/views.py: 35.00%

34 statements  

« prev     ^ index     » next       coverage.py v7.6.7, created at 2025-08-14 10:31 +0000

1import copy 

2 

3from django.db.models import Prefetch, Q, prefetch_related_objects 

4from django.utils import timezone 

5 

6from rest_framework.generics import ListAPIView 

7from rest_framework.permissions import IsAuthenticated 

8 

9from members.api.calendarjs.serializers import MemberBirthdaySerializer 

10from members.models import Member, Membership 

11from utils.snippets import extract_date_range 

12 

13 

14class CalendarJSBirthdayListView(ListAPIView): 

15 """Define a custom route that outputs the correctly formatted events information for CalendarJS, published events only.""" 

16 

17 serializer_class = MemberBirthdaySerializer 

18 permission_classes = [IsAuthenticated] 

19 pagination_class = None 

20 

21 def _get_birthdays(self, member, start, end): 

22 birthdays = [] 

23 

24 start_year = max(start.year, member.profile.birthday.year) 

25 for year in range(start_year, end.year + 1): 

26 bday = copy.deepcopy(member) 

27 try: 

28 bday.profile.birthday = bday.profile.birthday.replace(year=year) 

29 except ValueError as e: 

30 if bday.profile.birthday.month == 2 and bday.profile.birthday.day == 29: 

31 bday.profile.birthday = bday.profile.birthday.replace( 

32 year=year, day=28 

33 ) 

34 else: 

35 raise e 

36 if start.date() <= bday.profile.birthday <= end.date(): 

37 birthdays.append(bday) 

38 return birthdays 

39 

40 def get_queryset(self): 

41 start, end = extract_date_range(self.request) 

42 

43 queryset = ( 

44 Member.current_members.with_birthdays_in_range(start, end) 

45 .filter(profile__show_birthday=True) 

46 .select_related("profile") 

47 ) 

48 

49 all_birthdays = [self._get_birthdays(m, start, end) for m in queryset.all()] 

50 birthdays = [x for sublist in all_birthdays for x in sublist] 

51 

52 today = timezone.now().date() 

53 prefetch_related_objects( 

54 birthdays, 

55 Prefetch( 

56 "membership_set", 

57 queryset=Membership.objects.filter( 

58 Q(until__isnull=True) | Q(until__gt=today), since__lte=today 

59 ).order_by("-since")[:1], 

60 to_attr="_current_membership", 

61 ), 

62 ) 

63 

64 return birthdays