ARI + restrictions — proposed SSOT (draft)
ARI = Availability · Rates · Inventory (+ restrictions).
Live v1 winner stays availability/check (computed from rooms + overlapping bookings). Do not delete that playbook until an inventory folder is live.
Proposed SSOT
| Concern | Writer | Not SSOT |
|---|---|---|
| Sellable units / day | Middleware inventory row per room×date (Core inventory entity optional) | Google / GuestTraction / OTAs |
| BAR | Same row or rate-plan rules that write inventory | Scraper prices |
| Restrictions | stopSell, minStay, maxStay, closedToArrival, closedToDeparture | Channel dashboards |
| Booked count | Booking create/cancel in the same Middleware transaction | Inbound OTA ARI |
Channels are outbound. Inbound ARI must not overwrite SSOT without an audited import.
propertyId, roomId, date
baseRate, inventoryCount, bookedCount
stopSell, minStay, maxStay, CTA, CTDAvailability ≈ inventoryCount - bookedCount plus restrictions and rate-plan linkage.
Rooms stay a rooms resource (live: /api/v1/bookdirect/rooms). Do not collapse rooms into rates-packages.
Push (after SSOT exists)
MelonQ calendar edit → Middleware inventory write → debounce GuestTraction / Booklogic (room content, availability, restrictions, pricing, promotions including AI Rate Match). Horizon constant e.g. GOOGLE_ARI_PUSH_DAYS ≈ 330.
What must exist
- One write API used by MelonQ and booking side-effects
- Booking create increments
bookedCountwith the booking insert (oversell guard) - Idempotent channel push + sync status
- Per room+ratePlan channel toggles
- No second “Google inventory” table
Core: optional inventory entity. No date-overlap engine in Laravel — Middleware owns the calendar math.
IDOR
Partner JWT for inventory writes. Availability reads return counts only. Channel creds stay on Middleware.
Acceptance
- Min stay in MelonQ changes guest eligibility without opening Google
- Channel disable stops push; SSOT still editable
- Concurrent booking cannot oversell
- AI Rate Match promotions use the same push pipeline