Class: AvailabilityService
Defined in: server/bookings/availability-service.ts:183
Open-window resolution + scheduling glue (spec §6.9, §11).
Reads (openWindows/freeSlots) are plain queries; window EDITS and
applyWeeklyHours are transactions that take the per-space
booking_resources row lock so they serialize against concurrent claims.
Constructors
Constructor
new AvailabilityService(deps: BookingFeatureDeps): AvailabilityService;Defined in: server/bookings/availability-service.ts:184
Parameters
| Parameter | Type |
|---|---|
deps | BookingFeatureDeps |
Returns
AvailabilityService
Properties
deps
protected readonly deps: BookingFeatureDeps;Defined in: server/bookings/availability-service.ts:184
Methods
addWindow()
addWindow(input: {
availabilityId: string;
endsAt: Date;
startsAt: Date;
}): Promise<{
availabilityId: string;
createdAt: Date;
createdBy: string | null;
deletedAt: Date | null;
deletedBy: string | null;
endsAt: Date;
id: string;
isException: boolean;
resourceId: string;
startsAt: Date;
updatedAt: Date;
updatedBy: string | null;
}>;Defined in: server/bookings/availability-service.ts:306
Add a one-off open window (the RDATE analogue, spec §6.9 — e.g. a special
midnight session). Always isException: true.
Parameters
| Parameter | Type |
|---|---|
input | { availabilityId: string; endsAt: Date; startsAt: Date; } |
input.availabilityId | string |
input.endsAt | Date |
input.startsAt | Date |
Returns
Promise<{
availabilityId: string;
createdAt: Date;
createdBy: string | null;
deletedAt: Date | null;
deletedBy: string | null;
endsAt: Date;
id: string;
isException: boolean;
resourceId: string;
startsAt: Date;
updatedAt: Date;
updatedBy: string | null;
}>
applyWeeklyHours()
applyWeeklyHours(
resourceId: string,
map: WeeklyHoursMap,
opts: WeeklyHoursToSeriesOptions
): Promise<ApplyWeeklyHoursResult>;Defined in: server/bookings/availability-service.ts:389
Apply a weekly hours map to a resource (spec §6.9 "Weekly hours stay a one-liner — and the EDIT path is specified, not just create"). NOT a destructive overwrite — a real this-and-following split per existing active series:
- the old series' rule is CAPPED at
effectiveFrom(the one capping implementation: loweredCOUNTfor COUNT-bounded rules, elseUNTIL) and its status flips to "ended"; - its already-materialized future NON-EXCEPTION windows (the machine-generated old-hours rows at/after the split) are removed — they are superseded by the new pattern's fan-out;
- exception windows — edited "special hours" AND soft-deleted holiday closures (the July-4 row) — are left UNTOUCHED on the capped old series, and the materializer's closure guard keeps the successor from re-opening a closed occurrence: a closure is never silently resurrected (§6.9);
- new pattern series are minted with
supersedesAvailabilityIdlineage.
Windows are NOT materialized here — run the availability materializer on the new series; until then the resource correctly fails closed beyond the split (§6.9 safe default).
Parameters
| Parameter | Type |
|---|---|
resourceId | string |
map | WeeklyHoursMap |
opts | WeeklyHoursToSeriesOptions |
Returns
Promise<ApplyWeeklyHoursResult>
closeWindow()
closeWindow(windowId: string): Promise<{
availabilityId: string;
createdAt: Date;
createdBy: string | null;
deletedAt: Date | null;
deletedBy: string | null;
endsAt: Date;
id: string;
isException: boolean;
resourceId: string;
startsAt: Date;
updatedAt: Date;
updatedBy: string | null;
}>;Defined in: server/bookings/availability-service.ts:358
Close one occurrence ("closed for the holiday" — spec §6.9): soft-deletes
the window row. The row PERSISTS (isException: true) and blocks
regeneration, exactly like a cancelled series child booking.
Parameters
| Parameter | Type |
|---|---|
windowId | string |
Returns
Promise<{
availabilityId: string;
createdAt: Date;
createdBy: string | null;
deletedAt: Date | null;
deletedBy: string | null;
endsAt: Date;
id: string;
isException: boolean;
resourceId: string;
startsAt: Date;
updatedAt: Date;
updatedBy: string | null;
}>
freeSlots()
freeSlots(
resourceId: string,
range: TimeRange,
opts: FreeSlotsOptions
): Promise<TimeRange[]>;Defined in: server/bookings/availability-service.ts:237
On-demand slot-stepping (§6.9 — bookable slot-steps are NEVER materialized): subtract exclusive conflicts or shared saturation from open windows, using the same live-occupancy predicate as claims. Results are advisory: claims recheck capacity and hours under locks. Booking-type policy and pricing are not evaluated here.
Parameters
| Parameter | Type |
|---|---|
resourceId | string |
range | TimeRange |
opts | FreeSlotsOptions |
Returns
Promise<TimeRange[]>
openWindows()
openWindows(resourceId: string, range: TimeRange): Promise<TimeRange[]>;Defined in: server/bookings/availability-service.ts:191
Merged union of live open windows for a resource, clamped to range.
Unconfigured hours mean the whole range is open; configured but
windowless resources remain closed. Returned in range.start's zone.
Parameters
| Parameter | Type |
|---|---|
resourceId | string |
range | TimeRange |
Returns
Promise<TimeRange[]>
updateWindow()
updateWindow(windowId: string, patch: {
endsAt?: Date;
startsAt?: Date;
}): Promise<{
availabilityId: string;
createdAt: Date;
createdBy: string | null;
deletedAt: Date | null;
deletedBy: string | null;
endsAt: Date;
id: string;
isException: boolean;
resourceId: string;
startsAt: Date;
updatedAt: Date;
updatedBy: string | null;
}>;Defined in: server/bookings/availability-service.ts:332
Per-occurrence edit ("special hours" — spec §6.9 this-occurrence scope):
patches the window row and flags it isException so series-wide edits
skip it. Serializes against claims on the per-space lock.
Parameters
| Parameter | Type |
|---|---|
windowId | string |
patch | { endsAt?: Date; startsAt?: Date; } |
patch.endsAt? | Date |
patch.startsAt? | Date |
Returns
Promise<{
availabilityId: string;
createdAt: Date;
createdBy: string | null;
deletedAt: Date | null;
deletedBy: string | null;
endsAt: Date;
id: string;
isException: boolean;
resourceId: string;
startsAt: Date;
updatedAt: Date;
updatedBy: string | null;
}>