1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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)
|