# Booking & payments — administrator panel specification This document describes the **guest booking domain** as implemented in the **Shitaye FrontEnd** demo today, and what a **separate administrator application** should support to manage **bookings**, **holds**, and **payments**. Use it as a blueprint when you build the admin API, database schema, and UI. The public site lives in this repository (`Shitaye-FrontEnd`). The admin panel is **not** included here; this README is the handoff for that work. --- ## 1. Goals of the admin system - **List and search** reservations (by date, status, guest, reference, room, payment state). - **Open a booking** and see full guest, stay, pricing, flight/arrival, coupons, and payment metadata. - **Reconcile payments** (paid, pending, failed, refunded) against holds or confirmed bookings. - **Operational actions** (policy-dependent): cancel hold, extend hold, mark no-show, issue refund, add internal notes, export for finance. --- ## 2. Current public app (this repo) — important limitations Today the storefront is a **client-side mock**: - State lives in **React context** (`BookingProvider`) in the browser — **nothing is persisted** to your backend when a guest “books”. - `submitBookingHold` and `processPayment` in `src/lib/mocks/api.ts` only **simulate latency** and return fake IDs (`SHY-…`, `PAY-…`). - **No real card processing**, no webhooks, no idempotent payment IDs. **Implication for admin:** you will introduce a **real backend** (or extend an existing PMS/booking engine). The admin panel should talk to **that** system, not to the in-memory Next.js state. **Reference files in this repo** | Area | Path | |------|------| | Guest & stay state | `src/context/BookingContext.tsx` | | Guest shape | `GuestDetails` in same file | | Hold / payment mock API | `src/lib/mocks/api.ts` | | Room catalogue (ids, rates) | `src/lib/mocks/rooms.ts` | | Tax rate | `src/lib/mocks/site.ts` (`taxRate`, e.g. `0.15` = 15%) | --- ## 3. Domain model (what to persist) ### 3.1 Guest (contact + arrival) Aligned with `GuestDetails`: | Field | Type | Notes | |-------|------|--------| | `firstName` | string | | | `lastName` | string | | | `email` | string | Primary contact; unique per booking or account policy TBD | | `phone` | string | E.164 recommended in production | | `flightBookingNumber` | string | PNR / record locator / ticket ref | | `arrivalTime` | string | Currently `HH:mm` from UI; store as time or datetime with timezone (Addis Ababa) in production | ### 3.2 Stay | Field | Type | Notes | |-------|------|--------| | `checkIn` | date (ISO date) | `YYYY-MM-DD` in UI | | `checkOut` | date (ISO date) | | | `guests` | integer | 1–12 in UI | | `roomId` | string | Catalogue key: `penthouse`, `standard`, `connecting-suite`, `junior-studio` (see `rooms.ts`) | | `nights` | integer | Derived; validate against check-in/out | ### 3.3 Pricing (display currency vs ledger) The storefront shows **USD catalogue rates** on the server-side math, with an optional **display currency** (EUR, GBP, AED, etc.) via `CurrencyContext` / `src/lib/currency.ts`. **Admin / accounting recommendation** - Store amounts in a **single base currency** (e.g. ETB or USD) per property policy. - Store **FX snapshot** at booking or payment time if you show multi-currency to guests. - Line items to persist (mirroring checkout): | Concept | Source in app | |---------|----------------| | Nightly subtotal | `nightlyRate × nights` from room catalogue | | Coupon code | string | | Discount % | e.g. `10` or `5` (mock codes `SHITAYE10`, `WELCOME5`) | | Discount amount | % of subtotal | | Tax | `siteConfig.taxRate` × taxable base (after discount) | | **Total** | Grand total charged or to be charged | ### 3.4 Hold vs payment (lifecycle) The UI distinguishes: | Concept | Flag / field | Meaning | |---------|----------------|--------| | Hold reference | `holdReference` | e.g. `SHY-…` — created when guest continues from `/booking` (pay now or pay later path) | | Pay later | `payLaterHold` | `true` if guest chose “Reserve now — pay later” before visiting payment | | Payment confirmation | `confirmationId` | e.g. `PAY-…` after successful (mock) payment | | Paid timestamp | `paidAt` | ISO datetime string | **Suggested persisted statuses** (you can rename): 1. `draft` — abandoned cart (optional) 2. `held` — hold created, **not** paid (`payLaterHold` may be true or false; both paths create a hold in the current flow) 3. `payment_pending` — guest on payment step (optional transient) 4. `confirmed` — payment succeeded (`confirmationId` + `paidAt`) 5. `cancelled` / `expired` — hold released or timeout Map the mock’s `payLaterHold` to your policy: e.g. **held unpaid** vs **held with intent to pay later**. --- ## 4. Mock API payloads (prototypes for real endpoints) Today’s TypeScript types in `src/lib/mocks/api.ts`: ### 4.1 Create hold (after guest details + flight) `BookingPayload`: - `roomId`, `email`, `flightBookingNumber`, `arrivalTime` **Real API should also accept:** `checkIn`, `checkOut`, `guests`, full guest name/phone, pricing breakdown, coupon fields — everything needed to reconstruct the reservation without trusting the client for totals. **Response (mock):** `{ reference: string }` ### 4.2 Process payment `PaymentPayload`: - `totalCents` (integer; mock uses USD × 100) - `last4` (optional; card last four — never store full PAN in admin DB) **Response (mock):** `{ confirmationId: string, paidAt: string }` **Production:** integrate PSP (Stripe, Chapa, etc.), store **payment intent ID**, **status**, **receipt URL**, and **audit trail**; admin reads from your payment service or synced tables. --- ## 5. Room catalogue keys (admin filters & reports) Use the same `id` values as `src/lib/mocks/rooms.ts` unless you migrate to UUIDs: | `roomId` | Display name (short) | |----------|----------------------| | `penthouse` | The 4 Bedroom Penthouse | | `standard` | Standard Rooms | | `connecting-suite` | Connecting Suite | | `junior-studio` | Junior Studios | Each room has `nightlyRate` (USD in mock), `maxGuests`, `slug` for public URLs. --- ## 6. Administrator panel — recommended features ### 6.1 Dashboard - Today’s arrivals / departures - Unpaid holds (pay-later + overdue) - Revenue snapshot (range selector) ### 6.2 Bookings list - Filters: status, date range (stay or created), room, email, hold ref, payment ref - Sort: check-in, created at, total - Bulk export CSV (finance) ### 6.3 Booking detail - Guest, stay, room, pricing lines, coupon, flight/PNR, arrival time - Payment section: provider, amount, currency, status, timestamps, refund button (if allowed) - Internal notes (staff-only), activity log ### 6.4 Payments - List transactions linked to bookings - Reconciliation view (settled vs pending) - Manual “mark paid” only if you accept bank transfer / cash — with strict RBAC ### 6.5 Configuration (optional) - Tax rate, active coupon codes, hold TTL, room rates (or sync from PMS) --- ## 7. Security & compliance - **RBAC:** roles such as `viewer`, `front_desk`, `finance`, `superadmin`. - **PII:** encrypt at rest where required; minimize data in logs; GDPR-style export/erase if you serve EU/UK guests. - **PCI:** never store raw card data; use tokenization via your PSP; admin UI shows only last4 / brand if provided. - **Audit:** who changed status, refunds, or manual overrides. --- ## 8. Integrating the public Next.js app later Replace `src/lib/mocks/api.ts` calls with `fetch`/`axios` to your backend: 1. **POST** `/bookings/hold` — persist reservation + return real `holdReference` 2. **POST** `/bookings/:id/pay` or PSP redirect + **webhook** — update status to confirmed 3. Optional **GET** `/bookings/:ref` for guest “lookup my booking” The admin app should use the **same API** (or an internal admin API with stronger scopes) so there is a single source of truth. --- ## 9. Open decisions (product / engineering) - Single vs multi-property admin - Whether “pay later” holds **expire** automatically and how guests resume payment (magic link vs login) - Official currency of record and whether ETB is required for local compliance - Connection to an existing PMS (Opera, Cloudbeds, etc.) vs custom DB only --- ## 10. Document maintenance When you change the guest booking flow in **Shitaye-FrontEnd**, update: - Section **3** (fields), **4** (payloads), and **5** (room ids) - This file path: `ADMIN_BOOKING_README.md` (repository root) --- *Prepared for Yaltopia / Shitaye Suite Hotel — booking management administrator development.*