UNPKG

@qompa/cci-utils

Version:

Utilities to convert between CCI and account numbers

186 lines (185 loc) 5.87 kB
var BankCode; (function (BankCode) { BankCode["BCP"] = "002"; BankCode["BBVA"] = "011"; })(BankCode || (BankCode = {})); export var BCPAccountTypes; (function (BCPAccountTypes) { BCPAccountTypes["Savings"] = "1"; BCPAccountTypes["Checking"] = "2"; BCPAccountTypes["CTS"] = "3"; })(BCPAccountTypes || (BCPAccountTypes = {})); export function convertBCPAccountNumberToCCI(accountNumber, accountType) { if (!/^\d{14}$/.test(accountNumber)) return null; const accountSegment1 = accountNumber.slice(0, 3); const accountSegment2 = accountNumber.slice(3).padStart(11, "0"); const cciSegment1 = BankCode.BCP + accountSegment1; const cciSegment2 = accountType + accountSegment2; function calculateCheckDigit(group) { const sum = group.split("").reduce((acc, char, index) => { const num = Number(char); const product = num * (index % 2 === 0 ? 1 : 2); return (acc + product .toString() .split("") .reduce((a, d) => a + Number(d), 0)); }, 0); return (10 - (sum % 10)) % 10; } const checkDigit1 = calculateCheckDigit(cciSegment1); const checkDigit2 = calculateCheckDigit(cciSegment2); return `${cciSegment1}${cciSegment2}${checkDigit1}${checkDigit2}`; } function calculateFirstBBVACheckDigit(bank, branch) { const input = bank + branch; const weights = [0, 1, 2, 1, 0, 2, 1, 2]; let sum = 0; for (let i = 0; i < input.length; i++) { const digit = Number.parseInt(input.charAt(i), 10); let product = digit * weights[i]; if (product >= 10) { product = Math.floor(product / 10) + (product % 10); } sum += product; } return ((10 - (sum % 10)) % 10).toString(); } function calculateSecondBBVACheckDigit(control, account) { const input = control + account; const weights = [1, 2, 1, 2, 1, 2, 1, 2, 1, 2]; let sum = 0; for (let i = 0; i < input.length; i++) { const digit = Number.parseInt(input.charAt(i), 10); let product = digit * weights[i]; if (product >= 10) { product = Math.floor(product / 10) + (product % 10); } sum += product; } return ((10 - (sum % 10)) % 10).toString(); } export function convertBBVAAccountNumberToCCI(accountNumber) { if (!/^\d{18}$/.test(accountNumber) && !/^\d{20}$/.test(accountNumber)) { return null; } const bank = accountNumber.slice(0, 4); const branch = accountNumber.slice(4, 8); let control; let account; if (accountNumber.length === 18) { control = accountNumber.slice(8, 10); account = accountNumber.slice(10); } else { const accountData = accountNumber.slice(10); control = accountData.slice(0, 2); account = accountData.slice(2); } const firstCheck = calculateFirstBBVACheckDigit(bank, branch); const secondCheck = calculateSecondBBVACheckDigit(control, account); return `${bank.substring(1)}${branch.substring(1)}00${control}${account}${firstCheck}${secondCheck}`; } const BANKS_CCI = [ { name: "BCP", id: BankCode.BCP, }, { name: "INTERBANK", id: "003", }, { name: "SCOTIABANK", id: "009", }, { name: "BBVA", id: BankCode.BBVA, }, { name: "BANCO DE LA NACION", id: "018", }, { name: "BANBIF", id: "038", }, { name: "MI BANCO", id: "049", }, ]; const getBankFromCCI = (cci) => { if (!cci.match(/^[0-9]{20}$/)) { throw new Error("CCI must be numeric and have exactly 20 digits"); } const bankIdentifier = cci.substring(0, 3); const bank = BANKS_CCI.find((item) => item.id === bankIdentifier); if (!bank) throw new Error("unknown bank identifier"); return bank.name; }; export function getCCIMetadata(cci) { const bank = getBankFromCCI(cci); switch (bank) { case "BCP": { const accountTypeDigit = cci.substring(6, 7); if (accountTypeDigit === "1") { return { bank, accountNumber: cci.substring(3, 6) + cci.substring(7, 18), cci, currency: cci.substring(15, 16) === "0" ? "PEN" : "USD", type: "Ahorro", }; } return { bank, accountNumber: cci.substring(3, 6) + cci.substring(8, 18), cci, currency: cci.substring(15, 16) === "0" ? "PEN" : "USD", type: "Corriente", }; } case "INTERBANK": return { bank, accountNumber: cci.substring(3, 6) + cci.substring(8, 18), cci, }; case "BBVA": return { bank, accountNumber: `00110${cci.substring(3, 6)}${cci.substring(8, 18)}`, cci, }; case "SCOTIABANK": return { bank, accountNumber: cci.substring(3, 6) + cci.substring(11, 18), cci, }; case "BANBIF": return { bank, accountNumber: `0${cci.substring(7, 18)}`, cci, }; case "MI BANCO": return { bank, accountNumber: cci.substring(8, 18), cci, }; case "BANCO DE LA NACION": return { bank, accountNumber: cci.substring(7, 18), cci, }; default: throw new Error("unknown bank identifier"); } }