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.
|
||||
"""
|
||||
_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"]
|
||||
for caldav_event in events:
|
||||
ical_event = caldav_event.icalendar_instance
|
||||
|
|
@ -556,7 +557,27 @@ class CalendarEvent(models.Model):
|
|||
)
|
||||
orphaned_events = orphaned_events._to_sync()
|
||||
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
|
||||
def _sync_event_from_ical(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
from collections.abc import Iterable
|
||||
from odoo.tests import TransactionCase
|
||||
from odoo import Command
|
||||
from unittest.mock import patch, MagicMock, PropertyMock
|
||||
from unittest.mock import patch, MagicMock, DEFAULT
|
||||
import icalendar
|
||||
from pathlib import Path
|
||||
from .common import CaldavTestCommon
|
||||
from contextlib import contextmanager
|
||||
from datetime import datetime, UTC, timedelta
|
||||
import caldav
|
||||
|
||||
WEEKDAY_MAP = {
|
||||
0: "SUN",
|
||||
|
|
@ -28,7 +29,6 @@ def _patch_caldav_with_events_from_ics(ics_paths, user, last_modified=None):
|
|||
with (
|
||||
patch("caldav.DAVClient") as MockDAVClient,
|
||||
patch("caldav.Calendar") as MockCalendar,
|
||||
patch("caldav.Event") as MockEvent,
|
||||
):
|
||||
mock_client = MockDAVClient.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.")
|
||||
|
||||
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 = []
|
||||
if ics_paths:
|
||||
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:
|
||||
ical_content = file.read()
|
||||
ical_events.append(icalendar.Calendar.from_ical(ical_content))
|
||||
mock_caldav_events = []
|
||||
for ical_event in ical_events:
|
||||
mock_event = MockEvent()
|
||||
mock_event.icalendar_instance = ical_event
|
||||
if last_modified:
|
||||
for component in ical_event.walk():
|
||||
if component.name == "VEVENT":
|
||||
component["last-modified"] = last_modified.strftime(
|
||||
"%Y%m%dT%H%M%SZ"
|
||||
)
|
||||
mock_caldav_events.append(mock_event)
|
||||
mock_calendar.events.return_value = mock_caldav_events
|
||||
if last_modified:
|
||||
for event in ical_events:
|
||||
event["last-modified"] = last_modified
|
||||
event["dtstamp"] = last_modified
|
||||
|
||||
base_events = [event for event in ical_events if not event.get("recurrence-id")]
|
||||
for base_event in base_events:
|
||||
child_events = [
|
||||
event
|
||||
for event in ical_events
|
||||
if event.get("recurrence-id")
|
||||
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()
|
||||
yield
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue