- 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
221 lines
8.5 KiB
Markdown
221 lines
8.5 KiB
Markdown
# 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.*
|