diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index e460eb5a..94bb0ea9 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -847,10 +847,12 @@ class Agenda(models.Model): @staticmethod def filter_for_guardian(qs, guardian_external_id, child_external_id, min_start=None, max_start=None): agendas = SharedCustodyAgenda.objects.filter(child__user_external_id=child_external_id).order_by( - '-date_start' + 'date_start' ) if max_start: agendas = agendas.filter(date_start__lte=max_start) + if min_start: + agendas = agendas.filter(Q(date_end__isnull=True) | Q(date_end__gte=min_start)) if not agendas: return qs @@ -861,20 +863,29 @@ class Agenda(models.Model): .annotate(odd_week=F('week_number') % 2) ) - previous_date_start = None + previous_date_end = None filtered_qs = Event.objects.none() for agenda in agendas: - if previous_date_start and min_start and previous_date_start < min_start.date(): - break - filtered_qs |= Agenda.filter_for_custody_agenda( - qs, agenda, guardian_external_id, date_end=previous_date_start - ) - previous_date_start = agenda.date_start + filtered_qs |= Agenda.filter_for_custody_agenda(qs, agenda, guardian_external_id) + + if not previous_date_end: + # first shared custody agenda, include all events before it begins + filtered_qs |= qs.filter(start_datetime__lt=agenda.date_start) + else: + # include all events between agendas + filtered_qs |= qs.filter( + start_datetime__lt=agenda.date_start, start_datetime__date__gt=previous_date_end + ) + previous_date_end = agenda.date_end + + if previous_date_end: + # last agenda has end date, include all events after it + filtered_qs |= qs.filter(start_datetime__gt=previous_date_end) return filtered_qs @staticmethod - def filter_for_custody_agenda(qs, agenda, guardian_external_id, date_end=None): + def filter_for_custody_agenda(qs, agenda, guardian_external_id): rules = ( SharedCustodyRule.objects.filter( guardian__user_external_id=guardian_external_id, @@ -916,8 +927,8 @@ class Agenda(models.Model): (rules_lookup | Q(in_exceptional_period=True)) & Q(in_excluded_exceptional_period=False), start_datetime__gte=agenda.date_start, ) - if date_end: - qs = qs.filter(start_datetime__lt=date_end) + if agenda.date_end: + qs = qs.filter(start_datetime__date__lte=agenda.date_end) return qs diff --git a/tests/api/datetimes/test_events_multiple_agendas.py b/tests/api/datetimes/test_events_multiple_agendas.py index d8802edc..c351f6c8 100644 --- a/tests/api/datetimes/test_events_multiple_agendas.py +++ b/tests/api/datetimes/test_events_multiple_agendas.py @@ -1281,6 +1281,8 @@ def test_datetimes_multiple_agendas_shared_custody_date_start(app): ) assert len(resp.json['data']) == 0 + agenda.date_end = datetime.date(year=2022, month=3, day=9) + agenda.save() agenda = SharedCustodyAgenda.objects.create( first_guardian=father, second_guardian=mother, @@ -1307,6 +1309,8 @@ def test_datetimes_multiple_agendas_shared_custody_date_start(app): 'first-agenda@event-wednesday--2022-03-30-1400', ] + agenda.date_end = datetime.date(year=2022, month=3, day=16) + agenda.save() agenda = SharedCustodyAgenda.objects.create( first_guardian=father, second_guardian=mother, @@ -1349,6 +1353,8 @@ def test_datetimes_multiple_agendas_shared_custody_date_start(app): 'first-agenda@event-wednesday--2022-03-09-1400', ] + agenda.date_end = datetime.date(year=2022, month=3, day=21) + agenda.save() other_person = Person.objects.create(user_external_id='other_person', first_name='O', last_name='P') agenda = SharedCustodyAgenda.objects.create( first_guardian=other_person, @@ -1385,6 +1391,78 @@ def test_datetimes_multiple_agendas_shared_custody_date_start(app): ] +@pytest.mark.freeze_time('2022-03-01 14:00') +def test_datetimes_multiple_agendas_shared_custody_date_boundaries(app): + agenda = Agenda.objects.create(label='First agenda', kind='events', maximal_booking_delay=0) + Desk.objects.create(agenda=agenda, slug='_exceptions_holder') + start_datetime = make_aware(datetime.datetime(year=2022, month=3, day=2, hour=14, minute=0)) + wednesday_event = Event.objects.create( + slug='event-wednesday', + start_datetime=start_datetime, + recurrence_days=[2], + recurrence_end_date=datetime.datetime(year=2022, month=5, day=15), + places=5, + agenda=agenda, + ) + wednesday_event.create_all_recurrences() + Subscription.objects.create( + agenda=agenda, + user_external_id='child_id', + date_start=wednesday_event.start_datetime, + date_end=wednesday_event.recurrence_end_date, + ) + + father = Person.objects.create(user_external_id='father_id', first_name='John', last_name='Doe') + mother = Person.objects.create(user_external_id='mother_id', first_name='Jane', last_name='Doe') + child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe') + agenda = SharedCustodyAgenda.objects.create( + first_guardian=father, + second_guardian=mother, + child=child, + date_start=datetime.datetime(year=2022, month=3, day=15), # 15 days after recurring event start + date_end=datetime.datetime(year=2022, month=3, day=30), # 30 days after recurring event start + ) + SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7))) + agenda = SharedCustodyAgenda.objects.create( + first_guardian=father, + second_guardian=mother, + child=child, + date_start=datetime.datetime(year=2022, month=4, day=13), # 45 days after recurring event start + date_end=datetime.datetime(year=2022, month=4, day=28), # 60 days after recurring event start + ) + SharedCustodyRule.objects.create(agenda=agenda, guardian=mother, days=list(range(7))) + + resp = app.get( + '/api/agendas/datetimes/', + params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'father_id'}, + ) + assert [d['id'] for d in resp.json['data']] == [ + 'first-agenda@event-wednesday--2022-03-02-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-03-09-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-03-16-1400', # has custody + 'first-agenda@event-wednesday--2022-03-23-1400', # has custody + 'first-agenda@event-wednesday--2022-03-30-1400', # has custody + 'first-agenda@event-wednesday--2022-04-06-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-05-04-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-05-11-1400', # no custody agenda + ] + + resp = app.get( + '/api/agendas/datetimes/', + params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, + ) + assert [d['id'] for d in resp.json['data']] == [ + 'first-agenda@event-wednesday--2022-03-02-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-03-09-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-04-06-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-04-13-1400', # has custody + 'first-agenda@event-wednesday--2022-04-20-1400', # has custody + 'first-agenda@event-wednesday--2022-04-27-1400', # has custody + 'first-agenda@event-wednesday--2022-05-04-1400', # no custody agenda + 'first-agenda@event-wednesday--2022-05-11-1400', # no custody agenda + ] + + def test_datetimes_multiple_agendas_with_status(app): agenda = Agenda.objects.create(label='agenda', kind='events') Desk.objects.create(agenda=agenda, slug='_exceptions_holder') diff --git a/tests/api/datetimes/test_recurring_events.py b/tests/api/datetimes/test_recurring_events.py index 429073e1..553ba6df 100644 --- a/tests/api/datetimes/test_recurring_events.py +++ b/tests/api/datetimes/test_recurring_events.py @@ -277,7 +277,11 @@ def test_recurring_events_api_list_shared_custody_start_date(app): child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe') custody_agenda = SharedCustodyAgenda.objects.create( - first_guardian=father, second_guardian=mother, child=child, date_start=now() + first_guardian=father, + second_guardian=mother, + child=child, + date_start=now(), + date_end=now() + datetime.timedelta(days=14), ) SharedCustodyRule.objects.create(agenda=custody_agenda, guardian=father, days=[0], weeks='even') SharedCustodyRule.objects.create(agenda=custody_agenda, guardian=mother, days=[1, 2], weeks='odd') diff --git a/tests/api/fillslot/test_events_multiple_agendas.py b/tests/api/fillslot/test_events_multiple_agendas.py index 5e7291f6..7ce99e1a 100644 --- a/tests/api/fillslot/test_events_multiple_agendas.py +++ b/tests/api/fillslot/test_events_multiple_agendas.py @@ -677,7 +677,11 @@ def test_api_events_fillslots_multiple_agendas_shared_custody_date_start(app, us child = Person.objects.create(user_external_id='child_id', first_name='James', last_name='Doe') agenda = SharedCustodyAgenda.objects.create( - first_guardian=father, second_guardian=mother, child=child, date_start=now() + first_guardian=father, + second_guardian=mother, + child=child, + date_start=now(), + date_end=datetime.date(year=2022, month=3, day=9), ) SharedCustodyRule.objects.create(agenda=agenda, guardian=father, days=list(range(7))) diff --git a/tests/api/fillslot/test_recurring_events.py b/tests/api/fillslot/test_recurring_events.py index 2394d3ec..5881b1d1 100644 --- a/tests/api/fillslot/test_recurring_events.py +++ b/tests/api/fillslot/test_recurring_events.py @@ -1376,6 +1376,8 @@ def test_recurring_events_api_fillslots_shared_custody(app, user, freezer): ] # give father full custody from 14/03/2022 + agenda.date_end = datetime.date(year=2022, month=3, day=13) + agenda.save() agenda2 = SharedCustodyAgenda.objects.create( first_guardian=father, second_guardian=mother, diff --git a/tests/api/test_shared_custody.py b/tests/api/test_shared_custody.py index 99a07aac..d68ddfae 100644 --- a/tests/api/test_shared_custody.py +++ b/tests/api/test_shared_custody.py @@ -90,18 +90,21 @@ def test_add_shared_custody_agenda_with_rules(app, user, settings): agenda = SharedCustodyAgenda.objects.get(pk=resp.json['data']['id']) assert not agenda.is_complete() assert not agenda.rules.exists() + agenda.delete() resp = app.post_json('/api/shared-custody/', params={'weeks': 'even', **params}) agenda = SharedCustodyAgenda.objects.get(pk=resp.json['data']['id']) assert agenda.is_complete() assert agenda.rules.filter(guardian__first_name='John', weeks='even').exists() assert agenda.rules.filter(guardian__first_name='Jane', weeks='odd').exists() + agenda.delete() resp = app.post_json('/api/shared-custody/', params={'weeks': 'odd', **params}) agenda = SharedCustodyAgenda.objects.get(pk=resp.json['data']['id']) assert agenda.is_complete() assert agenda.rules.filter(guardian__first_name='John', weeks='odd').exists() assert agenda.rules.filter(guardian__first_name='Jane', weeks='even').exists() + agenda.delete() resp = app.post_json( '/api/shared-custody/', params={'christmas_holidays:periodicity': 'first-half', **params} @@ -114,6 +117,7 @@ def test_add_shared_custody_agenda_with_rules(app, user, settings): guardian__first_name='Jane', holiday__slug='christmas_holidays', periodicity='second-half', years='' ).exists() assert agenda.periods.count() == 12 + agenda.delete() resp = app.post_json( '/api/shared-custody/', @@ -149,6 +153,7 @@ def test_add_shared_custody_agenda_with_rules(app, user, settings): years='odd', ).exists() assert agenda.periods.count() == 20 + agenda.delete() # unknown holiday resp = app.post_json(