Skip to content

feat(partners): Fornecedor pessoa física (CPF) — SupplierDocument, PF sem Razão Social/Nome Fantasia #1022

Description

@lekadecastro

Contexto

O cliente tem fornecedores pessoa física, pagos por RPA. Hoje o cadastro de Fornecedor só aceita CNPJ, então esse fornecedor não entra no sistema.

O cálculo do RPA já existe: o Contas a Pagar ativa o motor fiscal para documento de RPA (campos de imposto abertos, bruto/líquido, obrigações tributárias). Esta issue é só o cadastro.

Colaborador e Fornecedor seguem separados: têm função e significado diferentes na operação do cliente. O mesmo CPF existir nos dois cadastros é aceito.

Estado atual (origin/dev)

  • domain/supplier/types.ts: cnpj: Cnpj (VO do kernel, parse exige 14 caracteres).
  • par_suppliers.cnpj: cnpjKey = varchar(14), UNIQUE par_suppliers_cnpj_idx. corporate_name e fantasy_name são NOT NULL.
  • supplier-schemas.ts:131: cnpj: z.string().length(14) (create e update).
  • supplier.mapper.ts:84: reidrata com Cnpj.parse, então uma linha com CPF quebraria na leitura.
  • Cpf já existe no kernel (shared/kernel/cpf.ts).
  • O CNAB já está pronto para CPF. financial/domain/payout/inscription.ts:83 deriva o tipo de inscrição do tamanho (11 → 1, senão 2), e o read-model financeiro já usa document (varchar(20)).

Desenho

1. Domínio: SupplierDocument (no módulo partners, não no kernel)

type SupplierDocument =
  | { kind: 'cpf';  value: Cpf }    // PF
  | { kind: 'cnpj'; value: Cnpj }   // PJ
  • parse: qualquer letra ou 14 caracteres usa Cnpj.parse; 11 dígitos usa Cpf.parse; outro tamanho é recusado com invalid-supplier-document.
  • O Cnpj do kernel não muda: Financiador e Acordo continuam usando ele.
  • O tipo (PF/PJ) não é gravado. Ele é derivado do documento, porque um campo separado permitiria gravar PF com um CNPJ.

2. Invariante PF × PJ

PF (CPF) PJ (CNPJ)
name nome completo, obrigatório como hoje
corporateName não existe (null) obrigatório
fantasyName não existe (null) obrigatório
  • PF com corporateName/fantasyName preenchido é recusado (422), não ignorado: supplier-corporate-name-not-allowed-for-pf e supplier-fantasy-name-not-allowed-for-pf.
  • Trocar PF ↔ PJ na edição é mudança do campo sensível e exige a mesma permissão de hoje (supplier:edit-sensitive). Ao virar PJ, corporateName e fantasyName passam a ser obrigatórios.

3. Migração 0020

  • Renomear cnpj para document (continua varchar(14)) e o índice para par_suppliers_document_idx. CPF (11) e CNPJ (14) nunca colidem no índice.
  • corporate_name e fantasy_name passam a aceitar NULL, com CHECK amarrado ao tamanho do documento:
    CHECK ((CHAR_LENGTH(document) = 11) = (corporate_name IS NULL)), e o mesmo para fantasy_name.
  • Sem backfill: toda linha atual tem CNPJ de 14 caracteres.
  • O mapper passa a reidratar com SupplierDocument.parse. A detecção de duplicata (supplier-repository.drizzle.ts:34-43) passa a olhar o novo nome do índice.

4. HTTP

  • Entrada (POST e PUT): document com 11 ou 14 caracteres. cnpj continua aceito como alias deprecated por um ciclo, para o backend subir antes do front sem quebrar a tela atual.
  • Resposta (detalhe e lista): document e personType: 'PF' | 'PJ' (derivado, não gravado). cnpj continua na resposta como alias deprecated por um ciclo.
  • Códigos de erro:
    • invalid-cnpj vira invalid-supplier-document.
    • register-supplier-cnpj-duplicate, supplier-cnpj-duplicate e edit-supplier-cnpj-duplicate viram *-document-duplicate.
    • Entram os dois códigos de PF da seção 2.
  • Busca da lista: passa a encontrar também por CPF.
  • Batch (suppliers:batch): já usa taxId, sem mudança.

5. O que depende do fornecedor

  • Evento SupplierRegistered: o campo cnpj vira document. Consumidores aceitam as duas formas enquanto houver eventos antigos no outbox.
  • Preenchimento pela leitura da nota (contractor-read.drizzle.ts:136, find-supplier-by-cnpj.ts): a busca por documento tenta CPF também.
  • CSV (supplier-csv.ts): cabeçalho "CPF/CNPJ".
  • CNAB/VAN: sem mudança de código. Entram testes com favorecido CPF em transferência, boleto (J-52) e Pix.
  • Documentação: ADR novo com supersedes parcial do ADR-0031 (o campo sensível do Supplier deixa de ser cnpj).

6. Legado

Verificar se a ETL de fornecedores recusou registros por não serem CNPJ. Se recusou, recarregar esses fornecedores depois desta entrega.

Critérios de aceite

  • POST com CPF válido e sem corporateName/fantasyName cria o fornecedor (personType: 'PF').
  • POST com CPF de dígito verificador errado → 422 invalid-supplier-document.
  • POST com CPF e corporateName → 422 supplier-corporate-name-not-allowed-for-pf.
  • POST com CNPJ sem corporateName → 422, como hoje.
  • POST com cnpj (alias) continua funcionando.
  • CPF duplicado → 409 register-supplier-document-duplicate.
  • GET de um fornecedor PF reidrata sem erro e devolve document e personType.
  • PUT trocando PF ↔ PJ sem supplier:edit-sensitive → recusado.
  • Remessa com favorecido fornecedor PF sai com tipo de inscrição 1.
  • Financiador e Acordo continuam recusando CPF.

Front

Spec web-app specs/117-fornecedor-pessoa-fisica. Na tela, uma chave segmentada Pessoa Jurídica | Pessoa Física controla o rótulo, a máscara e os campos. O front consome personType em Contratos e no Lançar Documento, e só vai para produção depois desta issue.

Activity

  1. lekadecastro commented on Oct 2, 2026

    @lekadecastro
    ContributorAuthor

    Front da #1022: situação e dois pontos para o backend

    O front do fornecedor pessoa física entrou na develop do web-app (web-app#409), validado em tela pela P.O. contra a dev do core-api com o #1025.

    1. O front envia document e o alias cnpj (web-app#412)

    O corpo de criar/editar fornecedor leva os dois campos, com o mesmo valor. O motivo é que front e backend sobem por esteiras separadas, e não conseguimos confirmar se o core-api da homologação (pipeline erp-bem-comum-backend-hml) já tem o fbbca89d4. Um core-api anterior só lê cnpj. Sem o alias, salvar qualquer fornecedor, inclusive PJ, daria 400 por lá.

    2. Pergunta: a homologação já está com o #1025?

    Precisamos dessa confirmação para a P.O. validar o cadastro de PF na homologação. Sem o #1025, PF falha (PJ segue funcionando, por causa do item 1). Daqui não temos acesso à pipeline da AWS nem a um endpoint que diga a versão.

    Para registro: o agregador /api/v1/partners não tem personType

    Contratos e Lançar Documento leem o agregador, que devolve document mas não personType. O front deriva o tipo pelo documento (11 dígitos = CPF). Funciona e não bloqueia nada. Se um dia o agregador passar a trazer personType, o front passa a usá-lo.

    🤖 Generated with Claude Code

  2. lekadecastro commented on Oct 2, 2026

    @lekadecastro
    ContributorAuthor

    Atualização: a P.O. confirmou que a homologação já está com o #1025. A pergunta do item 2 do comentário anterior está respondida. Segue valendo o item 1: avisem aqui antes de retirar o alias cnpj.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions