# CRM Plan — Current Status

> Load this file first. It gives you the implementation state and next action.
> Last updated: planning phase — Phase 0 not yet started.

---

## Status Snapshot

| Phase | Status | Notes |
|-------|--------|-------|
| Phase 0 — Scaffolding | ⏳ Not started | Directory trees + PSR-4 + module registration |
| Phase 1 — Engine Foundations | ⏳ Not started | 16 migrations + 6 engines + 5 packs + setup:crm |
| Phase 2 — v1 CRM End-to-End | ⏳ Not started | Lead, Deal, Contact, Activity modules + Kanban |
| Phase 3 — Admin UIs | ⏳ Deferred | WorkflowEngine UI, Pipeline builder, Proposal UI |

---

## Architecture in One Paragraph

`CoreApp` is a single headless nwidart module containing 6 engines (FieldEngine, PipelineEngine,
ActivityEngine, WorkflowEngine, EntityEngine, LabelEngine). It has no Inertia pages, no sidebar entries.
`CrmApp` contains 5 application modules (Lead, Deal, Pipeline, Contact, Activity) each as a separate
nwidart module with full MVC stacks. Feature packs (JSON files) configure custom fields, pipelines,
and workflow rules per product profile. `setup:crm --profile=<slug>` provisions a tenant end-to-end.

---

## File Map

| Concern | File |
|---------|------|
| Architecture diagram + module tree | [`_core/architecture.md`](_core/architecture.md) |
| DB scope — all 16 tenant tables | [`_core/database.md`](_core/database.md) |
| Risk register (5 risks) | [`_core/risks.md`](_core/risks.md) |
| CRM-specific coding conventions | [`_core/conventions.md`](_core/conventions.md) |
| FieldEngine spec | [`engines/field-engine.md`](engines/field-engine.md) |
| PipelineEngine spec | [`engines/pipeline-engine.md`](engines/pipeline-engine.md) |
| ActivityEngine spec | [`engines/activity-engine.md`](engines/activity-engine.md) |
| WorkflowEngine + loop guard | [`engines/workflow-engine.md`](engines/workflow-engine.md) |
| EntityEngine spec | [`engines/entity-engine.md`](engines/entity-engine.md) |
| LabelEngine spec | [`engines/label-engine.md`](engines/label-engine.md) |
| FeaturePackSeeder code | [`packs/overview.md`](packs/overview.md) |
| Default CRM pack | [`packs/default.md`](packs/default.md) |
| Education pack | [`packs/education.md`](packs/education.md) |
| Real Estate pack | [`packs/real-estate.md`](packs/real-estate.md) |
| Pharma pack | [`packs/pharma.md`](packs/pharma.md) |
| Garments pack | [`packs/garments.md`](packs/garments.md) |
| setup:crm command + product profiles | [`setup.md`](setup.md) |
| Lead module (full spec) | [`modules/lead.md`](modules/lead.md) |
| Deal module + Kanban | [`modules/deal.md`](modules/deal.md) |
| Pipeline read-only endpoint | [`modules/pipeline.md`](modules/pipeline.md) |
| Contact CRM view | [`modules/contact.md`](modules/contact.md) |
| Activity timeline + feed | [`modules/activity.md`](modules/activity.md) |
| Phase 0 checklist | [`phases/phase0.md`](phases/phase0.md) |
| Phase 1 checklist | [`phases/phase1.md`](phases/phase1.md) |
| Phase 2 checklist | [`phases/phase2.md`](phases/phase2.md) |
| Phase 3 deferred items | [`phases/phase3.md`](phases/phase3.md) |

---

## 5 Product Profiles

| Profile slug | Pack | Lead label | Deal label | Contact label |
|-------------|------|-----------|-----------|--------------|
| `taskco-crm-general` | `default_crm_pack` | Lead | Deal | Contact |
| `taskco-crm-education` | `education_pack` | Application | Enrollment | Student |
| `taskco-crm-realstate` | `real_estate_pack` | Enquiry | Property Deal | Client |
| `taskco-crm-pharma` | `pharma_pack` | Doctor | Order | Contact |
| `taskco-crm-garments` | `garments_pack` | Buyer | Order | Buyer Contact |

---

## Key Architectural Decisions (locked)

1. **Hybrid storage**: Searchable fields (`preferred_country`, `preferred_study_level`, `score`, `country`) are REAL columns in migrations. `is_searchable: true` in pack JSON = documentation only.
2. **WorkflowEngine loop guard**: `static array $running` in `WorkflowDispatcher`. Key = `event:morphClass:id`. Check before dispatch, clear in `finally`. No exceptions.
3. **Additive-only seeders**: `FeaturePackSeeder` never deletes rows. `updateOrCreate` everywhere. Re-running is always safe.
4. **Lead conversion transaction**: `DB::transaction` wraps entire convert(). `LeadConverted` event fires in `DB::afterCommit()`. Never outside the transaction.
5. **Redirect rule**: Every Inertia-facing mutation returns `redirect()`. Never `response()->json()` from non-AJAX routes.
6. **LabelResolver cache**: `once()` per request. Never queries inside Blade/TSX loops. Shared via `HandleInertiaRequests::share()`.

---

## Next Action

Start **Phase 0**. Read [`phases/phase0.md`](phases/phase0.md) and create directory structure.

Quick command to verify after Phase 0:
```bash
php artisan module:list | grep -E 'CoreApp|CrmApp'
```
