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";

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);

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
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?

Copy link

@diasbruno diasbruno Oct 26, 2021

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);

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);

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);

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);

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);

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);

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);

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);

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