[FIX] microsoft_calendar: issue when archiving several events
In the `write` method, accessing the `ms_organizer_event_id` field of `self` leads to an exception if `self` represents several records. So, the idea of this fix is to set the `need_sync_m` field of all modified records to `True` when at least a field to sync with Outlook is modified (see `_get_microsoft_synced_fields()`) and then, at the end of the `write` method, really patch or delete records that are already linked to Outlook (that means they already have their `ms_organizer_event_id` field set). closes odoo/odoo#96761 X-original-commit: 1a66343327f9ea9f59ba25ea63e26331cabb65b5 Signed-off-by: Arnaud Joset <arj@odoo.com>
This commit is contained in:
committed by
Arnaud Joset
parent
1a77ace252
commit
77e89e893c
@@ -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
|
||||
|
||||
|
||||
@@ -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")],
|
||||
|
||||
@@ -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):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user