# CRM Architecture

Date: 2026-05-21

Status: Phase 4 CRM Core foundation, medium safe scope.

## Scope

This phase delivers an operational CRM Core, not marketing automation.

Current scope includes:

- CRM dashboard
- manual lead entry
- lead list and lead detail
- assignment workflow
- stage history
- follow-up tasks
- CRM activity timeline
- safe event-driven ingestion from already wired lifecycle events

Out of scope for this phase:

- direct enrollment mutations
- direct payment mutations
- direct attendance mutations
- marketing automation and campaigns
- broad rewrites of legacy registration or finance workflows

## Ownership

CRM owns:

- `crm_leads`
- `crm_tasks`
- `crm_activities`
- `crm_stage_history`
- lead assignment
- CRM stage transitions
- follow-up scheduling inside CRM

CRM does not own:

- `enrollments`
- `payments`
- `attendance_records`
- WhatsApp conversations or message transport

CRM may link to those modules, but it must not mutate their workflow state directly.

## Pipelines

### Student Enrollment Pipeline

- `new`
- `interested`
- `qualified`
- `course_recommended`
- `enrollment_started`
- `deposit_pending`
- `confirmed`
- `attended`
- `completed`
- `lost`

### Corporate / B2B Pipeline

- `new`
- `contacted`
- `qualified`
- `proposal_sent`
- `negotiation`
- `agreement_pending`
- `active`
- `won`
- `lost`

### Webinar / Event Pipeline

- `registered`
- `reminded`
- `attended`
- `followup_pending`
- `converted`
- `lost`

## Core Screens

### `/admin/crm`

Provides:

- total leads
- unassigned leads
- my leads
- overdue followups
- my open tasks
- stage distribution
- pipeline distribution
- overdue task snapshot

### `/admin/crm/leads`

Provides:

- searchable lead list
- filtering by pipeline
- filtering by stage
- assignment filters: all / mine / unassigned
- operational priority cues: `hot`, `warm`, `normal`

### `/admin/crm/leads/create`

Provides manual CRM lead entry with:

- pipeline
- stage
- source
- contact info
- optional assignee
- notes

### `/admin/crm/leads/{lead}`

Provides:

- lead profile
- linked entity shortcuts when policies allow access
- assignment update
- stage update
- stage history
- follow-up task creation
- task completion
- task snooze
- task reschedule with reason
- manual internal notes
- CRM activity timeline

### `/admin/crm/tasks`

Provides:

- my task queue by default
- optional all-task visibility for broader CRM managers
- queue filters: open / overdue / completed
- search by task title, description, or linked lead

## Event Integration

Current CRM listeners are intentionally narrow and safe:

- `WhatsAppLeadCreated`
  - creates one CRM lead for a newly created WhatsApp-origin B2B lead
- `B2bLeadConverted`
  - links the CRM lead to the resulting organization
  - records CRM conversion activity
- `WhatsAppReplySent`
  - records CRM activity only
- `EnrollmentCreated`
  - creates one student CRM lead for an enrollment that enters the safe messaging seam
- `PaymentConfirmed`
  - advances the linked student CRM lead to `confirmed`
  - records CRM payment confirmation activity
- `EnrollmentConfirmed`
  - reacts to the new domain contract emitted from the current payment confirmation seam
  - ensures the linked student CRM lead is in `confirmed` when needed
  - records one lifecycle confirmation activity without mutating enrollment state directly
- `StudentNoShowDetected`
  - reacts to the new domain contract emitted from the current attendance completion seam for first-session absences
  - creates one CRM `no_show_recovery` task when the lead is already assigned
  - records CRM activity without mutating attendance state directly
- `DepositPaymentApproved`
  - reacts to the domain contract emitted from the current deposit approval seam in `PaymentObserver`
  - creates one CRM `payment_reminder` task when a confirmed deposit still leaves an outstanding balance and the lead is already assigned
  - records CRM activity without mutating enrollment or finance state
- `EventRegistrationCreated`
  - creates one webinar/event CRM lead on the current safe event funnel seam
  - links CRM visibility to the source event registration without mutating event state
- `WebinarAttended`
  - advances the linked webinar/event CRM lead to `attended`
  - records CRM activity when attendance is confirmed on the safe event funnel seam
- `WebinarNoShowDetected`
  - advances the linked webinar/event CRM lead to `followup_pending` unless it is already terminal
  - creates one CRM no-show recovery task when the lead is already assigned
  - records CRM activity when a webinar/event no-show is marked on the safe event funnel seam

Planned integrations remain documented but not wired yet:

- `AttendanceMarked`

## Idempotency

CRM listeners use `ListenerIdempotency` and stable keys:

- one CRM lead per safe WhatsApp-created B2B lead
- one CRM conversion activity per B2B conversion event
- one CRM reply activity per WhatsApp outbound message
- one CRM lead per enrollment on the current safe enrollment seam
- one CRM confirmation activity per confirmed payment on the current safe payment seam
- one CRM enrollment confirmation lifecycle activity per confirmed enrollment on the current safe registration seam
- one CRM deposit follow-up activity per approved deposit payment on the current safe payment observer seam
- one CRM first-session no-show recovery activity per enrollment/session pair on the current safe attendance seam
- one CRM lead per event registration on the current safe event funnel seam
- one CRM attendance activity per webinar/event registration on the current safe attendance seam
- one CRM no-show recovery update per webinar/event registration on the current safe no-show seam

## Assignment Rules

- assignment is a CRM-owned operation
- assignment changes are logged in CRM activities
- broader visibility is permission-driven
- support users can work inside CRM only within granted permissions

## Task Rules

- tasks are CRM-owned follow-up records
- creating a task updates `next_followup_at`
- completing the last open task clears `next_followup_at`
- snoozing or rescheduling a task recalculates `next_followup_at`
- task creation and completion both log CRM activities

## Operational Priority Cues

CRM now exposes a lightweight visual priority layer for triage only. It does not change workflow state and it is not a sales scoring engine.

- `hot`
  - follow-up overdue
  - or lead is in an operationally sensitive stage such as `deposit_pending`, `followup_pending`, `proposal_sent`, or `agreement_pending`
- `warm`
  - follow-up due within 24 hours
  - or lead is still unassigned
- `normal`
  - all other visible leads

These cues are used in:

- the dashboard hot-leads panel
- the CRM lead list priority column

The rule set is intentionally simple so teams can understand why a lead appears as urgent without inspecting hidden scoring logic.

## Security

Permissions used in this phase:

- `crm.view`
- `crm.manage`
- `crm.assign`
- `crm.tasks.manage`
- `crm.pipeline.manage`

Guardrails:

- routes are permission-protected
- Livewire mutating actions call `authorize()`
- CRM changes happen through Actions, not direct heavy writes inside the UI
- `app:architecture-check` now flags forbidden CRM cross-module writes

## Future Automation Readiness

This CRM Core is ready for later additions such as:

- automatic task generation
- conversion reminders
- abandoned enrollment recovery
- no-show recovery queues
- webinar conversion follow-ups

Those future automations should attach through lifecycle events and listeners, not by embedding side effects into UI screens.
