diff --git a/package.json b/package.json index 30c5449..5ae7f17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@useblu/utils", - "version": "1.2.2", + "version": "1.2.3", "private": false, "license": "MIT", "main": "lib/index.js", diff --git a/src/masks/maskBankAccount.ts b/src/masks/maskBankAccount.ts index c04df47..f416583 100644 --- a/src/masks/maskBankAccount.ts +++ b/src/masks/maskBankAccount.ts @@ -1,10 +1,6 @@ import VMasker from 'vanilla-masker'; -import { - BANK_ACCOUNT_MASKS, - DEFAULT_BANK_ACCOUNT_MASK, - ALPHANUMERIC_BANK_CODES, -} from './masks'; -import { stripAlphanumeric, stripNumeric } from './strip'; +import { BANK_ACCOUNT_MASKS, DEFAULT_BANK_ACCOUNT_MASK } from './masks'; +import { stripNumeric } from './strip'; import type { BankCompensationCode } from './types'; export default function maskBankAccount( @@ -15,9 +11,6 @@ export default function maskBankAccount( const code = compensationCode as BankCompensationCode; const pattern = BANK_ACCOUNT_MASKS[code] ?? DEFAULT_BANK_ACCOUNT_MASK; - const stripped = ALPHANUMERIC_BANK_CODES.includes(code) - ? stripAlphanumeric(String(value)) - : stripNumeric(String(value)); - return VMasker.toPattern(stripped, pattern); + return VMasker.toPattern(stripNumeric(String(value)), pattern); } diff --git a/src/masks/maskBankBranch.ts b/src/masks/maskBankBranch.ts index beb23fc..1d4d95f 100644 --- a/src/masks/maskBankBranch.ts +++ b/src/masks/maskBankBranch.ts @@ -1,17 +1,18 @@ import VMasker from 'vanilla-masker'; -import { BANK_BRANCH_MASKS, DEFAULT_BANK_BRANCH_MASK } from './masks'; +import { DEFAULT_BANK_BRANCH_MASK } from './masks'; import { stripNumeric } from './strip'; -import type { BankCompensationCode } from './types'; export default function maskBankBranch( value: string | null | undefined, + // Mantido por compatibilidade de API e simetria com maskBankAccount: a + // agência usa sempre 4 dígitos, independente do banco (o DV, quando há, é + // calculado pelo backend). + // eslint-disable-next-line @typescript-eslint/no-unused-vars compensationCode?: string, ): string { if (value === null || value === undefined || value === '') return ''; const stripped = stripNumeric(String(value)); - const pattern = BANK_BRANCH_MASKS[compensationCode as BankCompensationCode] - ?? DEFAULT_BANK_BRANCH_MASK; - return VMasker.toPattern(stripped, pattern); + return VMasker.toPattern(stripped, DEFAULT_BANK_BRANCH_MASK); } diff --git a/src/masks/maskComplete.ts b/src/masks/maskComplete.ts index 7024b6e..b67941d 100644 --- a/src/masks/maskComplete.ts +++ b/src/masks/maskComplete.ts @@ -2,9 +2,7 @@ import { MASKS, DEFAULT_BANK_BRANCH_MASK, DEFAULT_BANK_ACCOUNT_MASK, - BANK_BRANCH_MASKS, BANK_ACCOUNT_MASKS, - ALPHANUMERIC_BANK_CODES, } from './masks'; import { stripAlphanumeric, stripNumeric, PATTERN_PLACEHOLDER_REGEX } from './strip'; import type { MaskType, BankCompensationCode } from './types'; @@ -31,13 +29,7 @@ const patternFor = ( case 'barCodeUtilities': return MASKS.BAR_CODE_UTILITIES; case 'darf': return MASKS.DARF; case 'number': return MASKS.NUMBER; - case 'bank_branch': { - if (compensationCode) { - const mapped = BANK_BRANCH_MASKS[compensationCode as BankCompensationCode]; - if (mapped) return mapped; - } - return DEFAULT_BANK_BRANCH_MASK; - } + case 'bank_branch': return DEFAULT_BANK_BRANCH_MASK; case 'bank_account': { if (compensationCode) { const mapped = BANK_ACCOUNT_MASKS[compensationCode as BankCompensationCode]; @@ -76,11 +68,7 @@ export default function maskComplete( const expected = placeholdersInPattern(pattern); - const isAlphanumeric = ALPHANUMERIC_MASKS.includes(type) - || ( - (type === 'bank_account' || type === 'bank_branch') - && ALPHANUMERIC_BANK_CODES.includes(compensationCode as BankCompensationCode) - ); + const isAlphanumeric = ALPHANUMERIC_MASKS.includes(type); const stripped = isAlphanumeric ? stripAlphanumeric(value) diff --git a/src/masks/maskValue.ts b/src/masks/maskValue.ts index cc4e357..d73b96f 100644 --- a/src/masks/maskValue.ts +++ b/src/masks/maskValue.ts @@ -5,9 +5,7 @@ import { PERCENTAGE_MASK_DEFAULTS, DEFAULT_BANK_BRANCH_MASK, DEFAULT_BANK_ACCOUNT_MASK, - BANK_BRANCH_MASKS, BANK_ACCOUNT_MASKS, - ALPHANUMERIC_BANK_CODES, } from './masks'; import { stripAlphanumeric, stripNumeric } from './strip'; import type { MaskType, CurrencyMaskOptions, BankCompensationCode } from './types'; @@ -23,25 +21,11 @@ export interface MaskValueOptions extends CurrencyMaskOptions { const ALPHANUMERIC_MASKS: ReadonlyArray = ['cnpj', 'cpf_cnpj']; -const stripFor = (value: string, type: MaskType, compensationCode?: string): string => { +const stripFor = (value: string, type: MaskType): 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); }; -const bankBranchPattern = (code?: string): string => { - if (code) { - const mapped = BANK_BRANCH_MASKS[code as BankCompensationCode]; - if (mapped) return mapped; - } - return DEFAULT_BANK_BRANCH_MASK; -}; - const bankAccountPattern = (code?: string): string => { if (code) { const mapped = BANK_ACCOUNT_MASKS[code as BankCompensationCode]; @@ -71,7 +55,7 @@ const patternFor = ( case 'barCodeUtilities': return MASKS.BAR_CODE_UTILITIES; case 'darf': return MASKS.DARF; case 'number': return MASKS.NUMBER; - case 'bank_branch': return bankBranchPattern(compensationCode); + case 'bank_branch': return DEFAULT_BANK_BRANCH_MASK; case 'bank_account': return bankAccountPattern(compensationCode); default: return ''; } @@ -94,7 +78,7 @@ export default function maskValue( return VMasker.toMoney(stringValue, { ...PERCENTAGE_MASK_DEFAULTS, ...(options || {}) }); } - const stripped = stripFor(stringValue, type, options?.compensationCode); + const stripped = stripFor(stringValue, type); const pattern = patternFor(type, stripped, options?.compensationCode); if (!pattern) return stringValue; diff --git a/src/masks/masks.ts b/src/masks/masks.ts index 62e0a93..c80b228 100644 --- a/src/masks/masks.ts +++ b/src/masks/masks.ts @@ -30,20 +30,18 @@ export const PERCENTAGE_MASK_DEFAULTS: CurrencyMaskOptions = { zeroCents: false, }; -export const BANK_BRANCH_MASKS: Partial> = { - 341: '99999-9', -}; - +// Toda agência bancária é informada com 4 dígitos no frontend; quando há DV +// na agência (BB, Banrisul, Bradesco, Arbi) ele é calculado/validado pelo +// backend a partir desses 4 dígitos. Por isso a agência não tem máscara por +// banco — todos usam este default. export const DEFAULT_BANK_BRANCH_MASK = '9999'; -export const ALPHANUMERIC_BANK_CODES: ReadonlyArray = ['1']; - export const BANK_ACCOUNT_MASKS: Partial> = { - 1: '99999999-S', + 1: '99999999-9', 33: '99999999-9', 41: '999999999-9', - 104: '999999999999-9', - 213: '9999999-9', + 104: '999999999-9', + 213: '99999-9', 237: '9999999-9', 341: '99999-9', 399: '999999-9', diff --git a/tests/masks/maskBankAccount.spec.ts b/tests/masks/maskBankAccount.spec.ts index 476b737..364585c 100644 --- a/tests/masks/maskBankAccount.spec.ts +++ b/tests/masks/maskBankAccount.spec.ts @@ -7,6 +7,10 @@ describe('maskBankAccount', () => { test('formata conta com dígito', () => { expect(maskBankAccount('123456789', '1')).toBe('12345678-9'); }); + + test('DV é numérico: caractere não numérico é removido', () => { + expect(maskBankAccount('12345678X', '1')).toBe('12345678'); + }); }); describe('Santander (33)', () => { @@ -28,8 +32,8 @@ describe('maskBankAccount', () => { }); describe('CEF (104)', () => { - test('formata conta longa com dígito', () => { - expect(maskBankAccount('1234567890123', '104')).toBe('123456789012-3'); + test('formata conta com dígito (9 dígitos, sem operação)', () => { + expect(maskBankAccount('1234567890123', '104')).toBe('123456789-0'); }); }); @@ -51,9 +55,9 @@ describe('maskBankAccount', () => { }); }); - describe('Banco Original (213)', () => { + describe('Arbi (213)', () => { test('formata conta com dígito', () => { - expect(maskBankAccount('12345678', '213')).toBe('1234567-8'); + expect(maskBankAccount('12345678', '213')).toBe('12345-6'); }); }); diff --git a/tests/masks/maskBankBranch.spec.ts b/tests/masks/maskBankBranch.spec.ts index 6dd260f..3d99eff 100644 --- a/tests/masks/maskBankBranch.spec.ts +++ b/tests/masks/maskBankBranch.spec.ts @@ -19,11 +19,11 @@ describe('maskBankBranch', () => { expect(maskBankBranch('1234', '33')).toBe('1234'); }); - test('agência Itaú (341) com dígito verificador', () => { - expect(maskBankBranch('123456', '341')).toBe('12345-6'); + test('agência Itaú (341) tem 4 dígitos sem DV', () => { + expect(maskBankBranch('123456', '341')).toBe('1234'); }); - test('agência Itaú (341) parcial', () => { + test('agência Itaú (341) com 4 dígitos', () => { expect(maskBankBranch('1234', '341')).toBe('1234'); }); diff --git a/tests/masks/maskComplete.spec.ts b/tests/masks/maskComplete.spec.ts index fe2dafe..b30b453 100644 --- a/tests/masks/maskComplete.spec.ts +++ b/tests/masks/maskComplete.spec.ts @@ -59,12 +59,12 @@ describe('maskComplete', () => { expect(maskComplete('12', 'bank_branch')).toBe(false); }); - test('bank_branch completo com compensationCode Itaú (341)', () => { - expect(maskComplete('123456', 'bank_branch', '341')).toBe(true); + test('bank_branch completo com compensationCode Itaú (341) são 4 dígitos', () => { + expect(maskComplete('1234', 'bank_branch', '341')).toBe(true); }); test('bank_branch incompleto com compensationCode Itaú (341)', () => { - expect(maskComplete('1234', 'bank_branch', '341')).toBe(false); + expect(maskComplete('12', 'bank_branch', '341')).toBe(false); }); test('bank_account completo (noop 12+1 dígitos)', () => { @@ -83,8 +83,8 @@ describe('maskComplete', () => { expect(maskComplete('123456789', 'bank_account', { compensationCode: '1' })).toBe(true); }); - test('bank_account completo com DV alfanumérico BB (1)', () => { - expect(maskComplete('12345678X', 'bank_account', { compensationCode: '1' })).toBe(true); + test('bank_account BB (1) com DV não numérico não conta como completo', () => { + expect(maskComplete('12345678X', 'bank_account', { compensationCode: '1' })).toBe(false); }); test('bank_account incompleto com compensationCode BB (1)', () => { diff --git a/tests/masks/maskHintBankAccount.spec.ts b/tests/masks/maskHintBankAccount.spec.ts index 2f657d2..375af11 100644 --- a/tests/masks/maskHintBankAccount.spec.ts +++ b/tests/masks/maskHintBankAccount.spec.ts @@ -16,7 +16,7 @@ describe('maskHintBankAccount', () => { }); test('CEF (104)', () => { - expect(maskHintBankAccount('104')).toBe('000000000000-0'); + expect(maskHintBankAccount('104')).toBe('000000000-0'); }); test('código desconhecido retorna placeholder default (noop)', () => { diff --git a/tests/masks/maskValue.spec.ts b/tests/masks/maskValue.spec.ts index 0efc7e5..5808b84 100644 --- a/tests/masks/maskValue.spec.ts +++ b/tests/masks/maskValue.spec.ts @@ -91,8 +91,8 @@ describe('maskValue', () => { test('strip de caracteres não numéricos', () => { expect(maskValue('12-34', 'bank_branch')).toBe('1234'); }); - test('com compensationCode Itaú (341) usa padrão 99999-9', () => { - expect(maskValue('123456', 'bank_branch', { compensationCode: '341' })).toBe('12345-6'); + test('com compensationCode Itaú (341) usa 4 dígitos (sem DV)', () => { + expect(maskValue('123456', 'bank_branch', { compensationCode: '341' })).toBe('1234'); }); test('com compensationCode desconhecido usa padrão noop', () => { expect(maskValue('1234', 'bank_branch', { compensationCode: '999' })).toBe('1234'); @@ -109,11 +109,11 @@ describe('maskValue', () => { test('strip de separadores antes de aplicar', () => { expect(maskValue('123456789012-3', 'bank_account')).toBe('123456789012-3'); }); - test('com compensationCode BB (1) usa padrão 99999999-S', () => { + test('com compensationCode BB (1) usa padrão 99999999-9', () => { expect(maskValue('123456789', 'bank_account', { compensationCode: '1' })).toBe('12345678-9'); }); - test('com compensationCode BB (1) preserva DV alfanumérico', () => { - expect(maskValue('12345678X', 'bank_account', { compensationCode: '1' })).toBe('12345678-X'); + test('com compensationCode BB (1) usa DV numérico (X é removido)', () => { + expect(maskValue('12345678X', 'bank_account', { compensationCode: '1' })).toBe('12345678'); }); test('com compensationCode Bradesco (237) usa padrão 9999999-9', () => { expect(maskValue('12345678', 'bank_account', { compensationCode: '237' })).toBe('1234567-8');