diff --git a/addons/microsoft_calendar/models/microsoft_sync.py b/addons/microsoft_calendar/models/microsoft_sync.py index a39001ee7e2..68eed99017d 100644 --- a/addons/microsoft_calendar/models/microsoft_sync.py +++ b/addons/microsoft_calendar/models/microsoft_sync.py @@ -78,30 +78,22 @@ class MicrosoftSync(models.AbstractModel): def write(self, vals): if 'ms_universal_event_id' in vals: self._from_uids.clear_cache(self) - synced_fields = self._get_microsoft_synced_fields() - if ( - 'need_sync_m' not in vals and vals.keys() & synced_fields - and self.ms_organizer_event_id - and not self.env.user.microsoft_synchronization_stopped - ): - fields_to_sync = [x for x in vals.keys() if x in synced_fields] - if fields_to_sync: - vals['need_sync_m'] = True - else: - fields_to_sync = [x for x in vals.keys() if x in synced_fields] + + fields_to_sync = [x for x in vals.keys() if x in self._get_microsoft_synced_fields()] + if fields_to_sync and 'need_sync_m' not in vals and not self.env.user.microsoft_synchronization_stopped: + vals['need_sync_m'] = True result = super().write(vals) - need_delete = 'active' in vals.keys() and not vals.get('active') - for record in self.filtered('need_sync_m'): - if record.ms_universal_event_id: - if need_delete: - # We need to delete the event. Cancel is not sufficant. Errors may occurs - record._microsoft_delete(record._get_organizer(), record.ms_organizer_event_id, timeout=3) - elif fields_to_sync: - values = record._microsoft_values(fields_to_sync) - if not values: - continue - record._microsoft_patch(record._get_organizer(), record.ms_organizer_event_id, values, timeout=3) + + for record in self.filtered(lambda e: e.need_sync_m and e.ms_organizer_event_id): + if not vals.get('active', True): + # We need to delete the event. Cancel is not sufficant. Errors may occurs + record._microsoft_delete(record._get_organizer(), record.ms_organizer_event_id, timeout=3) + elif fields_to_sync: + values = record._microsoft_values(fields_to_sync) + if not values: + continue + record._microsoft_patch(record._get_organizer(), record.ms_organizer_event_id, values, timeout=3) return result diff --git a/addons/microsoft_calendar/tests/common.py b/addons/microsoft_calendar/tests/common.py index 09108d3f8d4..84e0bd011c3 100644 --- a/addons/microsoft_calendar/tests/common.py +++ b/addons/microsoft_calendar/tests/common.py @@ -423,6 +423,18 @@ class TestCommon(HttpCase): ) ) + # a group of events + self.several_events = self.env["calendar.event"].search([("name", "like", "event%")]) + if not self.several_events: + self.several_events = self.env["calendar.event"].with_user(self.organizer_user).create([ + dict( + self.simple_event_values, + name=f"event{i}", + microsoft_id=combine_ids(f"e{i}", f"u{i}"), + ) + for i in range(1, 4) + ]) + # a recurrent event with 7 occurrences self.recurrent_base_event = self.env["calendar.event"].search( [("name", "=", "recurrent_event")], diff --git a/addons/microsoft_calendar/tests/test_delete_events.py b/addons/microsoft_calendar/tests/test_delete_events.py index 7e3d45a056f..508e32919b4 100644 --- a/addons/microsoft_calendar/tests/test_delete_events.py +++ b/addons/microsoft_calendar/tests/test_delete_events.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from unittest.mock import patch, ANY +from unittest.mock import patch, ANY, call from odoo.addons.microsoft_calendar.utils.microsoft_calendar import MicrosoftCalendarService from odoo.addons.microsoft_calendar.utils.microsoft_event import MicrosoftEvent @@ -81,6 +81,24 @@ class TestDeleteEvents(TestCommon): timeout=ANY ) + @patch.object(MicrosoftCalendarService, 'delete') + def test_archive_several_events_at_once(self, mock_delete): + """ + Archive several events at once should not produce any exception. + """ + # act + self.several_events.action_archive() + self.call_post_commit_hooks() + self.several_events.invalidate_recordset() + + # assert + self.assertFalse(all(e.active for e in self.several_events)) + + mock_delete.assert_has_calls([ + call(e.ms_organizer_event_id, token=ANY, timeout=ANY) + for e in self.several_events + ]) + @patch.object(MicrosoftCalendarService, 'get_events') def test_cancel_simple_event_from_outlook_organizer_calendar(self, mock_get_events): """