[FIX] microsoft_calendar: rollback sync view range approach

Before this commit, errors were introduced when optimizing the synchronization by limiting it to the calendar's view range. For users different than the first to synchronize its calendar, when trying to create events in Odoo before or after the synchronized view range (e.g. 1 month), these events were being auto-archived in Odoo right after their creation in Outlook. This happens because the first range to be sent to Microsoft Outlook is currently defining how much time in the past and in the future the events will be synchronized.

After this commit, the previous approach of defining a range of two years for the delta synchronization (events that were last updated) in the future is back temporarily, now with one year in the past. This behavior must be improved considering the calendar view range and must be flexible with the first synchronized view range.

Issue from: 3525764

closes odoo/odoo#147366

X-original-commit: 2a503c1b08bd31c9ac0098e774eea8dd5b5c2c1e
Signed-off-by: Arnaud Joset (arj) <arj@odoo.com>
Signed-off-by: Gabriel de Paula Felix (gdpf) <gdpf@odoo.com>
This commit is contained in:
Gabriel de Paula Felix (gdpf)
2023-12-28 13:09:27 +00:00
parent e70a2eb0f6
commit 4bd40ec507
4 changed files with 12 additions and 55 deletions
+1 -13
View File
@@ -5,8 +5,6 @@ from odoo import http
from odoo.http import request
from odoo.addons.calendar.controllers.main import CalendarController
from dateutil.parser import parse
class MicrosoftCalendarController(CalendarController):
@@ -42,19 +40,9 @@ class MicrosoftCalendarController(CalendarController):
"status": "need_auth",
"url": url
}
# Get synchronization time window form calendar view if received through parameters.
sync_context = {}
range_start_date = kw.get('rangeStart')
range_end_date = kw.get('rangeEnd')
if range_start_date and range_end_date:
sync_context.update({
'range_start_date': parse(range_start_date),
'range_end_date': parse(range_end_date),
})
# If App authorized, and user access accepted, We launch the synchronization
sync_context.update({'dont_notify': True})
need_refresh = request.env.user.sudo().with_context(sync_context)._sync_microsoft_calendar()
need_refresh = request.env.user.sudo().with_context(dont_notify=True)._sync_microsoft_calendar()
# If synchronization has been stopped or paused
sync_status = request.env.user._get_microsoft_sync_status()
@@ -2,7 +2,6 @@
import { AttendeeCalendarModel } from "@calendar/views/attendee_calendar/attendee_calendar_model";
import { patch } from "@web/core/utils/patch";
import { serializeDateTime } from "@web/core/l10n/dates";
patch(AttendeeCalendarModel, {
services: [...AttendeeCalendarModel.services, "rpc"],
@@ -41,18 +40,12 @@ patch(AttendeeCalendarModel.prototype, {
async syncMicrosoftCalendar(silent = false) {
this.microsoftPendingSync = true;
const request = {
model: this.resModel,
fromurl: window.location.href,
}
// Check if this.data.range is not null before adding rangeStart and rangeEnd.
if (this.data && this.data.range) {
request.rangeStart = serializeDateTime(this.data.range.start);
request.rangeEnd = serializeDateTime(this.data.range.end);
}
const result = await this.rpc(
"/microsoft_calendar/sync_data",
request,
{
model: this.resModel,
fromurl: window.location.href
},
{
silent,
},
@@ -38,8 +38,8 @@ class TestMicrosoftService(TransactionCase):
self.call_without_sync_token = call(
"/v1.0/me/calendarView/delta",
{
'startDateTime': fields.Datetime.subtract(fields.Datetime.now(), days=365).strftime("%Y-%m-%dT00:00:00Z"),
'endDateTime': fields.Datetime.add(fields.Datetime.now(), days=365).strftime("%Y-%m-%dT00:00:00Z"),
'startDateTime': fields.Datetime.subtract(fields.Datetime.now(), years=1).strftime("%Y-%m-%dT00:00:00Z"),
'endDateTime': fields.Datetime.add(fields.Datetime.now(), years=2).strftime("%Y-%m-%dT00:00:00Z"),
},
{**self.header, 'Prefer': self.header_prefer},
method="GET", timeout=DEFAULT_TIMEOUT,
@@ -226,8 +226,8 @@ class TestMicrosoftService(TransactionCase):
mock_do_request.assert_called_with(
"/v1.0/me/events/123/instances",
{
'startDateTime': fields.Datetime.subtract(fields.Datetime.now(), days=365).strftime("%Y-%m-%dT00:00:00Z"),
'endDateTime': fields.Datetime.add(fields.Datetime.now(), days=365).strftime("%Y-%m-%dT00:00:00Z"),
'startDateTime': fields.Datetime.subtract(fields.Datetime.now(), years=1).strftime("%Y-%m-%dT00:00:00Z"),
'endDateTime': fields.Datetime.add(fields.Datetime.now(), years=2).strftime("%Y-%m-%dT00:00:00Z"),
},
{**self.header, 'Prefer': self.header_prefer},
method='GET', timeout=DEFAULT_TIMEOUT,
@@ -64,20 +64,10 @@ class MicrosoftCalendarService():
'Prefer': 'outlook.body-content-type="html", odata.maxpagesize=50'
}
if not params:
# Get context keys limiting query range for reducing requests and then increase performance.
start_date = self.microsoft_service._context.get('range_start_date')
end_date = self.microsoft_service._context.get('range_end_date')
if start_date and end_date:
start_date = start_date.strftime("%Y-%m-%dT00:00:00Z")
end_date = fields.Datetime.add(end_date, days=1).strftime("%Y-%m-%dT00:00:00Z")
else:
ICP = self.microsoft_service.env['ir.config_parameter'].sudo()
day_range = int(ICP.get_param('microsoft_calendar.sync.range_days', default=365))
start_date = fields.Datetime.subtract(fields.Datetime.now(), days=day_range).strftime("%Y-%m-%dT00:00:00Z")
end_date = fields.Datetime.add(fields.Datetime.now(), days=day_range).strftime("%Y-%m-%dT00:00:00Z")
# By default, fetch events from at most one year in the past and two years in the future.
params = {
'startDateTime': start_date,
'endDateTime': end_date,
'startDateTime': fields.Datetime.subtract(fields.Datetime.now(), years=1).strftime("%Y-%m-%dT00:00:00Z"),
'endDateTime': fields.Datetime.add(fields.Datetime.now(), years=2).strftime("%Y-%m-%dT00:00:00Z"),
}
# get the first page of events
@@ -125,20 +115,6 @@ class MicrosoftCalendarService():
return self._get_events_delta(token=token, timeout=timeout)
raise e
# update sync min and max date range after retrieving occurrences, they must be entirely created once
# otherwise we would have to retrieve everytime all occurrences from all recurrences in _get_occurrence_details
min_start_dt = self.microsoft_service._context.get('range_start_date')
max_stop_dt = self.microsoft_service._context.get('range_end_date')
for event in events:
if event.get('type') == 'occurrence' and event.get('start') and event.get('end'):
# get time values and update min start and max stop from sync context range
time_values = self.microsoft_service.env['calendar.event']._microsoft_to_odoo_recurrence_values(MicrosoftEvent([event]))
if not min_start_dt or time_values['start'] < min_start_dt:
min_start_dt = time_values['start']
if not max_stop_dt or time_values['stop'] > max_stop_dt:
max_stop_dt = time_values['stop']
self.microsoft_service = self.microsoft_service.with_context(range_start_date=min_start_dt, range_end_date=max_stop_dt)
# event occurrences (from a recurrence) are retrieved separately to get all their info,
# # and mainly the iCalUId attribute which is not provided by the 'get_delta' api end point
events = [e for e in events if e.get('type') != 'occurrence']