Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { isLastChar } from './is-last-char';
export { onlyNumbers } from './only-numbers';
export { generateChecksum } from './generate-checksum';
export { generateRandomNumber } from './generate-random-number';
export { isEven } from './is-even';
3 changes: 3 additions & 0 deletions src/helpers/is-even/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isEven(number: number): boolean {
return number % 2 === 0;
}
12 changes: 12 additions & 0 deletions src/utilities/conta-bancaria/__tests__/bancoBanrisul.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { BankValidator } from "./bankValidator";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an implementation, not a test.


export class BancoBanrisulValidator extends BankValidator{

protected isValidFormat(bankAccount: string): boolean {
return /^\d{8}\-(\d{1}|x)$/.test(bankAccount);
}

protected checkDV(bankAccount: string): boolean {
return true;
}
}
20 changes: 20 additions & 0 deletions src/utilities/conta-bancaria/__tests__/bancoDoBrasil.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("001", '00210169-6')).toBe(true);
expect(isValidAccount("001", '1171032-2')).toBe(true);
expect(isValidAccount("001", '19932-X')).toBe(true);
expect(isValidAccount("001", '1050769-8')).toBe(true);
expect(isValidAccount("001", '87889-8')).toBe(true);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("001", '')).toBe(false);
expect(isValidAccount("001", '123456789-0')).toBe(false);
expect(isValidAccount("001", 'asdfasdf')).toBe(false);
})
})
})
27 changes: 27 additions & 0 deletions src/utilities/conta-bancaria/__tests__/bradesco.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("237", '0238069-2')).toBe(true);
expect(isValidAccount("237", '0301357-P')).toBe(true);
expect(isValidAccount("237", '0325620-0')).toBe(true);
expect(isValidAccount("237", '0284025-1')).toBe(true);
expect(isValidAccount("237", '0195470-9')).toBe(true);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("237", '')).toBe(false);
expect(isValidAccount("237", '123456789-0')).toBe(false);
expect(isValidAccount("237", 'asdfasdf')).toBe(false);
})
})
describe("invalid account",()=>{
it("returns false", ()=>{
expect(isValidAccount("237", '0195470-1')).toBe(false);
expect(isValidAccount("237", '0195471-P')).toBe(false);
expect(isValidAccount("237", '0195491-0')).toBe(false);
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("104", '00100000448-6', "2004")).toBe(true);
})
})
describe("invalid accounts",()=>{
it("returns false", ()=>{
expect(isValidAccount("104", '00100000448-7', "0189")).toBe(false);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("104", '', "")).toBe(false);
expect(isValidAccount("104", '123456789-0', "")).toBe(false);
expect(isValidAccount("104", 'asdfasdf', "")).toBe(false);
})
})
})
22 changes: 22 additions & 0 deletions src/utilities/conta-bancaria/__tests__/citibank.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("745", '0007500465-8', "0075")).toBe(true);
expect(isValidAccount("745", '1420412612-0', "0013")).toBe(true);
})
})
describe("invalid accounts",()=>{
it("returns false", ()=>{
expect(isValidAccount("745", '1420412612-1', "0013")).toBe(false);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("745", '', "")).toBe(false);
expect(isValidAccount("745", '123456789-0', "")).toBe(false);
expect(isValidAccount("745", 'asdfasdf', "")).toBe(false);
})
})
})
21 changes: 21 additions & 0 deletions src/utilities/conta-bancaria/__tests__/hsbc.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("399", '853838-6', "0007")).toBe(true);
})
})
describe("invalid accounts",()=>{
it("returns false", ()=>{
expect(isValidAccount("399", '853838-5', "0007")).toBe(false);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("399", '', "")).toBe(false);
expect(isValidAccount("399", '123456789-0', "")).toBe(false);
expect(isValidAccount("399", 'asdfasdf', "")).toBe(false);
})
})
})
23 changes: 23 additions & 0 deletions src/utilities/conta-bancaria/__tests__/itau.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("341", '02366-1', "2545")).toBe(true);
expect(isValidAccount("341", '98197-0', "0031")).toBe(true);
expect(isValidAccount("341", '11745-6', "4102")).toBe(true);
})
})
describe("invalid accounts",()=>{
it("returns false", ()=>{
expect(isValidAccount("341", '11745-6', "0031")).toBe(false);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("341", '', "")).toBe(false);
expect(isValidAccount("341", '123456789-0', "")).toBe(false);
expect(isValidAccount("341", 'asdfasdf', "")).toBe(false);
})
})
})
21 changes: 21 additions & 0 deletions src/utilities/conta-bancaria/__tests__/real.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("356", '5711460-9', "1835")).toBe(true);
})
})
describe("invalid accounts",()=>{
it("returns false", ()=>{
expect(isValidAccount("356", '5711460-0', "1835")).toBe(false);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("356", '', "")).toBe(false);
expect(isValidAccount("356", '123456789-0', "")).toBe(false);
expect(isValidAccount("356", 'asdfasdf', "")).toBe(false);
})
})
})
21 changes: 21 additions & 0 deletions src/utilities/conta-bancaria/__tests__/santander.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isValidAccount } from '..';

describe("isValid", ()=>{
describe("valid accounts",()=>{
it("returns true", ()=>{
expect(isValidAccount("033", '01017417-9', "0189")).toBe(true);
})
})
describe("invalid accounts",()=>{
it("returns false", ()=>{
expect(isValidAccount("033", '01017417-1', "0189")).toBe(false);
})
})
describe("wrong format",()=>{
it("returns false", ()=>{
expect(isValidAccount("001", '', "")).toBe(false);
expect(isValidAccount("001", '123456789-0', "")).toBe(false);
expect(isValidAccount("001", 'asdfasdf', "")).toBe(false);
})
})
})
33 changes: 33 additions & 0 deletions src/utilities/conta-bancaria/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { CitibankValidator } from './validators/citibank';
import { HSBCValidator } from './validators/hsbc';
import { RealValidator } from './validators/real';
import { ItauValidator } from './validators/itau';
import { BradescoValidator } from './validators/bradesco';
import { CaixaEconomicaFederalValidator } from './validators/caixaEconomicaFederal';
import { SantanderValidator } from './validators/santander';
import { BancoDoBrasilValidator } from './validators/bancoDoBrasil';

type BankCode = "001" | "033" | "104" | "237" | "341" | "356" | "399" | "745";

const BANKS = {
"001": BancoDoBrasilValidator,
"033": SantanderValidator,
"104": CaixaEconomicaFederalValidator,
"237": BradescoValidator,
"341": ItauValidator,
"356": RealValidator,
"399": HSBCValidator,
"745": CitibankValidator
}

/**
*
* @param bankCode 001: Banco do Brasil, 033: Santander, 104: CEF, 237: Bradesco, 341: Itau, 356: Real, 399: HSBC, 745: Citibank
* @param accountNumber
* @param agencyNumber Banks 003, 104, 237, 341, 356, 399 and 745 requires agencyNumber
* @returns
*/
export function isValidAccount(bankCode:BankCode, accountNumber: string, agencyNumber?: string) {
const bank = new BANKS[bankCode]();
return bank.isValid(accountNumber, agencyNumber);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of more banks in Brazil...It would be nice to provide something where we can add more banks to BANKS.

addBankValidator(BankCode, Validator);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont know if we need that... I think if some bank appears and we don't have support for it, we just can integrate and publish another library version, probably if someone needs that and we don't have it, they can open an issue telling that to us and we just add it. What do you think about it?

@diasbruno diasbruno Oct 26, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only case where I'm a pessimist...It's more likely that people will implement on their end and don't make a PR. 😞

So, it'd be nice to have that, but it's not mandatory.

}
31 changes: 31 additions & 0 deletions src/utilities/conta-bancaria/validators/bancoDoBrasil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { BankValidator } from "./bankValidator";

export class BancoDoBrasilValidator extends BankValidator{

protected isValidFormat(bankAccount: string): boolean {
return /^\d{1,8}(\-(\d{1}|X))?$/.test(bankAccount);
}

protected checkDV(bankAccount: string): boolean {
const bankAccountSplited = bankAccount.split("-");
const account = bankAccountSplited[0].length < 8 ? this.formatLeftZeros(8 - bankAccountSplited[0].length, bankAccountSplited[0]) : bankAccountSplited[0];
const verificationDigit = bankAccountSplited[1] || 'X'
return this.getAccountVerificationDigit(account) === verificationDigit;
}

private formatLeftZeros(count:number, initialValue:string):string{
if(count) {
return this.formatLeftZeros(count-1, `0${initialValue}`)
}
return initialValue;
}

private getAccountVerificationDigit(accountNumber:string){
const digitSum = accountNumber.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (9-index),0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const digitSum = accountNumber.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (9-index),0);
const digitSum = accountNumber.split("").reduce((acc, digit, index) => acc + parseInt(digit) * (9-index), 0);

const dv = (11 - digitSum%11);
if(dv === 10) return "X";
if(dv === 11) return "0";
return dv.toString()
}

}
9 changes: 9 additions & 0 deletions src/utilities/conta-bancaria/validators/bankValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export abstract class BankValidator {
public isValid(bankAccount: string, bankAgency?: string): boolean {
return this.isValidFormat(bankAccount,bankAgency) && this.checkDV(bankAccount, bankAgency);
}

protected abstract isValidFormat(bankAccount: string, bankAgency?: string): boolean;

protected abstract checkDV(bankAccount: string, bankAgency?: string): boolean;
}
22 changes: 22 additions & 0 deletions src/utilities/conta-bancaria/validators/bradesco.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { BankValidator } from "./bankValidator";

export class BradescoValidator extends BankValidator{
protected isValidFormat(bankAccount: string): boolean {
return /^\d{7}\-(\d{1}|P)?$/.test(bankAccount);
}

protected checkDV(bankAccount: string): boolean {
const bankAccountSplited = bankAccount.split("-");
const account = bankAccountSplited[0];
const verificationDigit = bankAccountSplited[1];
return this.getAccountVerificationDigit(account) === verificationDigit;
}

private getAccountVerificationDigit(accountNumber:string){
const digitSum = accountNumber.split("").reverse().map(Number).reduce((acc,cur,index)=> acc + cur * ((index%7+2)),0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const digitSum = accountNumber.split("").reverse().map(Number).reduce((acc,cur,index)=> acc + cur * ((index%7+2)),0);
const digitSum = accountNumber.split("").reverse().reduce((acc, digit, index)=> acc + parseInt(digit) * ((index%7+2)), 0);

const rest = digitSum%11;
if(rest === 1) return "P";
if(rest === 0) return "0";
return (11 - rest).toString()
}
}
25 changes: 25 additions & 0 deletions src/utilities/conta-bancaria/validators/caixaEconomicaFederal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { BankValidator } from "./bankValidator";

export class CaixaEconomicaFederalValidator extends BankValidator{
protected isValidFormat(bankAccount: string, agencyNumber:string): boolean {
return /^\d{11}\-\d{1}$/.test(bankAccount) && /^\d{4}$/.test(agencyNumber);
}

protected checkDV(bankAccount: string, agencyNumber:string): boolean {
const account = bankAccount.split("-")[0];
const accountType = account.slice(0,3);
const accountNumber = account.slice(-8)
const verificationDigit = bankAccount.split("-")[1];
return this.getAccountVerificationDigit(accountNumber, agencyNumber, accountType) === verificationDigit;
}

private getAccountVerificationDigit(accountNumber:string, agencyNumber:string, accountType: string){
const agencySum = agencyNumber.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (8 - index),0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const agencySum = agencyNumber.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (8 - index),0);
const agencySum = agencyNumber.split("").reduce((acc, digit, index)=> acc + parseInt(digit) * (8 - index), 0);

const accountTypeSum = accountType.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (4 - index),0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const accountTypeSum = accountType.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (4 - index),0);
const accountTypeSum = accountType.split("").reduce((acc, digit, index)=> acc + parseInt(digit) * (4 - index),0);

const accountNumberSum = accountNumber.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (9 - index),0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const accountNumberSum = accountNumber.split("").map(Number).reduce((acc,cur,index)=> acc + cur * (9 - index),0);
const accountNumberSum = accountNumber.split("").reduce((acc, digit, index) => acc + parseInt(digit) * (9 - index), 0);

const sum = (agencySum + accountNumberSum + accountTypeSum)* 10
const mod = Math.trunc(sum/11);
const rest = Math.abs(mod * 11 - sum)
return (rest === 10 ? 0: rest).toString();
}
}
20 changes: 20 additions & 0 deletions src/utilities/conta-bancaria/validators/citibank.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { BankValidator } from "./bankValidator";

export class CitibankValidator extends BankValidator{
protected isValidFormat(bankAccount: string, agencyNumber:string): boolean {
return /^\d{7}\-\d{1}$/.test(bankAccount) && /^\d{4}$/.test(agencyNumber);
}

protected checkDV(bankAccount: string, bankAgency:string): boolean {
const accountNumber = bankAccount.split("-")[0];
const verificationDigit = bankAccount.split("-")[1];
return this.getAccountVerificationDigit(accountNumber, bankAgency) === verificationDigit;
}

private getAccountVerificationDigit(accountNumber:string, agencyNumber:string){
const sum = `${agencyNumber}${accountNumber}`.split("").map(Number).reduce((acc,cur,index) => acc + cur * (11-index),0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const sum = `${agencyNumber}${accountNumber}`.split("").map(Number).reduce((acc,cur,index) => acc + cur * (11-index),0);
const sum = `${agencyNumber}${accountNumber}`.split("").reduce((acc, digit,index) => acc + parseInt(digit) * (11-index),0);

const rest = (sum - Math.trunc(sum / 11) * 11);
if (rest > 1) return (11 - rest).toString()
return "0"
}
}
23 changes: 23 additions & 0 deletions src/utilities/conta-bancaria/validators/hsbc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { BankValidator } from "./bankValidator";

export class HSBCValidator extends BankValidator{
private agencyMultiplicationWeights = [8,9,2,3];

protected isValidFormat(bankAccount: string, agencyNumber:string): boolean {
return /^\d{6}\-\d{1}$/.test(bankAccount) && /^\d{4}$/.test(agencyNumber);
}

protected checkDV(bankAccount: string, bankAgency:string): boolean {
const accountNumber = bankAccount.split("-")[0];
const verificationDigit = bankAccount.split("-")[1];
return this.getAccountVerificationDigit(accountNumber, bankAgency) === verificationDigit;
}

private getAccountVerificationDigit(accountNumber:string, agencyNumber:string){
const agencySum = agencyNumber.split("").map(Number).reduce((acc,cur,index) => acc + cur * this.agencyMultiplicationWeights[index],0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const agencySum = agencyNumber.split("").map(Number).reduce((acc,cur,index) => acc + cur * this.agencyMultiplicationWeights[index],0);
const agencySum = agencyNumber.split("").reduce((acc,digit,index) => acc + parseInt(digit) * this.agencyMultiplicationWeights[index],0);

const accountSum = accountNumber.split("").map(Number).reduce((acc,cur,index) => acc + cur * (index + 4),0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const accountSum = accountNumber.split("").map(Number).reduce((acc,cur,index) => acc + cur * (index + 4),0);
const accountSum = accountNumber.split("").reduce((acc,digit,index) => acc + parseInt(digit) * (index + 4), 0);

const rest = (agencySum+accountSum)%11;
if (rest === 10) return "0"
return rest.toString();
}
}
Loading