TorbatYar/docs/crm-phase-6-1.md
Mortezakoohjani 064d67f099 Ship CRM Core Platform (phases 6.0–6.3) with docs and prod deploy.
Add the Sales CRM service through collaboration, sync architecture/registry docs, expose crm.torbatyar.ir, and include a production deploy script.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 20:32:00 +03:30

7.0 KiB
Raw Blame History

Phase 6.1 — Enterprise CRM Core Business Entities

Field Value
Status Complete
Module crm
Version 0.6.1.0
Database crm_db
Migration 0002_phase_61_entities
Depends On Phase 6.0

Goal

Implement the Sales CRM core business entities only: leads, contacts, organizations, lookups, tags, addresses, custom fields, notes, attachments (file references), and audit.

Out of scope: Workflow, Automation, Customer360, Marketing, Communication, Helpdesk, Analytics, AI, Accounting / Restaurant / Marketplace integrations.

Created Models

Core aggregates (expanded)

Model Table Notes
Lead leads lead_number, names, company, phones, source/status refs, owner, priority, soft delete, actors
Contact contacts personal/business, multi phone/email JSON, social links, birthday, soft delete
Organization organizations company/branch/department, legal/trade names, tax IDs, parent org, soft delete

Lookups

Model Table
LeadSource lead_sources
LeadStatusDefinition lead_statuses
ContactType contact_types
OrganizationType organization_types
OrganizationIndustry organization_industries

Supporting

Model Table
LeadAssignment lead_assignments
CrmTag crm_tags
LeadTag / ContactTag / OrganizationTag lead_tags, contact_tags, organization_tags
CrmCustomField / CrmCustomFieldValue crm_custom_fields, crm_custom_field_values
CrmAddress crm_addresses
CrmNote / CrmNoteVersion crm_notes, crm_note_versions
CrmAttachment crm_attachments (file_storage_id only)
CrmAuditLog crm_audit

Phase 6.0 aggregates retained: Pipeline, PipelineStage, Opportunity, SalesActivity, Quote.

Relationships

UUID references within crm_db only (no SQLAlchemy relationship graphs between aggregates):

  • Lead → lead_source_id, lead_status_id, contact_id, organization_id
  • Contact → contact_type_id, organization_id
  • Organization → organization_type_id, organization_industry_id, parent_organization_id
  • Addresses / Notes / Attachments / CustomFieldValues → (entity_type, entity_id)
  • Tag join tables → entity id + tag_id
  • Attachment → file_storage_id (File Storage service contract)

ER Diagram

erDiagram
    LEAD ||--o{ LEAD_ASSIGNMENT : assigns
    LEAD ||--o{ LEAD_TAG : tagged
    CONTACT ||--o{ CONTACT_TAG : tagged
    ORGANIZATION ||--o{ ORGANIZATION_TAG : tagged
    CRM_TAG ||--o{ LEAD_TAG : used
    CRM_TAG ||--o{ CONTACT_TAG : used
    CRM_TAG ||--o{ ORGANIZATION_TAG : used
    LEAD_SOURCE ||--o{ LEAD : sources
    LEAD_STATUS ||--o{ LEAD : statuses
    CONTACT_TYPE ||--o{ CONTACT : types
    ORGANIZATION_TYPE ||--o{ ORGANIZATION : types
    ORGANIZATION_INDUSTRY ||--o{ ORGANIZATION : industries
    ORGANIZATION ||--o{ ORGANIZATION : parent
    CRM_CUSTOM_FIELD ||--o{ CRM_CUSTOM_FIELD_VALUE : values
    LEAD ||--o{ CRM_ADDRESS : addresses
    LEAD ||--o{ CRM_NOTE : notes
    CRM_NOTE ||--o{ CRM_NOTE_VERSION : versions
    LEAD ||--o{ CRM_ATTACHMENT : attachments
    LEAD ||--o{ CRM_AUDIT : audited

Business Rules

  • Lead number unique per tenant; auto-generated when omitted (LEAD-XXXXXXXXXX)
  • Lead owner required
  • Soft delete + restore for Lead / Contact / Organization / Address / Note / Attachment
  • Organization name unique per tenant; parent cannot be self
  • Attachment stores reference only (no binary in CRM)
  • Notes are versioned on body update
  • Custom fields are per-tenant and per-entity with typed validation

Validation Rules

Area Rules
Email RFC-ish format, lowercased
Phone / Mobile 530 chars of digits/spaces/+()-
Owner non-empty
Lead status known enum / status definition
Amount non-negative
Custom fields type match; required; select option membership
Attachment file_storage_id + file_name required
Address line1 required

Events

Event When
crm.lead.created / crm.lead.updated Lead create/update
crm.contact.created Contact create
crm.organization.created Organization create
crm.note.created Note create
crm.attachment.added Attachment reference create

Permissions

crm.leads.*, crm.contacts.*, crm.organizations.*, crm.notes.*, crm.attachments.*, crm.customfields.* (+ existing 6.0 trees).

API Endpoints

Area Paths
Leads POST/GET/PATCH /api/v1/leads, /assign, /delete, /restore
Contacts POST/GET/PATCH /api/v1/contacts, /delete
Organizations POST/GET/PATCH /api/v1/organizations, /delete
Lookups /api/v1/lookups/lead-sources|lead-statuses|contact-types|organization-types|organization-industries
Tags /api/v1/tags, /tags/leads|contacts|organizations/{id}
Addresses /api/v1/addresses
Notes /api/v1/notes
Attachments /api/v1/attachments
Custom fields /api/v1/custom-fields, /custom-fields/values
Audit /api/v1/audit

Migration Summary

  • Alembic revision 0002_phase_61_entities (down_revision 0001_initial)
  • Expands metadata via create_all for additive tables/columns on fresh installs
  • Indexes on tenant + status/email/owner/entity polymorphic keys
  • Unique constraints: lead_number, org name, lookup codes, tag names, custom field keys

Services / Repositories / Validators

Service Repository
LeadService LeadRepository (+ LeadAssignmentRepository)
ContactService ContactRepository
OrganizationService OrganizationRepository
AddressService CrmAddressRepository
TagService CrmTagRepository + join repos
CustomFieldService CrmCustomField* repositories
AttachmentService CrmAttachmentRepository
NoteService CrmNote* repositories
AuditService CrmAuditLogRepository
LookupService lookup repositories

Validators live in app/validators/ (lead/contact/org/address/tag/custom field/attachment rules).

Tests Executed

  • Model / architecture / dependency
  • Repository / service / validation / audit
  • API / permission / migration / tenant isolation
  • Documentation validation

Known Limitations

  • File Storage resolve is contract-only (FileStorageProvider); no live S3/upload in CRM
  • Multi phone/email stored as JSON arrays (not separate child tables)
  • Schema evolution on already-applied 6.0 Postgres may need operational ALTER if 0001 ran with old columns only
  • No Automation / Customer360 consumption yet

Next Phase

Phase 6.2 completed — see crm-phase-6-2.md. CRM Core Platform complete through crm-phase-6-3.md.