Refactor calendar event update flow
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user