product/prd.md

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