diff --git a/addons/microsoft_calendar/i18n/microsoft_calendar.pot b/addons/microsoft_calendar/i18n/microsoft_calendar.pot index 04f8dd36ea4..40855de147d 100644 --- a/addons/microsoft_calendar/i18n/microsoft_calendar.pot +++ b/addons/microsoft_calendar/i18n/microsoft_calendar.pot @@ -166,6 +166,15 @@ msgstr "" msgid "Event Recurrence Rule" msgstr "" +#. module: microsoft_calendar +#: code:addons/microsoft_calendar/models/calendar.py:0 +#, python-format +msgid "" +"For a correct synchronization between Odoo and Outlook Calendar, all attendees must have an email address. However, some events do not respect this condition. As long as the events are incorrect, the calendars will not be synchronized.\n" +"Either update the events/attendees or archive these events %s:\n" +"%s" +msgstr "" + #. module: microsoft_calendar #: model:ir.model.fields,field_description:microsoft_calendar.field_calendar_attendee__id #: model:ir.model.fields,field_description:microsoft_calendar.field_calendar_event__id diff --git a/addons/microsoft_calendar/models/calendar.py b/addons/microsoft_calendar/models/calendar.py index 233f53e544d..1c98788a596 100644 --- a/addons/microsoft_calendar/models/calendar.py +++ b/addons/microsoft_calendar/models/calendar.py @@ -6,7 +6,7 @@ from dateutil.parser import parse from dateutil.relativedelta import relativedelta from odoo import api, fields, models, _ -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError ATTENDEE_CONVERTER_O2M = { 'needsAction': 'notresponded', @@ -353,6 +353,27 @@ class Meeting(models.Model): return values + def _ensure_attendees_have_email(self): + invalid_event_ids = self.env['calendar.event'].search_read( + domain=[('id', 'in', self.ids), ('attendee_ids.partner_id.email', '=', False)], + fields=['display_time', 'display_name'], + order='start', + ) + if invalid_event_ids: + list_length_limit = 50 + total_invalid_events = len(invalid_event_ids) + invalid_event_ids = invalid_event_ids[:list_length_limit] + invalid_events = ['\t- %s: %s' % (event['display_time'], event['display_name']) + for event in invalid_event_ids] + invalid_events = '\n'.join(invalid_events) + details = "(%d/%d)" % (list_length_limit, total_invalid_events) if list_length_limit < total_invalid_events else "(%d)" % total_invalid_events + raise ValidationError(_("For a correct synchronization between Odoo and Outlook Calendar, " + "all attendees must have an email address. However, some events do " + "not respect this condition. As long as the events are incorrect, " + "the calendars will not be synchronized." + "\nEither update the events/attendees or archive these events %s:" + "\n%s", details, invalid_events)) + def _microsoft_values_occurence(self, initial_values={}): values = dict(initial_values) values['id'] = self.microsoft_id diff --git a/addons/microsoft_calendar/models/calendar_recurrence_rule.py b/addons/microsoft_calendar/models/calendar_recurrence_rule.py index 55c735fa03b..b26776195b3 100644 --- a/addons/microsoft_calendar/models/calendar_recurrence_rule.py +++ b/addons/microsoft_calendar/models/calendar_recurrence_rule.py @@ -108,3 +108,6 @@ class RecurrenceRule(models.Model): values += [event_value] return values + + def _ensure_attendees_have_email(self): + self.calendar_event_ids.filtered(lambda e: e.active)._ensure_attendees_have_email() diff --git a/addons/microsoft_calendar/models/microsoft_sync.py b/addons/microsoft_calendar/models/microsoft_sync.py index cbec487ff45..5145002d992 100644 --- a/addons/microsoft_calendar/models/microsoft_sync.py +++ b/addons/microsoft_calendar/models/microsoft_sync.py @@ -129,6 +129,7 @@ class MicrosoftSync(models.AbstractModel): records_to_sync = self cancelled_records = self - records_to_sync + records_to_sync._ensure_attendees_have_email() updated_records = records_to_sync.filtered('microsoft_id') new_records = records_to_sync - updated_records for record in cancelled_records.filtered('microsoft_id'): @@ -297,6 +298,7 @@ class MicrosoftSync(models.AbstractModel): def _microsoft_patch(self, microsoft_service: MicrosoftCalendarService, microsoft_id, values, timeout=TIMEOUT): with microsoft_calendar_token(self.env.user.sudo()) as token: if token: + self._ensure_attendees_have_email() microsoft_service.patch(microsoft_id, values, token=token, timeout=timeout) self.need_sync_m = False @@ -306,6 +308,7 @@ class MicrosoftSync(models.AbstractModel): return with microsoft_calendar_token(self.env.user.sudo()) as token: if token: + self._ensure_attendees_have_email() microsoft_id = microsoft_service.insert(values, token=token, timeout=timeout) self.write({ 'microsoft_id': microsoft_id, @@ -343,6 +346,9 @@ class MicrosoftSync(models.AbstractModel): """ raise NotImplementedError() + def _ensure_attendees_have_email(self): + raise NotImplementedError() + def _get_microsoft_sync_domain(self): """Return a domain used to search records to synchronize. e.g. return a domain to synchronize records owned by the current user. diff --git a/addons/microsoft_calendar/tests/test_sync_microsoft2odoo.py b/addons/microsoft_calendar/tests/test_sync_microsoft2odoo.py index 9528666f0b1..a3922d87eb2 100644 --- a/addons/microsoft_calendar/tests/test_sync_microsoft2odoo.py +++ b/addons/microsoft_calendar/tests/test_sync_microsoft2odoo.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo.addons.microsoft_calendar.utils.microsoft_calendar import MicrosoftEvent +from odoo.addons.microsoft_calendar.utils.microsoft_calendar import MicrosoftCalendarService, MicrosoftEvent +from odoo.exceptions import ValidationError import pytz from datetime import datetime, date from odoo.tests.common import TransactionCase @@ -221,3 +222,20 @@ class TestSyncMicrosoft2Odoo(TransactionCase): events = self.env['calendar.event'].browse(event_ids).exists() self.assertFalse(recurrence, "It should remove recurrence") self.assertFalse(events, "It should remove all events") + + def test_attendees_must_have_email(self): + """ + Synching with a partner without mail raises a ValidationError because Microsoft don't accept attendees without one. + """ + MicrosoftCal = MicrosoftCalendarService(self.env['microsoft.service']) + partner = self.env['res.partner'].create({ + 'name': 'SuperPartner', + }) + event = self.env['calendar.event'].create({ + 'name': "SuperEvent", + 'start': datetime(2020, 3, 16, 11, 0), + 'stop': datetime(2020, 3, 16, 13, 0), + 'partner_ids': [(4, partner.id)], + }) + with self.assertRaises(ValidationError): + event._sync_odoo2microsoft(MicrosoftCal)