# Hotel Flow (spec §128 "Critical Hotel Test")

Executed live against the seeded database (guest "John Fernandes", reservation
`RES-PTZ01-000001`, room 103 / Suite).

1. **Guest + reservation** already seeded (`hotel_guests`,
   `hotel_room_reservations` — 2 nights, ₹7,500/night + 12% tax = ₹16,800).
2. **Check-in** →

   ```http
   POST /api/checkins
   { "reservation_id": 1, "room_id": 3, "id_verified": true }
   ```

   Creates `hotel_checkins`, flips the reservation to `checked_in`, sets
   `hotel_rooms.status = occupied` / `housekeeping_status = dirty`, and
   **opens a folio** (`hotel_folios`) seeded with the room charge line
   (`hotel_folio_items`, `charge_type: "room"`, `total: 15900.00` =
   ₹15,000 room + ₹900 tax) — `folio.balance = 15900.00`.

3. **Open restaurant POS, select Room Service, order for the guest**:

   ```http
   POST /api/pos
   { "outlet_id": 1, "order_type": "room_service", "guests": 2,
     "items": [{ "item_id": 4, "quantity": 1 }] }   // Butter Chicken
   ```

   Order total: ₹402.80 (₹380 + 6% CGST).

4. **Submit KOT, kitchen completes, deliver to room** — same KOT lifecycle
   as the restaurant flow (`docs/POS-FLOW.md`).
5. **Charge to Room**:

   ```http
   POST /api/pos/2/charge-to-room
   { "room_number": "103" }
   ```

   Finds the checked-in guest's open folio for room 103, posts a
   `restaurant` `hotel_folio_items` row for ₹402.80, links it via
   `restaurant_room_charges`, records a `payments` row with
   `method: "room_charge"`, and closes the restaurant order
   (`charged_to_room: true`, `balance_amount: 0`).

6. **Verify folio** → `GET /api/folios/1`:
   `total_charges: 16302.80` (₹15,900 room + ₹402.80 restaurant),
   `balance: 16302.80` (nothing paid toward the stay yet).
7. **Add a laundry charge** (spec §52) →
   `POST /api/folios/1/items { "charge_type": "laundry", "description": "Laundry service", "amount": 250 }`.
8. **Checkout** —

   ```http
   POST /api/checkouts
   { "reservation_id": 1, "payment_amount": 16302.80 }
   ```

   (If `payment_amount` is less than the outstanding balance, the API
   returns `400` with the remaining balance unless `force: true` is passed —
   checkout never silently writes off a balance.) On success: folio
   `status: "closed"`, reservation `status: "checked_out"`,
   `hotel_rooms.status → cleaning`.
9. **Housekeeping** — `PATCH /api/housekeeping/rooms/3 { "housekeeping_status": "cleaning" }`,
   then `{ "housekeeping_status": "inspected" }` → room automatically flips
   back to `status: "available"` once inspected (spec §108 workflow:
   Occupied → Checkout → Dirty → Cleaning → Inspected → Available).

Every step above was captured from real API responses during development —
none of the numbers are illustrative placeholders.
