Add the possibility to stop/restart the synchronization with Google Calendar. Change the calendar event popover of the calendar view to display an 'Archive' button if the event was synced at least one. Add some tests for the new stop/restart features.
130 lines
5.1 KiB
Python
130 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import re
|
|
|
|
from odoo import api, fields, models
|
|
|
|
from odoo.addons.google_calendar.utils.google_calendar import GoogleCalendarService
|
|
|
|
|
|
class RecurrenceRule(models.Model):
|
|
_name = 'calendar.recurrence'
|
|
_inherit = ['calendar.recurrence', 'google.calendar.sync']
|
|
|
|
|
|
# Don't sync by default. Sync only when the recurrence is applied
|
|
need_sync = fields.Boolean(default=False)
|
|
|
|
def _apply_recurrence(self, specific_values_creation=None, no_send_edit=False):
|
|
events = self.calendar_event_ids
|
|
detached_events = super()._apply_recurrence(specific_values_creation, no_send_edit)
|
|
|
|
google_service = GoogleCalendarService(self.env['google.service'])
|
|
|
|
# If a synced event becomes a recurrence, the event needs to be deleted from
|
|
# Google since it's now the recurrence which is synced.
|
|
# Those events are kept in the database and their google_id is updated
|
|
# according to the recurrence google_id, therefore we need to keep an inactive copy
|
|
# of those events with the original google id. The next sync will then correctly
|
|
# delete those events from Google.
|
|
vals = []
|
|
for event in events.filtered('google_id'):
|
|
if event.active and event.google_id != event.recurrence_id._get_event_google_id(event):
|
|
vals += [{
|
|
'name': event.name,
|
|
'google_id': event.google_id,
|
|
'start': event.start,
|
|
'stop': event.stop,
|
|
'active': False,
|
|
'need_sync': True,
|
|
}]
|
|
event._google_delete(google_service, event.google_id)
|
|
event.google_id = False
|
|
self.env['calendar.event'].create(vals)
|
|
|
|
for recurrence in self:
|
|
values = recurrence._google_values()
|
|
if not recurrence.google_id:
|
|
recurrence._google_insert(google_service, values)
|
|
else:
|
|
recurrence._google_patch(google_service, recurrence.google_id, values)
|
|
self.calendar_event_ids.need_sync = False
|
|
return detached_events
|
|
|
|
def _get_event_google_id(self, event):
|
|
"""Return the Google id of recurring event.
|
|
Google ids of recurrence instances are formatted as: {recurrence google_id}_{UTC starting time in compacted ISO8601}
|
|
"""
|
|
if self.google_id:
|
|
if event.allday:
|
|
time_id = event.start_date.isoformat().replace('-', '')
|
|
else:
|
|
# '-' and ':' are optional in ISO8601
|
|
start_compacted_iso8601 = event.start.isoformat().replace('-', '').replace(':', '')
|
|
# Z at the end for UTC
|
|
time_id = '%sZ' % start_compacted_iso8601
|
|
return '%s_%s' % (self.google_id, time_id)
|
|
return False
|
|
|
|
def _write_events(self, values, dtstart=None):
|
|
values.pop('google_id', False)
|
|
# If only some events are updated, sync those events.
|
|
# If all events are updated, sync the recurrence instead.
|
|
values['need_sync'] = bool(dtstart)
|
|
if not dtstart:
|
|
self.need_sync = True
|
|
return super()._write_events(values, dtstart=dtstart)
|
|
|
|
def _get_google_synced_fields(self):
|
|
return {'rrule'}
|
|
|
|
@api.model
|
|
def _restart_google_sync(self):
|
|
self.env['calendar.recurrence'].search(self._get_sync_domain()).write({
|
|
'need_sync': True,
|
|
})
|
|
|
|
@api.model
|
|
def _sync_google2odoo(self, *args, **kwargs):
|
|
synced_recurrences = super()._sync_google2odoo(*args, **kwargs)
|
|
detached_events = synced_recurrences._apply_recurrence()
|
|
detached_events.unlink()
|
|
return synced_recurrences
|
|
|
|
def _get_sync_domain(self):
|
|
return [('calendar_event_ids.user_id', '=', self.env.user.id)]
|
|
|
|
@api.model
|
|
def _odoo_values(self, google_recurrence, default_reminders=()):
|
|
base_values = dict(self.env['calendar.event']._odoo_values(google_recurrence, default_reminders), need_sync=False)
|
|
base_event = self.env['calendar.event'].create(base_values)
|
|
return {
|
|
'rrule': google_recurrence.rrule,
|
|
'google_id': google_recurrence.id,
|
|
'base_event_id': base_event.id,
|
|
'calendar_event_ids': [(4, base_event.id)],
|
|
}
|
|
|
|
def _google_values(self):
|
|
event = self._get_first_event()
|
|
if not event:
|
|
return {}
|
|
values = event._google_values()
|
|
values['id'] = self.google_id
|
|
|
|
if not self._is_allday():
|
|
values['start']['timeZone'] = self.event_tz
|
|
values['end']['timeZone'] = self.event_tz
|
|
|
|
# DTSTART is not allowed by Google Calendar API.
|
|
# Event start and end times are specified in the start and end fields.
|
|
rrule = re.sub('DTSTART:[0-9]{8}T[0-9]{1,8}\\n', '', self.rrule)
|
|
values['recurrence'] = ['RRULE:%s' % rrule] if 'RRULE:' not in rrule else [rrule]
|
|
values['extendedProperties'] = {
|
|
'shared': {
|
|
'%s_odoo_id' % self.env.cr.dbname: self.id,
|
|
},
|
|
}
|
|
return values
|