Skip to content

PRD 07 — Customers (directory, profile, tags, groups, notes, account rules)

Status: draft · Priority tier: P0 (list, add, detail core, suspend/delete) / P1 (notes, tags, waivers, lifecycle) / P2 (family, mobile verification) · Size: L · Depends on: PRD 01 (workspace, roles), existing auth (email-OTP, Google), PRD 06 (plans, pricing groups), PRD 08 (transactions)

1. Summary

The back-office customer directory and per-customer workspace: find, create, understand and manage customers, with tags, pricing groups, notes, waiver signatures, lifecycle status, and account-level rules (family accounts, mobile verification). Every other module (bookings, sales, plans) points at a customer record.

2. Problem & goals

  • Front desk finds any customer by name, email or phone in ≤ 2 interactions; the list responds in < 1 s for 10k customers.
  • Add a customer in ≤ 7 clicks (original: ~7), duplicates prevented.
  • One screen shows everything about a customer (spend, bookings, plans, notes, waivers).
  • Non-goals (v1): bulk import/export (not present in original; list as could), customer self-service portal (store PRD), marketing sends (marketing PRD), saved payment methods (needs gateway, PRD 08).

3. Users & roles

Owner, manager, front desk (create/view customers, sell), instructor (view-only on own attendance, assumption), customer (own profile via store, covered in the store PRD). See section 11.

4. Scope

In (v1)

  • must: Customer list with search, joined-date, lifecycle, status filters, sortable columns, 50 per page, row actions
  • must: Add customer (2 steps): email or mobile login, then name and optional details
  • must: Customer detail with Overview, Profile, Attendance, Packages, Memberships, Transactions, Notes, Forms, Settings tabs
  • must: Suspend (with reason) and delete (soft)
  • must: Pricing groups assignment (CRUD is PRD 06) and tags CRUD + assignment
  • should: Notes with categories and attachments
  • should: Lifecycle computed (member, non-member, lost member, trial)
  • should: Waiver form builder and signatures (customer Forms tab)
  • should: Overview KPIs and charts
  • should: Marketing consent per channel on profile Later (v2+)

  • should: Mobile verification rules (4 triggers)

  • should: Family account (parent with child profiles)
  • could: Events (courses) tab, once courses ship; bulk import/export; column chooser; membership rules for recurring billing live in PRD 08
  • could: Saved payment method on profile Out

  • A "RezervPass" cross-business identity (original has a platform-wide customer id; we use our own account id only; cross-business identity is a marketplace decision, not v1).

5. User stories

  • US-07-01 As a front desk user, I want to search by name, phone or email so that I find the customer at the counter.
  • US-07-02 As a front desk user, I want to add a walk-in with only a phone number so that I can book them immediately.
  • US-07-03 As an owner, I want to see lifecycle (member, non-member, lost, trial) so that I know who to win back.
  • US-07-04 As an owner, I want to tag and group customers so that I target offers and pricing.
  • US-07-05 As a staff member, I want internal notes with attachments so that team knowledge is shared.
  • US-07-06 As an owner, I want to suspend a customer with a reason so that they cannot book or buy.
  • US-07-07 As an owner, I want customers to sign a waiver so that liability forms are on file.
  • US-07-08 As a parent, I want to manage my children under my account so that I can book for them.
  • US-07-09 As an owner, I want to require a verified mobile at chosen moments so that no-shows can be reached.
  • US-07-10 As an owner, I want to delete a customer but let them rejoin so that data requests are honoured.

6. Functional requirements

ID requirement priority evidence
FR-07-01 List columns: name, joined date/time, lifecycle, phone, email, status chip, row menu; sortable; 50 per page with pager must S63, S200
FR-07-02 Filters: free-text search (name, email, phone); customer id; joined date presets (today, yesterday, 7/30/90 days, last month, last year, till date, exact, custom range); lifecycle multi-select; status (active, suspended); reset must S63b-g
FR-07-03 Row actions: view, add pricing plan (opens PRD 08 flow), assign pricing group, assign tag, suspend, delete must S63g
FR-07-04 Empty state with Add customer call to action must S63
FR-07-05 Add customer step 1: choose login method email or mobile (country code picker), enter it; Next disabled until valid; reject if already used (inline error, link to existing customer) must S64, F25
FR-07-06 Add customer step 2: first and last name required; optional DOB, pricing groups (multi), gender, address; waiver list; Add creates customer as non-member, active, then opens detail must S64d, F25, F72
FR-07-07 Quick add-customer drawer reusable from the add-transaction screen should S74
FR-07-08 Detail header: avatar, name, joined date, contact, lifecycle chip, status chip, KPI card (total spend, total bookings, classes attended) must S65
FR-07-09 Overview tab: refunds total, cancellations total, avg bookings per month with trend, date-range selector, line charts (spend, bookings, appointments) should S65b
FR-07-10 Profile tab: account number, verified mobile and email with edit, resend verification email, marketing consent per channel (email, SMS), lifecycle, gender, DOB/age, pricing groups, tags, address must S66
FR-07-11 Edit profile modal incl. marketing consent; every consent change stored with timestamp and actor must S66d, reports (marketing consent)
FR-07-12 Attendance tab: segmented class / appointment / (course, access later); filters search, date, location, staff, status, plan used should S67, S209zf
FR-07-13 Packages and Memberships tabs: owned plans with credits left, start, end, status, transaction number, "first purchase" tag; filters location, group, status; Add Package / Add Membership (manual sale via PRD 08) must S68, S209ze
FR-07-14 Transactions tab: search by number; date range, method, status, type filters; 20 per page must S68d, S209zg
FR-07-15 Notes: add with optional category, text ≤500, attachments (JPEG, PNG, GIF, PDF, Word, Excel, PowerPoint; ≤1 MB each); card shows author, time; delete with icon; search, date, category filters should S69
FR-07-16 Note categories: add/edit/delete page should S69c
FR-07-17 Tags: list (name, customer count, preview, updated), add/edit drawer with name + hex colour (default grey) and live preview, delete confirm, "assign customers" page, assign from customer profile drawer must S62, F26
FR-07-18 Pricing group assignment from add form, profile, list row action and group's own assign page must S61, S64e, F26
FR-07-19 Suspend: modal with reason (≤250), confirm; suspended customer cannot book or purchase and sees a clear message; reason visible on Settings tab; can be reactivated must S69g, F29
FR-07-20 Delete: confirm "cannot be recovered"; soft delete removes customer from lists; the same email/phone can rejoin as a new record; financial records remain for reporting must S69h, F29
FR-07-21 Lifecycle computed nightly and on plan events: member = has active membership; trial = holds a plan flagged trial and no membership; lost member = had a membership that ended with no active one; non-member = otherwise should S63d, S192 trial flag
FR-07-22 Waiver forms (settings): title ≤100, rich text body, staff booking enforcement: none / warn but allow / must resolve (class bookings only); list, add, edit should S152, S152b
FR-07-23 Customer Forms tab lists signed and unsigned waivers; staff can add a waiver to a customer; signature stores timestamp, version of text should S69e, S209x
FR-07-24 Family account toggle (business setting) enabling parent with child profiles; children get no login; booking/purchase on behalf could S153, S74 note
FR-07-25 Mobile verification rules (business settings): require mobile number; verify at sign-up; at first purchase of selected plans; at first booking of selected classes/appointments could S154
FR-07-26 Verification flow for mobile (code via messaging channel) and email (link); verified tick on profile should S66, S154
FR-07-27 Customer API list endpoint supports the filters in FR-07-02 server-side with keyset or offset pagination must derived
FR-07-28 Audit trail of suspend, delete, consent, group and tag changes (who, when) should S209l events pattern ✱

7. Screens

Our screen Modelled on States
Customers list S63 empty, loading, filled, filtered-empty, error
Add customer (2 steps) S64 step 1, invalid, step 2, duplicate error
Customer detail shell + 9 tabs (Events later = 10th) S65-S69 per tab: empty, filled
Tags list/drawer, assign page S62 empty, filled
Notes drawer, note categories page S69 empty, filled
Suspend / delete modals S69 open, error
Waiver list/editor S152 empty, edit
Settings: family account, mobile verification S153, S154 off, on

8. Flows

  • Add customer (target ≤ 7 clicks): Add → pick email/mobile → value → Next → first, last → Add → detail. Edge: existing contact shows "already exists, open record"; invalid contact keeps Next disabled; email customers get a verification/sign-in email, mobile ones a code only when verification is required.
  • Tag/group assign: from list row, profile, tag page, or plan automation (PRD 06).
  • Suspend: Settings tab or row menu → reason → confirm → status chip changes; existing future bookings stay (assumption, confirm).
  • Delete: confirm → soft delete; future bookings cancelled with notification ✱ (confirm).

9. Data model (✱ = guess)

  • Customer(id, account_no, first_name, last_name, email, email_verified_at, mobile, mobile_verified_at, dob, gender, address_*, status active|suspended|deleted, suspend_reason, lifecycle, marketing_email, marketing_sms, marketing_updated_at, parent_customer_id ✱, user_id null (link to auth user when they sign in), joined_at, created_by)
  • Tag(id, name, colour) + CustomerTag; PricingGroup + CustomerPricingGroup (owned by PRD 06)
  • CustomerNote(id, customer_id, category_id, text, author_id, created_at, deleted_at) + NoteAttachment(note_id, file_ref, name, size) + NoteCategory(id, name)
  • Waiver(id, title, body, version, enforcement none|warn|block) + WaiverSignature(customer_id, waiver_id, version, signed_at, signed_by ✱ staff or customer)
  • BusinessCustomerSettings(family_enabled, mobile_required, verify_on_signup, verify_plan_ids, verify_class_ids, verify_appt_ids)
  • Reuses existing user/auth identity: a Customer may be unlinked (staff-created) until the person signs in with matching verified email/mobile, then linked.

10. Business rules & edge cases

  1. Email and mobile are unique per business among non-deleted customers; stored normalised (lowercase email, E.164 mobile).
  2. At least one of email or mobile is required.
  3. New customers start non-member, active.
  4. Suspended customers cannot book, buy or check in; staff can still see them and sell on their behalf only after reactivation.
  5. Deleting is soft and rejoin creates a fresh customer record but keeps financial history on the old one.
  6. Tag/group deletion removes assignments, not customers.
  7. Attachments over 1 MB or other types rejected with a message.
  8. Marketing consent default off for staff-created customers ✱ (legal review).
  9. Waiver enforcement "must resolve" blocks staff-added class bookings until signed.
  10. Pagination and filters are stable when new customers arrive (keyset preferred).

11. Permissions

Action Owner Manager Front desk Instructor
View list/detail yes yes yes view (own classes) ✱
Create/edit customer yes yes yes no
Suspend/delete yes yes no ✱ no
Notes add/delete yes yes add no
Tags / pricing groups CRUD yes yes no no
Waiver, family, verification settings yes no no no
Customer detail sub-areas (overview, profile, bookings, packages, transactions, notes, forms, settings) are separately view/edit-able in the original matrix; we mirror at tab level.

12. Acceptance criteria

  • Given 120 customers, When I open the list, Then 50 appear with a pager and sorting by joined date works.
  • Given filter lifecycle = Lost member and status = Active, Then only matching customers show; Reset clears both.
  • Given email [email protected] exists, When I add another customer with it, Then I see a duplicate error with a link and nothing is created.
  • Given I add a customer with only a mobile number, When I finish step 2, Then the customer exists with status active and lifecycle non-member.
  • Given a customer is suspended, When they try to book, Then the booking is refused with the suspension message and no reason text is shown to them ✱.
  • Given a customer is deleted, When I search their email, Then no result; When the same email signs up, Then a new customer is created.
  • Given a membership purchase with auto tag "VIP", When the transaction is paid, Then the tag appears on the profile.
  • Given a note with a 2 MB file, Then the upload is rejected.
  • Given waiver enforcement "must resolve", When staff add the customer to a class without a signed waiver, Then the booking is blocked.

13. Dependencies & open questions

Depends on existing auth/profile, PRD 06, 08, 02/04 (bookings tabs), 01 (roles). Open questions:

  1. Merge of staff-created customers with self-signup users: auto-link on verified email only?
  2. What happens to future bookings and active plans on suspend and on delete?
  3. Lifecycle exact rules and "lost member" threshold (days since membership ended) — the original rules are not documented in recon.
  4. Family accounts: child login, shared credits? Plan-gated in original (pricing tier: TBD); behaviour not observed.
  5. Mobile verification channel (SMS, WhatsApp) and provider cost: not observed.
  6. Data protection obligations (Indonesia PDP law, others) for consent, deletion and attachments.
  7. Import/export of customers: absent in original but commonly needed for migration.
  8. Waiver customer-side signing UI not observed (staff side only).

14. Evidence

See evidence/evidence.md.