From d6bce1bacf57aac53572a5a404d137898c9944b1 Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Mon, 1 Apr 2024 15:35:51 -0400 Subject: [PATCH 1/2] fix date comparison --- ambition_utils/docs/release_notes.rst | 4 ++ ambition_utils/rrule/forms.py | 9 +++-- ambition_utils/rrule/tests/form_tests.py | 47 ++++++++++++++++++++++++ ambition_utils/version.py | 2 +- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/ambition_utils/docs/release_notes.rst b/ambition_utils/docs/release_notes.rst index 060acf2..16a0b6b 100644 --- a/ambition_utils/docs/release_notes.rst +++ b/ambition_utils/docs/release_notes.rst @@ -2,6 +2,10 @@ Release Notes ============= +3.1.12 +------ +* Fix possible null date comparison in rrule form update logic + 3.1.11 ------ * migration adjustment diff --git a/ambition_utils/rrule/forms.py b/ambition_utils/rrule/forms.py index 2c2bac3..9ec7bd7 100644 --- a/ambition_utils/rrule/forms.py +++ b/ambition_utils/rrule/forms.py @@ -225,7 +225,7 @@ def __init__(self, *args, **kwargs): # cause the base form init to fail kwargs.pop('instance', None) - super(RecurrenceForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def clean_rrule_exclusion(self): # Get the value from data @@ -255,12 +255,15 @@ def save(self, **kwargs): # Get the rrule model from the cleaned data rrule_model = self.cleaned_data.get('rrule') if rrule_model: - # Refresh if the next occurrence is not expired. - need_to_refresh_next_occurrence = rrule_model.next_occurrence > datetime.utcnow() + need_to_refresh_next_occurrence = True else: # Use the recurrence passed into save kwargs rrule_model = kwargs.get('recurrence') or RRule() + # Do not refresh if the next occurrence has not been handled yet + if rrule_model.next_occurrence and rrule_model.next_occurrence <= datetime.utcnow(): + need_to_refresh_next_occurrence = False + # Create or update the rule rrule_model.rrule_params = self.get_rrule_params_from_cleaned_data() rrule_model.rrule_exclusion_params = self.cleaned_data.get('rrule_exclusion') diff --git a/ambition_utils/rrule/tests/form_tests.py b/ambition_utils/rrule/tests/form_tests.py index 6a84d8f..56ed57d 100644 --- a/ambition_utils/rrule/tests/form_tests.py +++ b/ambition_utils/rrule/tests/form_tests.py @@ -498,6 +498,53 @@ def test_update(self): RRule.objects.update_next_occurrences([rrule_model]) self.assertEqual(rrule_model.next_occurrence, datetime.datetime(2017, 6, 7)) + def test_update_finished_rrule(self): + """ + Handles the case of trying to update an rrule that has completed so it no longer has a next + occurrence. It should be able to update without any errors. + """ + # Create an object, update its next occurrence, and assert it changes. + with freeze_time(datetime.datetime(2017, 6, 6)): + data = { + 'freq': rrule.DAILY, + 'interval': 1, + 'dtstart': '6/4/2017', + 'byhour': '0', + 'time_zone': 'UTC', + 'ends': RecurrenceEnds.ON, + 'until': '6/5/2017', + } + form = RecurrenceForm(data=data) + self.assertTrue(form.is_valid()) + rrule_model = form.save( + occurrence_handler_path='ambition_utils.rrule.handler.OccurrenceHandler', + ) + + # Refresh next occurrence so it completes + rrule_model.refresh_next_occurrence() + rrule_model.save() + self.assertEqual(RRule.objects.count(), 1) + self.assertEqual(rrule_model.next_occurrence, None) + + # In the future from the original completion date, try to update the rrule + with freeze_time(datetime.datetime(2017, 6, 9)): + data = { + 'rrule': str(rrule_model.id), + 'freq': rrule.DAILY, + 'interval': 1, + 'dtstart': '6/4/2017', + 'byhour': '0', + 'time_zone': 'UTC', + 'ends': RecurrenceEnds.ON, + 'until': '6/10/2017', + } + form = RecurrenceForm(data=data) + self.assertTrue(form.is_valid()) + rrule_model = form.save( + occurrence_handler_path='ambition_utils.rrule.handler.OccurrenceHandler', + ) + self.assertEqual(rrule_model.next_occurrence, datetime.datetime(2017, 6, 10)) + def test_exclusion_rule(self): exclusion_data = { 'freq': rrule.MONTHLY, diff --git a/ambition_utils/version.py b/ambition_utils/version.py index f71ed60..1e6263a 100644 --- a/ambition_utils/version.py +++ b/ambition_utils/version.py @@ -1 +1 @@ -__version__ = '3.1.11' +__version__ = '3.1.12' From c75fdb635867dae092d02daa8a70d04a71e73479 Mon Sep 17 00:00:00 2001 From: Wes Okes Date: Mon, 1 Apr 2024 15:53:50 -0400 Subject: [PATCH 2/2] version --- ambition_utils/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ambition_utils/version.py b/ambition_utils/version.py index 1e6263a..6b2e93c 100644 --- a/ambition_utils/version.py +++ b/ambition_utils/version.py @@ -1 +1 @@ -__version__ = '3.1.12' +__version__ = '3.1.13'