User Journeys

This chapter documents the primary user journeys through the Membership platform. Each journey is presented as a step-by-step flow with a Mermaid diagram, entry conditions, exit conditions, and notes on error handling. These journeys drive the API design (Chapter 10), the frontend screen inventory (Chapter 09), and the test scenarios.

Journey 1: Consumer Self-Onboarding (Web)

A prospective member discovers a club or studio through its landing page and completes the entire sign-up process without any admin intervention. This is the primary acquisition funnel.

Entry point: Club/studio landing page or direct link to membership offers. Prerequisite: The organization has published at least one membership offer with visibility set to "public". Exit condition: Member has a verified account, an active contract, and (if applicable) a SEPA mandate on file.

flowchart TD A[Visit club landing page] --> B[Browse membership offers] B --> C[Select membership plan] C --> D[Create account<br/>Email + password] D --> E[Receive verification email] E --> F[Click verification link] F --> G[Complete personal profile<br/>Name, address, birthday] G --> H{Age < 18?} H -->|Yes| I[Enter guardian/emergency contact<br/>Name, phone, relationship] H -->|No| J[Select start date] I --> J J --> K{Payment method?} K -->|SEPA Direct Debit| L[Enter IBAN<br/>Sign SEPA mandate] K -->|Free membership| M[Skip payment] K -->|Other| N[Select payment method] L --> O[Review summary<br/>Plan, price, start date, payment] M --> O N --> O O --> P[Confirm and accept terms] P --> Q[Contract created<br/>Confirmation email sent] Q --> R[Download mobile app<br/>Login with same credentials] style A fill:#e3f2fd style Q fill:#e8f5e9 style R fill:#e8f5e9

Key screens: Landing page (public, no auth) -> Offer selector -> Registration form -> Email verification interstitial -> Profile form -> Payment form -> Review/confirm -> Success page with app download links.

Error handling: - Email already registered: offer login instead of registration, with password reset option. - IBAN validation failure: inline error with format hint, allow retry. - Verification email not received: resend button with 60-second cooldown. - Session timeout during multi-step form: persist partial data in local storage, restore on return.

API calls involved: 1. GET /mobile/v1/entity/search -- Find clubs 2. GET /mobile/v1/contract-pre-defined/{entityId} -- List available offers 3. POST /mobile/v1/account/register -- Create account 4. POST /mobile/v1/account/verify -- Verify email 5. POST /mobile/v1/consumer/create -- Complete profile 6. POST /mobile/v1/bank-account/create/{idMcEntity} -- Add SEPA bank account 7. POST /mobile/v1/contract/create/{predefinedId} -- Purchase membership

Journey 2: Consumer Mobile App Experience

A registered member uses the mobile app for their daily interaction with the platform: checking in at the gym, viewing their membership, tracking payments, and managing their profile.

Entry point: App launch. Prerequisite: Member has a verified account and at least one active contract. Exit condition: Member completes their intended action (check-in, view data, update profile).

flowchart TD A[Open app] --> B{Authenticated?} B -->|No| C[Login screen<br/>Email + password] B -->|Yes, token valid| F C --> D[Enter credentials] D --> E{Login success?} E -->|No| C2[Show error<br/>Retry or forgot password] E -->|Yes| F[Home screen<br/>Active memberships] C2 -->|Forgot password| FP[Enter email<br/>Receive reset link<br/>Set new password] FP --> C F --> G{What does the user want?} G -->|Check in| H[Navigate to Access tab] H --> I[Show QR code for active membership] I --> J[Scan QR at turnstile<br/>or show to staff] J --> K{Access granted?} K -->|Yes| L[Show green confirmation<br/>Log entry] K -->|No| M[Show reason<br/>Contract expired, no access, etc.] G -->|View payments| N[Navigate to Payments tab] N --> O[Transaction list<br/>Date, amount, status] O --> P[Tap transaction for detail] G -->|Browse gyms| Q[Navigate to search] Q --> R[Search by name or radius] R --> S[View gym detail<br/>Offers, location, hours] S --> T[Purchase new membership<br/>Redirects to onboarding flow] G -->|Manage profile| U[Navigate to Profile tab] U --> V[View/edit personal data] V --> W[Save changes] G -->|Manage bank account| X[Profile > Bank Accounts] X --> Y[View existing accounts] Y --> Z[Add or update bank account] style A fill:#e3f2fd style L fill:#e8f5e9 style M fill:#ffcdd2

Key screens (mapped to bottom navigation): 1. Memberships tab -- List of active contracts with status indicators, start/end dates, next payment. 2. Access tab -- QR code display for check-in. If multiple contracts, show selector. Real-time confirmation after scan. 3. Payments tab -- Transaction history with filters (date range, status). Tap for detail view showing contract, amount, due date, payment method, status. 4. Profile tab -- Personal data, emergency contacts, bank accounts, notification preferences, password change, account deletion, data export.

Offline mode behavior: - QR code for check-in is cached locally and works without network (the check-in terminal validates the QR signature, not the backend). - Transaction list shows cached data with "last updated" timestamp. - Profile edits are queued and synced when connectivity returns.

Journey 3: Admin Member Management

A club admin manages the full lifecycle of a member: creation, contract assignment, payment management, and document handling. This is the day-to-day admin workflow.

Entry point: Admin web app, Members section. Prerequisite: Admin is logged in with Club Admin role or higher. Exit condition: Member is fully set up with contract and payment method.

flowchart TD A[Open Members section] --> B[Click 'Add Member'] B --> C[Enter member data<br/>Name, email, phone, address, birthday] C --> D{Member already exists?} D -->|Yes, in same org| E[Show existing record<br/>Offer to add contract] D -->|Yes, in other org| F[Create link<br/>Shared consumer, new contract] D -->|No| G[Create new member record] G --> H[Assign membership] E --> H F --> H H --> I[Select contract template<br/>from predefined offers] I --> J[Set start date and<br/>customize if needed] J --> K[Select payment method] K -->|SEPA| L[Enter or select bank account<br/>IBAN, account holder] K -->|Invoice| M[Invoice settings<br/>Frequency, delivery method] K -->|Cash| N[Mark as cash payment] K -->|Free| O[No payment required] L --> P[Review and confirm] M --> P N --> P O --> P P --> Q[Contract created<br/>Welcome email sent to member] Q --> R{Next action?} R -->|Generate SEPA| S[Add to next SEPA export batch] R -->|View documents| T[Open contract PDF<br/>SEPA mandate PDF] R -->|Manage payments| U[View transaction list<br/>Create manual adjustments] R -->|Send communication| V[Send email or notification<br/>to member] style A fill:#e3f2fd style Q fill:#e8f5e9

Admin screens involved: 1. Member list -- Data table with search, filters (status, membership type, payment status), sort, and export. Supports bulk actions (bulk email, bulk status change). 2. Member detail -- Tabbed view: Personal Data, Contracts, Transactions, Bank Accounts, Documents, Communication History, Audit Log. 3. Contract assignment wizard -- Step-by-step: select template -> customize -> payment method -> review -> confirm. 4. SEPA batch management -- View pending SEPA transactions, create export file, download XML, mark as submitted.

Business rules enforced: - Duplicate detection by email address across the current organization. - Minor members (age < 18) require guardian information before contract creation. - Contract start date cannot be in the past. - SEPA mandate requires valid IBAN with checksum validation. - Welcome email is sent automatically upon contract creation (configurable template per organization).

Journey 4: Admin Initial Setup

A new organization administrator configures their club or studio from scratch. This is the first-time setup flow that must be completed before the organization can accept members.

Entry point: First admin login after organization provisioning. Prerequisite: Organization entity created by a group admin, franchisor admin, or system admin. Initial admin account created with invitation. Exit condition: Organization is fully configured and ready to accept members.

flowchart TD A[Accept invitation email<br/>Set password] --> B[First login] B --> C[Setup wizard starts] C --> D[Step 1: Organization Profile<br/>Name, address, phone, email<br/>Logo, description, website] D --> E[Step 2: Business Settings<br/>Working hours, timezone<br/>Currency, tax rates] E --> F[Step 3: Membership Offers<br/>Create contract templates<br/>Name, price, duration, benefits] F --> G[Step 4: Payment Configuration<br/>Bank account for SEPA<br/>Payment methods accepted<br/>Billing cycle schedule] G --> H[Step 5: Communication Setup<br/>Email sender address<br/>Upload logo for emails<br/>Customize welcome template] H --> I[Step 6: Access Control<br/>Check-in method selection<br/>QR code / NFC / manual<br/>Working hours for check-in] I --> J[Step 7: User Management<br/>Invite additional admins<br/>Assign roles] J --> K[Step 8: Review and Launch<br/>Summary of all settings<br/>Checklist of completed items] K --> L{All required steps done?} L -->|Yes| M[Organization status: ACTIVE<br/>Ready to accept members] L -->|No| N[Highlight missing items<br/>Allow skip for optional steps] N --> M M --> O[Dashboard<br/>Getting started tips<br/>Quick actions] style A fill:#e3f2fd style M fill:#e8f5e9 style O fill:#e8f5e9

Setup wizard behavior: - Steps are sequential but individually accessible (admin can jump to any step). - Required steps are marked. Optional steps can be skipped and completed later. - Progress indicator shows "Step 3 of 8" with completion percentage. - Each step has contextual help with tooltips, example data, and links to documentation. - The wizard can be exited and resumed. Progress is saved automatically.

Required vs. optional steps:

Step Required Rationale
Organization profile Yes Legal name and address are required for invoices and SEPA mandates
Business settings Yes Currency and timezone affect all financial operations
Membership offers Yes (at least one) Cannot accept members without at least one contract template
Payment configuration Yes (bank account) Cannot process payments without bank details
Communication setup No System uses defaults; customization is optional
Access control No Check-in is not required for basic operation
User management No Single admin is sufficient to start
Review and launch Yes Explicit confirmation before going live

Journey 5: Trainer / Coach Daily Workflow

A trainer uses the app to manage their daily schedule, run classes, track attendance, and communicate with participants. This journey covers a typical day for a fitness instructor or sports coach.

Entry point: App launch, Trainer role active. Prerequisite: Trainer account with assigned classes and schedule. Exit condition: Classes conducted, attendance recorded.

flowchart TD A[Open app as Trainer] --> B[View today's schedule<br/>List of assigned classes] B --> C{Select a class} C --> D[Class detail view<br/>Name, time, location, capacity] D --> E[View registered participants<br/>Name, membership status, notes] E --> F{Class starting?} F -->|Not yet| G[Send reminder notification<br/>to registered participants] F -->|Yes| H[Start class check-in] H --> I{Check-in method} I -->|QR scan| J[Scan member QR codes<br/>at class entrance] I -->|Manual| K[Mark attendance<br/>from participant list] I -->|NFC| L[Members tap NFC<br/>at class reader] J --> M[Attendance recorded<br/>Green checkmark per member] K --> M L --> M M --> N[Class in progress<br/>Real-time attendance counter] N --> O[Class ends] O --> P{Post-class actions} P -->|Record notes| Q[Add class notes<br/>Exercise details, observations] P -->|Report issue| R[Report equipment defect<br/>or room issue] P -->|View stats| S[Attendance rate, trends<br/>Repeat participants] Q --> T[Day summary<br/>Classes conducted, total attendance] R --> T S --> T style A fill:#e3f2fd style M fill:#e8f5e9 style T fill:#e8f5e9

Trainer-specific screens: 1. Schedule -- Weekly/daily calendar view with assigned classes. Color-coded by class type (fitness, yoga, swimming, martial arts). 2. Class detail -- Participants list, capacity indicator, resource assignment (room, equipment). Quick actions: send notification, start check-in, add waitlist member. 3. Attendance -- Real-time checklist with QR/NFC/manual entry. Shows attendance history per participant. 4. Communication -- Send messages to class participants (push notification, in-app message). Templates for common messages (class cancelled, room change, schedule update). 5. Statistics -- Attendance trends, popular time slots, class utilization, repeat rate.

Trainer permissions boundary: - Can view participant names, membership status, and attendance history for their assigned classes only. - Cannot view financial data (payments, bank accounts, contract prices). - Cannot modify member profiles or contracts. - Can report equipment defects and room issues (creates a ticket for the admin). - Can propose schedule changes (submitted as a request to the admin for approval).

Journey 6: Data Import (CSV)

A club admin imports member data from an existing system (spreadsheet, legacy software export, or another platform). The import wizard guides them through file upload, column mapping, conflict resolution, and execution.

Entry point: Admin web app, Data Management > Import. Prerequisite: Admin has a CSV file with member data. Headers may not match the system's field names. Exit condition: Members are created or updated in the system according to the selected import mode.

flowchart TD A[Open Data Import] --> B[Upload CSV file<br/>Drag and drop or browse] B --> C[File validation<br/>Encoding, delimiter, row count] C --> D{Valid file?} D -->|No| E[Show error<br/>Wrong format, too large, etc.] E --> B D -->|Yes| F[Preview first 5 rows<br/>Show detected columns] F --> G[Column mapping<br/>Map CSV columns to system fields] G --> H{All required fields mapped?} H -->|No| I[Highlight missing required fields<br/>Name, email minimum] I --> G H -->|Yes| J[Select import mode] J --> K{Import mode?} K -->|Import new only| L[Skip existing<br/>Create new records] K -->|Import and update| M[Create new + update existing<br/>Match by email] K -->|Update existing only| N[Only update matches<br/>Skip new records] L --> O[Dry run preview<br/>X new, Y skipped, Z errors] M --> O N --> O O --> P{Review results} P -->|Errors found| Q[Show error rows<br/>Invalid email, missing data, etc.] Q --> R[Fix in CSV and re-upload<br/>or skip error rows] R --> O P -->|Acceptable| S[Execute import] S --> T[Processing...<br/>Progress bar with row counter] T --> U[Import complete<br/>X created, Y updated, Z skipped, W errors] U --> V[Download error report<br/>CSV with failed rows and reasons] style A fill:#e3f2fd style U fill:#e8f5e9

Import wizard steps: 1. Upload -- Accept CSV (and optionally XLSX). Detect encoding (UTF-8, ISO-8859-1, Windows-1252) and delimiter (comma, semicolon, tab). Show file metadata: row count, column count, estimated processing time. 2. Column mapping -- Two-column interface: left side shows CSV headers, right side shows system fields (dropdown). Auto-map matching names (case-insensitive, common aliases like "Vorname" -> "First Name"). Required fields highlighted. 3. Mode selection -- Three radio buttons with clear explanations. "Import new only" is the safe default. "Import and update" uses a match key (email by default, configurable). 4. Dry run -- Processes all rows without persisting. Shows counts: new, update, skip, error. Error rows are clickable with specific error messages per field. 5. Execution -- Real-time progress bar. Runs in a background job (via RabbitMQ) so the admin can navigate away. Notification when complete. 6. Results -- Summary statistics. Downloadable error report (CSV with original rows plus error columns). Link to view imported members in the member list (pre-filtered).

Supported fields for import: - Required: First name, Last name, Email - Optional: Phone, Address (street, city, postal code, country), Birthday, Gender, Membership type, IBAN, Custom attributes (mapped to JSONB)

Conflict resolution rules: - Duplicate email in "import new" mode: row is skipped, reported as duplicate. - Duplicate email in "import and update" mode: existing record is updated with non-empty CSV values. Empty CSV cells do not overwrite existing data. - Invalid IBAN: row is imported without bank account, error reported. Admin can add bank account manually later.

Journey 7: Cross-Organization Member Access

A member who belongs to a franchise network visits a different location within the network. Their membership grants access across all participating locations.

Entry point: Member arrives at a franchise location they have not visited before. Prerequisite: Member has an active contract with a franchise-level membership. The visited location is part of the same franchise network. Exit condition: Member is checked in at the new location.

flowchart TD A[Member arrives at<br/>franchise location B] --> B[Open app, Access tab] B --> C[Show QR code] C --> D[Scan QR at Location B turnstile] D --> E{Authorization check} E --> F[Check member contract] F --> G{Contract scope?} G -->|Single location| H[Access denied<br/>Contract valid only at Location A] G -->|Franchise-wide| I[Check entity hierarchy<br/>Is Location B in same franchise?] I --> J{Same franchise network?} J -->|No| K[Access denied<br/>Different franchise] J -->|Yes| L[Check contract status] L --> M{Contract active?} M -->|No| N[Access denied<br/>Contract expired/suspended] M -->|Yes| O[Access granted<br/>Check-in logged at Location B] O --> P[Member enters facility] P --> Q[Location B admin sees<br/>guest check-in in dashboard] H --> R[Show member alternative:<br/>Purchase day pass or<br/>upgrade to franchise membership] style A fill:#e3f2fd style O fill:#e8f5e9 style H fill:#ffcdd2 style K fill:#ffcdd2 style N fill:#ffcdd2

Technical implementation: - The QR code contains a signed token with: member ID, contract ID, home entity ID, and contract scope. - The check-in terminal at Location B calls the central API to verify the token. - The API checks the entity hierarchy: if the member's home entity and the current entity share a common ancestor at or above the contract's scope level, access is granted. - Cross-location check-ins are logged with both the home entity and the visited entity, enabling inter-organization billing reconciliation.

Journey 8: Billing Cycle Execution

An automated billing cycle runs monthly (or at a configured frequency) to generate transactions for all active contracts within an organization. This is a system-initiated journey triggered by the scheduler.

Entry point: Scheduled job trigger (e.g., first day of the month at 02:00 AM). Prerequisite: Organization has active contracts with recurring billing configured. Exit condition: Transactions generated, SEPA file created and ready for submission.

flowchart TD A[Scheduler triggers<br/>billing cycle] --> B[Load all active contracts<br/>with next billing date <= today] B --> C[For each contract:] C --> D{Contract status?} D -->|Active| E[Calculate amount<br/>Base price + adjustments - discounts] D -->|Suspended| F[Skip, log reason] D -->|Cancelled| G[Skip, no further billing] E --> H[Create transaction record<br/>Status: PENDING] H --> I{Payment method?} I -->|SEPA| J[Add to SEPA batch] I -->|Invoice| K[Generate invoice PDF] I -->|Cash| L[Mark for manual collection] J --> M[Update next billing date<br/>on contract] K --> M L --> M M --> C C --> N[All contracts processed] N --> O[Generate SEPA XML file<br/>via Cash360 API] O --> P[Send invoice emails<br/>with PDF attachments] P --> Q[Notify admin<br/>Billing cycle complete] Q --> R[Admin reviews<br/>billing dashboard] R --> S{Issues?} S -->|Failed transactions| T[Review and retry<br/>or create adjustments] S -->|All clean| U[Submit SEPA file<br/>to bank via EBICS] style A fill:#e3f2fd style Q fill:#e8f5e9 style U fill:#e8f5e9

Processing rules: - Billing cycles run per organization (each entity has its own schedule). - Transactions are created in batch with status PENDING. - SEPA transactions are grouped into a single XML file per organization per billing run. - Failed IBAN validation during SEPA batch creation: transaction marked as FAILED, member and admin notified. - Pro-rata calculation for mid-month start dates. - Discount rules applied in order: contract-level discount > membership-type discount > promotional discount. Discounts are not stackable unless configured. - The entire billing cycle runs as a single database transaction with savepoints per contract. A failure on one contract does not roll back others.

Journey 9: Executive KPI Review (Franchise CEO)

A franchise network CEO reviews performance across all locations, identifies underperforming studios, drills into detail, sets up alerts, and exports a board report.

Entry point: Admin web app, Dashboard section. Prerequisite: User has Franchisor Admin or CEO role with access to network-wide dashboards. Exit condition: CEO has reviewed KPIs, set alerts for at-risk metrics, and exported a board report.

flowchart TD A[Login as Franchise CEO] --> B[Network Dashboard loads<br/>Aggregated KPIs across all locations] B --> C[Review key metrics:<br/>Total members, revenue, churn,<br/>growth rate, occupancy] C --> D{Any location<br/>underperforming?} D -->|Yes| E[Click location in ranking table<br/>Drill into location detail] E --> F[View location-specific KPIs<br/>Member count, revenue trend,<br/>churn reason breakdown] F --> G{Root cause identified?} G -->|Yes| H[Add note / action item<br/>for location manager] G -->|No| I[Schedule meeting<br/>with location manager] D -->|No| J[Review trend charts<br/>Month-over-month comparison] J --> K[Configure alerts<br/>Set threshold: churn > 5%/month<br/>Revenue drop > 10%] K --> L[Set alert recipients<br/>Email to CEO + Operations Manager] H --> M[Export board report<br/>PDF with all KPIs + commentary] I --> M L --> M M --> N[Schedule monthly auto-delivery<br/>Every 1st at 08:00] N --> O[Done — report scheduled] style A fill:#e3f2fd style O fill:#e8f5e9

Key screens: 1. Network dashboard — Top-level KPIs with sparklines, location ranking table (sortable), trend charts. 2. Location drill-down — Single-location dashboard with member/revenue/churn/utilization detail. 3. Alert configuration — Metric selector, threshold, comparison (vs. last month / vs. budget), notification recipients. 4. Report builder — Select KPIs to include, add commentary, preview PDF, schedule delivery.

API calls involved: 1. GET /api/v1/admin/reports/network-kpi — Aggregated network metrics 2. GET /api/v1/admin/reports/location-comparison — Location ranking data 3. GET /api/v1/admin/reports/location/{id} — Single-location detail 4. POST /api/v1/admin/alerts — Create alert configuration 5. POST /api/v1/admin/reports/export — Generate PDF report 6. POST /api/v1/admin/reports/schedule — Schedule recurring delivery

Journey 10: Accountant Monthly Close with DATEV

A club treasurer performs the monthly accounting close: reviews auto-generated journal entries from billing, creates manual entries for expenses, reconciles the bank account, exports to DATEV format, and sends the file to the tax advisor.

Entry point: Admin web app, Accounting section. Prerequisite: User has Finance Admin or Club Admin role. Billing cycle for the month has completed. Exit condition: Month is closed, DATEV file exported, and sent to tax advisor.

flowchart TD A[Open Accounting section] --> B[Select period: March 2026] B --> C[Review auto-generated postings<br/>from billing engine] C --> D[List of journal entries:<br/>Membership fees, setup fees,<br/>product sales, refunds] D --> E{All auto-postings correct?} E -->|Yes| F[Proceed to manual entries] E -->|No| G[Edit posting:<br/>Correct account, amount,<br/>or cost center] G --> F F --> H[Create manual entries<br/>Rent, utilities, insurance,<br/>equipment purchase] H --> I[Upload receipt photos<br/>for each expense] I --> J[Assign cost centers<br/>per department] J --> K[Bank reconciliation] K --> L[Import bank statement<br/>MT940/CAMT file from bank] L --> M[Auto-match: system matches<br/>bank transactions to journal entries] M --> N{Unmatched items?} N -->|Yes| O[Manually match or<br/>create new entries] N -->|No| P[Reconciliation complete] O --> P P --> Q[Review P&L summary<br/>Revenue vs. expenses] Q --> R[Close period<br/>No further edits allowed] R --> S[Export to DATEV] S --> T{Format?} T -->|DATEV CSV| U[Generate DATEV CSV<br/>Windows-1252 encoding] T -->|DATEV XML| V[Generate DATEV XML<br/>with schema validation] U --> W[Download file] V --> W W --> X[Send to tax advisor<br/>via email or DATEV portal] X --> Y[Done — month closed] style A fill:#e3f2fd style Y fill:#e8f5e9

Key screens: 1. Journal entries list — Filterable by period, type (auto/manual), status (draft/posted), cost center. Inline editing. 2. Manual entry form — Date, amount, account (with SKR03/SKR04 picker), contra account, description, receipt upload. 3. Bank reconciliation — Split view: bank statement on left, journal entries on right. Drag-and-drop matching. Unmatched items highlighted. 4. P&L summary — Revenue/expense categories with totals. Comparison to previous period and budget. 5. DATEV export wizard — Period selector, format (CSV/XML), chart of accounts (SKR03/SKR04), preview, download.

API calls involved: 1. GET /api/v1/accounting/entries?period=2026-03 — List journal entries for period 2. POST /api/v1/accounting/entries — Create manual journal entry 3. POST /api/v1/accounting/reconciliation/import — Upload bank statement 4. GET /api/v1/accounting/reconciliation/unmatched — List unmatched items 5. POST /api/v1/accounting/period/close — Close accounting period 6. POST /api/v1/accounting/datev-export — Generate DATEV export 7. GET /api/v1/accounting/reports/pl?period=2026-03 — P&L summary

Journey 11: Sales Lead-to-Member Pipeline

A sales/marketing coordinator receives a new lead, qualifies them through the pipeline stages, books a trial session, sends a proposal, and converts the won lead into a full member.

Entry point: Admin web app, CRM section (or notification of new lead). Prerequisite: User has Sales/Marketing Admin or Club Admin role. Exit condition: Lead converted to member with active contract.

flowchart TD A[New lead arrives<br/>Source: website form] --> B[Lead appears in pipeline<br/>Stage: NEW] B --> C[Sales coordinator reviews lead<br/>Name, email, source, interest] C --> D[Log activity: Initial call<br/>Duration, outcome, notes] D --> E{Reached?} E -->|No| F[Schedule follow-up<br/>Try again tomorrow] F --> D E -->|Yes| G[Move to CONTACTED<br/>Discuss membership options] G --> H[Qualify lead<br/>Budget, timeline, needs] H --> I{Qualified?} I -->|No| J[Move to LOST<br/>Reason: not interested / budget] I -->|Yes| K[Move to QUALIFIED<br/>Log qualification notes] K --> L[Book trial session<br/>Create trial contract] L --> M[Move to TRIAL<br/>Send confirmation email] M --> N{Trial completed?} N -->|No show| O[Log activity: no-show<br/>Schedule follow-up call] O --> P{Re-engaged?} P -->|No| J P -->|Yes| L N -->|Attended| Q[Log activity: trial feedback<br/>Positive / needs more time] Q --> R[Create proposal<br/>Select membership plan, price] R --> S[Move to PROPOSAL<br/>Send proposal email] S --> T{Decision?} T -->|Accepted| U[Move to WON<br/>Convert lead to member] U --> V[One-click conversion:<br/>Create Member from Lead data<br/>Create Contract<br/>Setup payment method] V --> W[Welcome email sent<br/>App download link] W --> X[Lead pipeline updated<br/>Conversion tracked for reporting] T -->|Declined| Y[Move to LOST<br/>Record reason: price / timing / competitor] T -->|Thinking| Z[Schedule follow-up<br/>in 3 days] Z --> T style A fill:#e3f2fd style X fill:#e8f5e9 style J fill:#ffcdd2 style Y fill:#ffcdd2

Key screens: 1. Pipeline board — Kanban view with columns per stage. Drag leads between stages. Lead cards show name, source, value, days in stage. 2. Lead detail — Contact info, activity timeline, linked deal, notes. Quick actions: call, email, schedule meeting. 3. Activity log — Chronological list of all interactions. Log new activity with type, subject, notes, next follow-up. 4. Proposal builder — Select membership plan, customize price, generate PDF proposal, send via email. 5. Conversion wizard — Pre-filled member creation form from lead data. Contract selection. Payment method setup.

API calls involved: 1. POST /api/v1/crm/leads — Create lead (or auto-created from web form) 2. PUT /api/v1/crm/leads/{id} — Update lead stage 3. POST /api/v1/crm/activities — Log activity 4. POST /api/v1/crm/deals — Create deal linked to lead 5. POST /api/v1/crm/leads/{id}/convert — Convert lead to member

Journey 12: Support Ticket Lifecycle

A member reports a billing issue through the mobile app. The ticket is auto-categorized, assigned to an agent, resolved with a canned response, and closed after the member confirms satisfaction.

Entry point: Member mobile app → Help → New Ticket. Or: email to support@club.example.com. Prerequisite: Member has an active account. Exit condition: Ticket resolved, member satisfied, CSAT recorded.

flowchart TD A[Member opens app<br/>Help section] --> B[Create new ticket<br/>Category: Billing<br/>Subject: 'Wrong amount charged'<br/>Description with details] B --> C[Ticket created<br/>Status: OPEN<br/>Priority: NORMAL<br/>SLA: respond in 4h, resolve in 24h] C --> D[Auto-assignment<br/>Route to Billing support agent<br/>based on category] D --> E[Agent receives notification<br/>Ticket appears in queue] E --> F[Agent opens ticket<br/>Views member context:<br/>Profile, contracts, transactions] F --> G[Agent identifies issue<br/>Double charge from billing engine] G --> H{Can resolve immediately?} H -->|Yes| I[Agent applies canned response<br/>'Billing adjustment processed'<br/>+ creates adjustment transaction] H -->|No| J[Agent adds internal note<br/>'Need to check with billing team'<br/>Status: WAITING] J --> K[Escalation if SLA at risk<br/>Auto-notify team lead] K --> L[Resolution found<br/>Agent updates ticket] L --> I I --> M[Agent sets status: RESOLVED<br/>Public response sent to member] M --> N[Member receives notification<br/>'Your ticket has been resolved'] N --> O{Member satisfied?} O -->|Yes| P[Member confirms<br/>or ticket auto-closes after 48h] O -->|No| Q[Member reopens ticket<br/>Adds comment explaining issue] Q --> E P --> R[CSAT survey sent<br/>'How was your experience? 1-5'] R --> S[Member rates: 4/5] S --> T[Ticket status: CLOSED<br/>CSAT recorded for analytics] style A fill:#e3f2fd style T fill:#e8f5e9

Key screens (admin side): 1. Ticket queue — List view with filters (status, priority, category, assignee, SLA status). Color-coded SLA indicators (green/yellow/red). 2. Ticket detail — Thread view: member messages + agent responses + internal notes. Member context panel (profile, contracts, transactions). Canned response selector. Status/priority controls. 3. SLA dashboard — Compliance rate, breach count, average response/resolution time. Drill-down by agent, category, time period.

Key screens (member side): 1. Help section — My tickets list + New ticket button + Knowledge base search. 2. Ticket detail — Conversation thread with agent. Status indicator. Reopen button if resolved unsatisfactorily.

API calls involved: 1. POST /api/v1/support/tickets — Create ticket (member or admin) 2. GET /api/v1/support/tickets — List tickets (filtered by role scope) 3. PUT /api/v1/support/tickets/{id}/assign — Assign to agent 4. POST /api/v1/support/tickets/{id}/comments — Add comment (public or internal) 5. PUT /api/v1/support/tickets/{id} — Update status/priority 6. POST /api/v1/support/tickets/{id}/satisfaction — Record CSAT rating

Journey 13: Member QR Door Access

A member arrives at the studio, sees a QR code posted on the door, scans it with their phone camera, and the door unlocks. Alternative path: BLE auto-unlock as the member approaches.

Entry point: Member physically arrives at the studio entrance. Prerequisite: Member has an active contract with access rights to this location. Studio has QR door access or BLE configured. Exit condition: Door unlocked, member enters, check-in logged.

flowchart TD A[Member arrives at studio door] --> B{Access method available?} B -->|QR door access| C[Member sees QR code<br/>posted on door/display] C --> D[Member opens phone camera<br/>Scans QR code] D --> E[Phone opens URL:<br/>mbr.example.com/access/zone-1?token=xyz] E --> F{Member logged in?} F -->|No| G[Redirect to login<br/>Then retry access] F -->|Yes| H[API validates:<br/>JWT valid?<br/>Contract active?<br/>Zone allowed?<br/>Token not expired?<br/>Anti-replay check] B -->|BLE auto-unlock| I[Member has BLE enabled<br/>Phone detects door beacon] I --> J[BLE handshake<br/>Phone sends encrypted credential] J --> H B -->|NFC card| K[Member taps NFC card<br/>at reader] K --> H H --> L{Access decision?} L -->|GRANTED| M[Door unlocks for 5 seconds<br/>Phone shows 'Door unlocked'] L -->|DENIED| N{Denial reason?} N -->|Contract expired| O[Show: 'Your membership has expired'<br/>Link to renew] N -->|Zone not included| P[Show: 'Upgrade required for this area'<br/>Link to upgrade] N -->|Facility at capacity| Q[Show: 'Facility is currently full'<br/>Estimated wait time] N -->|Outside allowed hours| R[Show: 'Access hours: Mon-Fri 06:00-22:00'] M --> S[Check-in recorded<br/>Member + zone + timestamp + method] S --> T[Occupancy updated<br/>Zone count +1] T --> U[Admin dashboard updated<br/>Real-time via WebSocket] U --> V[Member enters facility] style A fill:#e3f2fd style V fill:#e8f5e9 style O fill:#ffcdd2 style P fill:#ffcdd2 style Q fill:#fff3e0 style R fill:#ffcdd2

Technical details: - QR code immutability: The member's personal QR code (displayed in the app or printed on paper/card) is static and does not change. It contains a stable member identifier, not a time-limited token. The security token validation and member association happen server-side when the code is scanned -- the QR code itself is merely a key that the backend resolves to the current member record. This means a QR code printed on a physical membership card remains valid for the lifetime of the membership, without requiring reprinting. - QR rotation (door display): The QR code on the door display (the one the member scans) refreshes every 30 seconds. Each QR contains a time-limited token that prevents screenshot sharing. - Anti-replay: Each door token can only be used once (tracked in Redis with 60-second TTL). - BLE range: Configurable 1-10 meters. Default 3 meters to prevent accidental unlock from the street. - Fallback chain: If BLE fails → show "Scan QR code instead". If QR fails → show "Present NFC card or ask front desk". - Offline resilience: Door controllers cache recent credential validations for 15 minutes. If the server is unreachable, cached credentials are accepted.

API calls involved: 1. GET /api/v1/access/zones/{zoneId}?token={token} — QR door access validation 2. POST /api/v1/access/ble-auth — BLE credential validation 3. POST /api/v1/checkin/process — Check-in recording (all methods) 4. GET /api/v1/access/zones/{zoneId}/occupancy — Current occupancy