summaryrefslogtreecommitdiff
path: root/addons/microsoft_calendar/models/calendar_recurrence_rule.py
diff options
context:
space:
mode:
Diffstat (limited to 'addons/microsoft_calendar/models/calendar_recurrence_rule.py')
-rw-r--r--addons/microsoft_calendar/models/calendar_recurrence_rule.py118
1 files changed, 118 insertions, 0 deletions
diff --git a/addons/microsoft_calendar/models/calendar_recurrence_rule.py b/addons/microsoft_calendar/models/calendar_recurrence_rule.py
new file mode 100644
index 00000000..431e01b6
--- /dev/null
+++ b/addons/microsoft_calendar/models/calendar_recurrence_rule.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import re
+
+from odoo import api, fields, models
+from dateutil.relativedelta import relativedelta
+
+from odoo.addons.microsoft_calendar.utils.microsoft_calendar import MicrosoftCalendarService
+
+
+class RecurrenceRule(models.Model):
+ _name = 'calendar.recurrence'
+ _inherit = ['calendar.recurrence', 'microsoft.calendar.sync']
+
+
+ # Don't sync by default. Sync only when the recurrence is applied
+ need_sync_m = fields.Boolean(default=False)
+
+ microsoft_id = fields.Char('Microsoft Calendar Recurrence Id')
+
+ 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)
+
+ microsoft_service = MicrosoftCalendarService(self.env['microsoft.service'])
+
+ # If a synced event becomes a recurrence, the event needs to be deleted from
+ # Microsoft since it's now the recurrence which is synced.
+ # Those events are kept in the database and their microsoft_id is updated
+ # according to the recurrence microsoft_id, therefore we need to keep an inactive copy
+ # of those events with the original microsoft_id. The next sync will then correctly
+ # delete those events from Microsoft.
+ vals = []
+ for event in events.filtered('microsoft_id'):
+ if event.active and event.microsoft_id and not event.recurrence_id.microsoft_id:
+ vals += [{
+ 'name': event.name,
+ 'microsoft_id': event.microsoft_id,
+ 'start': event.start,
+ 'stop': event.stop,
+ 'active': False,
+ 'need_sync_m': True,
+ }]
+ event._microsoft_delete(microsoft_service, event.microsoft_id)
+ event.microsoft_id = False
+ self.env['calendar.event'].create(vals)
+
+ if not no_send_edit:
+ for recurrence in self:
+ values = recurrence._microsoft_values(self._get_microsoft_synced_fields())
+ if not values:
+ continue
+ values = values[0]
+ if not recurrence.microsoft_id:
+ recurrence._microsoft_insert(microsoft_service, values)
+ else:
+ recurrence._microsoft_patch(microsoft_service, recurrence.microsoft_id, values)
+
+ self.calendar_event_ids.need_sync_m = False
+ return detached_events
+
+ def _write_events(self, values, dtstart=None):
+ # If only some events are updated, sync those events.
+ # If all events are updated, sync the recurrence instead.
+ values['need_sync_m'] = bool(dtstart)
+ if not dtstart:
+ self.need_sync_m = True
+ return super()._write_events(values, dtstart=dtstart)
+
+ def _get_microsoft_synced_fields(self):
+ return {'rrule'} | self.env['calendar.event']._get_microsoft_synced_fields()
+
+ def _get_microsoft_sync_domain(self):
+ return [('calendar_event_ids.user_id', '=', self.env.user.id)]
+
+ def _cancel_microsoft(self):
+ self.calendar_event_ids._cancel_microsoft()
+ self.microsoft_id = False # Set to False to avoid error with unlink from microsoft and avoid to synchronize.
+ self.unlink()
+
+ @api.model
+ def _microsoft_to_odoo_values(self, microsoft_recurrence, default_reminders=(), default_values={}):
+ recurrence = microsoft_recurrence.get_recurrence()
+
+ return {
+ **recurrence,
+ 'microsoft_id': microsoft_recurrence.id,
+ }
+
+ def _microsoft_values(self, fields_to_sync):
+ events = self.calendar_event_ids.sorted('start')
+ events_outliers = self.calendar_event_ids.filtered(lambda e: not e.follow_recurrence)
+ normal_event = (events - events_outliers)[:1] or events[:1]
+ if not normal_event:
+ return {}
+ values = [normal_event._microsoft_values(fields_to_sync, initial_values={'type': 'seriesMaster'})]
+
+ if self.microsoft_id:
+ values[0]['id'] = self.microsoft_id
+ for event in events_outliers:
+ event_value = event._microsoft_values(fields_to_sync)
+ values += [event_value]
+
+ return values
+
+ def _ensure_attendees_have_email(self):
+ self.calendar_event_ids.filtered(lambda e: e.active)._ensure_attendees_have_email()
+
+ def _notify_attendees(self):
+ recurrences = self.filtered(
+ lambda recurrence: recurrence.base_event_id.alarm_ids and (
+ not recurrence.until or recurrence.until >= fields.Date.today() - relativedelta(days=1)
+ ) and max(recurrence.calendar_event_ids.mapped('stop')) >= fields.Datetime.now()
+ )
+ partners = recurrences.base_event_id.partner_ids
+ if partners:
+ self.env['calendar.alarm_manager']._notify_next_alarm(partners.ids)