feat(api): keyless unavailable-ranges feed for the guest calendar
GET /api/v1/public/rooms/{id}/unavailable?start=&end= and its RPC twin
chatelet_room_unavailable return the nights a guest cannot book over a
window (default today → +365 d, capped at 400 d): occupying bookings —
live holds included, so the feed always agrees with POST /availability —
and manual blocks, clipped, sorted and coalesced into anonymous half-open
spans. Adjacent spans merge on purpose so a guest cannot tell where one
occupant's dates end and the next begin, nor a block from a stay.
is_available now uses the OCCUPYING_STATUSES constant it was inlining.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
64607a00bc
commit
feaaef93e3
8 changed files with 278 additions and 8 deletions
21
models.py
21
models.py
|
|
@ -231,6 +231,27 @@ class AvailabilityQuery(BaseModel):
|
|||
check_out: str # YYYY-MM-DD exclusive
|
||||
|
||||
|
||||
class DateRange(BaseModel):
|
||||
"""Half-open [start, end) span of nights, YYYY-MM-DD. `end` is the morning
|
||||
the room frees up — a guest may check in on that day."""
|
||||
|
||||
start: str
|
||||
end: str
|
||||
|
||||
|
||||
class UnavailableRanges(BaseModel):
|
||||
"""Everything a guest calendar needs to grey out nights for one room
|
||||
over a window: bookings that still occupy the room (incl. live unpaid
|
||||
holds, so this always agrees with `POST /availability`) and manual
|
||||
blocks, merged into indistinguishable date spans — a guest can't tell a
|
||||
block from another guest's stay."""
|
||||
|
||||
room_id: str
|
||||
start: str
|
||||
end: str
|
||||
ranges: list[DateRange] = Field(default_factory=list)
|
||||
|
||||
|
||||
class AvailabilityResult(BaseModel):
|
||||
room_id: str
|
||||
check_in: str
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue