[IMP] google_calendar: add single event synchronization
Purpose ======= Add the possibility to only synchronize one specific event of a user calendar instead of syncing the whole calendar. Specification ============= In certain cases, we do not want to synchronize the whole user calendar with all the events and recurrences but only a specific event. For example, in appointment, to retrieve the generated google meet url of a specified event. To perform the single event synchronization a synchronization token is needed, meaning we cannot do a single event synchronization prior to a full calendar synchronization as it is the full sync which generates the temporary sync token. To prevent the need of doing a full sync before a single event sync, the permanent synchronization token is been used instead of the temporary one when performing a single event synchronization. Task-3285601 Part-of: odoo/odoo#133921
This commit is contained in:
@@ -53,24 +53,10 @@ class User(models.Model):
|
||||
|
||||
def _sync_google_calendar(self, calendar_service: GoogleCalendarService):
|
||||
self.ensure_one()
|
||||
if self._get_google_sync_status() != "sync_active":
|
||||
results = self._sync_request(calendar_service)
|
||||
if not results or not results.get('events'):
|
||||
return False
|
||||
# don't attempt to sync when another sync is already in progress, as we wouldn't be
|
||||
# able to commit the transaction anyway (row is locked)
|
||||
self.env.cr.execute("""SELECT id FROM res_users WHERE id = %s FOR NO KEY UPDATE SKIP LOCKED""", [self.id])
|
||||
if not self.env.cr.rowcount:
|
||||
_logger.info("skipping calendar sync, locked user %s", self.login)
|
||||
return False
|
||||
|
||||
full_sync = not bool(self.google_calendar_sync_token)
|
||||
with google_calendar_token(self) as token:
|
||||
try:
|
||||
events, next_sync_token, default_reminders = calendar_service.get_events(self.google_calendar_account_id.calendar_sync_token, token=token)
|
||||
except InvalidSyncToken:
|
||||
events, next_sync_token, default_reminders = calendar_service.get_events(token=token)
|
||||
full_sync = True
|
||||
self.google_calendar_account_id.calendar_sync_token = next_sync_token
|
||||
|
||||
events, default_reminders, full_sync = results.values()
|
||||
# Google -> Odoo
|
||||
send_updates = not full_sync
|
||||
events.clear_type_ambiguity(self.env)
|
||||
@@ -89,6 +75,50 @@ class User(models.Model):
|
||||
|
||||
return bool(events | synced_events) or bool(recurrences | synced_recurrences)
|
||||
|
||||
def _sync_single_event(self, calendar_service: GoogleCalendarService, odoo_event, event_id):
|
||||
self.ensure_one()
|
||||
results = self._sync_request(calendar_service, event_id)
|
||||
if not results or not results.get('events'):
|
||||
return False
|
||||
event, default_reminders, full_sync = results.values()
|
||||
# Google -> Odoo
|
||||
send_updates = not full_sync
|
||||
event.clear_type_ambiguity(self.env)
|
||||
synced_events = self.env['calendar.event']._sync_google2odoo(event, default_reminders=default_reminders)
|
||||
# Odoo -> Google
|
||||
odoo_event.with_context(send_updates=send_updates)._sync_odoo2google(calendar_service)
|
||||
return bool(odoo_event | synced_events)
|
||||
|
||||
def _sync_request(self, calendar_service, event_id=None):
|
||||
if self._get_google_sync_status() != "sync_active":
|
||||
return False
|
||||
# don't attempt to sync when another sync is already in progress, as we wouldn't be
|
||||
# able to commit the transaction anyway (row is locked)
|
||||
self.env.cr.execute("""SELECT id FROM res_users WHERE id = %s FOR NO KEY UPDATE SKIP LOCKED""", [self.id])
|
||||
if not self.env.cr.rowcount:
|
||||
_logger.info("skipping calendar sync, locked user %s", self.login)
|
||||
return False
|
||||
|
||||
full_sync = not bool(self.google_calendar_sync_token)
|
||||
with google_calendar_token(self) as token:
|
||||
try:
|
||||
if not event_id:
|
||||
events, next_sync_token, default_reminders = calendar_service.get_events(self.google_calendar_account_id.calendar_sync_token, token=token)
|
||||
else:
|
||||
# We force the sync_token parameter to avoid doing a full sync.
|
||||
# Other events are fetched when the calendar view is displayed.
|
||||
events, next_sync_token, default_reminders = calendar_service.get_events(sync_token=token, token=token, event_id=event_id)
|
||||
except InvalidSyncToken:
|
||||
events, next_sync_token, default_reminders = calendar_service.get_events(token=token)
|
||||
full_sync = True
|
||||
if next_sync_token:
|
||||
self.google_calendar_account_id.calendar_sync_token = next_sync_token
|
||||
return {
|
||||
'events': events,
|
||||
'default_reminders': default_reminders,
|
||||
'full_sync': full_sync,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def _sync_all_google_calendar(self):
|
||||
""" Cron job """
|
||||
|
||||
@@ -29,8 +29,10 @@ class GoogleCalendarService():
|
||||
self.google_service = google_service
|
||||
|
||||
@requires_auth_token
|
||||
def get_events(self, sync_token=None, token=None, timeout=TIMEOUT):
|
||||
def get_events(self, sync_token=None, token=None, event_id=None, timeout=TIMEOUT):
|
||||
url = "/calendar/v3/calendars/primary/events"
|
||||
if event_id:
|
||||
url += f"/{event_id}"
|
||||
headers = {'Content-type': 'application/json'}
|
||||
params = {'access_token': token}
|
||||
if sync_token:
|
||||
@@ -51,6 +53,11 @@ class GoogleCalendarService():
|
||||
raise InvalidSyncToken("Invalid sync token. Full sync required")
|
||||
raise e
|
||||
|
||||
if event_id:
|
||||
next_sync_token = None
|
||||
default_reminders = ()
|
||||
return GoogleEvent([data]), next_sync_token, default_reminders
|
||||
|
||||
events = data.get('items', [])
|
||||
next_page_token = data.get('nextPageToken')
|
||||
while next_page_token:
|
||||
|
||||
Reference in New Issue
Block a user