caldav_sync: all seems good. further testing to come before merging into 17.0
This commit is contained in:
parent
90d05d75a2
commit
992778e353
2 changed files with 50 additions and 16 deletions
|
|
@ -539,7 +539,8 @@ class CalendarEvent(models.Model):
|
||||||
:param user: The res.user record for whom to synchronize events.
|
:param user: The res.user record for whom to synchronize events.
|
||||||
"""
|
"""
|
||||||
_logger.info(f"Polling CalDAV server for user {user.name}")
|
_logger.info(f"Polling CalDAV server for user {user.name}")
|
||||||
events = user._get_caldav_events()
|
calendar = user._get_caldav_client().calendar(url=user.caldav_calendar_url)
|
||||||
|
events = calendar.events()
|
||||||
synced_events = self.env["calendar.event"]
|
synced_events = self.env["calendar.event"]
|
||||||
for caldav_event in events:
|
for caldav_event in events:
|
||||||
ical_event = caldav_event.icalendar_instance
|
ical_event = caldav_event.icalendar_instance
|
||||||
|
|
@ -556,7 +557,27 @@ class CalendarEvent(models.Model):
|
||||||
)
|
)
|
||||||
orphaned_events = orphaned_events._to_sync()
|
orphaned_events = orphaned_events._to_sync()
|
||||||
if orphaned_events:
|
if orphaned_events:
|
||||||
orphaned_events.with_context(caldav_no_sync=True).with_user(user).unlink()
|
base_orphans = orphaned_events.filtered(
|
||||||
|
lambda ev: ev.recurrence_id and ev.is_base_event
|
||||||
|
)
|
||||||
|
for base_orphan in base_orphans:
|
||||||
|
try:
|
||||||
|
if calendar.event_by_uid(base_orphan.caldav_uid):
|
||||||
|
# There are some events remaining in this recurrence series,
|
||||||
|
# so we have synchronized them individually.
|
||||||
|
pass
|
||||||
|
except caldav.error.NotFoundError:
|
||||||
|
# There are no more events with this UID, so we need to clear
|
||||||
|
# out the whole recurrence chain from the Odoo side.
|
||||||
|
ctx = {"caldav_no_sync": True}
|
||||||
|
recurrence = base_orphan.recurrence_id
|
||||||
|
recurrence.calendar_event_ids.with_context(**ctx).with_user(
|
||||||
|
user
|
||||||
|
).unlink()
|
||||||
|
recurrence.with_context(**ctx).with_user(user).unlink()
|
||||||
|
(orphaned_events - base_orphans).with_context(
|
||||||
|
caldav_no_sync=True
|
||||||
|
).with_user(user).unlink()
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _sync_event_from_ical(
|
def _sync_event_from_ical(
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from odoo.tests import TransactionCase
|
from odoo.tests import TransactionCase
|
||||||
from odoo import Command
|
from odoo import Command
|
||||||
from unittest.mock import patch, MagicMock, PropertyMock
|
from unittest.mock import patch, MagicMock, DEFAULT
|
||||||
import icalendar
|
import icalendar
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from .common import CaldavTestCommon
|
from .common import CaldavTestCommon
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from datetime import datetime, UTC, timedelta
|
from datetime import datetime, UTC, timedelta
|
||||||
|
import caldav
|
||||||
|
|
||||||
WEEKDAY_MAP = {
|
WEEKDAY_MAP = {
|
||||||
0: "SUN",
|
0: "SUN",
|
||||||
|
|
@ -28,7 +29,6 @@ def _patch_caldav_with_events_from_ics(ics_paths, user, last_modified=None):
|
||||||
with (
|
with (
|
||||||
patch("caldav.DAVClient") as MockDAVClient,
|
patch("caldav.DAVClient") as MockDAVClient,
|
||||||
patch("caldav.Calendar") as MockCalendar,
|
patch("caldav.Calendar") as MockCalendar,
|
||||||
patch("caldav.Event") as MockEvent,
|
|
||||||
):
|
):
|
||||||
mock_client = MockDAVClient.return_value
|
mock_client = MockDAVClient.return_value
|
||||||
mock_calendar = MockCalendar.return_value
|
mock_calendar = MockCalendar.return_value
|
||||||
|
|
@ -43,6 +43,12 @@ def _patch_caldav_with_events_from_ics(ics_paths, user, last_modified=None):
|
||||||
raise Exception("Calendar does not exist.")
|
raise Exception("Calendar does not exist.")
|
||||||
|
|
||||||
mock_calendar.side_effect = calendar_side_effect
|
mock_calendar.side_effect = calendar_side_effect
|
||||||
|
|
||||||
|
def event_by_uid_side_effect(self, uid):
|
||||||
|
for event in self.events:
|
||||||
|
if str(event.icalendar_component.get("uid")) == uid:
|
||||||
|
return event
|
||||||
|
|
||||||
ical_events = []
|
ical_events = []
|
||||||
if ics_paths:
|
if ics_paths:
|
||||||
if not isinstance(ics_paths, Iterable):
|
if not isinstance(ics_paths, Iterable):
|
||||||
|
|
@ -51,18 +57,25 @@ def _patch_caldav_with_events_from_ics(ics_paths, user, last_modified=None):
|
||||||
with ics_path.open("rb") as file:
|
with ics_path.open("rb") as file:
|
||||||
ical_content = file.read()
|
ical_content = file.read()
|
||||||
ical_events.append(icalendar.Calendar.from_ical(ical_content))
|
ical_events.append(icalendar.Calendar.from_ical(ical_content))
|
||||||
mock_caldav_events = []
|
if last_modified:
|
||||||
for ical_event in ical_events:
|
for event in ical_events:
|
||||||
mock_event = MockEvent()
|
event["last-modified"] = last_modified
|
||||||
mock_event.icalendar_instance = ical_event
|
event["dtstamp"] = last_modified
|
||||||
if last_modified:
|
|
||||||
for component in ical_event.walk():
|
base_events = [event for event in ical_events if not event.get("recurrence-id")]
|
||||||
if component.name == "VEVENT":
|
for base_event in base_events:
|
||||||
component["last-modified"] = last_modified.strftime(
|
child_events = [
|
||||||
"%Y%m%dT%H%M%SZ"
|
event
|
||||||
)
|
for event in ical_events
|
||||||
mock_caldav_events.append(mock_event)
|
if event.get("recurrence-id")
|
||||||
mock_calendar.events.return_value = mock_caldav_events
|
and event.get("uid") == base_event.get("uid")
|
||||||
|
]
|
||||||
|
for child_event in child_events:
|
||||||
|
base_event.add_component(child_event)
|
||||||
|
mock_calendar.add_event(base_event)
|
||||||
|
caldav_events = [caldav.Event(data=event) for event in base_events]
|
||||||
|
mock_calendar.events.return_value = caldav_events
|
||||||
|
mock_calendar.event_by_uid.side_effect = event_by_uid_side_effect
|
||||||
user._compute_is_caldav_enabled()
|
user._compute_is_caldav_enabled()
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue