Skip to main content

CRM Module

🎯 Overview​

internal/api/v1/crm powers DashClicks' customer relationship management stack. It combines ten focused services that orchestrate contacts, deals, pipelines, reminders, and automations while enforcing account-level permissions, owner visibility rules, and data hygiene workflows. Controllers keep HTTP concerns thin; almost all business decisions live inside the service layer.

The module exposes /v1/crm/* routes, backs the dashboard CRM experience, and feeds reporting as well as downstream automation systems (notifications, queue-manager jobs, warehouse exports).

πŸ“ Directory Structure​

internal/api/v1/crm/
β”œβ”€β”€ .gitignore
β”œβ”€β”€ index.js # Router bootstrap that mounts entity routers
β”œβ”€β”€ README.md # Developer setup guide specific to CRM module
β”œβ”€β”€ controllers/ # Express controllers (automation, contact, deal, ...)
β”‚ β”œβ”€β”€ automation.controller.js
β”‚ β”œβ”€β”€ contact.controller.js
β”‚ β”œβ”€β”€ deal.controller.js
β”‚ β”œβ”€β”€ field.controller.js
β”‚ β”œβ”€β”€ import.controller.js
β”‚ β”œβ”€β”€ index.js
β”‚ β”œβ”€β”€ note.controller.js
β”‚ β”œβ”€β”€ pipeline.controller.js
β”‚ β”œβ”€β”€ reminder.controller.js
β”‚ └── tag.controller.js
β”œβ”€β”€ routes/ # Router definitions + middleware wiring per entity
β”‚ β”œβ”€β”€ automation.route.js
β”‚ β”œβ”€β”€ contact.route.js
β”‚ β”œβ”€β”€ deal.route.js
β”‚ β”œβ”€β”€ field.route.js
β”‚ β”œβ”€β”€ import.route.js
β”‚ β”œβ”€β”€ index.js
β”‚ β”œβ”€β”€ note.route.js
β”‚ β”œβ”€β”€ pipeline.route.js
β”‚ β”œβ”€β”€ reminder.route.js
β”‚ β”œβ”€β”€ stage.route.js
β”‚ └── tag.route.js
β”œβ”€β”€ services/ # Business logic layer (contact.service.js, etc.)
β”‚ β”œβ”€β”€ automation.service.js
β”‚ β”œβ”€β”€ contact.service.js
β”‚ β”œβ”€β”€ deal.service.js
β”‚ β”œβ”€β”€ field.service.js
β”‚ β”œβ”€β”€ import.service.js
β”‚ β”œβ”€β”€ index.js
β”‚ β”œβ”€β”€ note.service.js
β”‚ β”œβ”€β”€ pipeline.service.js
β”‚ β”œβ”€β”€ reminder.service.js
β”‚ β”œβ”€β”€ stage.service.js
β”‚ └── tag.service.js
β”œβ”€β”€ tests/ # Jest suites (service/controller specs + fixtures)
β”‚ β”œβ”€β”€ automation.test.js
β”‚ β”œβ”€β”€ contact.test.js
β”‚ β”œβ”€β”€ deal.test.js
β”‚ β”œβ”€β”€ field.test.js
β”‚ β”œβ”€β”€ note.test.js
β”‚ β”œβ”€β”€ pipeline.test.js
β”‚ β”œβ”€β”€ reminder.test.js
β”‚ β”œβ”€β”€ stage.test.js
β”‚ β”œβ”€β”€ tag.test.js
β”‚ └── fixtures/
β”‚ └── field.js
β”œβ”€β”€ utils/ # Shared helpers (contact/deal/pipeline mappers, expansions)
β”‚ β”œβ”€β”€ automation.js
β”‚ β”œβ”€β”€ contact.js
β”‚ β”œβ”€β”€ deal.js
β”‚ β”œβ”€β”€ field.js
β”‚ β”œβ”€β”€ index.js
β”‚ β”œβ”€β”€ pipeline.js
β”‚ └── stage.js
└── validations/ # Joi schemas by domain (contact/, deal/, reminder/, ...)
β”œβ”€β”€ index.js
β”œβ”€β”€ automation/
β”‚ └── index.js
β”œβ”€β”€ contact/
β”‚ β”œβ”€β”€ attachment.js
β”‚ β”œβ”€β”€ filter.js
β”‚ β”œβ”€β”€ getAll.js
β”‚ β”œβ”€β”€ index.js
β”‚ β”œβ”€β”€ search.js
β”‚ β”œβ”€β”€ business/
β”‚ β”‚ β”œβ”€β”€ business-put.js
β”‚ β”‚ β”œβ”€β”€ business.js
β”‚ β”‚ β”œβ”€β”€ get.js
β”‚ β”‚ β”œβ”€β”€ getAll.js
β”‚ β”‚ └── index.js
β”‚ └── person/
β”‚ β”œβ”€β”€ get.js
β”‚ β”œβ”€β”€ getAll.js
β”‚ β”œβ”€β”€ index.js
β”‚ β”œβ”€β”€ person-put.js
β”‚ └── person.js
β”œβ”€β”€ deal/
β”‚ └── index.js
β”œβ”€β”€ field/
β”‚ └── index.js
β”œβ”€β”€ import/
β”‚ └── index.js
β”œβ”€β”€ note/
β”‚ └── index.js
β”œβ”€β”€ pipeline/
β”‚ └── index.js
β”œβ”€β”€ reminder/
β”‚ └── index.js
β”œβ”€β”€ stage/
β”‚ └── index.js
└── tag/
└── index.js

Each subdirectory mirrors the service names below; there are no Git-tracked models/ or utilities/ folders here because Mongoose models and helpers are copied from shared/ at build time (see repository guide).

πŸ—„οΈ MongoDB Collections​

πŸ“š Full Schema: See Database Collections Documentation

Core Entities​

  • crm.contacts β†’ person/business records with embedded addresses, custom fields, attachments
  • crm.deals β†’ pipeline-bound opportunities with stage, owner, value, and automation flags
  • crm.pipeline / crm.pipeline.stages β†’ pipeline definitions, stage ordering, automation metadata
  • crm.activity β†’ audit log of notes, reminders, stage changes (read via utilities)
  • crm.reminders β†’ scheduled follow-ups and tasks
  • crm.notes β†’ entity notes + threaded comments
  • crm.tags β†’ account-scoped tagging taxonomy

Supporting Collections​

  • _accountsβ†’ sub-account linkage and configuration
  • crm.contact.import.results β†’ status + diagnostics for import jobs
  • queues β†’ background jobs spawned by CRM services (imports, mass linking, automations)
  • automation.logs β†’ execution history for stage automations

πŸ—οΈ Architecture Overview​

Key Responsibilities​

  • Normalise and secure CRUD for CRM entities under strict account/owner scoping
  • Link contacts ↔ deals ↔ pipelines for reporting and automation triggers
  • Provide mass operations (bulk delete, export, import) backed by queues
  • Surface analytics endpoints (new contacts, pipeline leaderboards, automation logs)

Design Decisions​

  • Service-first pattern: Controllers defer to services; tests target services directly
  • Owner visibility enforcement: Most queries branch on is_owner flag and account preferences
  • Mongoose aggregations: Heavy pipelines compute filtered lists, analytics, exports
  • Background work: Expensive flows push jobs into Queue or Google Pub/Sub
  • Shared utilities: utils/contact|deal|pipeline supply reusable expansion, mapping, tag validation, timezone helpers

πŸ”— Submodules​

DomainDocWhat it covers
ContactsπŸ‘₯ ContactsPeople & businesses, linking, exports, mass updates
DealsπŸ’Ό DealsPipeline-scoped opportunities, attachments, automation flags
PipelinesπŸ”„ PipelinesPipeline CRUD, analytics, automation logs
Stagesβš™οΈ StagesPer-pipeline stage CRUD and automation snapshots
AutomationπŸ€– AutomationStage-triggered workflow definitions and lifecycle
NotesπŸ“ NotesNotes, comments, activity fan-out
Reminders⏰ RemindersTask queues, categorisation, completion rules
TagsπŸ”– TagsTag CRUD, locking, bulk removal side-effects
Fields🧩 FieldsCustom property configuration + user layout alignment
ImportπŸ“₯ ImportCSV/connector ingestion and queue orchestration

πŸ”„ Data Flow​

flowchart TD
subgraph Contact Intake
A[Create/Import Request] --> B{Validate + Map}
B -->|pass| C[Persist Contact]
C --> D[Expand/Enrich]
D --> E[Queue Background Work]
end
subgraph Deal Lifecycle
F[Deal Mutations] --> G[Pipeline Stage Logic]
G --> H{Automation?
Stage change?}
H -->|yes| I[Trigger Jobs + Logs]
G --> J[Currency Normalisation]
end
C -. links .-> F
E --> K[Queue Collection]
I --> L[automation.logs]
K --> M[Queue Manager]
M --> N[Notifications / Imports / Mass updates]

πŸ” Configuration & Dependencies​

VariableDescriptionRequired
BASE_CURRENCYFallback currency for deal/pipeline conversionsβœ…
GOOGLE_CLOUD_PROJECT_IDPub/Sub project used by import serviceβœ… (imports)
APP_SECRETJWT secret for internal socket notifications (contact linking)βœ… (contacts)
CONVERSATION_SOCKETBase URL for socket emit service when notifying supportβœ… (contacts)

External Services​

  • Wasabi S3 via shared/utilities/wasabi for contact exports + attachment cleanup
  • Google Pub/Sub for asynchronous imports (CSV + connectors)
  • Queue Manager for mass association jobs, automation retries, reminder fan-out
  • Currency util uses shared exchanger to display pipeline totals consistently

πŸš€ Quick Start​

  1. Install shared dependencies: pnpm install (root) followed by npm run dev:build as outlined in repo guide.
  2. Start CRM service through VS Code debug configuration β€œInternal API – CRM”. This ensures symlinked models/utilities and proper env injection.
  3. Seed required configs: confirm BASE_CURRENCY, Pub/Sub credentials, and Wasabi keys exist in environment.
  4. Run targeted tests before shipping changes: pnpm test --filter crm (integration suites cover controllers + services).
  5. Copy shared models if editing shared/ dependencies: npm run copySharedFiles.
πŸ’¬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM