UNPKG

@disruptive-learning/cfdi-to-pdf

Version:

Librería para crear un pdf basado en un XML CFDI o Retenciones

190 lines (189 loc) 6.22 kB
const getGroupToCurrency = (rawGroup) => { let group = rawGroup; // Necessary arrays needed to convert from numbers to currency const basics = [ 'cero', 'un', 'dos', 'tres', 'cuatro', 'cinco', 'seis', 'siete', 'ocho', 'nueve', 'diez', 'once', 'doce', 'trece', 'catorce', 'quince', ]; const teens = [ '', 'dieci', 'veinti', 'treinta', 'cuarenta', 'cincuenta', 'sesenta', 'setenta', 'ochenta', 'noventa', ]; const hundreds = [ '', 'ciento', 'doscientos', 'trescientos', 'cuatrocientos', 'quinientos', 'seiscientos', 'setecientos', 'ochocientos', 'novecientos', ]; // Variable used to temporarily store currency let temporalCurrency = ''; // Handle hundreds if (group.length === 3) { switch (Number.parseInt(group, 10)) { case 100: { return 'cien '; } case 0: { return ''; } default: { temporalCurrency += `${hundreds[Number.parseInt(group[0], 10)]} `; } } group = group.slice(1, 3); } // Handle teens and 'basic' numbers if (Number.parseInt(group, 10) <= 15) { // If group is less than 15, select from basics array if (group === '00') { return temporalCurrency; } temporalCurrency += `${basics[Number.parseInt(group, 10)]} `; } else { // Else look for the number in both teens and basics arrays const zeroAtTheEnd = group[1] === '0'; if (Number.parseInt(group, 10) === 20) { return `${temporalCurrency}veinte `; } temporalCurrency += `${teens[Number.parseInt(group[0], 10)] + (Number.parseInt(group[0], 10) >= 3 && !zeroAtTheEnd ? ' y ' : '') + (zeroAtTheEnd ? '' : basics[Number.parseInt(group[1], 10)])} `; } return temporalCurrency; }; const evaluateThousandsOfMillions = (integers, numberToCurrency) => { const group = integers.slice(0, Math.max(0, integers.length - 9)); let fixedNumberToCurrency = numberToCurrency; switch (Number.parseInt(group, 10)) { /* istanbul ignore next */ case 0: { break; } case 1: { fixedNumberToCurrency += 'mil '; break; } default: { fixedNumberToCurrency += `${getGroupToCurrency(group)}mil `; } } return { numberToCurrency: fixedNumberToCurrency, integers: integers.slice(-9), }; }; const evaluateMillions = (integers, numberToCurrency, thousandsOfMillions) => { let fixedNumberToCurrency = numberToCurrency; const group = integers.slice(0, Math.max(0, integers.length - 6)); fixedNumberToCurrency += getGroupToCurrency(group); fixedNumberToCurrency += !thousandsOfMillions && Number.parseInt(group, 10) === 1 ? 'millón ' : 'millones '; return { numberToCurrency: fixedNumberToCurrency, integers: integers.slice(-6), }; }; export const toCurrency = (initial, moneda = 'MXN') => { // Number to string const number = initial.toFixed(2); // Separate decimals (only 2) and integers let integers = number.slice(0, Math.max(0, number.indexOf('.'))); const decimals = number.slice(number.indexOf('.') + 1); const monedaName = moneda === 'MXN' ? 'M.N.' : moneda; // Initialize string to store currency let numberToCurrency = ''; // Some helpful variables let noThousands = false; let noHundreds = false; let thousandsOfMillions = false; // Maximum supported number is 999,999,999,999.99 if (integers.length > 12) { throw new Error('El número es demasiado grande.'); } // Evaluate each group of 3 digits (hundreds, thousands, millions, thousands of millions) // Evaluate thousands of millions if (integers.length === 12 || integers.length === 11 || integers.length === 10) { thousandsOfMillions = true; const result = evaluateThousandsOfMillions(integers, numberToCurrency); integers = result.integers; numberToCurrency = result.numberToCurrency; } // Evaluate millions if (integers.length === 9 || integers.length === 8 || integers.length === 7) { const result = evaluateMillions(integers, numberToCurrency, thousandsOfMillions); integers = result.integers; numberToCurrency = result.numberToCurrency; } // Evaluate thousands if (integers.length === 6 || integers.length === 5 || integers.length === 4) { const group = integers.slice(0, Math.max(0, integers.length - 3)); noThousands = Number.parseInt(group, 10) === 0; switch (Number.parseInt(group, 10)) { case 0: { break; } case 1: { numberToCurrency += 'mil '; break; } default: { numberToCurrency += `${getGroupToCurrency(group)}mil `; } } integers = integers.slice(-3); } // Evaluate hundreds noHundreds = Number.parseInt(integers, 10) === 0; numberToCurrency += getGroupToCurrency(integers); numberToCurrency += `${(noThousands && noHundreds ? 'de ' : '') + (numberToCurrency === 'un ' ? 'peso ' : 'pesos ') + decimals}/100 ${monedaName}`; return numberToCurrency.toUpperCase(); }; export const toNumber = (currency) => { let fixedCurrency = currency; if (typeof fixedCurrency === 'string') { fixedCurrency = Number(fixedCurrency); } return Number.isNaN(fixedCurrency) ? 0 : Number(fixedCurrency); }; export const formatCurrency = (currency, currencyDisplay = 'symbol') => { const number = toNumber(currency); return Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', currencyDisplay, }) .format(number) .replace('USD', '') .trim(); };