npm package: @hed-hog/contact
Description: ```markdown # @hed-hog/contact
Latest version: 0.0.303

```markdown
# @hed-hog/contact

## 1. Visão geral do módulo

O módulo `@hed-hog/contact` gerencia informações relacionadas a contatos, documentos, pessoas e seus tipos, além das relações entre pessoas. Ele oferece funcionalidades completas de CRUD para tipos de contato, tipos de documento, pessoas e suas relações, com suporte a internacionalização (locales), paginação e controle de acesso baseado em roles.

## 2. Escopo e responsabilidades

- Gerenciar tipos de contato (`contact_type`).
- Gerenciar tipos de documento (`document_type`).
- Gerenciar pessoas (`person`), incluindo contatos, documentos, endereços e metadados.
- Gerenciar tipos de relação entre pessoas (`person_relation_type`), que são fixos e imutáveis via API.
- Validar regras específicas de negócio, como unicidade de contatos primários e restrições para registro de empresas.
- Suportar autenticação e autorização baseada em roles (`admin`, `admin-contact`).
- Suportar internacionalização para mensagens e dados localizados.
- Integrar com serviços de paginação, banco de dados Prisma e envio de emails.

## 3. Endpoints

### Person Contact Type (`/person-contact-type`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Lista tipos de contato com paginação e locale. |
| GET    | `/person-contact-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de contato por ID com locale. |
| POST   | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Cria um novo tipo de contato. |
| PATCH  | `/person-contact-type/:id` | Autenticado (roles: admin, admin-contact) | Atualiza um tipo de contato existente. |
| DELETE | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Exclui tipos de contato por IDs. |

**Parâmetros e corpo:**

- `CreateDTO` para criação:
  - `code` (string): código do tipo de contato.
  - `locale` (objeto): nomes localizados, ex: `{ "pt": { "name": "Telefone" }, "en": { "name": "Phone" } }`.

- `UpdateDTO` para atualização: campos parciais de `CreateDTO`, `locale` opcional.

**Resposta:**

- Listagem paginada ou objeto do tipo criado/atualizado.
- Erros:
  - 400 Bad Request: dados inválidos, `locale` vazio, IDs para exclusão não informados.
  - 404 Not Found: tipo de contato não encontrado.

---

### Person Document Type (`/person-document-type`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Lista tipos de documento com paginação e locale. |
| GET    | `/person-document-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de documento por ID com locale. |
| POST   | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Cria um novo tipo de documento. |
| PATCH  | `/person-document-type/:id` | Autenticado (roles: admin, admin-contact) | Atualiza um tipo de documento existente. |
| DELETE | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Exclui tipos de documento por IDs. |

**Parâmetros e corpo:**

- `CreateDTO` para criação:
  - `code` (string): código do tipo de documento.
  - `country_code` (string): código do país.
  - `is_unique` (boolean): indica se o documento é único.
  - `locale` (objeto): nomes localizados.

- `UpdateDTO` para atualização: campos parciais de `CreateDTO`, `locale` opcional.

**Resposta:**

- Listagem paginada ou objeto do tipo criado/atualizado.
- Erros:
  - 400 Bad Request: dados inválidos, `locale` vazio, IDs para exclusão não informados.
  - 404 Not Found: tipo de documento não encontrado.

---

### Person (`/person`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person`              | Autenticado (roles: admin, admin-contact) | Lista pessoas com filtros e paginação. |
| GET    | `/person/stats`        | Autenticado (roles: admin, admin-contact) | Estatísticas de pessoas. |
| GET    | `/person/owner-options`| Autenticado (roles: admin, admin-contact) | Lista usuários possíveis para atribuição como responsáveis. |
| GET    | `/person/:id`          | Autenticado (roles: admin, admin-contact) | Obtém pessoa por ID com detalhes. |
| GET    | `/person/avatar/:id`   | Pública                             | Abre avatar público pelo ID do arquivo. |
| POST   | `/person`              | Autenticado (roles: admin, admin-contact) | Cria uma nova pessoa. |
| PATCH  | `/person/:id`          | Autenticado (roles: admin, admin-contact) | Atualiza pessoa existente. |
| DELETE | `/person`              | Autenticado (roles: admin, admin-contact) | Exclui pessoas por IDs. |

**Parâmetros e corpo:**

- `CreateDTO` para criação:
  - `name` (string): nome da pessoa.
  - `type` (enum: individual, company): tipo da pessoa.
  - `status` (enum: active, inactive): status da pessoa.
  - Campos opcionais: `avatar_id`, `birth_date`, `gender`, `job_title`, `trade_name`, `foundation_date`, `legal_nature`, `notes`, `employer_company_id`.

- `UpdateAllPersonDTO` para atualização:
  - Inclui todos os campos do `CreateDTO`.
  - Arrays para `contacts`, `addresses`, `documents` com seus respectivos campos e validações.
  - Validação para garantir apenas um contato, endereço ou documento primário por tipo.
  - Campos opcionais `branch_ids` (array de números) e `headquarter_id` (número).

**Resposta:**

- Listagem paginada, objeto da pessoa criada/atualizada, ou estatísticas.
- Erros:
  - 400 Bad Request: dados inválidos, mais de um primário por tipo, referência inválida, registro de empresa desabilitado, IDs para exclusão não informados.
  - 404 Not Found: pessoa não encontrada, avatar não encontrado.

---

### Person Relation Type (`/person-relation-type`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | Lista tipos fixos de relação entre pessoas. |
| GET    | `/person-relation-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de relação por ID. |
| POST   | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |
| PATCH  | `/person-relation-type/:id` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |
| DELETE | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |

**Observação:** Tipos de relação são fixos e não podem ser criados, atualizados ou deletados via API. Tentativas resultam em erro 400.

---

## 4. Regras de autenticação e autorização

- A maioria dos endpoints requer autenticação via JWT.
- Acesso restrito a usuários com roles `admin` ou `admin-contact`.
- O endpoint de avatar (`/person/avatar/:id`) é público.
- Tentativas de criar, atualizar ou deletar tipos de relação entre pessoas resultam em erro 400, pois são fixos.

## 5. Estruturas de request/response

### CreateDTO (Person Contact Type)

```json
{
  "code": "string",
  "locale": {
    "pt": { "name": "string" },
    "en": { "name": "string" }
  }
}
```

### UpdateDTO (Person Contact Type)

Campos parciais de CreateDTO, `locale` opcional.

---

### CreateDTO (Person Document Type)

```json
{
  "code": "string",
  "country_code": "string",
  "is_unique": true,
  "locale": {
    "pt": { "name": "string" },
    "en": { "name": "string" }
  }
}
```

### UpdateDTO (Person Document Type)

Campos parciais de CreateDTO, `locale` opcional.

---

### CreateDTO (Person)

```json
{
  "name": "string",
  "type": "individual | company",
  "status": "active | inactive",
  "avatar_id": "number | null",
  "birth_date": "string (date) | null",
  "gender": "male | female | other | null",
  "job_title": "string | null",
  "trade_name": "string | null",
  "foundation_date": "string (date) | null",
  "legal_nature": "string | null",
  "notes": "string | null",
  "employer_company_id": "number | null"
}
```

### UpdateAllPersonDTO (Person)

Inclui todos os campos do CreateDTO e:

- `contacts`: array de objetos com `id?`, `value`, `is_primary`, `contact_type_id`.
- `addresses`: array de objetos com `id?`, `line1`, `line2?`, `city`, `state`, `country_code?`, `postal_code?`, `is_primary`, `address_type`.
- `documents`: array de objetos com `id?`, `value`, `document_type_id`.
- `branch_ids?`: array de números.
- `headquarter_id?`: número opcional para empresa.

---

## 6. Erros comuns

- **400 Bad Request**
  - Falta de campos obrigatórios (ex: `locale` vazio).
  - Tentativa de criar/atualizar tipos de relação (não suportado).
  - Mais de um contato, endereço ou documento primário do mesmo tipo.
  - Tentativa de registrar empresa quando registro está desabilitado.
  - Referência inválida para empresa ou endereço.
  - IDs para exclusão não informados.

- **404 Not Found**
  - Entidade não encontrada por ID (pessoa, tipo de contato, tipo de documento).
  - Pessoa do tipo empresa não encontrada quando registro está desabilitado.
  - Avatar não encontrado.

## 7. Banco de dados (tabelas YAML)

### contact

- Finalidade: Armazena contatos associados a pessoas.
- Colunas:
  - `id` (PK)
  - `person_id` (FK para `person.id`)
  - `contact_type_id` (FK para `contact_type.id`)
  - `value` (string)
  - `is_primary` (boolean, default: false)
  - `created_at`, `updated_at`
- Índices:
  - Único em `(person_id, contact_type_id, is_primary)` onde `is_primary = true`.

---

### contact_type

- Finalidade: Define tipos de contato.
- Colunas:
  - `id` (PK)
  - `name` (locale_varchar, com traduções pt/en)
  - `code` (string)
  - `created_at`, `updated_at`

---

### document

- Finalidade: Armazena documentos associados a pessoas.
- Colunas:
  - `id` (PK)
  - `person_id` (FK para `person.id`)
  - `document_type_id` (FK para `document_type.id`)
  - `value` (string)
  - `created_at`, `updated_at`

---

### document_type

- Finalidade: Define tipos de documento.
- Colunas:
  - `id` (PK)
  - `name` (locale_varchar, pt/en)
  - `code` (string)
  - `country_code` (string)
  - `is_unique` (boolean)
  - `created_at`, `updated_at`

---

### person

- Finalidade: Armazena pessoas (indivíduos e empresas).
- Colunas:
  - `id` (PK)
  - `name` (string)
  - `type` (enum: individual, company)
  - `status` (enum: active, inactive)
  - `avatar_id` (FK para `file.id`, nullable, onDelete SET NULL)
  - `created_at`, `updated_at`

---

### person_address

- Finalidade: Associação entre pessoas e endereços.
- Colunas:
  - `id` (PK)
  - `person_id` (FK para `person.id`)
  - `address_id` (FK para `address.id`)
  - `created_at`, `updated_at`
- Índices:
  - Único em `address_id`.

---

### person_company

- Finalidade: Dados específicos para pessoas do tipo empresa.
- Colunas:
  - `id` (PK, FK para `person.id`)
  - `trade_name` (string, nullable)
  - `foundation_date` (date, nullable)
  - `legal_nature` (string, nullable)
  - `headquarter_id` (FK para `person_company.id`, nullable, onDelete SET NULL, onUpdate CASCADE)
  - `created_at`, `updated_at`
- Índices:
  - Em `headquarter_id`

---

### person_individual

- Finalidade: Dados específicos para pessoas do tipo indivíduo.
- Colunas:
  - `id` (PK, FK para `person.id`)
  - `birth_date` (date, nullable)
  - `gender` (enum: male, female, other, nullable)
  - `job_title` (string, nullable)
  - `created_at`, `updated_at`

---

### person_individual_relation

- Finalidade: Relações entre pessoas do tipo indivíduo.
- Colunas:
  - `id` (PK)
  - `person_individual_id` (FK para `person_individual.id`, onDelete CASCADE, onUpdate CASCADE)
  - `related_person_individual_id` (FK para `person_individual.id`, onDelete CASCADE, onUpdate CASCADE)
  - `relation_type` (enum: parent, child, spouse, sibling, guardian, dependent, partner, responsible, emergency_contact, other)
  - `created_at`, `updated_at`
- Índices:
  - Em `person_individual_id`, `related_person_individual_id`, `relation_type`
  - Único em `(person_individual_id, related_person_individual_id, relation_type)`

---

### person_metadata

- Finalidade: Metadados arbitrários associados a pessoas.
- Colunas:
  - `id` (PK)
  - `person_id` (FK para `person.id`)
  - `key` (string)
  - `value` (json)
  - `created_at`, `updated_at`

---

## 8. Regras de negócio relevantes

- Tipos de relação entre pessoas são fixos e não podem ser alterados via API.
- Apenas um contato, endereço ou documento pode ser marcado como primário por tipo para uma pessoa.
- Registro de pessoas do tipo empresa pode ser desabilitado via configuração `contact-allow-company-registration`.
- Ao criar ou atualizar pessoa, validações garantem integridade das relações e dados.
- Exclusão de pessoas remove em cascata contatos, documentos, endereços, relações e metadados associados.
- Avatar público pode ser acessado via endpoint público, com cache control configurado.
- Ao criar pessoa sem usuário, é enviado email com link para criação de conta, com token JWT válido por 1 dia.
- Metadados como `notes` e `employer_company_id` são armazenados separadamente e sincronizados.
- Empresas não podem ser vinculadas como sua própria matriz (headquarter).
- Apenas empresas podem ser vinculadas como matriz ou filial.
- Validações específicas impedem inconsistências nas relações de empresas e indivíduos.
- Atualização de pessoa sincroniza contatos, endereços e documentos, criando, atualizando ou removendo conforme necessário.
- Pesquisa de pessoas suporta filtros por nome, tipo, status, e busca por dados normalizados em contatos, documentos e endereços.

## 9. Guia rápido de uso (exemplos)

### Criar tipo de contato

```http
POST /person-contact-type
Authorization: Bearer <token>
Content-Type: application/json

{
  "code": "phone",
  "locale": {
    "pt": { "name": "Telefone" },
    "en": { "name": "Phone" }
  }
}
```

### Atualizar tipo de documento

```http
PATCH /person-document-type/3
Authorization: Bearer <token>
Content-Type: application/json

{
  "is_unique": true,
  "locale": {
    "pt": { "name": "CPF" },
    "en": { "name": "CPF" }
  }
}
```

### Listar pessoas com filtro e paginação

```http
GET /person?search=joao&type=individual&status=active&page=1&pageSize=20
Authorization: Bearer <token>
```

### Criar pessoa

```http
POST /person
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "João Silva",
  "type": "individual",
  "status": "active",
  "birth_date": "1980-05-10",
  "gender": "male",
  "contacts": [
    {
      "value": "joao@example.com",
      "is_primary": true,
      "contact_type_id": 1
    }
  ],
  "addresses": [
    {
      "line1": "Rua A, 123",
      "city": "São Paulo",
      "state": "SP",
      "country_code": "BRA",
      "postal_code": "01000-000",
      "is_primary": true,
      "address_type": "residential"
    }
  ],
  "documents": [
    {
      "value": "123.456.789-00",
      "document_type_id": 1
    }
  ]
}
```

### Atualizar pessoa

```http
PATCH /person/10
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "João da Silva",
  "status": "active",
  "contacts": [
    {
      "id": 5,
      "value": "joao.novo@example.com",
      "is_primary": true,
      "contact_type_id": 1
    }
  ]
}
```

### Excluir pessoas

```http
DELETE /person
Authorization: Bearer <token>
Content-Type: application/json

{
  "ids": [10, 11, 12]
}
```

---

Este README documenta as funcionalidades principais do módulo `@hed-hog/contact` com base no código e definições atuais. Para detalhes adicionais, consulte o código fonte e as definições de DTOs.
```