Product Requirements Document (PRD)
Product: Salon Booking System Version: MVP 1.0 Date: 2026-04-06 Based on: Product Brief | Architecture
1. Overview
Hệ thống booking & quản lý salon mobile-first cho thị trường Na Uy. MVP tập trung beauty cluster (nail, salon, barbershop) với smartphone-as-POS approach.
Roles: Owner, Staff, Customer, Admin
2. Epics & User Stories
Epic 1: Tenant & Onboarding
Admin tạo và quản lý salon accounts.
US-1.1: Admin tạo tenant mới
As Admin, I want to tạo salon account mới so that salon owner có thể bắt đầu sử dụng hệ thống.
Acceptance Criteria:
- Tạo tenant với: name, slug (unique), industry_type, settings
- Slug dùng cho subdomain:
{slug}.app.no - Default settings phù hợp với industry_type
- Owner account được tạo kèm tenant
API: POST /api/tenants
US-1.2: Owner customizes salon branding
As Owner, I want to tùy chỉnh branding (logo, colors, cover) so that customer portal phản ánh thương hiệu salon.
Acceptance Criteria:
- Upload logo, cover image
- Chọn primary/secondary colors
- Preview trước khi lưu
- Branding áp dụng ngay trên customer portal
API: PATCH /api/tenants/:id (branding field)
US-1.3: Owner quản lý salon settings
As Owner, I want to cấu hình salon settings so that hệ thống hoạt động đúng với business model.
Acceptance Criteria:
- Toggle: walk_in_enabled, auto_confirm, pos_enabled
- Đặt booking_mode: assigned_only | allow_unassigned
- Cấu hình business hours (default schedule)
- Cấu hình cancellation policy (hours before)
API: PATCH /api/tenants/:id (settings field)
Epic 2: Resource Management (Staff)
Owner quản lý staff — beauty layer map Staff vào Resource.
US-2.1: Owner thêm staff mới
As Owner, I want to thêm nhân viên vào salon so that họ có thể nhận booking.
Acceptance Criteria:
- Tạo resource (type=staff) với: name, color, contact
- Gửi invite link cho staff → staff tạo account
- Staff account liên kết với resource
- Staff mặc định inactive, owner activate
API: POST /api/resources
US-2.2: Owner quản lý staff skills
As Owner, I want to assign services mà mỗi staff có thể thực hiện so that booking chỉ match đúng staff.
Acceptance Criteria:
- Assign/remove services cho resource
- Khi booking, chỉ hiển thị resource có skill phù hợp
- Bulk assign cho nhiều resource cùng lúc
API: POST /api/resources/:id/skills, DELETE /api/resources/:id/skills/:serviceId
US-2.3: Owner quản lý staff schedule
As Owner, I want to đặt lịch làm việc cho staff so that hệ thống biết khi nào staff available.
Acceptance Criteria:
- Set weekly recurring schedule (day_of_week + start/end time)
- Có thể set nhiều shifts/ngày
- Override cho ngày cụ thể (nghỉ, đổi ca)
- Staff chỉ bookable trong schedule
API: POST /api/resources/:id/schedules, PATCH /api/resources/:id/schedules/:scheduleId
US-2.4: Staff xem lịch cá nhân
As Staff, I want to xem lịch booking của mình so that biết khách nào, dịch vụ gì, khi nào.
Acceptance Criteria:
- View daily/weekly schedule
- Hiển thị: customer name, service, time, status
- Real-time update khi có booking mới
- Offline mode: xem được schedule đã sync
API: GET /api/bookings?resourceId={id}&date={date}
Epic 3: Service Catalog
Owner quản lý danh mục dịch vụ.
US-3.1: Owner tạo & quản lý services
As Owner, I want to tạo danh mục dịch vụ so that customer có thể chọn khi booking.
Acceptance Criteria:
- CRUD service: name, description, duration (minutes), price (NOK)
- Organize theo category
- Set sort order
- Toggle active/inactive
- Price in smallest unit (øre)
API: POST /api/services, PATCH /api/services/:id
US-3.2: Owner quản lý service categories
As Owner, I want to nhóm services theo category so that customer dễ browse.
Acceptance Criteria:
- CRUD categories: name, sort_order
- Assign services vào category
- Categories hiển thị trên customer portal theo sort order
API: POST /api/service-categories, PATCH /api/service-categories/:id
Epic 4: Booking Engine
Core booking flow — tạo, assign, manage bookings.
US-4.1: Customer đặt booking online
As Customer, I want to đặt lịch online qua salon portal so that không cần gọi điện.
Acceptance Criteria:
- Chọn service → xem available time slots
- Chọn resource (staff) hoặc "bất kỳ ai" (unassigned)
- Chọn date + time slot
- Nhập thông tin: name, phone, email (optional), notes
- Nhận confirmation (theo tenant settings: auto_confirm hoặc pending)
- Guest booking (không cần tạo account)
API: POST /api/bookings (source=ONLINE)
US-4.2: Available time slots
As System, I want to tính toán available slots so that customer chỉ thấy thời gian có thể book.
Acceptance Criteria:
- Dựa trên: resource schedule + existing bookings + service duration
- Exclude: conflicting bookings (status != CANCELLED, NO_SHOW)
- Nếu unassigned: slot available khi >=1 qualified resource rảnh
- Configurable slot interval (15/30/60 min)
API: GET /api/availability?serviceId={id}&date={date}&resourceId={id}
US-4.3: Owner/Staff tạo booking thủ công
As Owner/Staff, I want to tạo booking từ app so that xử lý booking qua điện thoại hoặc tại chỗ.
Acceptance Criteria:
- Chọn service + resource + time
- Chọn existing customer hoặc tạo mới
- Source = PHONE hoặc ADMIN
- Conflict detection: cảnh báo nếu resource bận
API: POST /api/bookings (source=PHONE|ADMIN)
US-4.4: Walk-in handling
As Staff, I want to tạo booking cho khách walk-in so that track tất cả appointments.
Acceptance Criteria:
- Quick-create: chọn service, tự assign staff hiện tại
- startTime = now, endTime = now + duration
- Status auto = IN_PROGRESS
- Source = WALK_IN
- Optional: nhập customer info
API: POST /api/bookings (source=WALK_IN)
US-4.5: Unassigned booking & Staff self-pick
As Staff, I want to tự nhận booking chưa assign so that tận dụng thời gian rảnh.
Acceptance Criteria:
- Danh sách bookings có resourceId=null (unassigned)
- Staff chỉ thấy bookings mà mình có skill phù hợp
- Staff tap "Nhận" → resourceId = staff's resource
- Nếu 2 staff nhận cùng lúc → first-come-first-served (optimistic lock)
- Owner nhận notification khi staff self-pick
API: PATCH /api/bookings/:id (resourceId assignment)
US-4.6: Booking status management
As Owner/Staff, I want to update booking status so that track tiến trình.
Acceptance Criteria:
- Status flow: PENDING → CONFIRMED → IN_PROGRESS → COMPLETED
- Alternative: PENDING/CONFIRMED → CANCELLED
- Alternative: CONFIRMED → NO_SHOW
- Owner can update any booking, Staff chỉ bookings của mình
- Mỗi status change ghi audit log
API: PATCH /api/bookings/:id/status/:status
US-4.7: Booking conflict detection
As System, I want to ngăn double-booking so that không có 2 bookings cùng resource cùng lúc.
Acceptance Criteria:
- Check overlap: startTime < existingEnd AND endTime > existingStart
- Exclude: CANCELLED, NO_SHOW bookings
- Return 409 Conflict nếu trùng
- Cho phép override (owner only, với confirm)
Epic 5: Customer Management
Quản lý danh sách khách hàng per tenant.
US-5.1: Customer database
As Owner, I want to lưu thông tin khách hàng so that track lịch sử và cá nhân hóa.
Acceptance Criteria:
- Auto-create customer khi booking lần đầu (match by phone)
- CRUD: name, phone, email, notes
- View booking history per customer
- Unique constraint: phone + tenantId, email + tenantId
API: GET /api/customers, POST /api/customers, PATCH /api/customers/:id
US-5.2: Customer check-in
As Staff, I want to mark customer đã đến so that owner biết real-time.
Acceptance Criteria:
- Booking status: CONFIRMED → IN_PROGRESS khi customer arrive
- Push notification tới owner
- Hiển thị trên dashboard real-time
API: PATCH /api/bookings/:id/status/IN_PROGRESS
Epic 6: Payment Tracking (MVP — Manual)
MVP chỉ track payment status, chưa integrate payment gateway.
US-6.1: Mark booking as paid
As Staff, I want to đánh dấu booking đã thanh toán so that track doanh thu.
Acceptance Criteria:
- Update: isPaid, paidAmount, paidMethod (cash/card/vipps/other)
- Paid amount có thể khác service price (tips, discount)
- Chỉ COMPLETED hoặc IN_PROGRESS bookings mới mark paid
API: PATCH /api/bookings/:id (isPaid, paidAmount, paidMethod)
Epic 7: Notifications (MVP — Basic)
Booking confirmations và status updates.
US-7.1: Booking confirmation notification
As Customer, I want to nhận xác nhận khi booking thành công so that biết appointment đã được ghi nhận.
Acceptance Criteria:
- SMS (primary) gửi khi booking status = CONFIRMED
- Template Norwegian: "Hei {name}! Din time hos {salon} er bekreftet for {date} kl {time}"
- Include: service name, staff name (nếu assigned), salon address
US-7.2: Booking status change notification
As Customer, I want to nhận thông báo khi booking bị thay đổi so that không bị miss.
Acceptance Criteria:
- Notify on: CANCELLED (by salon), rescheduled (time change)
- SMS template per event type
- Norwegian language
US-7.3: Owner/Staff push notifications
As Owner/Staff, I want to nhận push notification so that biết ngay khi có booking mới.
Acceptance Criteria:
- New booking → notify owner + assigned staff
- Unassigned booking → notify all active staff
- Walk-in check-in → notify owner
- Push notification trên mobile app
Epic 8: Admin Portal (Web)
Super-admin quản lý toàn hệ thống.
US-8.1: Admin dashboard
As Admin, I want to xem overview tất cả tenants so that monitor hệ thống.
Acceptance Criteria:
- List tenants: name, industry, active status, booking count
- Search/filter tenants
- Quick stats: total tenants, total bookings today
US-8.2: Admin support access
As Admin, I want to truy cập salon data để hỗ trợ so that giúp owner setup/troubleshoot.
Acceptance Criteria:
- Login as tenant (impersonate) — with audit log
- View/edit tenant settings
- Mandatory audit trail cho mọi admin action
Epic 9: Customer Portal (Web)
Subdomain booking page cho mỗi salon.
US-9.1: Salon booking page
As Customer, I want to truy cập {slug}.app.no so that đặt lịch online.
Acceptance Criteria:
- Hiển thị salon branding (logo, colors, cover)
- Service catalog (grouped by category)
- Booking flow: service → (optional) staff → date/time → confirm
- Responsive, mobile-first
- SEO optimized (SSR)
3. Non-functional Requirements
Performance
- API response time: < 200ms (p95)
- Customer portal load time: < 2s (LCP)
- Support 100 concurrent bookings per tenant
Security
- JWT authentication + refresh tokens
- Tenant isolation: mọi query filter by tenant_id
- RLS (Row Level Security) ở PostgreSQL
- Rate limiting: 100 req/min per IP
- OWASP Top 10 compliance
Reliability
- 99.9% uptime target
- Offline mode cho mobile app (WatermelonDB sync)
- Graceful degradation khi services down
Localization
- Primary: Norwegian Bokmål (nb-NO)
- UI text feel native, không phải bản dịch
- Date/time format: dd.MM.yyyy, HH:mm
- Currency: NOK (Norwegian Krone), display with "kr"
- Phone: Norwegian format (+47)
Audit
- Mọi mutation ghi audit log: who, what, when, before/after
- Admin actions có mandatory audit trail
- Retention: 12 months minimum
4. Data Model Reference
See Architecture for full schema.
Core entities: Tenant, User, Resource, ResourceSkill, ResourceSchedule, Service, ServiceCategory, Booking, Customer
Key relationships:
- Tenant → has many Resources, Services, Bookings, Customers
- Resource → has many Skills (services it can perform), Schedules
- Booking → belongs to Tenant, Customer (optional), Resource (optional = unassigned), Service
5. API Overview
Base URL: {api-domain}/api
Auth: Bearer JWT
Tenant: x-tenant-id header (hoặc từ JWT)
| Endpoint | Methods | Description |
|---|---|---|
/tenants |
GET, POST | List/create tenants (admin) |
/tenants/:id |
GET, PATCH | Get/update tenant |
/tenants/slug/:slug |
GET | Resolve tenant by subdomain |
/resources |
GET, POST | List/create resources |
/resources/:id |
GET, PATCH | Get/update resource |
/resources/:id/skills |
POST, DELETE | Manage resource skills |
/resources/:id/schedules |
GET, POST, PATCH | Manage schedules |
/services |
GET, POST | List/create services |
/services/:id |
GET, PATCH | Get/update service |
/service-categories |
GET, POST | List/create categories |
/bookings |
GET, POST | List/create bookings |
/bookings/:id |
GET, PATCH | Get/update booking |
/bookings/:id/status/:status |
PATCH | Update booking status |
/availability |
GET | Available time slots |
/customers |
GET, POST | List/create customers |
/customers/:id |
GET, PATCH | Get/update customer |
/auth/login |
POST | Login |
/auth/register |
POST | Register |
/auth/refresh |
POST | Refresh token |
6. MVP Milestones
Phase 1: Foundation (Current)
- Project setup (repos, Docker, NestJS scaffold)
- Prisma schema & core modules
- Docker Compose running
- Database migration
- Auth module (JWT)
Phase 2: Core API
- Availability engine
- Booking conflict detection (done in service, needs testing)
- Resource schedule management
- Resource skills management
- Customer auto-create on booking
Phase 3: Notifications & Real-time
- SMS notification (Twilio/local provider)
- WebSocket for live booking updates
- Push notifications (Expo)
Phase 4: Customer Portal (Web)
- Next.js setup + OpenAPI codegen
- Subdomain routing
- Booking flow UI
- Salon branding
Phase 5: Mobile App
- Expo setup + OpenAPI codegen
- Owner screens (dashboard, schedule, staff management)
- Staff screens (schedule, self-pick, check-in, payment)
- Offline sync (WatermelonDB)
Phase 6: Admin Portal
- Admin dashboard
- Tenant management
- Support access + audit