Koovira Dev Docs
20-modules/hotels/overview.md

Module: StayGo / Hotels (hotels / hotels)

Status: 🟑 Partially implemented (5,218 hotels imported, 2026-09-06 live count; booking side unexercised β€” 0 bookings) Β· Last validated: 2026-09-06 Β· Priority: P0

Hotel/stay discovery and booking, incl. external-source import, meal plans, add-ons, bulk/group bookings, and per-property invoicing/tax/refund settings. Validated against classs/HotelModule.php (8,987 lines by wc -l, 2026-09-06 β€” corrected from an earlier "~3,000 lines" estimate, which undercounted the file by roughly two-thirds) and the live schema.


A. Purpose

Customers search stays and book rooms; hotel owners manage properties, room types/units, rates, availability, refund policy, invoices. Commission 5% (wired). Revenue potential high; booking throughput currently ~0.

B. Actors

Customer/guest; hotel owner + hotel_staff_assignments; admin. External sources (import) via upsertExternalHotel/RoomType/Package.

C. Entry points

Consumer: /staygo_intro.php, /hotelslist.php, hotel detail, booking. Merchant: hotel dashboard, room types, rates, bookings-finance. Trip Planner integration via tripPlannerMatch (:2712).

D. Onboarding

createHotel(ownerId, data) (:1071) or bulk importHotelsFromXls (:168) / upsertExternalHotel (:808). Room types via saveRoomType (:1576). Module hotels on; owner enrolled; refund policy + invoice/tax settings configured before selling.

E. Feature registry (prefix STAY-)

IDFeatureActorMethodTablesStatus
STAY-001Import hotels (XLS/external)owner/adminimportHotelsFromXls :168, upsertExternalHotel :808hotels_master🟒
STAY-002Create/update hotelownercreateHotel :1071, ownerUpdateHotel :1383hotels_master🟒
STAY-003Room types & unitsownersaveRoomType :1576, listRoomTypes :1695hotel_room_types, hotel_room_units🟒
STAY-004Rates / availabilityownerrate overrides / inventoryhotel_room_rate_overrides, hotel_inventory_calendar🟑
STAY-005Meal plans & add-onsowner(meal/addon config)hotel_meal_plans (1,796), hotel_addons (1,347), hotel_meals_master (1,353)🟒
STAY-006Refund policyownerownerSaveRefundPolicy :1930hotel_refund_policies (62, 2026-09-06 β€” was 57)🟒
STAY-007Invoice / tax settingsownerownerSaveInvoiceSettings :2211hotel_invoice_settings (9), hotel_tax_settings (543, 2026-09-06 β€” was 525)🟒
STAY-008Quote a roomcustomerquoteRoomType :2935β€”πŸŸ’
STAY-009Book a staycustomer(booking write path)hotel_bookings, hotel_booking_unit_assignments, hotel_guest_folio, hotel_payments🟑 (0 bookings)
STAY-010Booking finance / folioownerownerListBookingsFinance :2418, ownerGetBookingFinance :2502hotel_payments, hotel_invoices, hotel_guest_folio🟑
STAY-011Bulk / group bookingscustomer/ownerbulk methodshotel_bulk_requests (2), hotel_bulk_orders🟑
STAY-012Trip Planner matchcustomertripPlannerMatch :2712β€”πŸŸ’

F. Booking flow (STAY-009)

hotelslist.php β†’ hotel detail β†’ quoteRoomType(payload)  :2935  (price + availability)
  β†’ book β†’ INSERT hotel_bookings (header) + hotel_booking_unit_assignments (which unit)
         β†’ hotel_guest_folio (charges) β†’ hotel_payments (wallet-first)
         β†’ central finance ledger (module_key='hotels', order_table='hotel_bookings')
         β†’ commission β†’ notifications

G. Data model (2026-09-06, re-verified β€” counts moved intraday, see anomaly below) β€” the real room/booking tables

TableRowsRole
hotels_master5,218properties (mostly imported)
hotel_room_types2,070room categories (the real "rooms", not hotel_rooms)
hotel_room_units193physical units within a type
hotel_inventory_calendar7date availability
hotel_room_rate_overrides0date/rate overrides
hotel_meal_plans / hotel_meals_master1,796 / 1,353meal plans
hotel_addons1,347add-ons
hotel_refund_policies62cancellation rules
hotel_tax_settings / hotel_invoice_settings543 / 9GST + invoice config
hotel_bookings0booking header
hotel_booking_unit_assignments38unit assigned per booking
hotel_guest_folio80folio charges
hotel_payments0payments
hotel_invoices0invoices
hotel_bulk_requests2bulk/group booking requests
Dormant/empty (don't use): hotel_rooms (0 β€” legacy; real rooms are hotel_room_types + hotel_room_units), hotel_master (0 β€” legacy singular; use hotels_master), hotel_packages (0 β€” use hotel_meal_plans). Data-state anomaly (requires verification β€” numbers moved during this same audit pass): an earlier reading today had hotel_bookings = 0 while hotel_payments = 362, hotel_guest_folio = 92, hotel_booking_unit_assignments = 39, hotel_invoices = 9 β€” read as "bookings occurred but the header table got purged while child/payment rows were retained." A re-run of the same exact COUNT(*) queries later the same day (2026-09-06) now shows hotel_payments = 0 and hotel_invoices = 0 as well (both fully emptied), while hotel_guest_folio dropped only to 80 (βˆ’12) and hotel_booking_unit_assignments only to 38 (βˆ’1). That is a live, in-progress data change, not a stale doc β€” this environment is under active testing tonight and something is deleting booking/payment/invoice rows table-by-table rather than a one-shot purge. Do not treat any of these counts as stable; re-run the _tools/ probes before quoting a number. Same general pattern (header/derived-table mismatch) as FoodVerse food_orders, but here the drift was observed happening in real time.

H. Financial impact

Wallet-first debit (HotelModule.php:4459) β†’ escrow credit to CLASSIFIED_ESCROW_BUCKET_USER_ID (:4465, "Hotel booking escrow") β†’ hotel_payments + central ledger (module_key='hotels') β†’ 5% commission (wired, CommissionEngineModule::computeAndRecord('hotel_booking', …) at :4424; zero commission_transactions rows exist for hotel bookings today β€” consistent with 0 live bookings) β†’ per-property invoice (hotel_invoices, GST via hotel_tax_settings) β†’ refund per hotel_refund_policies. See ../../40-financial/central-finance-ledger.md. Note: the guest debit (:4459) and escrow credit (:4465) share one $meta array that carries no acct_purpose, so both fall through to WalletModule::journalAccountsFor()'s historical default (classs/WalletModule.php:952-983): the guest's debit books as USER_WALLET_LIABILITY β†’ REVENUE_GENERAL (recognised revenue) rather than an escrow-liability movement, and the escrow credit books as if it were an external top-up rather than a liability reclassification. Same gap noted on the Food and Freelancer pages β€” real today, but currently unexercised in practice since hotel_bookings = 0.

K. State machine (hotel_bookings)

quoted β†’ confirmed β†’ checked_in β†’ checked_out β†’ completed, with cancelled (refund per policy) / no_show / modified (hotel_booking_modifications).

L. Errors (prefix STAY-E)

  • STAY-E001 no availability β€” quoteRoomType/inventory calendar returns none.
  • STAY-E002 booking header missing for a payment β€” see data-state anomaly.

M / N. Dependencies & change-impact

Wallet, finance ledger, commission, invoicing, Trip Planner, notifications. Changing the booking path affects availability, folio, payments and invoicing — re-test quote→book→folio→payment→invoice.