@hed-hog/contact 0.0.270 → 0.0.275
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +483 -0
- package/dist/person/person.controller.d.ts +4 -0
- package/dist/person/person.controller.d.ts.map +1 -1
- package/dist/person/person.controller.js +10 -0
- package/dist/person/person.controller.js.map +1 -1
- package/dist/person/person.service.d.ts +12 -3
- package/dist/person/person.service.d.ts.map +1 -1
- package/dist/person/person.service.js +62 -11
- package/dist/person/person.service.js.map +1 -1
- package/hedhog/data/role.yaml +9 -1
- package/hedhog/data/route.yaml +8 -0
- package/hedhog/frontend/app/person/_components/person-form-sheet.tsx.ejs +865 -585
- package/hedhog/frontend/app/person/_components/person-types.ts.ejs +157 -115
- package/hedhog/frontend/app/person/page.tsx.ejs +1353 -1209
- package/hedhog/frontend/messages/pt.json +41 -0
- package/package.json +5 -5
- package/src/person/person.controller.ts +48 -43
- package/src/person/person.service.ts +1137 -1071
package/README.md
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
```markdown
|
|
2
|
+
# @hed-hog/contact
|
|
3
|
+
|
|
4
|
+
## 1. Visão geral do módulo
|
|
5
|
+
|
|
6
|
+
O módulo `@hed-hog/contact` é responsável pela gestão de informações relacionadas a contatos, documentos, pessoas e seus tipos, além de relações entre pessoas. Ele oferece funcionalidades para criação, leitura, atualização e exclusão (CRUD) de entidades como tipos de contato, tipos de documento, pessoas, e suas relações, com suporte a internacionalização (locales) e paginação.
|
|
7
|
+
|
|
8
|
+
## 2. Escopo e responsabilidades
|
|
9
|
+
|
|
10
|
+
- Gerenciar tipos de contato (`contact_type`).
|
|
11
|
+
- Gerenciar tipos de documento (`document_type`).
|
|
12
|
+
- Gerenciar pessoas (`person`), incluindo seus contatos, documentos, endereços e metadados.
|
|
13
|
+
- Gerenciar tipos de relação entre pessoas (`person_relation_type`).
|
|
14
|
+
- Fornecer serviços para criação e atualização de pessoas, incluindo validações específicas de negócio.
|
|
15
|
+
- Suportar autenticação e autorização baseada em roles para acesso aos endpoints.
|
|
16
|
+
- Suportar internacionalização para mensagens e dados localizados.
|
|
17
|
+
- Integrar com serviços de paginação, banco de dados Prisma, e envio de emails.
|
|
18
|
+
|
|
19
|
+
## 3. Endpoints
|
|
20
|
+
|
|
21
|
+
### Person Contact Type (`/person-contact-type`)
|
|
22
|
+
|
|
23
|
+
| Método | Path | Autenticação | Descrição |
|
|
24
|
+
|--------|----------------------|-------------------------------------|----------------------------------|
|
|
25
|
+
| GET | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Lista tipos de contato com paginação e locale. |
|
|
26
|
+
| GET | `/person-contact-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de contato por ID com locale. |
|
|
27
|
+
| POST | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Cria um novo tipo de contato. |
|
|
28
|
+
| PATCH | `/person-contact-type/:id` | Autenticado (roles: admin, admin-contact) | Atualiza um tipo de contato existente. |
|
|
29
|
+
| DELETE | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Exclui tipos de contato por IDs. |
|
|
30
|
+
|
|
31
|
+
**Parâmetros e corpo:**
|
|
32
|
+
|
|
33
|
+
- `CreateDTO` para criação:
|
|
34
|
+
- `code` (string): código do tipo de contato.
|
|
35
|
+
- `locale` (objeto): nomes localizados, ex: `{ "pt": { "name": "Telefone" }, "en": { "name": "Phone" } }`.
|
|
36
|
+
|
|
37
|
+
- `UpdateDTO` para atualização: campos parciais de `CreateDTO`, `locale` opcional.
|
|
38
|
+
|
|
39
|
+
**Resposta:**
|
|
40
|
+
|
|
41
|
+
- Listagem paginada ou objeto do tipo criado/atualizado.
|
|
42
|
+
- Erros:
|
|
43
|
+
- 400 Bad Request: dados inválidos, `locale` vazio, IDs para exclusão não informados.
|
|
44
|
+
- 404 Not Found: tipo de contato não encontrado.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
### Person Document Type (`/person-document-type`)
|
|
49
|
+
|
|
50
|
+
| Método | Path | Autenticação | Descrição |
|
|
51
|
+
|--------|----------------------|-------------------------------------|----------------------------------|
|
|
52
|
+
| GET | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Lista tipos de documento com paginação e locale. |
|
|
53
|
+
| GET | `/person-document-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de documento por ID com locale. |
|
|
54
|
+
| POST | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Cria um novo tipo de documento. |
|
|
55
|
+
| PATCH | `/person-document-type/:id` | Autenticado (roles: admin, admin-contact) | Atualiza um tipo de documento existente. |
|
|
56
|
+
| DELETE | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Exclui tipos de documento por IDs. |
|
|
57
|
+
|
|
58
|
+
**Parâmetros e corpo:**
|
|
59
|
+
|
|
60
|
+
- `CreateDTO` para criação:
|
|
61
|
+
- `code` (string): código do tipo de documento.
|
|
62
|
+
- `country_code` (string): código do país.
|
|
63
|
+
- `is_unique` (boolean): indica se o documento é único.
|
|
64
|
+
- `locale` (objeto): nomes localizados.
|
|
65
|
+
|
|
66
|
+
- `UpdateDTO` para atualização: campos parciais de `CreateDTO`, `locale` opcional.
|
|
67
|
+
|
|
68
|
+
**Resposta:**
|
|
69
|
+
|
|
70
|
+
- Listagem paginada ou objeto do tipo criado/atualizado.
|
|
71
|
+
- Erros:
|
|
72
|
+
- 400 Bad Request: dados inválidos, `locale` vazio, IDs para exclusão não informados.
|
|
73
|
+
- 404 Not Found: tipo de documento não encontrado.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### Person (`/person`)
|
|
78
|
+
|
|
79
|
+
| Método | Path | Autenticação | Descrição |
|
|
80
|
+
|--------|----------------------|-------------------------------------|----------------------------------|
|
|
81
|
+
| GET | `/person` | Autenticado (roles: admin, admin-contact) | Lista pessoas com filtros e paginação. |
|
|
82
|
+
| GET | `/person/stats` | Autenticado (roles: admin, admin-contact) | Estatísticas de pessoas. |
|
|
83
|
+
| GET | `/person/owner-options` | Autenticado (roles: admin, admin-contact) | Lista usuários possíveis para atribuição como responsáveis. |
|
|
84
|
+
| GET | `/person/:id` | Autenticado (roles: admin, admin-contact) | Obtém pessoa por ID com detalhes. |
|
|
85
|
+
| GET | `/person/avatar/:id` | Pública | Abre avatar público pelo ID do arquivo. |
|
|
86
|
+
| POST | `/person` | Autenticado (roles: admin, admin-contact) | Cria uma nova pessoa. |
|
|
87
|
+
| PATCH | `/person/:id` | Autenticado (roles: admin, admin-contact) | Atualiza pessoa existente. |
|
|
88
|
+
| DELETE | `/person` | Autenticado (roles: admin, admin-contact) | Exclui pessoas por IDs. |
|
|
89
|
+
|
|
90
|
+
**Parâmetros e corpo:**
|
|
91
|
+
|
|
92
|
+
- `CreateDTO` para criação:
|
|
93
|
+
- `name` (string): nome da pessoa.
|
|
94
|
+
- `type` (enum: individual, company): tipo da pessoa.
|
|
95
|
+
- `status` (enum: active, inactive): status da pessoa.
|
|
96
|
+
- Campos opcionais: `avatar_id`, `birth_date`, `gender`, `job_title`, `trade_name`, `foundation_date`, `legal_nature`, `notes`, `employer_company_id`.
|
|
97
|
+
|
|
98
|
+
- `UpdateAllPersonDTO` para atualização:
|
|
99
|
+
- Inclui todos os campos do `CreateDTO`.
|
|
100
|
+
- Arrays para `contacts`, `addresses`, `documents` com seus respectivos campos e validações.
|
|
101
|
+
- Validação para garantir apenas um contato, endereço ou documento primário por tipo.
|
|
102
|
+
- Campo opcional `branch_ids` para empresas.
|
|
103
|
+
|
|
104
|
+
**Resposta:**
|
|
105
|
+
|
|
106
|
+
- Listagem paginada, objeto da pessoa criada/atualizada, ou estatísticas.
|
|
107
|
+
- Erros:
|
|
108
|
+
- 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.
|
|
109
|
+
- 404 Not Found: pessoa não encontrada, avatar não encontrado.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Person Relation Type (`/person-relation-type`)
|
|
114
|
+
|
|
115
|
+
| Método | Path | Autenticação | Descrição |
|
|
116
|
+
|--------|----------------------|-------------------------------------|----------------------------------|
|
|
117
|
+
| GET | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | Lista tipos fixos de relação entre pessoas. |
|
|
118
|
+
| GET | `/person-relation-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de relação por ID. |
|
|
119
|
+
| POST | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |
|
|
120
|
+
| PATCH | `/person-relation-type/:id` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |
|
|
121
|
+
| DELETE | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |
|
|
122
|
+
|
|
123
|
+
**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.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 4. Regras de autenticação e autorização
|
|
128
|
+
|
|
129
|
+
- A maioria dos endpoints requer autenticação via JWT.
|
|
130
|
+
- Acesso restrito a usuários com roles `admin` ou `admin-contact`.
|
|
131
|
+
- O endpoint de avatar (`/person/avatar/:id`) é público.
|
|
132
|
+
- Tentativas de criar, atualizar ou deletar tipos de relação entre pessoas resultam em erro 400, pois são fixos.
|
|
133
|
+
|
|
134
|
+
## 5. Estruturas de request/response
|
|
135
|
+
|
|
136
|
+
### CreateDTO (Person Contact Type)
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"code": "string",
|
|
141
|
+
"locale": {
|
|
142
|
+
"pt": { "name": "string" },
|
|
143
|
+
"en": { "name": "string" }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### UpdateDTO (Person Contact Type)
|
|
149
|
+
|
|
150
|
+
Campos parciais de CreateDTO, `locale` opcional.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### CreateDTO (Person Document Type)
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"code": "string",
|
|
159
|
+
"country_code": "string",
|
|
160
|
+
"is_unique": true,
|
|
161
|
+
"locale": {
|
|
162
|
+
"pt": { "name": "string" },
|
|
163
|
+
"en": { "name": "string" }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### UpdateDTO (Person Document Type)
|
|
169
|
+
|
|
170
|
+
Campos parciais de CreateDTO, `locale` opcional.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### CreateDTO (Person)
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"name": "string",
|
|
179
|
+
"type": "individual | company",
|
|
180
|
+
"status": "active | inactive",
|
|
181
|
+
"avatar_id": "number | null",
|
|
182
|
+
"birth_date": "string (date) | null",
|
|
183
|
+
"gender": "male | female | other | null",
|
|
184
|
+
"job_title": "string | null",
|
|
185
|
+
"trade_name": "string | null",
|
|
186
|
+
"foundation_date": "string (date) | null",
|
|
187
|
+
"legal_nature": "string | null",
|
|
188
|
+
"notes": "string | null",
|
|
189
|
+
"employer_company_id": "number | null"
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### UpdateAllPersonDTO (Person)
|
|
194
|
+
|
|
195
|
+
Inclui todos os campos do CreateDTO e:
|
|
196
|
+
|
|
197
|
+
- `contacts`: array de objetos com `id?`, `value`, `is_primary`, `contact_type_id`.
|
|
198
|
+
- `addresses`: array de objetos com `id?`, `line1`, `line2?`, `city`, `state`, `country_code?`, `postal_code?`, `is_primary`, `address_type`.
|
|
199
|
+
- `documents`: array de objetos com `id?`, `value`, `document_type_id`.
|
|
200
|
+
- `branch_ids?`: array de números.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 6. Erros comuns
|
|
205
|
+
|
|
206
|
+
- **400 Bad Request**
|
|
207
|
+
- Falta de campos obrigatórios (ex: `locale` vazio).
|
|
208
|
+
- Tentativa de criar/atualizar tipos de relação (não suportado).
|
|
209
|
+
- Mais de um contato, endereço ou documento primário do mesmo tipo.
|
|
210
|
+
- Tentativa de registrar empresa quando registro está desabilitado.
|
|
211
|
+
- Referência inválida para empresa ou endereço.
|
|
212
|
+
- IDs para exclusão não informados.
|
|
213
|
+
|
|
214
|
+
- **404 Not Found**
|
|
215
|
+
- Entidade não encontrada por ID (pessoa, tipo de contato, tipo de documento).
|
|
216
|
+
- Pessoa do tipo empresa não encontrada quando registro está desabilitado.
|
|
217
|
+
- Avatar não encontrado.
|
|
218
|
+
|
|
219
|
+
## 7. Banco de dados (tabelas YAML)
|
|
220
|
+
|
|
221
|
+
### contact
|
|
222
|
+
|
|
223
|
+
- Finalidade: Armazena contatos associados a pessoas.
|
|
224
|
+
- Colunas:
|
|
225
|
+
- `id` (PK)
|
|
226
|
+
- `person_id` (FK para `person.id`)
|
|
227
|
+
- `contact_type_id` (FK para `contact_type.id`)
|
|
228
|
+
- `value` (string)
|
|
229
|
+
- `is_primary` (boolean, default: false)
|
|
230
|
+
- `created_at`, `updated_at`
|
|
231
|
+
- Índices:
|
|
232
|
+
- Único em `(person_id, contact_type_id, is_primary)` onde `is_primary = true`.
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### contact_type
|
|
237
|
+
|
|
238
|
+
- Finalidade: Define tipos de contato.
|
|
239
|
+
- Colunas:
|
|
240
|
+
- `id` (PK)
|
|
241
|
+
- `name` (locale_varchar, com traduções pt/en)
|
|
242
|
+
- `code` (string)
|
|
243
|
+
- `created_at`, `updated_at`
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### document
|
|
248
|
+
|
|
249
|
+
- Finalidade: Armazena documentos associados a pessoas.
|
|
250
|
+
- Colunas:
|
|
251
|
+
- `id` (PK)
|
|
252
|
+
- `person_id` (FK para `person.id`)
|
|
253
|
+
- `document_type_id` (FK para `document_type.id`)
|
|
254
|
+
- `value` (string)
|
|
255
|
+
- `created_at`, `updated_at`
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
### document_type
|
|
260
|
+
|
|
261
|
+
- Finalidade: Define tipos de documento.
|
|
262
|
+
- Colunas:
|
|
263
|
+
- `id` (PK)
|
|
264
|
+
- `name` (locale_varchar, pt/en)
|
|
265
|
+
- `code` (string)
|
|
266
|
+
- `country_code` (string)
|
|
267
|
+
- `is_unique` (boolean)
|
|
268
|
+
- `created_at`, `updated_at`
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### person
|
|
273
|
+
|
|
274
|
+
- Finalidade: Armazena pessoas (indivíduos e empresas).
|
|
275
|
+
- Colunas:
|
|
276
|
+
- `id` (PK)
|
|
277
|
+
- `name` (string)
|
|
278
|
+
- `type` (enum: individual, company)
|
|
279
|
+
- `status` (enum: active, inactive)
|
|
280
|
+
- `avatar_id` (FK para `file.id`, nullable, onDelete SET NULL)
|
|
281
|
+
- `created_at`, `updated_at`
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### person_address
|
|
286
|
+
|
|
287
|
+
- Finalidade: Associação entre pessoas e endereços.
|
|
288
|
+
- Colunas:
|
|
289
|
+
- `id` (PK)
|
|
290
|
+
- `person_id` (FK para `person.id`)
|
|
291
|
+
- `address_id` (FK para `address.id`)
|
|
292
|
+
- `created_at`, `updated_at`
|
|
293
|
+
- Índices:
|
|
294
|
+
- Único em `address_id`.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
### person_company
|
|
299
|
+
|
|
300
|
+
- Finalidade: Dados específicos para pessoas do tipo empresa.
|
|
301
|
+
- Colunas:
|
|
302
|
+
- `id` (PK, FK para `person.id`)
|
|
303
|
+
- `trade_name` (string, nullable)
|
|
304
|
+
- `foundation_date` (date, nullable)
|
|
305
|
+
- `legal_nature` (string, nullable)
|
|
306
|
+
- `headquarter_id` (FK para `person_company.id`, nullable, onDelete SET NULL, onUpdate CASCADE)
|
|
307
|
+
- `created_at`, `updated_at`
|
|
308
|
+
- Índices:
|
|
309
|
+
- Em `headquarter_id`
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
### person_individual
|
|
314
|
+
|
|
315
|
+
- Finalidade: Dados específicos para pessoas do tipo indivíduo.
|
|
316
|
+
- Colunas:
|
|
317
|
+
- `id` (PK, FK para `person.id`)
|
|
318
|
+
- `birth_date` (date, nullable)
|
|
319
|
+
- `gender` (enum: male, female, other, nullable)
|
|
320
|
+
- `job_title` (string, nullable)
|
|
321
|
+
- `created_at`, `updated_at`
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### person_individual_relation
|
|
326
|
+
|
|
327
|
+
- Finalidade: Relações entre pessoas do tipo indivíduo.
|
|
328
|
+
- Colunas:
|
|
329
|
+
- `id` (PK)
|
|
330
|
+
- `person_individual_id` (FK para `person_individual.id`, onDelete CASCADE, onUpdate CASCADE)
|
|
331
|
+
- `related_person_individual_id` (FK para `person_individual.id`, onDelete CASCADE, onUpdate CASCADE)
|
|
332
|
+
- `relation_type` (enum: parent, child, spouse, sibling, guardian, dependent, partner, responsible, emergency_contact, other)
|
|
333
|
+
- `created_at`, `updated_at`
|
|
334
|
+
- Índices:
|
|
335
|
+
- Em `person_individual_id`, `related_person_individual_id`, `relation_type`
|
|
336
|
+
- Único em `(person_individual_id, related_person_individual_id, relation_type)`
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
### person_metadata
|
|
341
|
+
|
|
342
|
+
- Finalidade: Metadados arbitrários associados a pessoas.
|
|
343
|
+
- Colunas:
|
|
344
|
+
- `id` (PK)
|
|
345
|
+
- `person_id` (FK para `person.id`)
|
|
346
|
+
- `key` (string)
|
|
347
|
+
- `value` (json)
|
|
348
|
+
- `created_at`, `updated_at`
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## 8. Regras de negócio relevantes
|
|
353
|
+
|
|
354
|
+
- Tipos de relação entre pessoas são fixos e não podem ser alterados via API.
|
|
355
|
+
- Apenas um contato, endereço ou documento pode ser marcado como primário por tipo para uma pessoa.
|
|
356
|
+
- Registro de pessoas do tipo empresa pode ser desabilitado via configuração `contact-allow-company-registration`.
|
|
357
|
+
- Ao criar ou atualizar pessoa, validações garantem integridade das relações e dados.
|
|
358
|
+
- Exclusão de pessoas remove em cascata contatos, documentos, endereços, relações e metadados associados.
|
|
359
|
+
- Avatar público pode ser acessado via endpoint público, com cache control configurado.
|
|
360
|
+
- Ao criar pessoa sem usuário, é enviado email com link para criação de conta, com token JWT válido por 1 dia.
|
|
361
|
+
- Metadados como `notes` e `employer_company_id` são armazenados separadamente e sincronizados.
|
|
362
|
+
- Empresas não podem ser vinculadas como sua própria matriz (headquarter).
|
|
363
|
+
- Apenas empresas podem ser vinculadas como matriz ou filial.
|
|
364
|
+
- Validações específicas impedem inconsistências nas relações de empresas e indivíduos.
|
|
365
|
+
|
|
366
|
+
## 9. Guia rápido de uso (exemplos)
|
|
367
|
+
|
|
368
|
+
### Criar tipo de contato
|
|
369
|
+
|
|
370
|
+
```http
|
|
371
|
+
POST /person-contact-type
|
|
372
|
+
Authorization: Bearer <token>
|
|
373
|
+
Content-Type: application/json
|
|
374
|
+
|
|
375
|
+
{
|
|
376
|
+
"code": "phone",
|
|
377
|
+
"locale": {
|
|
378
|
+
"pt": { "name": "Telefone" },
|
|
379
|
+
"en": { "name": "Phone" }
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Atualizar tipo de documento
|
|
385
|
+
|
|
386
|
+
```http
|
|
387
|
+
PATCH /person-document-type/3
|
|
388
|
+
Authorization: Bearer <token>
|
|
389
|
+
Content-Type: application/json
|
|
390
|
+
|
|
391
|
+
{
|
|
392
|
+
"is_unique": true,
|
|
393
|
+
"locale": {
|
|
394
|
+
"pt": { "name": "CPF" },
|
|
395
|
+
"en": { "name": "CPF" }
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Listar pessoas com filtro e paginação
|
|
401
|
+
|
|
402
|
+
```http
|
|
403
|
+
GET /person?search=joao&type=individual&status=active&page=1&pageSize=20
|
|
404
|
+
Authorization: Bearer <token>
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Criar pessoa
|
|
408
|
+
|
|
409
|
+
```http
|
|
410
|
+
POST /person
|
|
411
|
+
Authorization: Bearer <token>
|
|
412
|
+
Content-Type: application/json
|
|
413
|
+
|
|
414
|
+
{
|
|
415
|
+
"name": "João Silva",
|
|
416
|
+
"type": "individual",
|
|
417
|
+
"status": "active",
|
|
418
|
+
"birth_date": "1980-05-10",
|
|
419
|
+
"gender": "male",
|
|
420
|
+
"contacts": [
|
|
421
|
+
{
|
|
422
|
+
"value": "joao@example.com",
|
|
423
|
+
"is_primary": true,
|
|
424
|
+
"contact_type_id": 1
|
|
425
|
+
}
|
|
426
|
+
],
|
|
427
|
+
"addresses": [
|
|
428
|
+
{
|
|
429
|
+
"line1": "Rua A, 123",
|
|
430
|
+
"city": "São Paulo",
|
|
431
|
+
"state": "SP",
|
|
432
|
+
"country_code": "BRA",
|
|
433
|
+
"postal_code": "01000-000",
|
|
434
|
+
"is_primary": true,
|
|
435
|
+
"address_type": "residential"
|
|
436
|
+
}
|
|
437
|
+
],
|
|
438
|
+
"documents": [
|
|
439
|
+
{
|
|
440
|
+
"value": "123.456.789-00",
|
|
441
|
+
"document_type_id": 1
|
|
442
|
+
}
|
|
443
|
+
]
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### Atualizar pessoa
|
|
448
|
+
|
|
449
|
+
```http
|
|
450
|
+
PATCH /person/10
|
|
451
|
+
Authorization: Bearer <token>
|
|
452
|
+
Content-Type: application/json
|
|
453
|
+
|
|
454
|
+
{
|
|
455
|
+
"name": "João da Silva",
|
|
456
|
+
"status": "active",
|
|
457
|
+
"contacts": [
|
|
458
|
+
{
|
|
459
|
+
"id": 5,
|
|
460
|
+
"value": "joao.novo@example.com",
|
|
461
|
+
"is_primary": true,
|
|
462
|
+
"contact_type_id": 1
|
|
463
|
+
}
|
|
464
|
+
]
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### Excluir pessoas
|
|
469
|
+
|
|
470
|
+
```http
|
|
471
|
+
DELETE /person
|
|
472
|
+
Authorization: Bearer <token>
|
|
473
|
+
Content-Type: application/json
|
|
474
|
+
|
|
475
|
+
{
|
|
476
|
+
"ids": [10, 11, 12]
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
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.
|
|
483
|
+
```
|
|
@@ -13,6 +13,10 @@ export declare class PersonController {
|
|
|
13
13
|
active: number;
|
|
14
14
|
inactive: number;
|
|
15
15
|
}>;
|
|
16
|
+
getOwnerOptions(user: any): Promise<{
|
|
17
|
+
id: number;
|
|
18
|
+
name: string;
|
|
19
|
+
}[]>;
|
|
16
20
|
list(paginationParams: any, filters: any): Promise<{
|
|
17
21
|
total: any;
|
|
18
22
|
lastPage: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"person.controller.d.ts","sourceRoot":"","sources":["../../src/person/person.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"person.controller.d.ts","sourceRoot":"","sources":["../../src/person/person.controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAsB,MAAM,cAAc,CAAC;AAiB7D,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,qBAEa,gBAAgB;IAGzB,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAIzC,QAAQ;;;;;;;IAKR,eAAe,CAAS,IAAI,KAAA;;;;IAK5B,IAAI,CAAe,gBAAgB,KAAA,EAAW,OAAO,KAAA;;;;;;;;;IAMrD,UAAU,CACa,EAAE,EAAE,MAAM,EAC9B,GAAG,EAAE,QAAQ,EACV,MAAM,EAAE,MAAM;IAMpB,GAAG,CAA4B,EAAE,EAAE,MAAM,EAAY,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAKnE,MAAM,CAAS,IAAI,EAAE,SAAS,EAAY,MAAM,EAAE,MAAM;;;;;;;;;IAKxD,MAAM,CACiB,EAAE,EAAE,MAAM,EAC7B,IAAI,EAAE,kBAAkB,EACtB,MAAM,EAAE,MAAM;;;IAMpB,MAAM,CAAS,IAAI,EAAE,SAAS,EAAY,MAAM,EAAE,MAAM;CAG/D"}
|
|
@@ -29,6 +29,9 @@ let PersonController = class PersonController {
|
|
|
29
29
|
async getStats() {
|
|
30
30
|
return this.personService.getStats();
|
|
31
31
|
}
|
|
32
|
+
async getOwnerOptions(user) {
|
|
33
|
+
return this.personService.getOwnerOptions(Number((user === null || user === void 0 ? void 0 : user.id) || 0));
|
|
34
|
+
}
|
|
32
35
|
async list(paginationParams, filters) {
|
|
33
36
|
return this.personService.list(Object.assign(Object.assign({}, paginationParams), filters));
|
|
34
37
|
}
|
|
@@ -55,6 +58,13 @@ __decorate([
|
|
|
55
58
|
__metadata("design:paramtypes", []),
|
|
56
59
|
__metadata("design:returntype", Promise)
|
|
57
60
|
], PersonController.prototype, "getStats", null);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, common_1.Get)('owner-options'),
|
|
63
|
+
__param(0, (0, api_1.User)()),
|
|
64
|
+
__metadata("design:type", Function),
|
|
65
|
+
__metadata("design:paramtypes", [Object]),
|
|
66
|
+
__metadata("design:returntype", Promise)
|
|
67
|
+
], PersonController.prototype, "getOwnerOptions", null);
|
|
58
68
|
__decorate([
|
|
59
69
|
(0, common_1.Get)(),
|
|
60
70
|
__param(0, (0, api_pagination_1.Pagination)()),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"person.controller.js","sourceRoot":"","sources":["../../src/person/person.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"person.controller.js","sourceRoot":"","sources":["../../src/person/person.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,10 +16,19 @@ export declare class PersonService {
|
|
|
16
16
|
active: number;
|
|
17
17
|
inactive: number;
|
|
18
18
|
}>;
|
|
19
|
+
getOwnerOptions(currentUserId?: number): Promise<{
|
|
20
|
+
id: number;
|
|
21
|
+
name: string;
|
|
22
|
+
}[]>;
|
|
19
23
|
list(paginationParams: PaginationDTO & {
|
|
20
|
-
type
|
|
21
|
-
status
|
|
22
|
-
|
|
24
|
+
type?: string;
|
|
25
|
+
status?: string;
|
|
26
|
+
owner_user_id?: string | number;
|
|
27
|
+
source?: string;
|
|
28
|
+
lifecycle_stage?: string;
|
|
29
|
+
follow_up_status?: string;
|
|
30
|
+
mine?: string | boolean;
|
|
31
|
+
}, currentUserId?: number): Promise<{
|
|
23
32
|
total: any;
|
|
24
33
|
lastPage: number;
|
|
25
34
|
page: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"person.service.d.ts","sourceRoot":"","sources":["../../src/person/person.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAQ5D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"person.service.d.ts","sourceRoot":"","sources":["../../src/person/person.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAQ5D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAc7C,qBACa,aAAa;IAGtB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAElC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBANd,aAAa,EAAE,aAAa,EAE5B,iBAAiB,EAAE,iBAAiB,EAEpC,WAAW,EAAE,WAAW,EAExB,cAAc,EAAE,cAAc;IAG3C,QAAQ;;;;;;;IAwCR,eAAe,CAAC,aAAa,CAAC,EAAE,MAAM;YAoCP,MAAM;cAAQ,MAAM;;IAYnD,IAAI,CACR,gBAAgB,EAAE,aAAa,GAAG;QAChC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;KACzB,EACD,aAAa,CAAC,EAAE,MAAM;;;;;;;;;IA8DlB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAoC9B,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM;;;;;;;;;IA8BtC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM;;;IAkE5C,MAAM,CAAC,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM;IAiFzC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG;YA2BjD,YAAY;IA+H1B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,gBAAgB;YAUV,qBAAqB;YA+GrB,mBAAmB;YAsDnB,kBAAkB;YAmBlB,mBAAmB;IAwCjC,OAAO,CAAC,sBAAsB;YAmBhB,YAAY;YAkBZ,aAAa;YAgEb,aAAa;IAkB3B,OAAO,CAAC,4BAA4B;IAuBpC,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,YAAY;YAKN,kBAAkB;IAiEhC,OAAO,CAAC,eAAe;YAIT,+BAA+B;YAoB/B,gCAAgC;YAkChC,4BAA4B;YAQ5B,qBAAqB;IAgBnC,OAAO,CAAC,8BAA8B;CAiBvC"}
|
|
@@ -19,6 +19,12 @@ const api_prisma_1 = require("@hed-hog/api-prisma");
|
|
|
19
19
|
const core_1 = require("@hed-hog/core");
|
|
20
20
|
const common_1 = require("@nestjs/common");
|
|
21
21
|
const CONTACT_ALLOW_COMPANY_REGISTRATION_SETTING = 'contact-allow-company-registration';
|
|
22
|
+
const CONTACT_OWNER_ROLE_SLUG = 'owner-contact';
|
|
23
|
+
const CONTACT_OWNER_ALLOWED_ROLE_SLUGS = [
|
|
24
|
+
'admin',
|
|
25
|
+
'admin-contact',
|
|
26
|
+
CONTACT_OWNER_ROLE_SLUG,
|
|
27
|
+
];
|
|
22
28
|
const EMPLOYER_COMPANY_METADATA_KEY = 'employer_company_id';
|
|
23
29
|
const NOTES_METADATA_KEY = 'notes';
|
|
24
30
|
let PersonService = class PersonService {
|
|
@@ -63,7 +69,52 @@ let PersonService = class PersonService {
|
|
|
63
69
|
inactive,
|
|
64
70
|
};
|
|
65
71
|
}
|
|
66
|
-
async
|
|
72
|
+
async getOwnerOptions(currentUserId) {
|
|
73
|
+
const where = {
|
|
74
|
+
OR: [
|
|
75
|
+
{
|
|
76
|
+
role_user: {
|
|
77
|
+
some: {
|
|
78
|
+
role: {
|
|
79
|
+
slug: {
|
|
80
|
+
in: CONTACT_OWNER_ALLOWED_ROLE_SLUGS,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
...(Number(currentUserId) > 0
|
|
87
|
+
? [
|
|
88
|
+
{
|
|
89
|
+
id: Number(currentUserId),
|
|
90
|
+
},
|
|
91
|
+
]
|
|
92
|
+
: []),
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
const users = await this.prismaService.user.findMany({
|
|
96
|
+
where,
|
|
97
|
+
select: {
|
|
98
|
+
id: true,
|
|
99
|
+
name: true,
|
|
100
|
+
},
|
|
101
|
+
orderBy: {
|
|
102
|
+
name: 'asc',
|
|
103
|
+
},
|
|
104
|
+
take: 500,
|
|
105
|
+
});
|
|
106
|
+
const byId = new Map();
|
|
107
|
+
for (const user of users) {
|
|
108
|
+
if (!(user === null || user === void 0 ? void 0 : user.id))
|
|
109
|
+
continue;
|
|
110
|
+
byId.set(user.id, {
|
|
111
|
+
id: user.id,
|
|
112
|
+
name: user.name || `#${user.id}`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return Array.from(byId.values());
|
|
116
|
+
}
|
|
117
|
+
async list(paginationParams, currentUserId) {
|
|
67
118
|
var _a;
|
|
68
119
|
const allowCompanyRegistration = await this.isCompanyRegistrationAllowed();
|
|
69
120
|
const where = {};
|
|
@@ -746,16 +797,16 @@ let PersonService = class PersonService {
|
|
|
746
797
|
}
|
|
747
798
|
async findPersonIdsByNormalizedDigits(normalizedDigits) {
|
|
748
799
|
const likeValue = `%${normalizedDigits}%`;
|
|
749
|
-
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
750
|
-
SELECT DISTINCT p.id
|
|
751
|
-
FROM person p
|
|
752
|
-
LEFT JOIN contact c ON c.person_id = p.id
|
|
753
|
-
LEFT JOIN document d ON d.person_id = p.id
|
|
754
|
-
LEFT JOIN person_address pa ON pa.person_id = p.id
|
|
755
|
-
LEFT JOIN address a ON a.id = pa.address_id
|
|
756
|
-
WHERE regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
757
|
-
OR regexp_replace(COALESCE(d.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
758
|
-
OR regexp_replace(COALESCE(a.postal_code, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
800
|
+
const rows = await this.prismaService.$queryRaw(api_prisma_1.Prisma.sql `
|
|
801
|
+
SELECT DISTINCT p.id
|
|
802
|
+
FROM person p
|
|
803
|
+
LEFT JOIN contact c ON c.person_id = p.id
|
|
804
|
+
LEFT JOIN document d ON d.person_id = p.id
|
|
805
|
+
LEFT JOIN person_address pa ON pa.person_id = p.id
|
|
806
|
+
LEFT JOIN address a ON a.id = pa.address_id
|
|
807
|
+
WHERE regexp_replace(COALESCE(c.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
808
|
+
OR regexp_replace(COALESCE(d.value, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
809
|
+
OR regexp_replace(COALESCE(a.postal_code, ''), '[^0-9]+', '', 'g') ILIKE ${likeValue}
|
|
759
810
|
`);
|
|
760
811
|
return rows.map((row) => row.id);
|
|
761
812
|
}
|