Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

09 — User Behaviour (CRM Module)

Behavioral expectations and mental models for CRM users; interaction patterns, error handling, and habits. Shared interaction conventions: 00-shared/08_Interaction_&_Motion.md.


1. Mental model: "a pipeline, not a folder"

Counselors think in stages (new → contacted → qualified → converted | closed). The UI must make the current stage and the next stage obvious on every lead row (status chip + next follow-up). Status is a statement of progress, not a tag: changes are deliberate (confirm on convert; reason on close).

2. Capture cadence (reception)

  • Fast entry is sacred: 3 required fields, everything else optional (08 §2); source pre-set by entry context (walk-in desk → walk_in).
  • Duplicate-email 409 must be inline and actionable, not a dead end — the receptionist cannot improvise while a parent waits (crm.service.ts:42-47).
  • Habit: after create → immediately offered "Add follow-up" from the detail view (post-create sheet with prefilled date +2 days).

3. Follow-up discipline

  • Mental model: every lead has a next action date. Derived client-side from the earliest uncompleted followUps[].scheduledAt (lead.schema.ts:28-31) — no dedicated field exists (gap; see 12_API_Mapping.md §7).
  • Overdue follow-ups surface as error-toned rows in S1; the day's queue = filter by status + client "overdue first" sort (client-side only today).
  • Completed follow-ups must be visibly checkable (timeline checkmark) — the distinction scheduled/completed drives trust.
  • (forward-looking): push reminder on due date (needs device registry).

4. Status transitions (server-enforced)

FromToRuleSource
anyconvertedvia Convert action only; blocked if already converted or closedcrm.service.ts:120-125
anyconvertedgrade + academic year + class must be setcrm.service.ts:145-149
anyclosedallowed; closedAt auto-stamp when no reasoncrm.service.ts:94-96
closedanythingnot possible (no reopen endpoint)

UI mirrors these rules as disabled buttons + tooltips, but server 400s are mapped to copy (rule drift handling). Users learn: converted and closed are terminal.

5. Admission decisions: terminal states

  • Deciding is a commitment: closed statuses (approved/rejected/waitlisted/ converted) are immutable (admission.service.ts:257-269). Warnings in S9 copy this explicitly; reject says "Application closes permanently."
  • Decision only from decidable statuses (admission.schema.ts:20-25) — UI hides the dialog otherwise.
  • The workflow timeline is the trust artifact: approver + comment per hop (admission.schema.ts:52-67) — surfaced read-only on S6.

6. Error-handling behaviours

SituationUser expectationContract
Duplicate lead emailClear "already exists" + path forward409 (crm.service.ts:42-47)
Convert preconditions missingKnow which field to fix400 exact message (crm.service.ts:145-149)
Convert already-converted/closedAction disabled with reason400 (crm.service.ts:120-125)
Edit closed admissionForm locked, banner explains400 (admission.service.ts:257-269)
Decision from wrong statusDialog not offered400 (admission.service.ts:141-145)
Cross-tenant id"Not found" — never existence leak404 (base.repository.ts:20-30)
OfflineBanner + cached list + no writes (CRM has no offline write queue; writes require connectivity)00-shared/07 §10
Rate limitCountdown, no auto-retry429 (00-shared/07 §4)

7. Sorting & scanning expectations

  • Default order: newest first (leads/campaigns by createdAt, admissions by submittedAtlead.repository.ts:31, admission.repository.ts:29).
  • Users scan by status chip + follow-up date; a sort by next-follow-up is the top (proposed) enhancement (server sort param (planned)).

8. Confirmation thresholds

ActionConfirm?Rationale
Create lead/admission/campaignNolow cost, reversible via edit
Update lead fieldsNo (inline save)cheap
Status → closedSoft: reason field, no modalreversible-in-record, but terminal-ish
Convert lead/admissionYes (modal)creates User + Student records, irreversible (crm.service.ts:118-176)
Decision approve/reject/waitlistYes (modal)terminal + immutable (admission.service.ts:136-170)
Add follow-upNocheap, append-only

9. Habit loops

  1. Daily queue: open Leads → status filter → work overdue-first → log follow-up → next contact.
  2. Weekly funnel check: Admissions → stats header (conversion rate) → status counts → chase stale applications (reminder worker (planned) automates).
  3. Campaign review: Campaigns list → compare lead metrics per campaign → adjust spend (metrics write path (planned)).

10. Anti-patterns to design out

  • Paper-slip duplication (409 catch + fast capture).
  • Re-keying identity at conversion (server derives User/Student from lead fields — UI must not re-ask).
  • Ghost pipelines: every lead always visible under some status filter; closed leads are inspectable, never silently deleted (no delete endpoint today; soft-delete (planned)).
  • Waiting on pages: all writes show explicit in-flight state; no silent double submits.