From fd96a99eefc7bd42535d39a0739b71126dbf1161 Mon Sep 17 00:00:00 2001 From: alt-odoo Date: Fri, 26 Nov 2021 07:59:46 +0000 Subject: [PATCH] [FIX] google_calendar: don't delete several times the same attendee Small side effect of commit https://github.com/odoo/odoo/commit/b19dc634684aab239575b9a9e784c7420d110b7d When deleting old attendees, we are removing the partner id associated with the email from the partner_ids set on the event. As the same partner can be set on more than one event, we need to loop only once on each attendee email, otherwise we will face the error "Record does not exist or has been deleted." Also, when deleting partner_ids on an event, the attendee is already automatically removed as well in _attendees_values method, there is no need to do it manually, as it will raise the error a second time. opw-2694428 opw-2695915 closes odoo/odoo#80828 X-original-commit: 766a1ad50a9dbc85ed2f9083f881781b7d5ec96c Signed-off-by: Arnaud Joset Signed-off-by: Alex Thuyls (alt) --- .../models/calendar_recurrence_rule.py | 7 +-- .../tests/test_sync_google2odoo.py | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/addons/google_calendar/models/calendar_recurrence_rule.py b/addons/google_calendar/models/calendar_recurrence_rule.py index 5ed93209d60..dd435137db6 100644 --- a/addons/google_calendar/models/calendar_recurrence_rule.py +++ b/addons/google_calendar/models/calendar_recurrence_rule.py @@ -106,14 +106,11 @@ class RecurrenceRule(models.Model): if attendee[2].get('displayName') and not partner.name: partner.name = attendee[2].get('displayName') - unlinked_attendee = self.env['calendar.attendee'] - for odoo_attendee_email in existing_attendees.mapped('email'): + for odoo_attendee_email in set(existing_attendees.mapped('email')): # Remove old attendees if email_normalize(odoo_attendee_email) not in emails: attendee = existing_attendees.filtered(lambda att: att.email == email_normalize(odoo_attendee_email)) - unlinked_attendee |= attendee - self.calendar_event_ids.write({'partner_ids': [(3, attendee.partner_id.id)]}) - unlinked_attendee.unlink() + self.calendar_event_ids.write({'need_sync': False, 'partner_ids': [(3, attendee.partner_id.id)]}) # Update the recurrence values old_event_values = self.base_event_id and self.base_event_id.read(base_event_time_fields)[0] diff --git a/addons/google_calendar/tests/test_sync_google2odoo.py b/addons/google_calendar/tests/test_sync_google2odoo.py index 1311614f662..08d9fe59dab 100644 --- a/addons/google_calendar/tests/test_sync_google2odoo.py +++ b/addons/google_calendar/tests/test_sync_google2odoo.py @@ -236,6 +236,50 @@ class TestSyncGoogle2Odoo(TestSyncGoogle): self.assertNotEqual(event.partner_ids, user.partner_id) self.assertGoogleAPINotCalled() + @patch_api + def test_attendee_removed_multiple(self): + + user = new_test_user(self.env, login='calendar-user') + google_id = 'oj44nep1ldf8a3ll02uip0c9aa' + base_event = self.env['calendar.event'].create({ + 'name': 'coucou', + 'allday': True, + 'start': datetime(2020, 1, 6), + 'stop': datetime(2020, 1, 6), + 'user_id': False, # user is not owner + 'need_sync': False, + 'partner_ids': [(6, 0, user.partner_id.ids)], # but user is attendee + }) + recurrence = self.env['calendar.recurrence'].create({ + 'google_id': google_id, + 'rrule': 'FREQ=WEEKLY;COUNT=2;BYDAY=MO', + 'need_sync': False, + 'base_event_id': base_event.id, + 'calendar_event_ids': [(4, base_event.id)], + }) + recurrence._apply_recurrence() + + gevent = GoogleEvent([{ + 'id': google_id, + "updated": self.now, + 'organizer': {'email': 'odoocalendarref@gmail.com', 'self': True}, + 'summary': 'coucou', + 'visibility': 'public', + 'attendees': [], # <= attendee removed in Google + 'recurrence': ['RRULE:FREQ=WEEKLY;COUNT=2;BYDAY=MO'], + 'reminders': {'useDefault': True}, + 'start': {'date': '2020-01-6'}, + 'end': {'date': '2020-01-7'}, + }]) + events = recurrence.calendar_event_ids.sorted('start') + self.assertEqual(events.partner_ids, user.partner_id) + self.assertEqual(events.attendee_ids.partner_id, user.partner_id) + self.sync(gevent) + # User attendee removed but gevent owner might be added after synch. + self.assertNotEqual(events.attendee_ids.partner_id, user.partner_id) + self.assertNotEqual(events.partner_ids, user.partner_id) + self.assertGoogleAPINotCalled() + @patch_api def test_recurrence(self): recurrence_id = 'oj44nep1ldf8a3ll02uip0c9aa'