Refactor calendar event update flow

This commit is contained in:
2026-07-21 12:33:43 +02:00
parent baf624c7a6
commit 41b9426670

View File

@@ -2918,7 +2918,13 @@ def create_event(session: Session, *, tenant_id: str, user_id: str | None, paylo
return event
def update_event(session: Session, *, tenant_id: str, user_id: str | None, event_id: str, payload: CalendarEventUpdateRequest) -> CalendarEvent:
def _event_update_calendar_ids(
session: Session,
*,
tenant_id: str,
event_id: str,
payload: CalendarEventUpdateRequest,
) -> tuple[str, str]:
event_locator = (
session.query(CalendarEvent.calendar_id)
.filter(
@@ -2934,6 +2940,16 @@ def update_event(session: Session, *, tenant_id: str, user_id: str | None, event
target_calendar_id = payload.calendar_id or original_calendar_id
if payload.calendar_id is not None:
get_calendar(session, tenant_id=tenant_id, calendar_id=target_calendar_id)
return original_calendar_id, target_calendar_id
def _lock_event_update_sources(
session: Session,
*,
tenant_id: str,
original_calendar_id: str,
target_calendar_id: str,
) -> tuple[CalendarSyncSource | None, CalendarSyncSource | None]:
original_source = active_sync_source_for_calendar(
session,
tenant_id=tenant_id,
@@ -2953,27 +2969,52 @@ def update_event(session: Session, *, tenant_id: str, user_id: str | None, event
original_source = locked_sources[original_source.id]
if target_source is not None:
target_source = locked_sources[target_source.id]
event = get_event(session, tenant_id=tenant_id, event_id=event_id)
previous = calendar_event_change_payload(event, prefix="previous_")
original_caldav = event.source_kind == "caldav" and bool(event.source_href)
return original_source, target_source
def _assert_event_update_sync_fields(
payload: CalendarEventUpdateRequest,
*,
original_source: CalendarSyncSource | None,
target_source: CalendarSyncSource | None,
) -> None:
supplied_sync_fields = {"source_kind", "source_href", "etag"} & payload.model_fields_set
if (original_source is not None or target_source is not None) and supplied_sync_fields:
raise CalendarError(
"source_kind, source_href, and etag are sync-owned fields on synchronized calendars"
)
if payload.calendar_id is not None:
assert_sync_mutation_allowed(target_source)
if payload.calendar_id != event.calendar_id and original_source and original_caldav:
assert_sync_mutation_allowed(original_source)
from govoplan_calendar.backend.outbox import enqueue_caldav_delete
enqueue_caldav_delete(session, source=original_source, event_model=event)
event.source_kind = "local"
event.source_href = None
event.etag = None
event.calendar_id = payload.calendar_id
else:
def _move_event_for_update(
session: Session,
*,
event: CalendarEvent,
payload: CalendarEventUpdateRequest,
original_source: CalendarSyncSource | None,
target_source: CalendarSyncSource | None,
) -> None:
if payload.calendar_id is None:
assert_sync_mutation_allowed(original_source)
return
assert_sync_mutation_allowed(target_source)
original_caldav = event.source_kind == "caldav" and bool(event.source_href)
if payload.calendar_id != event.calendar_id and original_source and original_caldav:
assert_sync_mutation_allowed(original_source)
from govoplan_calendar.backend.outbox import enqueue_caldav_delete
enqueue_caldav_delete(session, source=original_source, event_model=event)
event.source_kind = "local"
event.source_href = None
event.etag = None
event.calendar_id = payload.calendar_id
def _apply_event_update_values(
event: CalendarEvent,
*,
user_id: str | None,
payload: CalendarEventUpdateRequest,
) -> None:
scalar_fields = (
"sequence",
"summary",
@@ -3002,7 +3043,13 @@ def update_event(session: Session, *, tenant_id: str, user_id: str | None, event
for attr in scalar_fields:
value = getattr(payload, attr)
if value is not None:
setattr(event, attr, value.upper() if attr in {"status", "transparency", "classification"} and isinstance(value, str) else value)
value = (
value.upper()
if attr in {"status", "transparency", "classification"}
and isinstance(value, str)
else value
)
setattr(event, attr, value)
if payload.start_at is not None:
event.start_at = normalize_datetime(payload.start_at)
if "end_at" in payload.model_fields_set:
@@ -3012,6 +3059,36 @@ def update_event(session: Session, *, tenant_id: str, user_id: str | None, event
event.updated_by_user_id = user_id
if payload.sequence is None:
event.sequence += 1
def update_event(session: Session, *, tenant_id: str, user_id: str | None, event_id: str, payload: CalendarEventUpdateRequest) -> CalendarEvent:
original_calendar_id, target_calendar_id = _event_update_calendar_ids(
session,
tenant_id=tenant_id,
event_id=event_id,
payload=payload,
)
original_source, target_source = _lock_event_update_sources(
session,
tenant_id=tenant_id,
original_calendar_id=original_calendar_id,
target_calendar_id=target_calendar_id,
)
event = get_event(session, tenant_id=tenant_id, event_id=event_id)
previous = calendar_event_change_payload(event, prefix="previous_")
_assert_event_update_sync_fields(
payload,
original_source=original_source,
target_source=target_source,
)
_move_event_for_update(
session,
event=event,
payload=payload,
original_source=original_source,
target_source=target_source,
)
_apply_event_update_values(event, user_id=user_id, payload=payload)
validate_event_time(event)
event.raw_ics = None
session.flush()