[FIX] google_calendar: Avoid unexpected recurring event duplication
When following recurring meeting are imported through google calendar synchronisation, it happens that a meeting get unexpectedly duplicated in Odoo, what will in turn duplicate the event on google and send invitations to all the existing attendees. As calendar.recurrence.calendar_event_ids is a One2many field, the update using self was setting the base_event_id's recurrence_id field to the last record of self recordset. Due to this, the event will not be considered to filter out the existing_ranges in calendar.recurrence._reconcile_events function. Therefore, a calendar.event will in turn be created using the same start and end datetime as the base_event_id of the calendar.recurrence. OPW-3143680 closes odoo/odoo#114392 X-original-commit: d1587758ac642b0181e660ea48222385d01098e3 Signed-off-by: Arnaud Joset <arj@odoo.com>
This commit is contained in:
@@ -217,7 +217,7 @@ class RecurrenceRule(models.Model):
|
||||
specific_values_creation = {}
|
||||
|
||||
for recurrence in self.filtered('base_event_id'):
|
||||
self.calendar_event_ids |= recurrence.base_event_id
|
||||
recurrence.calendar_event_ids |= recurrence.base_event_id
|
||||
event = recurrence.base_event_id or recurrence._get_first_event(include_outliers=False)
|
||||
duration = event.stop - event.start
|
||||
if specific_values_creation:
|
||||
|
||||
@@ -742,6 +742,86 @@ class TestSyncGoogle2Odoo(TestSyncGoogle):
|
||||
self.assertEqual(recurrence.event_tz, 'Pacific/Auckland', "The Google event Timezone should be saved on the recurrency")
|
||||
self.assertGoogleAPINotCalled()
|
||||
|
||||
@patch_api
|
||||
def test_recurrence_no_duplicate(self):
|
||||
values = [
|
||||
{
|
||||
"attendees": [
|
||||
{
|
||||
"email": "myemail@exampl.com",
|
||||
"responseStatus": "needsAction",
|
||||
"self": True,
|
||||
},
|
||||
{"email": "jane.doe@example.com", "responseStatus": "needsAction"},
|
||||
{
|
||||
"email": "john.doe@example.com",
|
||||
"organizer": True,
|
||||
"responseStatus": "accepted",
|
||||
},
|
||||
],
|
||||
"created": "2023-02-20T11:45:07.000Z",
|
||||
"creator": {"email": "john.doe@example.com"},
|
||||
"end": {"dateTime": "2023-02-25T16:20:00+01:00", "timeZone": "Europe/Zurich"},
|
||||
"etag": '"4611038912699385"',
|
||||
"eventType": "default",
|
||||
"iCalUID": "9lxiofipomymx2yr1yt0hpep99@google.com",
|
||||
"id": "9lxiofipomymx2yr1yt0hpep99",
|
||||
"kind": "calendar#event",
|
||||
"organizer": {"email": "john.doe@example.com"},
|
||||
"recurrence": ["RRULE:FREQ=WEEKLY;BYDAY=SA"],
|
||||
"reminders": {"useDefault": True},
|
||||
"sequence": 0,
|
||||
"start": {"dateTime": "2023-02-25T15:30:00+01:00", "timeZone": "Europe/Zurich"},
|
||||
"status": "confirmed",
|
||||
"summary": "Weekly test",
|
||||
"updated": "2023-02-20T11:45:08.547Z",
|
||||
},
|
||||
{
|
||||
"attendees": [
|
||||
{
|
||||
"email": "myemail@exampl.com",
|
||||
"responseStatus": "needsAction",
|
||||
"self": True,
|
||||
},
|
||||
{
|
||||
"email": "jane.doe@example.com",
|
||||
"organizer": True,
|
||||
"responseStatus": "needsAction",
|
||||
},
|
||||
{"email": "john.doe@example.com", "responseStatus": "accepted"},
|
||||
],
|
||||
"created": "2023-02-20T11:45:44.000Z",
|
||||
"creator": {"email": "john.doe@example.com"},
|
||||
"end": {"dateTime": "2023-02-26T15:20:00+01:00", "timeZone": "Europe/Zurich"},
|
||||
"etag": '"5534851880843722"',
|
||||
"eventType": "default",
|
||||
"iCalUID": "hhb5t0cffjkndvlg7i22f7byn1@google.com",
|
||||
"id": "hhb5t0cffjkndvlg7i22f7byn1",
|
||||
"kind": "calendar#event",
|
||||
"organizer": {"email": "jane.doe@example.com"},
|
||||
"recurrence": ["RRULE:FREQ=WEEKLY;BYDAY=SU"],
|
||||
"reminders": {"useDefault": True},
|
||||
"sequence": 0,
|
||||
"start": {"dateTime": "2023-02-26T14:30:00+01:00", "timeZone": "Europe/Zurich"},
|
||||
"status": "confirmed",
|
||||
"summary": "Weekly test 2",
|
||||
"updated": "2023-02-20T11:48:00.634Z",
|
||||
},
|
||||
]
|
||||
google_events = GoogleEvent(values)
|
||||
self.env['calendar.recurrence']._sync_google2odoo(google_events)
|
||||
no_duplicate_gevent = google_events.filter(lambda e: e.id == "9lxiofipomymx2yr1yt0hpep99")
|
||||
dt_start = datetime.fromisoformat(no_duplicate_gevent.start["dateTime"]).astimezone(pytz.utc).replace(tzinfo=None).replace(hour=0)
|
||||
dt_end = datetime.fromisoformat(no_duplicate_gevent.end["dateTime"]).astimezone(pytz.utc).replace(tzinfo=None).replace(hour=23)
|
||||
no_duplicate_event = self.env["calendar.event"].search(
|
||||
[
|
||||
("name", "=", no_duplicate_gevent.summary),
|
||||
("start", ">=", dt_start),
|
||||
("stop", "<=", dt_end,)
|
||||
]
|
||||
)
|
||||
self.assertEqual(len(no_duplicate_event), 1)
|
||||
|
||||
@patch_api
|
||||
def test_simple_event_into_recurrency(self):
|
||||
""" Synched single events should be converted in recurrency without problems"""
|
||||
|
||||
Reference in New Issue
Block a user