Skip to content

OR-145: Corrige gaps de máscaras DARF e banco#35

Merged
FabioRolin merged 5 commits into
masterfrom
feature/OR-145-fix-mask-gaps
May 13, 2026
Merged

OR-145: Corrige gaps de máscaras DARF e banco#35
FabioRolin merged 5 commits into
masterfrom
feature/OR-145-fix-mask-gaps

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented May 12, 2026

Description

Corrige gaps de máscaras identificados na varredura de 33 MFEs, complementando o PR #33 (Fase 1 — centralização de máscaras).

Mudanças

  • DARF: corrige padrão de '99.999.999-9' para '99 9 99 999999-99' (formato original dos MFEs)
  • phone_idd: adiciona ao MaskType com padrão '+99 (99) 99999-9999' (usado pelo mfe-pix)
  • bank_branch / bank_account: adicionados ao MaskType para uso direto via maskValue
  • compensationCode dinâmico: maskValue aceita options.compensationCode para resolver máscaras bancárias por banco
  • Strip alfanumérico: maskValue e maskComplete usam stripAlphanumeric para bancos com DV alfanumérico (BB código 1), alinhando com maskBankAccount
  • maskComplete: aceita options?: string | MaskCompleteOptions para consistência de API com maskValue
  • maskBankBranch / maskBankAccount: funções dedicadas para uso direto (API pública)
  • maskHintBankAccount: alinhado fallback noop com padrão original (000000000000-0)
  • BANK_ACCOUNT_MASKS: alterado para Partial<Record> (reflete comportamento real de fallback)
  • ALPHANUMERIC_BANK_CODES: extraído para masks.ts como fonte única de verdade
  • MaskValueOptions / MaskCompleteOptions: interfaces exportadas para tipagem

Links

Co-authored-by: FabioRolin fabio.oliveira@useblu.com.br

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as before)

Nota sobre breaking changes: A varredura dos 33 MFEs confirmou que nenhum MFE consumia maskValue(x, 'darf') via blu-utils — todos usavam máscaras locais. O padrão DARF foi alterado de '99.999.999-9' (9 dígitos) para '99 9 99 999999-99' (13 dígitos) para alinhar com o formato original dos MFEs. O fallback de maskHintBankAccount também mudou de '0000000000-0' (10 dígitos) para '000000000000-0' (12 dígitos). Ambas as mudanças são retrocompatíveis na prática (nenhum consumidor existente), mas estão marcadas como breaking por precaução.

Checklist

  • Read the Contributing Guide
  • Perform a code self-review
  • Comment the code, particularly in hard-to-understand areas
  • Add documentation
  • Cover changes with tests
  • Ensure the test suite passes (yarn test)
  • Make sure code lints (yarn lint). Fix it with yarn lint:fix in case of failure.
  • Make sure types are fine (yarn lint:types).

Link to Devin session: https://app.devin.ai/sessions/018e523413e74f6882e82c8b5c9bf92d
Requested by: @FabioRolin

…ão do mfe-bill

- Corrige padrão DARF de '99.999.999-9' para '99 9 99 999999-99' (formato original dos MFEs)
- Adiciona maskBankBranch() para máscara de agência (padrão 9999, Itaú 99999-9)
- Adiciona maskBankAccount() para máscara de conta por código de compensação
- Alinha fallback noop do maskHintBankAccount com padrão original (999999999999-9)
- Exporta novas funções via index.ts

Relates to Pagnet/mfe-core#336

Co-authored-by: FabioRolin <fabio.oliveira@useblu.com.br>
Co-Authored-By: fabio.oliveira@useblu.com.br <fabio.oliveira@useblu.com.br>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Original prompt from fabio.oliveira@useblu.com.br

@playbook:playbook-93a1cfc594744b9ba2a2958123c50408

Crie uma PRD a partir do Card: https://useblu.atlassian.net/browse/OR-145

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@devin-ai-integration devin-ai-integration Bot requested a review from a team May 12, 2026 19:07
@FabioRolin FabioRolin marked this pull request as ready for review May 12, 2026 19:12
…nk_account

- Adiciona 'bank_branch' e 'bank_account' ao tipo MaskType
- maskValue('1234', 'bank_branch') → '1234' (padrão noop)
- maskValue('1234567890123', 'bank_account') → '123456789012-3' (padrão noop)
- maskComplete suporta validação de completude para os novos tipos
- Testes para maskValue e maskComplete cobrindo DARF, bank_branch e bank_account

Co-authored-by: FabioRolin <fabio.oliveira@useblu.com.br>
Co-Authored-By: fabio.oliveira@useblu.com.br <fabio.oliveira@useblu.com.br>
Comment thread src/masks/maskValue.ts Outdated
Comment thread src/masks/maskValue.ts Outdated
devin-ai-integration Bot and others added 2 commits May 12, 2026 19:24
Co-authored-by: FabioRolin <fabio.oliveira@useblu.com.br>
Co-Authored-By: fabio.oliveira@useblu.com.br <fabio.oliveira@useblu.com.br>
- Adiciona 'phone_idd' ao MaskType com padrão '+99 (99) 99999-9999' (mfe-pix)
- Estende maskValue com options.compensationCode para resolver máscaras bancárias
  dinâmicas por banco (ex: maskValue('123456', 'bank_branch', { compensationCode: '341' }))
- Estende maskComplete com compensationCode para validação de completude
- Exporta MaskValueOptions interface para consumo externo
- 143 testes passando (15 novos: phone_idd, bank dinâmico com compensationCode)

Co-authored-by: FabioRolin <fabio.oliveira@useblu.com.br>
Co-Authored-By: fabio.oliveira@useblu.com.br <fabio.oliveira@useblu.com.br>
FabioRolin
FabioRolin previously approved these changes May 12, 2026
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Status de Testes

  • 143 testes passando (15 novos)
  • CI green: ESLint + build
  • Novos testes cobrem: phone_idd, bank_branch com compensationCode, bank_account com compensationCode, maskComplete com compensationCode

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Breaking Changes

  • Padrão DARF: alterado de '99.999.999-9' (9 dígitos) para '99 9 99 999999-99' (13 dígitos) — alinhado com o formato original usado nos MFEs (mfe-bill/src/utils/masks.ts)
  • Hint de banco desconhecido (maskHintBankAccount): fallback noop alterado de '0000000000-0' (10 dígitos) para '000000000000-0' (12 dígitos) — alinhado com o padrão bank.noop.account dos MFEs

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Guia de Migração nos MFEs (Fase 2)

# mfe-bill (DARFFormik.js)
- mask="darf.referenceNumber"
+ mask="darf"

- mask="bank.noop.branch"
+ mask="bank_branch"

# mfe-pix (CreateContactDrawer)
- mask: 'phone_idd'  (local masks.js)
+ mask: 'phone_idd'  (core/blu-utils — mesma chave)

# mfe-payment-transfer (NewClientForm)
- mask={`bank.${values.bank.compensation_code}.branch`}
+ mask="bank_branch" + maskOptions={{ compensationCode: values.bank.compensation_code }}

- mask={`bank.${values.bank.compensation_code}.account`}
+ mask="bank_account" + maskOptions={{ compensationCode: values.bank.compensation_code }}

Exemplos de uso da nova API:

import { maskValue, maskComplete } from 'core/blu-utils';

// phone_idd
maskValue('5511999998888', 'phone_idd'); // '+55 (11) 99999-8888'

// bank dinâmico com compensationCode
maskValue('123456', 'bank_branch', { compensationCode: '341' }); // '12345-6' (Itaú)
maskValue('123456789', 'bank_account', { compensationCode: '1' }); // '12345678-9' (BB)

// maskComplete com compensationCode
maskComplete('123456', 'bank_branch', '341'); // true (Itaú: 5+1 dígitos)

@danimuller20
Copy link
Copy Markdown
Contributor

Revisão — ajustes sugeridos

Complemento bem alinhado ao #33 e a cobertura de testes está sólida. Encontrei 1 bug real e algumas inconsistências de API/tipagem que vale endereçar antes do merge.


🔴 Bug — strip divergente entre maskValue e maskBankAccount para BB (compensationCode: '1')

BANK_ACCOUNT_MASKS['1'] = '99999999-S' — o S é placeholder alfanumérico (o DV de BB pode ser letra, ex.: X).

  • maskBankAccount('1234567X', '1')stripAlphanumeric (correto — preserva o X)
  • maskValue('1234567X', 'bank_account', { compensationCode: '1' }) → cai no stripFor, que olha só o MaskType. Como bank_account não está em ALPHANUMERIC_MASKS, faz stripNumeric e descarta o X.

Mesma entrada, saídas diferentes dependendo de qual função o consumidor usar — exatamente o que a centralização deveria evitar.

Sugestão: no maskValue.ts, decidir o stripper considerando também compensationCode (espelhar o ALPHANUMERIC_CODES de maskBankAccount.ts) ou extrair uma função compartilhada de strip que receba (type, compensationCode).


🟡 Tipagem permissiva esconde o fallback em BANK_ACCOUNT_MASKS

export const BANK_BRANCH_MASKS:  Partial<Record<BankCompensationCode, string>> = { 341: '99999-9' };
export const BANK_ACCOUNT_MASKS: Record<BankCompensationCode, string>          = { 1: ..., 33: ..., ... };

Como BANK_ACCOUNT_MASKS é Record completo (não Partial), o BANK_ACCOUNT_MASKS[code] ?? DEFAULT_BANK_ACCOUNT_MASK vira "código morto" para o TS — mas vivo em runtime por causa do as BankCompensationCode. O cast mascara o lookup miss em vez de explicitá-lo.

Sugestão: trocar para Partial<Record<BankCompensationCode, string>> (igual ao branch). Tipo passa a refletir o comportamento real e o ?? fica honesto.


🟡 API inconsistente para passar compensationCode

Três assinaturas diferentes para o mesmo conceito:

Função Forma
maskValue(v, type, { compensationCode }) options
maskBankBranch(v, compensationCode) posicional
maskBankAccount(v, compensationCode) posicional
maskComplete(v, type, compensationCode) posicional

Não é bug, mas obriga o consumidor a lembrar qual estilo usar em cada função. Sugestão: padronizar via options em todas — extensão futura (ex.: novos modificadores por banco) fica mais fácil sem virar breaking change.


🟡 Mudança de DARF é potencialmente breaking

- DARF: '99.999.999-9',
+ DARF: '99 9 99 999999-99',

O checkbox "Breaking change" está desmarcado, mas qualquer consumidor que já chamava maskValue(x, 'darf') passa a receber output diferente (tamanho e separadores).

Sugestão: se a varredura dos 33 MFEs confirmou que ninguém consumia o formato antigo, registrar isso na descrição. Caso contrário, marcar como breaking e mencionar no changelog/release notes.


🟢 Cosméticos / pontos menores

  • tests/masks/maskBankBranch.spec.ts: títulos "agência Banco do Brasil (001)" e "Santander (033)" mas os códigos passados são '1' e '33'. Alinhar para evitar confusão.
  • DEFAULT_BANK_BRANCH_MASK = '9999' descarta DV de agência para todos os bancos exceto Itaú. Bradesco e BB têm DV de 1 dígito no padrão real — confirmar com produto se é intencional para esta fase ou se faltou mapear esses códigos.
  • MaskValueOptions extends CurrencyMaskOptions faz com que maskValue(x, 'cpf', { compensationCode: '341' }) compile sem erro (campo silenciosamente ignorado em tipos não-bancários). Aceitável, mas um comentário no tipo ajudaria quem vai consumir.

👍 O que está bom

  • Cobertura de testes ampla (branch + account + complete + value + hint).
  • DEFAULT_HINT em maskHintBankAccount agora derivado de DEFAULT_BANK_ACCOUNT_MASK — eliminou divergência silenciosa que existia antes.
  • Exportar MaskValueOptions permite que consumidores tipem o options sem importar caminho interno.
  • Separação DEFAULT_*_MASK vs. map por código deixa a intenção clara.

Prioridade sugerida: 1 (bug de strip) → 2 (tipagem Partial) → 4 (rotular breaking ou justificar) → 3 (uniformizar API) → 5 (cosméticos).

… padroniza API e tipagem

- Fix: stripFor em maskValue e maskComplete agora considera compensationCode
  para bancos com DV alfanumérico (BB código 1), alinhando com maskBankAccount
- Fix: BANK_ACCOUNT_MASKS alterado para Partial<Record> (reflete fallback real)
- Refactor: extrai ALPHANUMERIC_BANK_CODES para masks.ts (fonte única)
- Refactor: maskComplete aceita options object além de string posicional
- Export: MaskCompleteOptions interface
- Docs: JSDoc em MaskValueOptions sobre compensationCode
- Tests: DV alfanumérico via maskValue e maskComplete, options object syntax
- Cosmético: títulos de testes alinhados com códigos reais (001→1, 033→33)

Co-authored-by: FabioRolin <fabio.oliveira@useblu.com.br>
Co-Authored-By: fabio.oliveira@useblu.com.br <fabio.oliveira@useblu.com.br>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

@danimuller20 Boa revisão! Todos os pontos foram endereçados no commit f491568. Segue o que foi feito para cada item:


🔴 Bug — strip divergente maskValue vs maskBankAccount (BB)

Corrigido. Extraí ALPHANUMERIC_BANK_CODES para masks.ts como fonte única de verdade (antes era const local no maskBankAccount.ts). Agora stripFor em maskValue.ts e maskComplete.ts também usa essa constante para decidir o strip:

// maskValue.ts
const stripFor = (value: string, type: MaskType, compensationCode?: string): string => {
  if (ALPHANUMERIC_MASKS.includes(type)) return stripAlphanumeric(value);
  if (
    (type === 'bank_account' || type === 'bank_branch')
    && ALPHANUMERIC_BANK_CODES.includes(compensationCode as BankCompensationCode)
  ) {
    return stripAlphanumeric(value);
  }
  return stripNumeric(value);
};

Teste adicionado:

maskValue('12345678X', 'bank_account', { compensationCode: '1' }) // '12345678-X'

🟡 Tipagem Partial<Record> em BANK_ACCOUNT_MASKS

Corrigido. Alterado para Partial<Record<BankCompensationCode, string>> — igual ao BANK_BRANCH_MASKS. O ?? agora é honesto com o TS.


🟡 API inconsistente para compensationCode

Parcialmente endereçado. maskComplete agora aceita tanto string (backward-compat) quanto { compensationCode }:

maskComplete(value, type, '1');                      // posicional (existente)
maskComplete(value, type, { compensationCode: '1' }) // options (novo)

maskBankBranch e maskBankAccount foram mantidos com parâmetro posicional por serem funções dedicadas de banco onde compensationCode é o parâmetro principal — options object seria over-engineering para estas. A interface MaskCompleteOptions foi exportada.


🟡 DARF breaking

Endereçado. Checkbox "Breaking change" agora está marcado na descrição com nota explicativa: a varredura dos 33 MFEs confirmou que nenhum MFE consumia maskValue(x, 'darf') via blu-utils (todos usavam máscaras locais), então é retrocompatível na prática, mas marcado como breaking por precaução.


🟢 Cosméticos

  • Títulos dos testes: Corrigidos — "Banco do Brasil (001)""Banco do Brasil (1)", "Santander (033)""Santander (33)"
  • DV de agência BB/Bradesco: Intencional para esta fase — o DEFAULT_BANK_BRANCH_MASK = '9999' é o padrão noop dos MFEs existentes. Mapear DV de agência por banco pode ser feito em follow-up se produto confirmar necessidade.
  • JSDoc em MaskValueOptions: Adicionado comentário explicando que compensationCode é usado apenas por bank_branch/bank_account.

CI: 146 testes passando (18 novos neste PR), ESLint + build green.

@FabioRolin FabioRolin merged commit 20fb33e into master May 13, 2026
2 checks passed
@FabioRolin FabioRolin deleted the feature/OR-145-fix-mask-gaps branch May 13, 2026 21:33
@devin-ai-integration devin-ai-integration Bot mentioned this pull request May 13, 2026
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants