Receba novidades do Hedhog no seu e-mail
Novos lançamentos, receitas e breaking changes — sem spam.
Submódulo CRM
persons
Gerencia pessoas e empresas no CRM — contatos, contas, interações, follow-ups, atividades, estágios de ciclo de vida e importação por CSV.
Caminho de origem: libraries/crm/src/person
Arquivo do módulo: person.module.ts
Introdução
O submódulo Persons é o núcleo do CRM: uma única tabela `person` representa tanto indivíduos quanto empresas (discriminados pelo campo `type`), com os registros de empresa adicionalmente expostos através de uma superfície dedicada de Accounts (`/person/accounts`) que filtra por `type: company` e adiciona campos específicos de conta, como setor, website, receita anual e número de funcionários. A tabela base `person` guarda apenas campos estruturais (nome, tipo, status, avatar). Todo o resto que o PersonController aceita na criação/atualização — notes, employer_company_id, owner_user_id, source, lifecycle_stage, next_action_at, score, deal_value, tags — é persistido como linhas de chave/valor em uma tabela companheira person_metadata e remontado no formato de resposta pelo serviço. Isso mantém o schema central estável enquanto permite que atributos específicos de CRM evoluam sem uma migration para cada novo campo.
O rastreamento de propriedade e de ciclo de vida são preocupações de primeira classe. Cada pessoa pode receber um owner_user_id (restrito às roles admin, admin-crm ou owner-crm) e um lifecycle_stage extraído de um funil de vendas (new, contacted, qualified, proposal, negotiation, customer, lost). O POST /person/:id/lifecycle-stage registra a transição explicitamente, em vez de silenciosamente sobrescrever o valor em uma atualização genérica, o que mantém um histórico limpo para relatórios. Os endpoints GET /person/dashboard e GET /person/reports agregam essas transições de estágio e logs de interação em métricas de funil e relatórios agrupados por tempo (dia/semana/mês/ano), dando ao painel de admin suas visualizações de pipeline sem um data warehousing separado.
Interações (call, email, whatsapp, meeting, note) e follow-ups (um next_action_at agendado mais notas) são registrados por pessoa e também expostos como endpoints de worklist entre pessoas — GET /person/followups e GET /person/activities retornam visões paginadas e filtráveis de todo o CRM para que um representante possa trabalhar uma fila sem abrir cada registro de pessoa individualmente. Atividades são um conceito separado e mais estruturado do que interações: elas carregam status e podem ser explicitamente concluídas via POST /person/activities/:id/complete.
A prevenção de duplicatas e a consolidação são tratadas por dois endpoints complementares. O GET /person/duplicates realiza uma verificação difusa por nome, e-mail ou telefone antes de criar um novo registro. O POST /person/merge consolida um par de duplicatas existente: contatos, documentos, endereços e metadata são mesclados no registro alvo dentro de uma única transação, a pessoa de origem é marcada como inativa e um ponteiro de metadata merged_into_person_id é deixado para rastreabilidade. Apenas pessoas do mesmo tipo podem ser mescladas, e somente a estratégia contact_only está implementada atualmente — o campo strategy do DTO é tipado para estratégias futuras, mas o serviço só aceita esse valor hoje.
O onboarding em massa é suportado via um fluxo de CSV em duas etapas: o POST /person/import/preview faz o parsing do arquivo enviado e retorna os cabeçalhos e linhas de amostra para que o chamador possa montar um mapeamento de colunas; em seguida, o POST /person/import aplica esse mapeamento (passado como uma string JSON em um campo multipart) para criar registros de pessoa, opcionalmente associando todos eles a uma empresa via company_id. Ambos os endpoints rejeitam uploads que não sejam CSV e limitam o tamanho do arquivo a 10 MB.
O GET /person/avatar/:id é o único endpoint público e não autenticado do submódulo — ele serve a imagem de avatar de uma pessoa por ID de arquivo com cache baseado em ETag (If-None-Match), de modo que o painel de admin e quaisquer widgets incorporados possam renderizar avatares sem precisar de um token de sessão. Vincular uma pessoa a uma conta de usuário da plataforma (user_id) é restrito a uma role dedicada person-user-linker, além de admin/admin-crm, já que isso concede àquele usuário visibilidade atrelada ao registro do CRM.
Endpoints HTTP
31 endpoints
Obtém estatísticas globais de pessoas do CRM (totais por tipo e status). Quando o cadastro de empresas está desabilitado, as contagens de empresas são reportadas como zero.
Obtém os dados do dashboard do CRM (métricas de funil/ciclo de vida) para um período determinado, opcionalmente restritas a um proprietário.
- Query
- owner_user_id?, period? (7d|30d|90d|custom), date_from?, date_to?
Obtém relatórios do CRM agrupados por período de tempo.
- Query
- date_from (required), date_to (required), group_by (day|week|month|year, required)
Lista opções de usuários para atribuir como proprietários de pessoas (autocomplete; restrito a detentores das roles admin, admin-crm ou owner-crm).
- Query
- search?
Lista opções de usuários da plataforma que podem ser vinculados a um registro de pessoa.
- Query
- search?
Verifica se um usuário já está vinculado a alguma pessoa (ou a uma específica).
- Query
- userId (required), personId?
Verifica potenciais pessoas duplicadas com base em nome, e-mail ou telefone antes de criar um novo registro.
- Query
- name?, email?, phone?
Lista paginada de pessoas com filtros opcionais.
- Query
- page, pageSize, search, type?, status?, lifecycle_stage?, owner_user_id?, source?, tags?
Serve a imagem pública de avatar de uma pessoa (sem autenticação necessária), com cache baseado em ETag via If-None-Match.
- Params
- id (int) — file ID of the avatar
Obtém os detalhes completos de uma única pessoa, incluindo contatos, endereços, documentos e relacionamentos.
- Params
- id (int)
Cria uma nova pessoa (indivíduo ou empresa).
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | — |
| type | PersonType (individual | company) | yes | — |
| status | PersonStatus (active | inactive) | yes | Defaults to active |
| avatar_id | int | no | — |
| birth_date | date string | no | — |
| gender | PersonGender (male | female | other) | no | — |
| job_title | string | no | — |
| trade_name | string | no | Company trade/fantasy name |
| foundation_date | date string | no | — |
| legal_nature | string | no | — |
| notes | string | no | Stored as person_metadata |
| employer_company_id | int | no | Stored as person_metadata |
| owner_user_id | int | no | Stored as person_metadata |
| user_id | int | no | Link to a platform user |
| source | PersonSource (referral | website | social | inbound | outbound | other) | no | Stored as person_metadata |
| lifecycle_stage | PersonLifecycleStage (new | contacted | qualified | proposal | negotiation | customer | lost) | no | Stored as person_metadata |
| next_action_at | date string | no | Stored as person_metadata |
| score | number | no | Stored as person_metadata |
| deal_value | number | no | Stored as person_metadata |
| tags | string[] | no | — |
Mescla duas pessoas duplicadas do mesmo tipo, consolidando contatos/documentos/endereços/metadata no alvo dentro de uma única transação.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| source_person_id | int | yes | Person to be merged and marked inactive |
| target_person_id | int | yes | Person to keep |
| strategy | "contact_only" | yes | Only contact_only is currently implemented |
Pré-visualiza a importação de CSV — retorna os cabeçalhos de coluna e linhas de amostra para o mapeamento de campos.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| file | multipart/CSV (max 10 MB) | yes | CSV file to preview before import |
Importa pessoas de um arquivo CSV com mapeamento de campos customizado.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| file | multipart/CSV (max 10 MB) | yes | — |
| mapping | JSON string (Record<string, string>) | yes | CSV column → person field mapping |
| company_id | int (form field) | no | Associate imported persons with a company |
Atualiza os dados da pessoa (atualização parcial, mesmos campos da criação — os arrays de contatos/endereços/documentos são sincronizados: criados, atualizados ou removidos conforme necessário).
- Params
- id (int)
Exclui uma ou mais pessoas (em cascata para contatos, documentos, endereços, relações e metadata).
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| ids | number[] | yes | IDs to delete |
Lista todas as interações registradas para uma pessoa.
- Params
- id (int)
Registra uma nova interação para a pessoa.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| type | PersonInteractionType (call | email | whatsapp | meeting | note) | yes | — |
| notes | string | no | — |
Lista paginada de follow-ups de todas as pessoas, filtrável por status ou intervalo de datas.
- Query
- page, pageSize, search, status? (all | today | upcoming | overdue), date_from?, date_to?
Estatísticas resumidas de follow-ups (contagens por status).
- Query
- search?
Agenda uma ação de follow-up para uma pessoa.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| next_action_at | date string | yes | — |
| notes | string | no | — |
Atualiza o estágio de ciclo de vida do CRM para uma pessoa, registrando explicitamente a transição de estágio para relatórios de funil.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| lifecycle_stage | PersonLifecycleStage (new | contacted | qualified | proposal | negotiation | customer | lost) | yes | — |
Lista paginada de atividades de todas as pessoas.
- Query
- page, pageSize, search, status?, type?, person_id?
Estatísticas resumidas de todas as atividades (contagens por status/tipo).
Obtém o detalhe completo de uma única atividade.
- Params
- id (int)
Marca uma atividade como concluída.
- Params
- id (int)
Lista paginada de contas de empresa (pessoas do tipo company) com filtragem por ciclo de vida do CRM.
- Query
- page, pageSize, search, status? (all | active | inactive), lifecycle_stage?, sortField? (name | created_at), sortOrder? (asc | desc)
Estatísticas resumidas de contas de empresa (contagens por estágio de ciclo de vida).
Cria uma nova conta de empresa.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | — |
| status | PersonStatus (active | inactive) | yes | — |
| trade_name | string | no | — |
| foundation_date | date string | no | — |
| legal_nature | string | no | — |
| industry | string | no | — |
| website | string | no | — |
| email string | no | — | |
| phone | string | no | — |
| owner_user_id | int | no | — |
| annual_revenue | number | no | — |
| employee_count | int | no | — |
| lifecycle_stage | AccountLifecycleStage (prospect | customer | churned | inactive) | no | — |
| city | string | no | — |
| state | string (max 2) | no | — |
| collaborator_person_ids | int[] | no | — |
| contacts | UpdateAllContactDTO[] | no | — |
| addresses | UpdateAllAddressDTO[] | no | — |
| documents | UpdateAllDocumentDTO[] | no | — |
| avatar_id | int | no | — |
Atualiza uma conta de empresa (mesmos campos da criação).
- Params
- id (int)
Exclui uma ou mais contas de empresa.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| ids | number[] | yes | IDs to delete |
Ferramentas MCP
Ferramentas nomeadas que podem ser chamadas por modelos de IA através do Model Context Protocol (MCP).
crm.persons.listLista pessoas (indivíduos ou empresas) com paginação e filtros
crm.persons.statsRetorna estatísticas de pessoas: contagens de total, indivíduos, empresas, ativos e inativos
crm.persons.dashboardRetorna os dados do dashboard do CRM com métricas de funil, agrupados por período
crm.persons.reportsRetorna os dados de relatórios do CRM
crm.persons.owner-optionsRetorna os usuários disponíveis como proprietários de um registro de pessoa
crm.persons.linked-user-optionsRetorna os usuários que podem ser vinculados a um registro de pessoa
crm.persons.duplicatesVerifica registros de pessoa duplicados por nome, e-mail ou telefone
crm.persons.getRetorna um único registro de pessoa por ID com detalhes completos
crm.persons.createCria um novo registro de pessoa (indivíduo ou empresa)
crm.persons.updateAtualiza um registro de pessoa existente por ID
crm.persons.deleteExclui um ou mais registros de pessoa pelos seus IDs
crm.persons.mergeMescla dois registros de pessoa duplicados em um
crm.persons.interactions.listLista todas as interações de uma pessoa (ligações, e-mails, reuniões, notas)
crm.persons.interactions.createRegistra uma nova interação com uma pessoa
crm.persons.followups.listLista todos os follow-ups de todas as pessoas com paginação e filtros
crm.persons.followups.statsRetorna estatísticas de follow-ups agrupadas por status e período
crm.persons.followups.createAgenda um follow-up para uma pessoa
crm.persons.activities.listLista atividades do CRM com paginação e filtros
crm.persons.activities.statsRetorna estatísticas de atividades
crm.persons.activities.getRetorna uma única atividade do CRM por ID
crm.persons.activities.completeMarca uma atividade do CRM como concluída
crm.persons.lifecycle-stage.updateAtualiza o estágio de ciclo de vida de um registro de pessoa
crm.persons.accounts.listLista contas de empresa com paginação e filtros
crm.persons.accounts.statsRetorna estatísticas de contas
crm.persons.accounts.createCria uma nova conta de empresa
crm.persons.accounts.updateAtualiza uma conta de empresa existente por ID
crm.persons.accounts.deleteExclui uma ou mais contas de empresa pelos seus IDs