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

03 — User Journey (CRM Module)

End-to-end journeys through the CRM. Steps marked (planned) are in docs/IMPLEMENTATION_PLAN.md but not implemented; (forward-looking) depends on infrastructure that does not exist yet (device registry, WS topics).


1. Journey: Walk-in lead capture → conversion (happy path)

Actors: Priya (receptionist) → Aditi (counselor)

  1. Parent walks in asking about Grade 6. Priya opens New Lead, picks entry walk_in (source default).
  2. Fills firstName, lastName, email (required), phone, grade interest → submit.
    • Server: duplicate email → 409 inline (crm.service.ts:42-47); else lead created status: new, emits LeadCreated (crm.service.ts:50-63).
  3. Priya hands off: Aditi opens lead detail, sets assignedTo to herself, logs a follow-up "Called; parent interested in June intake" scheduledAt: +2d.
  4. Next day: leads list filtered by her assignment (status filter exists; assignment filter (planned)) → she sees the lead, calls, sets status: contacted.
  5. School visit happens; Aditi sets status: qualified, adds grade/academicYear/class (lead.schema.ts:64-74).
  6. Aditi taps Convert → confirm dialog → server creates User (+ Student, ADM{timestamp} admission number) and marks lead converted with convertedToStudentId (crm.service.ts:151-164), emits LeadConverted (crm.service.ts:166-173).
  7. Lead list: lead now shows converted badge; detail links to student.

2. Journey: Duplicate / already-in-system

  1. Receptionist types an email that already exists → 409 on submit (crm.service.ts:42-47).
  2. UI shows "A lead with this email already exists" + actions: open existing lead / edit fields. No merge endpoint exists — merge is (planned).

3. Journey: Uninterested lead → closed

  1. Counselor sets status: closed (+ optional closedReason).
  2. Server auto-stamps closedAt when no reason given (crm.service.ts:94-96).
  3. Closed leads remain visible under the status filter (no hard delete anywhere; soft-delete API (planned), base.repository.ts:68-74).
  4. Convert action is disabled for closed leads (server 400 guard, crm.service.ts:123-125).

4. Journey: Admission application → enrollment (happy path)

Actors: applicant (submitted via office) → Aditi → interview panel → admin

  1. Office submits application (POST /crm/admissions) → status submitted, workflow records draft → submitted (admission.service.ts:39-59), emits AdmissionSubmitted.
  2. Aditi adds required documents (TC/marksheet/certificate/photo — admission.schema.ts:27-33) → status auto-advances to documents_pending (admission.service.ts:112-114).
  3. Aditi schedules interview (datetime, panel staff, mode online/offline, feedback later) → status interview_scheduled (admission.service.ts:118-134).
  4. Panel records feedback; Aditi moves status under_review.
  5. Decision: Approve with comment → status approved, decidedAt set, emits AdmissionApproved (admission.service.ts:136-170). Workflow history now shows approver + comment per hop (admission.schema.ts:52-67).
  6. Admin/Aditi converts → User + Student created, status converted + conversion{studentId, convertedAt} (admission.service.ts:172-225), emits AdmissionConverted.
  7. Reminder automation (planned): reminder worker nudges incomplete docs; expiry worker auto-rejects stale (findStale, admission.repository.ts:53-62; IMPLEMENTATION_PLAN.md §1.3).

5. Journey: Rejection / waitlist

  1. Decision reject or waitlist from a decidable status (ADMISSION_DECIDABLE_STATUSES, admission.schema.ts:20-25).
  2. Status becomes terminal-immutable: further edits blocked (admission.service.ts:257-269); convert blocked unless approved (admission.service.ts:174-178).
  3. Emits AdmissionRejected (reject only — waitlist emits no event today).

6. Journey: Campaign-driven leads

  1. Kabir creates campaign (name, type, status, dates) — POST /crm/campaigns (crm.controller.ts:83-87).
  2. Website/print leads arrive with source: campaign (lead.schema.ts:58-59).
  3. Kabir views campaign list (crm.controller.ts:77-81) — no per-campaign lead drill-down today; source-based funnel analytics (planned).
  4. metrics (campaign.schema.ts:45-52) are schema-only; no write endpoint exists → metrics are (planned).

7. Cross-cutting journey points

  • Search (planned): leads join global search (IMPLEMENTATION_PLAN.md §3).
  • Bulk import of leads (planned) (IMPLEMENTATION_PLAN.md §3).
  • Push follow-up reminders (forward-looking): no device registry; WS has no CRM topics — the client polls; reminders surface only in-app today.
  • Coaching conversion (planned): Lead → batch enrollment flow (not class/section) for coaching institutions (IMPLEMENTATION_PLAN.md §6.6).