Skip to content

Commit

Permalink
[FIX] google_calendar: don't remove organizer as attendee
Browse files Browse the repository at this point in the history
Before this commit, when updating recurrences from the Google side, if the attendees
were not specified by Google, then attendees from the previous events would be deleted
in the Odoo side. By doing it, the events were being updated but they were disappearing
from the organizer's calendar view, since there was no attendee.

After this commit, when updating the recurrences and not receiving the specific attendees,
the organizer will be kept as an attendee of the recurrent events, fixing the problem of
events disappearing from its calendar.

task-3731542

closes odoo#164408

X-original-commit: 47daaf7
Signed-off-by: Arnaud Joset (arj) <arj@odoo.com>
Signed-off-by: Gabriel de Paula Felix (gdpf) <gdpf@odoo.com>
  • Loading branch information
geflx committed May 6, 2024
1 parent 33fd2b1 commit 95e20f4
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 4 deletions.
6 changes: 3 additions & 3 deletions addons/google_calendar/models/calendar_recurrence_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ def _write_from_google(self, gevent, vals):
if attendee[2].get('displayName') and not partner.name:
partner.name = attendee[2].get('displayName')

organizers_partner_ids = [event.user_id.partner_id for event in self.calendar_event_ids if event.user_id]
for odoo_attendee_email in set(existing_attendees.mapped('email')):
# Remove old attendees. Sometimes, several partners have the same email.
# Sometimes, several partners have the same email. Remove old attendees except organizer, otherwise the events will disappear.
if email_normalize(odoo_attendee_email) not in emails:
attendees = existing_attendees.exists().filtered(lambda att: att.email == email_normalize(odoo_attendee_email))
attendees = existing_attendees.exists().filtered(lambda att: att.email == email_normalize(odoo_attendee_email) and att.partner_id not in organizers_partner_ids)
self.calendar_event_ids.write({'need_sync': False, 'partner_ids': [Command.unlink(att.partner_id.id) for att in attendees]})

# Update the recurrence values
old_event_values = self.base_event_id and self.base_event_id.read(base_event_time_fields)[0]
if old_event_values and any(new_event_values[key] != old_event_values[key] for key in base_event_time_fields):
# we need to recreate the recurrence, time_fields were modified.
Expand Down
51 changes: 50 additions & 1 deletion addons/google_calendar/tests/test_sync_google2odoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,7 @@ def test_alias_email_sync_recurrence(self):
'start': datetime(2020, 1, 6),
'stop': datetime(2020, 1, 6),
'need_sync': False,
'user_id': self.env.uid
})
recurrence = self.env['calendar.recurrence'].create({
'google_id': google_id,
Expand Down Expand Up @@ -1539,7 +1540,9 @@ def test_alias_email_sync_recurrence(self):
self.env['calendar.recurrence']._sync_google2odoo(GoogleEvent([values]))
events = recurrence.calendar_event_ids.sorted('start')
self.assertEqual(len(events), 2)
self.assertFalse(events.mapped('attendee_ids'))
# Only the event organizer must remain as attendee.
self.assertEqual(len(events.mapped('attendee_ids')), 1)
self.assertEqual(events.mapped('attendee_ids')[0].partner_id, self.env.user.partner_id)
self.assertGoogleAPINotCalled()

@patch_api
Expand Down Expand Up @@ -2157,3 +2160,49 @@ def test_accepting_recurrent_event_with_all_following_option_synced_by_organizer
]).sorted(key=lambda r: r.event_id.start)
for i, expected_state in enumerate(expected_states):
self.assertEqual(attendees[i].state, expected_state)
for i, event in enumerate(recurrence.calendar_event_ids.sorted("start")):
self.assertEqual(event.attendee_ids[1].state, expected_states[i])

@patch_api
def test_keep_organizer_attendee_writing_recurrence_from_google(self):
"""
When receiving recurrence updates from google in 'write_from_google', make
sure the organizer is kept as attendee of the events. This will guarantee
that the newly updated events will not disappear from the calendar view.
"""
def check_organizer_as_single_attendee(self, recurrence, organizer):
""" Ensure that the organizer is the single attendee of the recurrent events. """
for event in recurrence.calendar_event_ids:
self.assertTrue(len(event.attendee_ids) == 1, 'Should have only one attendee.')
self.assertEqual(event.attendee_ids[0].partner_id, organizer.partner_id, 'The single attendee must be the organizer.')

# Generate a regular recurrence with only the organizer as attendee.
recurrence_id = "rec_id"
recurrence = self.generate_recurring_event(
mock_dt="2024-04-10",
google_id=recurrence_id,
rrule="FREQ=DAILY;INTERVAL=1;COUNT=4",
start=datetime(2024, 4, 11, 9, 0),
stop=datetime(2024, 4, 11, 10, 0),
partner_ids=[Command.set([self.organizer_user.partner_id.id])],
)
check_organizer_as_single_attendee(self, recurrence, self.organizer_user)

# Update the recurrence without specifying its attendees, the organizer must be kept as
# attendee after processing it, thus the new events will be kept in its calendar view.
values = [{
'summary': 'updated_rec',
'id': recurrence_id,
'recurrence': ['RRULE:FREQ=DAILY;INTERVAL=1;COUNT=3'],
'start': {'dateTime': '2024-04-13T8:00:00+01:00'},
'end': {'dateTime': '2024-04-13T9:00:00+01:00'},
'reminders': {'useDefault': True},
'organizer': {'email': self.organizer_user.partner_id.email},
'attendees': [],
'updated': self.now,
}]
self.env['calendar.recurrence'].with_user(self.organizer_user)._sync_google2odoo(GoogleEvent(values))
events = recurrence.calendar_event_ids.sorted('start')
self.assertEqual(len(events), 3, "The new recurrence must have three events.")
check_organizer_as_single_attendee(self, recurrence, self.organizer_user)
self.assertGoogleAPINotCalled()

0 comments on commit 95e20f4

Please sign in to comment.