diff --git a/addons/microsoft_calendar/models/calendar_recurrence_rule.py b/addons/microsoft_calendar/models/calendar_recurrence_rule.py index fc1aa66f77c..4c1113e3333 100644 --- a/addons/microsoft_calendar/models/calendar_recurrence_rule.py +++ b/addons/microsoft_calendar/models/calendar_recurrence_rule.py @@ -100,7 +100,8 @@ class RecurrenceRule(models.Model): vals['event_tz'] = microsoft_event.start.get('timeZone') super()._write_from_microsoft(microsoft_event, vals) new_event_values = self.env["calendar.event"]._microsoft_to_odoo_values(microsoft_event) - if self._has_base_event_time_fields_changed(new_event_values): + # Edge case: if the base event was deleted manually in 'self_only' update, skip applying recurrence. + if self._has_base_event_time_fields_changed(new_event_values) and (new_event_values['start'] >= self.base_event_id.start): # we need to recreate the recurrence, time_fields were modified. base_event_id = self.base_event_id # We archive the old events to recompute the recurrence. These events are already deleted on Microsoft side. diff --git a/addons/microsoft_calendar/tests/test_delete_events.py b/addons/microsoft_calendar/tests/test_delete_events.py index 508e32919b4..71896521493 100644 --- a/addons/microsoft_calendar/tests/test_delete_events.py +++ b/addons/microsoft_calendar/tests/test_delete_events.py @@ -270,3 +270,26 @@ class TestDeleteEvents(TestCommon): """ Same than test_delete_first_event_and_future_from_recurrence_from_outlook_calendar. """ + + @patch.object(MicrosoftCalendarService, 'delete') + def test_delete_single_event_from_recurrence_from_odoo_calendar(self, mock_delete): + """ + Deletes the base_event of a recurrence and checks if the event was archived and the recurrence was updated. + """ + # arrange + idx = 0 + event_id = self.recurrent_events[idx].ms_organizer_event_id + + # act + self.recurrent_events[idx].with_user(self.organizer_user).action_mass_archive('self_only') + self.call_post_commit_hooks() + + # assert that event is not active anymore and that a new base_event was select for the recurrence + self.assertFalse(self.recurrent_events[idx].active) + self.assertNotEqual(self.id, self.recurrent_events[idx].recurrence_id.base_event_id.id) + self.assertTrue(self.id not in [rec.id for rec in self.recurrent_events[idx].recurrence_id.calendar_event_ids]) + mock_delete.assert_called_once_with( + event_id, + token=mock_get_token(self.organizer_user), + timeout=ANY + )