Database¶
Implementação real¶
O CRM usa Django ORM sobre PostgreSQL. As entidades de negócio usam UUID como chave primária por meio de apps.core.models.BaseModel; User, Role, AuditLog e HistoricoEtapaOportunidade possuem estruturas próprias. O catálogo abaixo foi conferido nos models.py do repositório coreflow-crm.
Diagrama entidade-relacionamento¶
Nota, Atividade e Tarefa possuem relacionamentos opcionais por colunas explícitas (conta, contato, lead e/ou oportunidade); o banco não usa GenericForeignKey. Lead mantém os vínculos de conversão para conta, contato e oportunidade com SET_NULL.
Tabelas e chaves¶
| Modelo | Tabela | Chave | Observações de integridade |
|---|---|---|---|
Role |
accounts_role |
id bigint |
name único |
User |
accounts_user |
id bigint |
role opcional, PROTECT |
Conta |
contas_conta |
id UUID |
responsavel opcional, PROTECT |
Contato |
contatos_contato |
id UUID |
no máximo um principal por conta |
Lead |
leads_lead |
id UUID |
responsável obrigatório; conversões opcionais |
Pipeline |
oportunidades_pipeline |
id UUID |
somente um pipeline padrão |
PipelineStage |
oportunidades_pipelinestage |
id UUID |
(pipeline, ordem) único |
Oportunidade |
oportunidades_oportunidade |
id UUID |
conta e responsável obrigatórios |
HistoricoEtapaOportunidade |
oportunidades_historicoetapaoportunidade |
id bigint |
histórico de mudança de etapa |
Atividade |
atividades_atividade |
id UUID |
responsável obrigatório |
Tarefa |
tarefas_tarefa |
id UUID |
responsável obrigatório |
Nota |
anotacoes_nota |
id UUID |
autor obrigatório; exclusão lógica |
AuditLog |
auditoria_auditlog |
id bigint |
ator pode ser nulo |
Dicionário de dados¶
Tipos são os tipos Django que originam as colunas PostgreSQL (UUIDField → uuid, CharField → varchar, TextField → text, DateTimeField → timestamptz, DecimalField → numeric). não na coluna Nulo significa null=False; campos opcionais aceitam NULL quando o model declara null=True.
Base, identidade e auditoria¶
| Entidade | Campo: tipo | Nulo | Default | FK / índice |
|---|---|---|---|---|
BaseModel |
id: uuid; created_at/updated_at: timestamptz; is_active: boolean |
não | uuid4; auto; true |
PK id; ordenação por criação |
Role |
id: bigint; name: varchar(50); description: text; timestamps |
não | auto; —; ""; auto |
PK; name UNIQUE |
User |
campos de AbstractUser; role: bigint; avatar: image; timestamps |
role/avatar sim | defaults do Django | role → Role PROTECT |
AuditLog |
id: bigint; acao: smallint; ator: bigint; tipo_entidade/id_entidade: varchar; descricao: text; três campos jsonb; endereco_ip: inet; user_agent: text; created_at: timestamptz |
ator, JSON e IP sim | auto; demais sem default | ator → User SET_NULL; índices por ação/entidade/data |
Contas, contatos e leads¶
| Entidade | Campos persistidos |
|---|---|
Conta |
id: uuid; timestamps; is_active: boolean=true; razao_social/nome_fantasia: varchar(200); numero_documento: varchar (nulo); tipo_conta/status: varchar(20) (default prospect); segmento/origem: varchar(100); email; telefone: varchar(20); site; cidade: varchar(100); estado: varchar(2); pais: varchar(100)=Brasil; observacoes: text; responsavel: uuid (nulo, FK User, PROTECT). |
Contato |
id: uuid; timestamps; is_active=true; conta: uuid (nulo, FK Conta, PROTECT); primeiro_nome/sobrenome: varchar(100); email; telefone/celular: varchar(20); cargo/departamento: varchar(100); principal: boolean=false; observacoes: text; responsavel: uuid (nulo, FK User, PROTECT). Constraint condicional: um principal por conta. |
Lead |
id: uuid; timestamps; is_active=true; nome: varchar(200); nome_contato: varchar(150); email; telefone: varchar(20); nome_empresa: varchar(200); origem: varchar(100); status: varchar(20)=novo; pontuacao_qualificacao: smallint (0–100, nulo); interesse: text; valor_estimado: numeric(12,2) (nulo); responsavel: uuid (FK User, PROTECT); motivo_perda: text; convertido_em: timestamptz (nulo); três FKs de conversão (nulas, SET_NULL). |
Pipeline, oportunidades e atividades¶
| Entidade | Campos persistidos |
|---|---|
Pipeline |
id: uuid; timestamps; is_active=true; nome: varchar(100); descricao: text; padrao: boolean=false. Constraint condicional: um padrão. |
PipelineStage |
id: uuid; timestamps; is_active=true; pipeline: uuid (FK, CASCADE); nome: varchar(100); ordem: integer; probabilidade: integer (0–100, nulo); etapa_ganho/perda: boolean=false. UNIQUE (pipeline, ordem). |
Oportunidade |
id: uuid; timestamps; is_active=true; titulo: varchar(200); conta: uuid (FK, PROTECT); contato/etapa: uuid (nulos, SET_NULL/PROTECT); status: varchar(20)=aberta; valor_estimado: numeric(12,2); probabilidade: integer; duas datas de fechamento; responsavel: uuid (FK, PROTECT); lead_origem: uuid (nulo, SET_NULL); motivo_perda/descricao: text. |
HistoricoEtapaOportunidade |
id: bigint; oportunidade: uuid (FK, CASCADE); etapa_anterior: uuid (nulo, SET_NULL); etapa_nova: uuid (FK, PROTECT); alterado_por: bigint (FK, PROTECT); alterado_em: timestamptz auto; motivo: text. Índice pela oportunidade/data. |
Atividade |
id, timestamps, is_active; tipo: varchar(20); titulo: varchar(200); descricao/resultado/proxima_acao: text; quatro FKs de contexto (nulas, CASCADE); responsavel: uuid (FK User, PROTECT); ocorrida_em: timestamptz; data_proxima_acao: timestamptz (nulo). |
Tarefa |
id, timestamps, is_active; titulo: varchar(200); descricao: text; status: varchar(20)=pendente; prioridade: varchar(10)=media; prazo/concluida_em: timestamptz (nulos); responsavel: uuid (FK User, PROTECT); quatro FKs de contexto (nulas, CASCADE). |
Nota |
id, timestamps, is_active; titulo: varchar(200); conteudo: text; quatro FKs de contexto (nulas, CASCADE); autor: uuid (FK User, PROTECT); privada: boolean=false. |
Limites confirmados¶
Não existe company_id, isolamento multi-tenant, created_by/updated_by universal, deleted_at ou tabelas de campanhas, propostas, produtos, concorrentes e customer success no MVP. A documentação reflete o schema real observado, não o blueprint original.