@77sol-ui/form-schemas 1.0.0
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 +166 -0
- package/package.json +61 -0
- package/src/domains/financing/enums/banks.ts +22 -0
- package/src/domains/financing/enums/index.ts +2 -0
- package/src/domains/financing/enums/occupation.ts +2 -0
- package/src/domains/financing/formalization/extras.ts +21 -0
- package/src/domains/financing/formalization/index.ts +16 -0
- package/src/domains/financing/formalization/refinements.ts +70 -0
- package/src/domains/financing/formalization/registry.ts +114 -0
- package/src/domains/financing/formalization/schemas/AlfaPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/AlfaPJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/BancoDoBrasilPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/BancoDoBrasilPJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/BtgPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/BtgPJSchema.ts +77 -0
- package/src/domains/financing/formalization/schemas/BvPFSchema.ts +59 -0
- package/src/domains/financing/formalization/schemas/BvPJSchema.ts +84 -0
- package/src/domains/financing/formalization/schemas/CaixaEconomicaFederalPFSchema.ts +48 -0
- package/src/domains/financing/formalization/schemas/CaixaEconomicaFederalPJSchema.ts +67 -0
- package/src/domains/financing/formalization/schemas/CashMePFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/CashMePJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/Credito77PFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/Credito77PJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/EosPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/EosPJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/HdtEnergyPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/HdtEnergyPJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/LosangoPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/LosangoPJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/SafraPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/SafraPJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/SantanderPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/SantanderPJSchema.ts +65 -0
- package/src/domains/financing/formalization/schemas/SolAgoraPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/SolAgoraPJSchema.ts +75 -0
- package/src/domains/financing/formalization/schemas/SolfacilPFSchema.ts +46 -0
- package/src/domains/financing/formalization/schemas/SolfacilPJSchema.ts +70 -0
- package/src/domains/financing/formalization/uiMeta.ts +122 -0
- package/src/domains/financing/index.ts +1 -0
- package/src/index.ts +1 -0
- package/src/shared/enums/document-type.ts +4 -0
- package/src/shared/enums/index.ts +3 -0
- package/src/shared/enums/nationality.ts +2 -0
- package/src/shared/enums/sex.ts +4 -0
- package/src/shared/fields/index.ts +1 -0
- package/src/shared/fields/primitives.ts +32 -0
- package/src/shared/regex/index.ts +75 -0
- package/src/shared/regex/patterns.ts +15 -0
- package/src/shared/regex/validators.spec.ts +162 -0
- package/src/shared/regex/validators.ts +96 -0
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# @77sol/form-schemas
|
|
2
|
+
|
|
3
|
+
Repositório **central de schemas (Zod) da 77**. Cada domínio de formulário mora em sua própria camada; o primeiro domínio é o de **financiamento**, e a camada `shared/` reúne primitivos reutilizáveis (regex/validadores de formato, primitivos de campo Zod e enums comuns) — agnósticos a domínio.
|
|
4
|
+
|
|
5
|
+
O domínio de financiamento define, por banco, uma ficha **PF** (pessoa física) e uma ficha **PJ** (pessoa jurídica). **Cada banco são dois arquivos próprios em `schemas/`**: `<Banco>PFSchema.ts` (ficha PF) e `<Banco>PJSchema.ts` (ficha PJ), ambos com o **shape declarado explicitamente** (`z.object({...}).strict()`) — você abre o arquivo e lê os campos do banco direto, sem build dinâmico nem catálogo. Consumido tanto pelo **backend** (api-v3, validação no submit) quanto pelo **frontend** (validação on blur) — **sem endpoint intermediário**.
|
|
6
|
+
|
|
7
|
+
> Contexto: [USI-4045](https://linear.app/77sol/issue/USI-4045).
|
|
8
|
+
|
|
9
|
+
## Import (subpath por banco)
|
|
10
|
+
|
|
11
|
+
Cada banco é **self-contained**: os arquivos `<Banco>PFSchema.ts`/`<Banco>PJSchema.ts`
|
|
12
|
+
ficam disponíveis individualmente via o **subpath export com wildcard**
|
|
13
|
+
`./financing/formalization/schemas/*`. Não há mais registry agregado nem mapas
|
|
14
|
+
centrais — você importa **diretamente o arquivo do banco**:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { bvPfSchema } from '@77sol/form-schemas/financing/formalization/schemas/BvPFSchema'
|
|
18
|
+
import { bvPjSchema } from '@77sol/form-schemas/financing/formalization/schemas/BvPJSchema'
|
|
19
|
+
import { santanderPjSchema } from '@77sol/form-schemas/financing/formalization/schemas/SantanderPJSchema'
|
|
20
|
+
import { credito77PfSchema } from '@77sol/form-schemas/financing/formalization/schemas/Credito77PFSchema'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
O nome do **arquivo** é PascalCase do slug (`bv`→`Bv`, `banco-do-brasil`→`BancoDoBrasil`,
|
|
24
|
+
`cash-me`→`CashMe`, `credito77`→`Credito77`, `hdt-energy`→`HdtEnergy`, `sol-agora`→`SolAgora`);
|
|
25
|
+
o nome do **export** continua camelCase (`bvPfSchema`, `bancoDoBrasilPjSchema`, …).
|
|
26
|
+
|
|
27
|
+
## Uso
|
|
28
|
+
|
|
29
|
+
A validação roda igual no front (on blur/submit) e no back (no submit), a partir do
|
|
30
|
+
mesmo schema. Importe o arquivo do banco e use `.parse()`/`.safeParse()`:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { bvPfSchema } from '@77sol/form-schemas/financing/formalization/schemas/BvPFSchema'
|
|
34
|
+
import { santanderPjSchema } from '@77sol/form-schemas/financing/formalization/schemas/SantanderPJSchema'
|
|
35
|
+
|
|
36
|
+
const result = bvPfSchema.safeParse(payloadPf)
|
|
37
|
+
if (!result.success) {
|
|
38
|
+
console.log(result.error.issues) // → 400 no back / feedback no front
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
santanderPjSchema.parse(payloadPj) // empresa + avalista[]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Cada arquivo também exporta o tipo inferido correspondente (`BvPfFicha`,
|
|
45
|
+
`SantanderPjFicha`, …). Como o shape é declarado explicitamente, `z.infer` produz
|
|
46
|
+
**tipos precisos por campo**.
|
|
47
|
+
|
|
48
|
+
> Como não há mais um mapa central, quem precisa **escolher o schema dinamicamente
|
|
49
|
+
> pelo slug** monta o próprio mapa local importando só os bancos que usa.
|
|
50
|
+
|
|
51
|
+
Bancos disponíveis (slug): `credito77`, `losango`, `santander`, `btg`, `bv`,
|
|
52
|
+
`banco-do-brasil`, `caixa-economica-federal`, `alfa`, `safra`, `cash_me_`,
|
|
53
|
+
`hdt_energy`, `solfacil`, `sol_agora`, `eos`.
|
|
54
|
+
|
|
55
|
+
## Estrutura
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
src/
|
|
59
|
+
shared/ # infra interna agnóstica a domínio (não exportada)
|
|
60
|
+
regex/ # patterns + validators (CPF/CNPJ/cpfCnpj, datas) + field schemas de formato
|
|
61
|
+
fields/ # primitivos de campo Zod (textField, numberField, integerField, fileUploadField…)
|
|
62
|
+
enums/ # enums reutilizáveis (tipo_documento, sexo, nacionalidade)
|
|
63
|
+
domains/
|
|
64
|
+
financing/
|
|
65
|
+
enums/ # bancos (BANK_SLUGS/BankEnum) + ocupações
|
|
66
|
+
formalization/
|
|
67
|
+
extras.ts # campos da formalização comuns (uploads, vínculo, seguro RD/RE)
|
|
68
|
+
refinements.ts # applyPfRefinements / applyPjRefinements (RN-011/012 + nacionalidade→RNE)
|
|
69
|
+
schemas/ # DOIS ARQUIVOS ACHATADOS POR BANCO, shape explícito — sem index/barril
|
|
70
|
+
BvPFSchema.ts # ficha PF do BV (bvPfSchema)
|
|
71
|
+
BvPJSchema.ts # ficha PJ do BV (bvPjSchema)
|
|
72
|
+
SantanderPFSchema.ts # … um par PF/PJ por banco
|
|
73
|
+
… # (14 bancos = 28 arquivos achatados)
|
|
74
|
+
index.ts # barrel do escopo (só BANK_SLUGS/BankEnum/tipos — NÃO os schemas)
|
|
75
|
+
index.ts
|
|
76
|
+
index.ts # API pública root
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Cada arquivo de banco é independente: `<Banco>PFSchema.ts` e `<Banco>PJSchema.ts`
|
|
80
|
+
importam os primitivos de `shared/`, os campos comuns de `extras.ts` e os refinements de
|
|
81
|
+
`refinements.ts`, e declaram o `z.object({...})` de PF e de PJ. Sem gerador, sem catálogo
|
|
82
|
+
de dados, sem builder e **sem registry agregado**: cada arquivo é exposto direto pelo
|
|
83
|
+
subpath export `./financing/formalization/schemas/*`.
|
|
84
|
+
|
|
85
|
+
## Manutenção
|
|
86
|
+
|
|
87
|
+
A manutenção é **manual e local aos arquivos do banco** — edite o shape direto em
|
|
88
|
+
`schemas/<Banco>PFSchema.ts` (PF) ou `schemas/<Banco>PJSchema.ts` (PJ).
|
|
89
|
+
|
|
90
|
+
- **Mudar campos de um banco:** abra `schemas/<Banco>PFSchema.ts` ou `schemas/<Banco>PJSchema.ts`
|
|
91
|
+
e edite o `z.object({...})` (adicione/remova chaves, troque o schema de formato, marque `.optional()`).
|
|
92
|
+
- **Regra de formato/primitivo:** `shared/regex` (CPF/CNPJ/datas…) ou
|
|
93
|
+
`shared/fields/primitives` (`textField`, `numberField`, `integerField`).
|
|
94
|
+
- **Campos comuns da formalização** (uploads, vínculo, seguro): `extras.ts`.
|
|
95
|
+
- **Regra cross-field (RN):** `refinements.ts`.
|
|
96
|
+
|
|
97
|
+
### Adicionar um banco
|
|
98
|
+
|
|
99
|
+
**Regra do pacote: cada banco são dois arquivos de schema próprios (achatados em `schemas/`).** O passo a passo
|
|
100
|
+
está na skill **`adicionar-banco-financing`** (`.claude/skills/`). Em resumo:
|
|
101
|
+
|
|
102
|
+
1. Crie `schemas/<Banco>PFSchema.ts` e `schemas/<Banco>PJSchema.ts` (shape explícito).
|
|
103
|
+
2. (Opcional) adicione o `slug` em `BANK_SLUGS` (`enums/banks.ts`) só se quiser o banco
|
|
104
|
+
listado no enum — os schemas não dependem mais dele.
|
|
105
|
+
3. `yarn check:fix && yarn typecheck`.
|
|
106
|
+
|
|
107
|
+
> Teste de schema é dispensado por enquanto — não crie `.spec.ts` por banco.
|
|
108
|
+
|
|
109
|
+
> Não há registry para registrar: os arquivos ficam disponíveis automaticamente via o
|
|
110
|
+
> subpath export `./financing/formalization/schemas/*`, sem fiação central.
|
|
111
|
+
|
|
112
|
+
## Regras de negócio materializadas
|
|
113
|
+
|
|
114
|
+
Aplicadas via `.superRefine(...)` em cada banco; os campos usam os nomes definidos no schema.
|
|
115
|
+
|
|
116
|
+
| RN | Onde |
|
|
117
|
+
| -- | -- |
|
|
118
|
+
| RN-011 (RG ≤ 10 anos) | `refinements.ts` (`type_doc='rg'` + `doc_issue_date`) · CNH "não vencida" → TODO (dado ausente) |
|
|
119
|
+
| RN-012 (CNPJ por ocupação) | `refinements.ts` (`nature_of_occupation` + `cnpj_proprietary`; presentes só onde o banco os declara, ex. BV) |
|
|
120
|
+
| RN-014 (Seguro RD/RE default ON) | `extras.ts` (`rd_re_insurance_toggle: z.boolean().default(true)`) |
|
|
121
|
+
| Nacionalidade → RNE | `refinements.ts` (`nationality` ≠ Brasil força `type_doc='rne'`) |
|
|
122
|
+
| Vínculo de terceiro | `refinements.ts` (`account_third_party` ≠ `nao_se_aplica` exige `bond_document_upload`) |
|
|
123
|
+
| `.strict()` | cada ficha rejeita qualquer campo fora do shape declarado do banco |
|
|
124
|
+
|
|
125
|
+
### Campos `dropdown`/`autocomplete`
|
|
126
|
+
|
|
127
|
+
Campos de seleção são **string validada** (`textField`), exceto `type_doc`
|
|
128
|
+
(`DocumentTypeEnum`) e `sex` (`SexEnum`). Para restringir um deles, troque no
|
|
129
|
+
`<Banco>PFSchema.ts`/`<Banco>PJSchema.ts` do banco por um `z.enum([...])` — está tudo explícito no shape.
|
|
130
|
+
|
|
131
|
+
## Distribuição (source-only)
|
|
132
|
+
|
|
133
|
+
Este repositório **armazena apenas os schemas em TypeScript** — **não faz build**. Os `exports` apontam direto para o source (`src/*.ts`); quem consome transpila.
|
|
134
|
+
|
|
135
|
+
```jsonc
|
|
136
|
+
"exports": {
|
|
137
|
+
".": "./src/index.ts",
|
|
138
|
+
"./financing/formalization": "./src/domains/financing/formalization/index.ts",
|
|
139
|
+
// wildcard: cada arquivo de banco é importável direto, sem registry central
|
|
140
|
+
"./financing/formalization/schemas/*": "./src/domains/financing/formalization/schemas/*.ts"
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- **Next.js / frontend:** adicione `@77sol/form-schemas` em `transpilePackages`.
|
|
145
|
+
- **api-v3 / backend (Node + TS):** garanta que o pacote seja transpilado.
|
|
146
|
+
- **`zod`** é `peerDependency`.
|
|
147
|
+
|
|
148
|
+
## Agnóstico a framework
|
|
149
|
+
|
|
150
|
+
Depende **apenas de `zod`** (peer) — zero React/Next/Vue/DOM. Entrega schemas Zod, não
|
|
151
|
+
componentes: valide com `.parse()`/`.safeParse()` e, para renderizar, derive os campos
|
|
152
|
+
do schema (`.shape`). Um guardrail do Biome (`noRestrictedImports`) barra imports de UI.
|
|
153
|
+
|
|
154
|
+
## Scripts
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
yarn typecheck # tsc --noEmit
|
|
158
|
+
yarn test # vitest
|
|
159
|
+
yarn lint # biome lint
|
|
160
|
+
yarn run check # biome check (lint + formatação)
|
|
161
|
+
yarn check:fix # biome check --write
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Versionamento
|
|
165
|
+
|
|
166
|
+
Conventional Commits + changelog automático via `semantic-release` (ver `.releaserc.json`).
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@77sol-ui/form-schemas",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Fonte central de schemas Zod da 77 (source-only). Financiamento (PF) é o primeiro domínio; consumido direto do código-fonte pelo backend e frontend.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"private": false,
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./src/index.ts",
|
|
9
|
+
"types": "./src/index.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./src/index.ts",
|
|
12
|
+
"./financing/formalization": "./src/domains/financing/formalization/index.ts",
|
|
13
|
+
"./financing/formalization/schemas/*": "./src/domains/financing/formalization/schemas/*.ts"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public",
|
|
21
|
+
"registry": "https://registry.npmjs.org"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "yarn typecheck && yarn lint && yarn test",
|
|
25
|
+
"release:local": "npm publish",
|
|
26
|
+
"prepublishOnly": "yarn build",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"lint": "biome lint",
|
|
31
|
+
"lint:fix": "biome lint --write",
|
|
32
|
+
"format": "biome format --write",
|
|
33
|
+
"format:check": "biome format",
|
|
34
|
+
"check": "biome check",
|
|
35
|
+
"check:fix": "biome check --write",
|
|
36
|
+
"docs:dev": "vitepress dev docs",
|
|
37
|
+
"docs:build": "vitepress build docs",
|
|
38
|
+
"docs:preview": "vitepress preview docs",
|
|
39
|
+
"prepare": "husky"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"zod": "^3.23.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@biomejs/biome": "2.4.15",
|
|
46
|
+
"@commitlint/cli": "^19.0.0",
|
|
47
|
+
"@commitlint/config-conventional": "^19.0.0",
|
|
48
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
49
|
+
"@semantic-release/git": "^10.0.1",
|
|
50
|
+
"@types/node": "^20.11.0",
|
|
51
|
+
"husky": "^9.0.0",
|
|
52
|
+
"semantic-release": "^23.0.0",
|
|
53
|
+
"typescript": "^5.4.0",
|
|
54
|
+
"vitepress": "^1.6.3",
|
|
55
|
+
"vitest": "^1.5.0",
|
|
56
|
+
"zod": "^3.23.0"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=20"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
export const BANK_SLUGS = [
|
|
4
|
+
'credito77',
|
|
5
|
+
'losango',
|
|
6
|
+
'santander',
|
|
7
|
+
'btg',
|
|
8
|
+
'bv',
|
|
9
|
+
'banco-do-brasil',
|
|
10
|
+
'caixa-economica-federal',
|
|
11
|
+
'alfa',
|
|
12
|
+
'safra',
|
|
13
|
+
'cash_me_',
|
|
14
|
+
'hdt_energy',
|
|
15
|
+
'solfacil',
|
|
16
|
+
'sol_agora',
|
|
17
|
+
'eos',
|
|
18
|
+
] as const
|
|
19
|
+
|
|
20
|
+
export const BankEnum = z.enum(BANK_SLUGS)
|
|
21
|
+
export type Bank = z.infer<typeof BankEnum>
|
|
22
|
+
export type BankSlug = Bank
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { fileUploadField, selectField } from '../../../shared/fields/primitives'
|
|
3
|
+
|
|
4
|
+
const THIRD_PARTY_OPTIONS = [
|
|
5
|
+
'nao_se_aplica',
|
|
6
|
+
'conjuge',
|
|
7
|
+
'pai_mae',
|
|
8
|
+
'filho_filha',
|
|
9
|
+
'parente',
|
|
10
|
+
'outro',
|
|
11
|
+
] as const
|
|
12
|
+
|
|
13
|
+
export const formalizationExtras = {
|
|
14
|
+
energy_bill_upload: fileUploadField,
|
|
15
|
+
account_third_party: selectField(THIRD_PARTY_OPTIONS),
|
|
16
|
+
bond_document_upload: fileUploadField.optional(),
|
|
17
|
+
document_front_upload: fileUploadField,
|
|
18
|
+
document_back_upload: fileUploadField,
|
|
19
|
+
// RN-014: seguro RD/RE começa ON.
|
|
20
|
+
rd_re_insurance_toggle: z.boolean().default(true),
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type { Bank, BankSlug } from '../enums'
|
|
2
|
+
export { BANK_SLUGS, BankEnum } from '../enums'
|
|
3
|
+
export type { PersonType } from './registry'
|
|
4
|
+
export {
|
|
5
|
+
getFormalizationBaseSchema,
|
|
6
|
+
getFormalizationSchema,
|
|
7
|
+
pfBaseSchemaRegistry,
|
|
8
|
+
pfSchemaRegistry,
|
|
9
|
+
pjBaseSchemaRegistry,
|
|
10
|
+
pjSchemaRegistry,
|
|
11
|
+
} from './registry'
|
|
12
|
+
export type {
|
|
13
|
+
FormalizationFieldKind,
|
|
14
|
+
FormalizationFieldMeta,
|
|
15
|
+
} from './uiMeta'
|
|
16
|
+
export { FORMALIZATION_FIELD_META } from './uiMeta'
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { NATIONALITY_BRAZIL } from '../../../shared/enums'
|
|
3
|
+
import { yearsSinceDMY } from '../../../shared/regex'
|
|
4
|
+
import { OCCUPATIONS_REQUIRING_CNPJ } from '../enums'
|
|
5
|
+
|
|
6
|
+
const RG_MAX_EMISSION_YEARS = 10
|
|
7
|
+
|
|
8
|
+
function applyCommonRefinements(data: Record<string, unknown>, ctx: z.RefinementCtx): void {
|
|
9
|
+
// Documento de vínculo obrigatório se a conta está em nome de terceiro.
|
|
10
|
+
if (
|
|
11
|
+
'account_third_party' in data &&
|
|
12
|
+
typeof data.account_third_party === 'string' &&
|
|
13
|
+
data.account_third_party !== 'nao_se_aplica' &&
|
|
14
|
+
!data.bond_document_upload
|
|
15
|
+
) {
|
|
16
|
+
ctx.addIssue({
|
|
17
|
+
code: z.ZodIssueCode.custom,
|
|
18
|
+
path: ['bond_document_upload'],
|
|
19
|
+
message: 'Documento de vínculo é obrigatório quando a conta está em nome de terceiro',
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function applyPfRefinements(data: Record<string, unknown>, ctx: z.RefinementCtx): void {
|
|
25
|
+
applyCommonRefinements(data, ctx)
|
|
26
|
+
|
|
27
|
+
// RN-012: CNPJ do proprietário obrigatório se ocupação ∈ {empresário/proprietário}.
|
|
28
|
+
if (
|
|
29
|
+
'nature_of_occupation' in data &&
|
|
30
|
+
typeof data.nature_of_occupation === 'string' &&
|
|
31
|
+
(OCCUPATIONS_REQUIRING_CNPJ as readonly string[]).includes(data.nature_of_occupation) &&
|
|
32
|
+
!data.cnpj_proprietary
|
|
33
|
+
) {
|
|
34
|
+
ctx.addIssue({
|
|
35
|
+
code: z.ZodIssueCode.custom,
|
|
36
|
+
path: ['cnpj_proprietary'],
|
|
37
|
+
message: 'CNPJ do proprietário é obrigatório para esta ocupação',
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// RN-011: RG aceito com no máximo 10 anos de emissão.
|
|
42
|
+
if (data.type_doc === 'rg' && typeof data.doc_issue_date === 'string') {
|
|
43
|
+
const years = yearsSinceDMY(data.doc_issue_date)
|
|
44
|
+
if (years !== null && years > RG_MAX_EMISSION_YEARS) {
|
|
45
|
+
ctx.addIssue({
|
|
46
|
+
code: z.ZodIssueCode.custom,
|
|
47
|
+
path: ['doc_issue_date'],
|
|
48
|
+
message: `RG deve ter no máximo ${RG_MAX_EMISSION_YEARS} anos de emissão`,
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Nacionalidade ≠ Brasil → tipo de documento deve ser RNE (estrangeiro).
|
|
54
|
+
if (
|
|
55
|
+
typeof data.nationality === 'string' &&
|
|
56
|
+
data.nationality.toLowerCase() !== NATIONALITY_BRAZIL &&
|
|
57
|
+
'type_doc' in data &&
|
|
58
|
+
data.type_doc !== 'rne'
|
|
59
|
+
) {
|
|
60
|
+
ctx.addIssue({
|
|
61
|
+
code: z.ZodIssueCode.custom,
|
|
62
|
+
path: ['type_doc'],
|
|
63
|
+
message: 'Para nacionalidade estrangeira, o documento deve ser Registro de Estrangeiro (RNE)',
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function applyPjRefinements(data: Record<string, unknown>, ctx: z.RefinementCtx): void {
|
|
69
|
+
applyCommonRefinements(data, ctx)
|
|
70
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { AnyZodObject, ZodTypeAny } from 'zod'
|
|
2
|
+
import type { BankSlug } from '../enums'
|
|
3
|
+
import { alfaPfObject, alfaPfSchema } from './schemas/AlfaPFSchema'
|
|
4
|
+
import { alfaPjObject, alfaPjSchema } from './schemas/AlfaPJSchema'
|
|
5
|
+
import { bancoDoBrasilPfObject, bancoDoBrasilPfSchema } from './schemas/BancoDoBrasilPFSchema'
|
|
6
|
+
import { bancoDoBrasilPjObject, bancoDoBrasilPjSchema } from './schemas/BancoDoBrasilPJSchema'
|
|
7
|
+
import { btgPfObject, btgPfSchema } from './schemas/BtgPFSchema'
|
|
8
|
+
import { btgPjObject, btgPjSchema } from './schemas/BtgPJSchema'
|
|
9
|
+
import { bvPfObject, bvPfSchema } from './schemas/BvPFSchema'
|
|
10
|
+
import { bvPjObject, bvPjSchema } from './schemas/BvPJSchema'
|
|
11
|
+
import {
|
|
12
|
+
caixaEconomicaFederalPfObject,
|
|
13
|
+
caixaEconomicaFederalPfSchema,
|
|
14
|
+
} from './schemas/CaixaEconomicaFederalPFSchema'
|
|
15
|
+
import {
|
|
16
|
+
caixaEconomicaFederalPjObject,
|
|
17
|
+
caixaEconomicaFederalPjSchema,
|
|
18
|
+
} from './schemas/CaixaEconomicaFederalPJSchema'
|
|
19
|
+
import { cashMePfObject, cashMePfSchema } from './schemas/CashMePFSchema'
|
|
20
|
+
import { cashMePjObject, cashMePjSchema } from './schemas/CashMePJSchema'
|
|
21
|
+
import { credito77PfObject, credito77PfSchema } from './schemas/Credito77PFSchema'
|
|
22
|
+
import { credito77PjObject, credito77PjSchema } from './schemas/Credito77PJSchema'
|
|
23
|
+
import { eosPfObject, eosPfSchema } from './schemas/EosPFSchema'
|
|
24
|
+
import { eosPjObject, eosPjSchema } from './schemas/EosPJSchema'
|
|
25
|
+
import { hdtEnergyPfObject, hdtEnergyPfSchema } from './schemas/HdtEnergyPFSchema'
|
|
26
|
+
import { hdtEnergyPjObject, hdtEnergyPjSchema } from './schemas/HdtEnergyPJSchema'
|
|
27
|
+
import { losangoPfObject, losangoPfSchema } from './schemas/LosangoPFSchema'
|
|
28
|
+
import { losangoPjObject, losangoPjSchema } from './schemas/LosangoPJSchema'
|
|
29
|
+
import { safraPfObject, safraPfSchema } from './schemas/SafraPFSchema'
|
|
30
|
+
import { safraPjObject, safraPjSchema } from './schemas/SafraPJSchema'
|
|
31
|
+
import { santanderPfObject, santanderPfSchema } from './schemas/SantanderPFSchema'
|
|
32
|
+
import { santanderPjObject, santanderPjSchema } from './schemas/SantanderPJSchema'
|
|
33
|
+
import { solAgoraPfObject, solAgoraPfSchema } from './schemas/SolAgoraPFSchema'
|
|
34
|
+
import { solAgoraPjObject, solAgoraPjSchema } from './schemas/SolAgoraPJSchema'
|
|
35
|
+
import { solfacilPfObject, solfacilPfSchema } from './schemas/SolfacilPFSchema'
|
|
36
|
+
import { solfacilPjObject, solfacilPjSchema } from './schemas/SolfacilPJSchema'
|
|
37
|
+
|
|
38
|
+
export type PersonType = 'pf' | 'pj'
|
|
39
|
+
|
|
40
|
+
export const pfSchemaRegistry = {
|
|
41
|
+
credito77: credito77PfSchema,
|
|
42
|
+
losango: losangoPfSchema,
|
|
43
|
+
santander: santanderPfSchema,
|
|
44
|
+
btg: btgPfSchema,
|
|
45
|
+
bv: bvPfSchema,
|
|
46
|
+
'banco-do-brasil': bancoDoBrasilPfSchema,
|
|
47
|
+
'caixa-economica-federal': caixaEconomicaFederalPfSchema,
|
|
48
|
+
alfa: alfaPfSchema,
|
|
49
|
+
safra: safraPfSchema,
|
|
50
|
+
cash_me_: cashMePfSchema,
|
|
51
|
+
hdt_energy: hdtEnergyPfSchema,
|
|
52
|
+
solfacil: solfacilPfSchema,
|
|
53
|
+
sol_agora: solAgoraPfSchema,
|
|
54
|
+
eos: eosPfSchema,
|
|
55
|
+
} satisfies Record<BankSlug, ZodTypeAny>
|
|
56
|
+
|
|
57
|
+
export const pjSchemaRegistry = {
|
|
58
|
+
credito77: credito77PjSchema,
|
|
59
|
+
losango: losangoPjSchema,
|
|
60
|
+
santander: santanderPjSchema,
|
|
61
|
+
btg: btgPjSchema,
|
|
62
|
+
bv: bvPjSchema,
|
|
63
|
+
'banco-do-brasil': bancoDoBrasilPjSchema,
|
|
64
|
+
'caixa-economica-federal': caixaEconomicaFederalPjSchema,
|
|
65
|
+
alfa: alfaPjSchema,
|
|
66
|
+
safra: safraPjSchema,
|
|
67
|
+
cash_me_: cashMePjSchema,
|
|
68
|
+
hdt_energy: hdtEnergyPjSchema,
|
|
69
|
+
solfacil: solfacilPjSchema,
|
|
70
|
+
sol_agora: solAgoraPjSchema,
|
|
71
|
+
eos: eosPjSchema,
|
|
72
|
+
} satisfies Record<BankSlug, ZodTypeAny>
|
|
73
|
+
|
|
74
|
+
export const pfBaseSchemaRegistry = {
|
|
75
|
+
credito77: credito77PfObject,
|
|
76
|
+
losango: losangoPfObject,
|
|
77
|
+
santander: santanderPfObject,
|
|
78
|
+
btg: btgPfObject,
|
|
79
|
+
bv: bvPfObject,
|
|
80
|
+
'banco-do-brasil': bancoDoBrasilPfObject,
|
|
81
|
+
'caixa-economica-federal': caixaEconomicaFederalPfObject,
|
|
82
|
+
alfa: alfaPfObject,
|
|
83
|
+
safra: safraPfObject,
|
|
84
|
+
cash_me_: cashMePfObject,
|
|
85
|
+
hdt_energy: hdtEnergyPfObject,
|
|
86
|
+
solfacil: solfacilPfObject,
|
|
87
|
+
sol_agora: solAgoraPfObject,
|
|
88
|
+
eos: eosPfObject,
|
|
89
|
+
} satisfies Record<BankSlug, AnyZodObject>
|
|
90
|
+
|
|
91
|
+
export const pjBaseSchemaRegistry = {
|
|
92
|
+
credito77: credito77PjObject,
|
|
93
|
+
losango: losangoPjObject,
|
|
94
|
+
santander: santanderPjObject,
|
|
95
|
+
btg: btgPjObject,
|
|
96
|
+
bv: bvPjObject,
|
|
97
|
+
'banco-do-brasil': bancoDoBrasilPjObject,
|
|
98
|
+
'caixa-economica-federal': caixaEconomicaFederalPjObject,
|
|
99
|
+
alfa: alfaPjObject,
|
|
100
|
+
safra: safraPjObject,
|
|
101
|
+
cash_me_: cashMePjObject,
|
|
102
|
+
hdt_energy: hdtEnergyPjObject,
|
|
103
|
+
solfacil: solfacilPjObject,
|
|
104
|
+
sol_agora: solAgoraPjObject,
|
|
105
|
+
eos: eosPjObject,
|
|
106
|
+
} satisfies Record<BankSlug, AnyZodObject>
|
|
107
|
+
|
|
108
|
+
export function getFormalizationSchema(bank: BankSlug, person: PersonType) {
|
|
109
|
+
return person === 'pf' ? pfSchemaRegistry[bank] : pjSchemaRegistry[bank]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getFormalizationBaseSchema(bank: BankSlug, person: PersonType) {
|
|
113
|
+
return person === 'pf' ? pfBaseSchemaRegistry[bank] : pjBaseSchemaRegistry[bank]
|
|
114
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { DocumentTypeEnum, SexEnum } from '../../../../shared/enums'
|
|
3
|
+
import { textField } from '../../../../shared/fields/primitives'
|
|
4
|
+
import {
|
|
5
|
+
birthDateSchema,
|
|
6
|
+
cepSchema,
|
|
7
|
+
cpfCnpjSchema,
|
|
8
|
+
cpfSchema,
|
|
9
|
+
currencySchema,
|
|
10
|
+
emailSchema,
|
|
11
|
+
issueDateSchema,
|
|
12
|
+
phoneBRSchema,
|
|
13
|
+
} from '../../../../shared/regex'
|
|
14
|
+
import { formalizationExtras } from '../extras'
|
|
15
|
+
import { applyPfRefinements } from '../refinements'
|
|
16
|
+
|
|
17
|
+
export const alfaPfObject = z.object({
|
|
18
|
+
...formalizationExtras,
|
|
19
|
+
name: textField(),
|
|
20
|
+
cep: cepSchema,
|
|
21
|
+
cpf: cpfSchema,
|
|
22
|
+
address: textField(),
|
|
23
|
+
birth_date: birthDateSchema,
|
|
24
|
+
number: textField(),
|
|
25
|
+
sex: SexEnum,
|
|
26
|
+
complement: textField(15).optional(),
|
|
27
|
+
mother_name: textField(),
|
|
28
|
+
district: textField(),
|
|
29
|
+
energy_account_in_requester_name: textField(),
|
|
30
|
+
city: textField(),
|
|
31
|
+
energy_bill_owner_document: cpfCnpjSchema.optional(),
|
|
32
|
+
state: textField(2),
|
|
33
|
+
nationality: textField(),
|
|
34
|
+
cellphone: phoneBRSchema,
|
|
35
|
+
email: emailSchema,
|
|
36
|
+
monthly_income: currencySchema,
|
|
37
|
+
profession: textField(),
|
|
38
|
+
type_doc: DocumentTypeEnum,
|
|
39
|
+
doc: textField(15),
|
|
40
|
+
issuing_body: textField(6),
|
|
41
|
+
doc_issue_date: issueDateSchema,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
export const alfaPfSchema = alfaPfObject.strict().superRefine(applyPfRefinements)
|
|
45
|
+
|
|
46
|
+
export type AlfaPfFicha = z.infer<typeof alfaPfSchema>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { SexEnum } from '../../../../shared/enums'
|
|
3
|
+
import { textField } from '../../../../shared/fields/primitives'
|
|
4
|
+
import {
|
|
5
|
+
birthDateSchema,
|
|
6
|
+
cepSchema,
|
|
7
|
+
cnpjSchema,
|
|
8
|
+
cpfSchema,
|
|
9
|
+
currencySchema,
|
|
10
|
+
emailSchema,
|
|
11
|
+
issueDateSchema,
|
|
12
|
+
phoneBRSchema,
|
|
13
|
+
} from '../../../../shared/regex'
|
|
14
|
+
import { formalizationExtras } from '../extras'
|
|
15
|
+
import { applyPjRefinements } from '../refinements'
|
|
16
|
+
|
|
17
|
+
export const alfaPjObject = z.object({
|
|
18
|
+
...formalizationExtras,
|
|
19
|
+
financing_company: z
|
|
20
|
+
.object({
|
|
21
|
+
corporate_name: textField(),
|
|
22
|
+
cep: cepSchema,
|
|
23
|
+
address: textField(),
|
|
24
|
+
foundation_date: issueDateSchema,
|
|
25
|
+
number: textField(),
|
|
26
|
+
cnpj: cnpjSchema,
|
|
27
|
+
email: emailSchema,
|
|
28
|
+
complement: textField(15).optional(),
|
|
29
|
+
phone: phoneBRSchema,
|
|
30
|
+
district: textField(),
|
|
31
|
+
legal_nature: textField(),
|
|
32
|
+
city: textField(),
|
|
33
|
+
economic_activity_group: textField(),
|
|
34
|
+
state: textField(2),
|
|
35
|
+
economic_activity: textField(),
|
|
36
|
+
monthly_income: currencySchema,
|
|
37
|
+
})
|
|
38
|
+
.strict(),
|
|
39
|
+
financing_company_guarantor: z.array(
|
|
40
|
+
z
|
|
41
|
+
.object({
|
|
42
|
+
name: textField(),
|
|
43
|
+
cep: cepSchema,
|
|
44
|
+
cpf: cpfSchema,
|
|
45
|
+
address: textField(),
|
|
46
|
+
birth_date: birthDateSchema,
|
|
47
|
+
number: textField(),
|
|
48
|
+
complement: textField(15).optional(),
|
|
49
|
+
cellphone: phoneBRSchema,
|
|
50
|
+
email: emailSchema,
|
|
51
|
+
district: textField(),
|
|
52
|
+
sex: SexEnum,
|
|
53
|
+
city: textField(),
|
|
54
|
+
state: textField(2),
|
|
55
|
+
office: textField(),
|
|
56
|
+
mother_name: textField(),
|
|
57
|
+
nationality: textField(),
|
|
58
|
+
})
|
|
59
|
+
.strict(),
|
|
60
|
+
),
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
export const alfaPjSchema = alfaPjObject.strict().superRefine(applyPjRefinements)
|
|
64
|
+
|
|
65
|
+
export type AlfaPjFicha = z.infer<typeof alfaPjSchema>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { DocumentTypeEnum, SexEnum } from '../../../../shared/enums'
|
|
3
|
+
import { textField } from '../../../../shared/fields/primitives'
|
|
4
|
+
import {
|
|
5
|
+
birthDateSchema,
|
|
6
|
+
cepSchema,
|
|
7
|
+
cpfCnpjSchema,
|
|
8
|
+
cpfSchema,
|
|
9
|
+
currencySchema,
|
|
10
|
+
emailSchema,
|
|
11
|
+
issueDateSchema,
|
|
12
|
+
phoneBRSchema,
|
|
13
|
+
} from '../../../../shared/regex'
|
|
14
|
+
import { formalizationExtras } from '../extras'
|
|
15
|
+
import { applyPfRefinements } from '../refinements'
|
|
16
|
+
|
|
17
|
+
export const bancoDoBrasilPfObject = z.object({
|
|
18
|
+
...formalizationExtras,
|
|
19
|
+
name: textField(),
|
|
20
|
+
cep: cepSchema,
|
|
21
|
+
cpf: cpfSchema,
|
|
22
|
+
address: textField(),
|
|
23
|
+
birth_date: birthDateSchema,
|
|
24
|
+
number: textField(),
|
|
25
|
+
sex: SexEnum,
|
|
26
|
+
complement: textField(15).optional(),
|
|
27
|
+
mother_name: textField(),
|
|
28
|
+
district: textField(),
|
|
29
|
+
energy_account_in_requester_name: textField(),
|
|
30
|
+
city: textField(),
|
|
31
|
+
energy_bill_owner_document: cpfCnpjSchema.optional(),
|
|
32
|
+
state: textField(2),
|
|
33
|
+
nationality: textField(),
|
|
34
|
+
cellphone: phoneBRSchema,
|
|
35
|
+
email: emailSchema,
|
|
36
|
+
monthly_income: currencySchema,
|
|
37
|
+
profession: textField(),
|
|
38
|
+
type_doc: DocumentTypeEnum,
|
|
39
|
+
doc: textField(15),
|
|
40
|
+
issuing_body: textField(6),
|
|
41
|
+
doc_issue_date: issueDateSchema,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
export const bancoDoBrasilPfSchema = bancoDoBrasilPfObject.strict().superRefine(applyPfRefinements)
|
|
45
|
+
|
|
46
|
+
export type BancoDoBrasilPfFicha = z.infer<typeof bancoDoBrasilPfSchema>
|