feat(responses): preserve editable availability history

This commit is contained in:
2026-07-20 18:22:21 +02:00
parent 6f298c36fe
commit 0f33e25c83
5 changed files with 541 additions and 18 deletions

View File

@@ -41,6 +41,30 @@ class SchedulingCandidateSlotInput(BaseModel):
return self
class SchedulingCandidateSlotUpdateRequest(BaseModel):
"""Partial update of one candidate slot.
A semantic option change invalidates existing answers for this slot in the
backing Poll. Exact repeats are safe no-ops.
"""
model_config = ConfigDict(extra="forbid")
label: str | None = Field(default=None, min_length=1, max_length=500)
description: str | None = None
start_at: datetime | None = None
end_at: datetime | None = None
timezone: str | None = Field(default=None, min_length=1, max_length=100)
location: str | None = Field(default=None, max_length=500)
metadata: dict[str, Any] | None = None
@model_validator(mode="after")
def validate_range(self) -> "SchedulingCandidateSlotUpdateRequest":
if self.start_at is not None and self.end_at is not None and self.end_at <= self.start_at:
raise ValueError("end_at must be after start_at")
return self
class SchedulingParticipantInput(BaseModel):
model_config = ConfigDict(extra="forbid")
@@ -183,6 +207,19 @@ class SchedulingAvailabilityResponseRequest(BaseModel):
return self
class SchedulingAvailabilityAnswerResponse(BaseModel):
slot_id: str
value: SchedulingAvailabilityValue
class SchedulingAvailabilityResponse(BaseModel):
request_id: str
participant_id: str
has_response: bool = False
submitted_at: datetime | None = None
answers: list[SchedulingAvailabilityAnswerResponse] = Field(default_factory=list)
class SchedulingPollOptionResultResponse(BaseModel):
option_id: str
option_key: str