From ff288feac898a620e11527c843b4204f61e6ab71 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Thu, 24 Mar 2022 17:04:53 +0100 Subject: [PATCH 3/4] agendas: exceptional custody periods should override holiday rules (#62801) --- chrono/agendas/models.py | 25 +++++++++++++++++++------ tests/api/test_datetimes.py | 20 ++++++++++++++++++++ tests/test_agendas.py | 16 ++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index 2d736446..c78a378e 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -896,14 +896,25 @@ class Agenda(models.Model): date_start__lte=OuterRef('start_datetime'), date_end__gt=OuterRef('start_datetime'), ) - custody_periods = all_periods.filter(guardian__user_external_id=guardian_external_id) - excluded_periods = all_periods.exclude(guardian__user_external_id=guardian_external_id) + holiday_periods = all_periods.filter(holiday_rule__isnull=False) + exceptional_periods = all_periods.filter(holiday_rule__isnull=True) qs = qs.annotate( - in_custody_period=Exists(custody_periods), - in_excluded_period=Exists(excluded_periods), + in_holiday_period=Exists(holiday_periods.filter(guardian__user_external_id=guardian_external_id)), + in_excluded_holiday_period=Exists( + holiday_periods.exclude(guardian__user_external_id=guardian_external_id) + ), + in_exceptional_period=Exists( + exceptional_periods.filter(guardian__user_external_id=guardian_external_id) + ), + in_excluded_exceptional_period=Exists( + exceptional_periods.exclude(guardian__user_external_id=guardian_external_id) + ), ) - return qs.filter((rules_lookup | Q(in_custody_period=True)) & Q(in_excluded_period=False)) + rules_lookup = (rules_lookup | Q(in_holiday_period=True)) & Q(in_excluded_holiday_period=False) + return qs.filter( + (rules_lookup | Q(in_exceptional_period=True)) & Q(in_excluded_exceptional_period=False) + ) @staticmethod def prefetch_recurring_events(qs): @@ -3117,7 +3128,9 @@ class SharedCustodyAgenda(models.Model): def get_custody_slots(self, min_date, max_date): slots = set() - periods = self.periods.filter(date_start__lt=max_date, date_end__gt=min_date) + periods = self.periods.filter(date_start__lt=max_date, date_end__gt=min_date).order_by( + '-holiday_rule' + ) for period in periods: date = period.date_start while date < period.date_end and date < max_date: diff --git a/tests/api/test_datetimes.py b/tests/api/test_datetimes.py index a70f2804..84cc102d 100644 --- a/tests/api/test_datetimes.py +++ b/tests/api/test_datetimes.py @@ -2731,3 +2731,23 @@ def test_datetimes_multiple_agendas_shared_custody_holiday_rules(app): params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, ) assert len(resp.json['data']) == 0 + + # check exceptional custody periods take precedence over holiday rules + SharedCustodyPeriod.objects.create( + agenda=agenda, + guardian=mother, + date_start=datetime.date(2021, 12, 22), + date_end=datetime.date(2021, 12, 30), + ) + + resp = app.get( + '/api/agendas/datetimes/', + params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'father_id'}, + ) + assert len(resp.json['data']) == 0 + + resp = app.get( + '/api/agendas/datetimes/', + params={'subscribed': 'all', 'user_external_id': 'child_id', 'guardian_external_id': 'mother_id'}, + ) + assert len(resp.json['data']) == 1 diff --git a/tests/test_agendas.py b/tests/test_agendas.py index 5b24a418..3675babc 100644 --- a/tests/test_agendas.py +++ b/tests/test_agendas.py @@ -3292,3 +3292,19 @@ def test_shared_custody_agenda_holiday_rules_application(): assert all(name == 'John Doe' for name in guardians[:21]) assert all(name == 'Jane Doe' for name in guardians[21:28]) assert all(name == 'John Doe' for name in guardians[28:]) + + # check exceptional custody periods take precedence over holiday rules + SharedCustodyPeriod.objects.create( + agenda=agenda, + guardian=mother, + date_start=datetime.date(year=2021, month=12, day=27), + date_end=datetime.date(year=2021, month=12, day=29), + ) + slots = agenda.get_custody_slots(date_start, date_start + datetime.timedelta(days=30)) + slots = [(x.date.strftime('%d/%m'), x.guardian.name) for x in slots] + assert slots[13:17] == [ + ('26/12', 'John Doe'), + ('27/12', 'Jane Doe'), + ('28/12', 'Jane Doe'), + ('29/12', 'John Doe'), + ] -- 2.30.2