Shitaye-FrontEnd/ADMIN_BOOKING_README.md
“kirukib” 1a37b91795 feat: soften brand gold, hero copy; OpenNext Cloudflare config
- Replace flat mustard with softer champagne tones and gentler shadows
- Hero eyebrow: Book direct · Shitaye Suite Hotel
- Lighter pattern grid, chips, badges, card hover ring; meetings band ring toned down
- Ignore .dev.vars and .wrangler for local secrets and cache

Made-with: Cursor
2026-03-25 00:18:51 +03:00

221 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 | 112 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 mocks `payLaterHold` to your policy: e.g. **held unpaid** vs **held with intent to pay later**.
---
## 4. Mock API payloads (prototypes for real endpoints)
Todays 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
- Todays 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.*