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
|
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 = (
|
event_locator = (
|
||||||
session.query(CalendarEvent.calendar_id)
|
session.query(CalendarEvent.calendar_id)
|
||||||
.filter(
|
.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
|
target_calendar_id = payload.calendar_id or original_calendar_id
|
||||||
if payload.calendar_id is not None:
|
if payload.calendar_id is not None:
|
||||||
get_calendar(session, tenant_id=tenant_id, calendar_id=target_calendar_id)
|
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(
|
original_source = active_sync_source_for_calendar(
|
||||||
session,
|
session,
|
||||||
tenant_id=tenant_id,
|
tenant_id=tenant_id,
|
||||||
@@ -2953,16 +2969,35 @@ def update_event(session: Session, *, tenant_id: str, user_id: str | None, event
|
|||||||
original_source = locked_sources[original_source.id]
|
original_source = locked_sources[original_source.id]
|
||||||
if target_source is not None:
|
if target_source is not None:
|
||||||
target_source = locked_sources[target_source.id]
|
target_source = locked_sources[target_source.id]
|
||||||
event = get_event(session, tenant_id=tenant_id, event_id=event_id)
|
return original_source, target_source
|
||||||
previous = calendar_event_change_payload(event, prefix="previous_")
|
|
||||||
original_caldav = event.source_kind == "caldav" and bool(event.source_href)
|
|
||||||
|
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
|
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:
|
if (original_source is not None or target_source is not None) and supplied_sync_fields:
|
||||||
raise CalendarError(
|
raise CalendarError(
|
||||||
"source_kind, source_href, and etag are sync-owned fields on synchronized calendars"
|
"source_kind, source_href, and etag are sync-owned fields on synchronized calendars"
|
||||||
)
|
)
|
||||||
if payload.calendar_id is not None:
|
|
||||||
|
|
||||||
|
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)
|
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:
|
if payload.calendar_id != event.calendar_id and original_source and original_caldav:
|
||||||
assert_sync_mutation_allowed(original_source)
|
assert_sync_mutation_allowed(original_source)
|
||||||
from govoplan_calendar.backend.outbox import enqueue_caldav_delete
|
from govoplan_calendar.backend.outbox import enqueue_caldav_delete
|
||||||
@@ -2972,8 +3007,14 @@ def update_event(session: Session, *, tenant_id: str, user_id: str | None, event
|
|||||||
event.source_href = None
|
event.source_href = None
|
||||||
event.etag = None
|
event.etag = None
|
||||||
event.calendar_id = payload.calendar_id
|
event.calendar_id = payload.calendar_id
|
||||||
else:
|
|
||||||
assert_sync_mutation_allowed(original_source)
|
|
||||||
|
def _apply_event_update_values(
|
||||||
|
event: CalendarEvent,
|
||||||
|
*,
|
||||||
|
user_id: str | None,
|
||||||
|
payload: CalendarEventUpdateRequest,
|
||||||
|
) -> None:
|
||||||
scalar_fields = (
|
scalar_fields = (
|
||||||
"sequence",
|
"sequence",
|
||||||
"summary",
|
"summary",
|
||||||
@@ -3002,7 +3043,13 @@ def update_event(session: Session, *, tenant_id: str, user_id: str | None, event
|
|||||||
for attr in scalar_fields:
|
for attr in scalar_fields:
|
||||||
value = getattr(payload, attr)
|
value = getattr(payload, attr)
|
||||||
if value is not None:
|
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:
|
if payload.start_at is not None:
|
||||||
event.start_at = normalize_datetime(payload.start_at)
|
event.start_at = normalize_datetime(payload.start_at)
|
||||||
if "end_at" in payload.model_fields_set:
|
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
|
event.updated_by_user_id = user_id
|
||||||
if payload.sequence is None:
|
if payload.sequence is None:
|
||||||
event.sequence += 1
|
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)
|
validate_event_time(event)
|
||||||
event.raw_ics = None
|
event.raw_ics = None
|
||||||
session.flush()
|
session.flush()
|
||||||
|
|||||||
Reference in New Issue
Block a user