summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Widart <awt@odoo.com>2021-03-09 07:57:04 +0000
committerAdrien Widart <awt@odoo.com>2021-03-26 07:37:11 +0000
commita2ba0b37a5eccf4f7ab96fd6f0b4f6e634c58ba9 (patch)
tree43bd81e059962cf48c4ca8899d25b4fafde43f95
parent8318ec332ddc3180cf6e3adcad015de31ae2f808 (diff)
[FIX] microsoft_calendar: warn user if attendee without email
When syncing both Odoo and Outlook Calendar, if one Odoo event has an attendee who does not have any email adress, it will lead to a traceback error. To reproduce the error: 1. Create a partner P who does not have an email address 2. In Calendar, create an event E with P 3. Sync with Outlook Error: An Odoo Error is raised. When syncing from Outlook to Odoo, it also sync the E-event (in case the latter has been updated on Outlook). The Microsoft2Odoo syncing uses the email address of each attendee. Since P does not have any, this creates the error. Although Odoo allows the use of participants without email, this is not the case for Outlook. On Outlook Calendar, as soon as a user adds an attendee to an Event, Outlook will want to send an invitation before saving this event (so, if the participant does not have any email address, it won't be possible to save the event). When syncing, the E-event will be added to Outlook Calendar. However, for the same reasons as in the previous paragraph, it will not be possible to update this event from Outlook Calendar. Therefore, the solution is to prevent the user from having attendees without email when his calendar is synchronized with Outlook. OPW-2439027 closes odoo/odoo#67637 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
-rw-r--r--addons/microsoft_calendar/i18n/microsoft_calendar.pot10
-rw-r--r--addons/microsoft_calendar/models/calendar.py23
-rw-r--r--addons/microsoft_calendar/models/calendar_recurrence_rule.py3
-rw-r--r--addons/microsoft_calendar/models/microsoft_sync.py6
-rw-r--r--addons/microsoft_calendar/tests/test_sync_microsoft2odoo.py20
5 files changed, 60 insertions, 2 deletions
diff --git a/addons/microsoft_calendar/i18n/microsoft_calendar.pot b/addons/microsoft_calendar/i18n/microsoft_calendar.pot
index efa15062d5e..84ca654e402 100644
--- a/addons/microsoft_calendar/i18n/microsoft_calendar.pot
+++ b/addons/microsoft_calendar/i18n/microsoft_calendar.pot
@@ -140,6 +140,16 @@ 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
#: model:ir.model.fields,field_description:microsoft_calendar.field_calendar_recurrence__id
#: model:ir.model.fields,field_description:microsoft_calendar.field_microsoft_calendar_account_reset__id
diff --git a/addons/microsoft_calendar/models/calendar.py b/addons/microsoft_calendar/models/calendar.py
index fe0274f0453..e7c647573ac 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',
@@ -347,6 +347,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 0044e3d499b..19010abb81c 100644
--- a/addons/microsoft_calendar/models/calendar_recurrence_rule.py
+++ b/addons/microsoft_calendar/models/calendar_recurrence_rule.py
@@ -102,3 +102,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 ea91094bff8..1e1147cbc78 100644
--- a/addons/microsoft_calendar/models/microsoft_sync.py
+++ b/addons/microsoft_calendar/models/microsoft_sync.py
@@ -131,6 +131,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'):
@@ -299,6 +300,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
@@ -308,6 +310,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,
@@ -345,6 +348,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 13b6f5a155f..f5d4d2dbae4 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 SavepointCase
@@ -221,3 +222,20 @@ class TestSyncMicrosoft2Odoo(SavepointCase):
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)