[FIX] google_calendar: sync setting needs action status to accepted event

When an event is created by user A and user B is invited, user A automatically
accepts the event. If both users are using google sync and user B accepts the
invitation from the google interface, the status of the events are set to
needAction for user A. This occurs because the odoo values will always write
the time related fields, even when those did not change. This causes the
status to be changed to needAction because we assume the time of the event has
changed and user A needs to verify it. This commit fixes this by only setting
time values when they were really changed and by switching the logic that
triggers the reset of the status. As most times a default alarm is generated
by google, we should not treat it as condition for updating the time and,
therefore, potentially updating the status of the attendee.

task-3464054

closes odoo/odoo#137471

Signed-off-by: Arnaud Joset (arj) <arj@odoo.com>
Signed-off-by: Leonardo Pavan Rocha <lpr@odoo.com>
This commit is contained in:
Leonardo Pavan Rocha
2023-10-09 09:33:48 +00:00
parent 7922b3502d
commit 8b7f1c892b
4 changed files with 57 additions and 6 deletions
+3 -1
View File
@@ -617,9 +617,11 @@ class Meeting(models.Model):
self.videocall_channel_id.add_members(new_partner_ids)
time_fields = self.env['calendar.event']._get_time_fields()
if any([values.get(key) for key in time_fields]) or 'alarm_ids' in values:
if any([values.get(key) for key in time_fields]):
update_alarms = True
update_time = True
if 'alarm_ids' in values:
update_alarms = True
if (not recurrence_update_setting or recurrence_update_setting == 'self_only' and len(self) == 1) and 'follow_recurrence' not in values:
if any({field: values.get(field) for field in time_fields if field in values}):
+6 -3
View File
@@ -171,8 +171,10 @@ class Meeting(models.Model):
if stop < start:
stop = parse(google_event.end.get('date'))
values['allday'] = True
values['start'] = start
values['stop'] = stop
if related_event['start'] != start:
values['start'] = start
if related_event['stop'] != stop:
values['stop'] = stop
return values
@api.model
@@ -189,7 +191,8 @@ class Meeting(models.Model):
emails = [a.get('email') for a in google_attendees]
existing_attendees = self.env['calendar.attendee']
if google_event.exists(self.env):
existing_attendees = self.browse(google_event.odoo_id(self.env)).attendee_ids
event = google_event.get_odoo_event(self.env)
existing_attendees = event.attendee_ids
attendees_by_emails = {tools.email_normalize(a.email): a for a in existing_attendees}
partners = self._get_sync_partner(emails)
for attendee in zip(emails, partners, google_attendees):
@@ -1146,8 +1146,8 @@ class TestSyncGoogle2Odoo(TestSyncGoogle):
}])
self.sync(gevent)
# User attendee removed but gevent owner might be added after synch.
mails = sorted(set(event.attendee_ids.mapped('email')))
self.assertEqual(mails, ['odoobot@example.com'])
mails = event.attendee_ids.mapped('email')
self.assertFalse(mails)
self.assertGoogleAPINotCalled()
@@ -1741,3 +1741,43 @@ class TestSyncGoogle2Odoo(TestSyncGoogle):
self.assertTrue(guest_user.google_synchronization_stopped)
guest_user.sudo().restart_google_synchronization()
self.assertFalse(guest_user.google_synchronization_stopped)
@patch_api
def test_attendee_status_is_not_updated_when_syncing_and_time_data_is_not_changed(self):
recurrence_id = "aaaaaaaa"
organizer = new_test_user(self.env, login="organizer")
other_user = new_test_user(self.env, login='calendar_user')
base_event = self.env['calendar.event'].with_user(organizer).create({
'name': 'coucou',
'start': datetime(2020, 1, 6, 9, 0),
'stop': datetime(2020, 1, 6, 10, 0),
'need_sync': False,
'partner_ids': [Command.set([organizer.partner_id.id, other_user.partner_id.id])]
})
recurrence = self.env['calendar.recurrence'].with_user(organizer).create({
'google_id': recurrence_id,
'rrule': 'FREQ=DAILY;INTERVAL=1;COUNT=3',
'need_sync': False,
'base_event_id': base_event.id,
})
recurrence._apply_recurrence()
self.assertTrue(all(len(event.attendee_ids) == 2 for event in recurrence.calendar_event_ids), 'should have 2 attendees in all recurring events')
organizer_state = recurrence.calendar_event_ids.sorted('start')[0].attendee_ids.filtered(lambda attendee: attendee.partner_id.email == organizer.partner_id.email).state
self.assertEqual(organizer_state, 'accepted', 'organizer should have accepted')
values = [{
'summary': 'coucou',
'id': recurrence_id,
'recurrence': ['RRULE:FREQ=DAILY;INTERVAL=1;COUNT=3'],
'start': {'dateTime': '2020-01-06T10:00:00+01:00'},
'end': {'dateTime': '2020-01-06T11:00:00+01:00'},
'reminders': {'useDefault': True},
'organizer': {'email': organizer.partner_id.email},
'attendees': [{'email': organizer.partner_id.email, 'responseStatus': 'accepted'}, {'email': other_user.partner_id.email, 'responseStatus': 'accepted'}],
'updated': self.now,
}]
self.env['calendar.recurrence'].with_user(other_user)._sync_google2odoo(GoogleEvent(values))
events = recurrence.calendar_event_ids.sorted('start')
self.assertEqual(len(events), 3, "it should have created a recurrence with 3 events")
self.assertEqual(events[0].attendee_ids[0].state, 'accepted', 'after google sync, organizer should have accepted status still')
self.assertGoogleAPINotCalled()
@@ -230,3 +230,9 @@ class GoogleEvent(abc.Set):
def is_available(self):
return self.transparency == 'transparent'
def get_odoo_event(self, env):
if self._get_model(env)._name == 'calendar.event':
return env['calendar.event'].browse(self.odoo_id(self.env))
else:
return env['calendar.recurrence'].browse(self.odoo_id(self.env)).base_event_id