/*** * funcion global para caclular los datos financieros y los textos de info ***/ function pepper (vPepperData){ return pepperCalculator(vPepperData); } /*** * funcion que recibe el JSON en bruto y lo convierte a objetos para que se interprete por JavaScript ***/ function pepperJsonParser(vPepperData){ // Parseamos JSON de entrada para convertirlo en un objeto var pepperData = JSON.parse(vPepperData); // separamos objeto en oferta comercial y en textos return{ //financialOffer : pepperData.calculator.financial_offer, commercialOffers : pepperData.calculator.commercial_offers, texts : pepperData.calculator.eco_texts, domain : pepperData.domain, publicKey : pepperData.publicKey, apiKey : pepperData.apiKey, currency : pepperData.currency }; } /*** * funcion base que retorna todos los valores desaeados ***/ function pepperCalculator(vPepperData) { // Inicializacion de clases var cFunctionalities = pepperFunctionalities(); // llamamos a la funcion de parseado var jsonData = pepperJsonParser(vPepperData); // variables "globales" y objetos de uso intero var commercialOffers = jsonData.commercialOffers; var texts = jsonData.texts; // inicializamos variables de comunicaciones var domain = jsonData.domain; var publicKey = jsonData.publicKey; var apiKey = jsonData.apiKey; var currency = jsonData.currency; var simulationsStorage = 'pepperCalculatedValues'; // inicializamos variables para el control de errores var message = null; var messages = []; // validamos datos de entrada message = cFunctionalities.ValidateDataEntry("commercialOffers", commercialOffers); if (message !== null){ messages.push(message); } message = cFunctionalities.ValidateDataEntry("texts", texts); if (message !== null){ messages.push(message); } if (messages.length > 0){ cFunctionalities.ThrowJsException(messages, "pepperCalculator"); } // Ordenamos el objeto con la oferta comercial por la cuota commercialOffers = commercialOffers.sort(fSortByTerms); // Funcion que usaremos para ordenar nuestra oferta comercial function fSortByTerms(a, b) { // if (a.term_total === b.term_total) { if (a.term === b.term) { return 0; } else { // return (a.term_total < b.term_total) ? -1 : 1; return (a.term < b.term) ? -1 : 1; } } // funcion base que dvuelve todos los calculos function fCalculator(amount, term){ var dataCalc = fGetDataCalc(amount, term); return { raw: dataCalc, mapped: pepperMapper().ReturnDataMapper(dataCalc)}; } function fAvailableFinance(amount, productType) { if (!productType) productType = 'STD'; function filterByProductType(offer) { return offer.product_type === productType; } var offers = commercialOffers; if(productType !== '*') offers = commercialOffers.filter(filterByProductType); var auxData = cFunctionalities.MaxMinAmount(offers); return (auxData.minAmount < amount && amount < auxData.maxAmount); } function fMaxMinAmount() { var auxData = cFunctionalities.MaxMinAmount(commercialOffers); var objRet = { minAmount: auxData.minAmount, maxAmount: auxData.maxAmount }; return objRet; } function storeSimulatedValue(simulation){ var previousValues; if (getSessionStoragePepper(simulationsStorage)!== null) { previousValues = JSON.parse(getSessionStoragePepper(simulationsStorage)); previousValues.calc.push(simulation); } else previousValues = { calc : [simulation]}; setSessionStoragePepper(simulationsStorage, JSON.stringify(previousValues)); } function getSimulatedValues(amount, term) { var previousValues; if (getSessionStoragePepper(simulationsStorage)!== null) { previousValues = JSON.parse(getSessionStoragePepper(simulationsStorage)); for(var i = 0; i < previousValues.calc.length; i++) { if (previousValues.calc[i].term == term && previousValues.calc[i].amount == amount) return previousValues.calc[i]; } } return; } function saveSimulation(amount, item) { var simulation = { amount: amount, financedAmount: item.financed_amount, totalPayment: item.total_cost, tae: item.tae, payment: item.regular_fee, openingFee: item.opening_fee_fix_amount, openingFeeType: item.opening_fee_type, interest: item.tin, term: item.term }; storeSimulatedValue(simulation); } function parseSimulatedValues(amount, responseText) { var response = JSON.parse(responseText); var financial_data = response.data.financial_data; financial_data.forEach((item) => saveSimulation(amount, item)); } function syncRequest(amount, domain, publicKey, apiKey) { var xhr = new XMLHttpRequest(); xhr.open("POST", domain + '/api-financial/v2/loan-simulations?currency=' + currency, false); xhr.setRequestHeader("x-merchant-key", publicKey); xhr.setRequestHeader("x-api-key", apiKey); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.send(JSON.stringify({ amount: amount, flow: "ECO" })); if (xhr.status == 200) { var response = JSON.parse(xhr.responseText); var result = response.result; if(typeof response == 'object'){ if (!result.errors) { return (xhr.responseText); } else throw result.errors; } else { throw 'error'; } } } // funcion que devuelve todos los calculos a través del api function fCalculatorApi(amount, term) { var dataCalc = getSimulatedValues(amount, term); if (!dataCalc) { try { var req = syncRequest(amount, domain, publicKey, apiKey); parseSimulatedValues(amount, req); dataCalc = getSimulatedValues(amount, term); } catch (err) { } if (!dataCalc) dataCalc = fGetDataCalc(amount, term); } return { raw: dataCalc, mapped: pepperMapper().ReturnDataMapper(dataCalc)}; } // funcion para calcular el texto del toolTip function fGetHTMLToolTip(amount, term){ // validamos datos de entrada try{ message = cFunctionalities.ValidateDataEntry("amount", amount); if (message !== null){ messages.push(message); } message = cFunctionalities.ValidateDataEntry("term", term); if (message !== null){ messages.push(message); } if (messages.length > 0){ cFunctionalities.ThrowJsException(messages, "fGetHTMLToolTip"); } var calc = fCalculator(amount, term); var HTMLToolTip = texts.html_tool_tip; HTMLToolTip = fReplaceTextToolTip(HTMLToolTip, calc); return HTMLToolTip; } catch(error){ cFunctionalities.ThrowJsException(error, 'fIncreaseTerm'); } } // funcion para calcular el texto de uso interno al pulsar mas informacion function fGetHTMLToolTipPepper(amount, term){ // validamos datos de entrada message = cFunctionalities.ValidateDataEntry("amount", amount); if (message !== null){ messages.push(message); } message = cFunctionalities.ValidateDataEntry("term", term); if (message !== null){ messages.push(message); } if (messages.length > 0){ cFunctionalities.ThrowJsException(messages, "fGetHTMLToolTipPepper"); } var calc = fCalculator(amount, term); var HTMLToolTipPepperExtended = texts.html_tool_tip_pepper_extended || "N/A"; HTMLToolTipPepperExtended = fReplaceTextToolTip(HTMLToolTipPepperExtended, calc); return HTMLToolTipPepperExtended; } /*** * funcion para calcular el texto a visualizar al cargar o cambiar los plazos en el popUp o widget en Pepper. * En caso de no enctrar nada devlvemos N/A ***/ function fGetHTMLToolTipPopup(type, calc){ var HTMLToolTipPopup =""; if (type === "total"){ HTMLToolTipPopup = texts.html_tool_tip_popup || "N/A"; } else{ HTMLToolTipPopup = texts.html_tool_tip_pepper || "N/A"; } HTMLToolTipPopup = fReplaceTextToolTip(HTMLToolTipPopup, calc); return HTMLToolTipPopup; } // funcion que devuelve el texto correspondiente al tipo de comision de apertura function fGetOpeningFeeText(openingFeeType, openingFee){ var openingFeeText = ""; /*** * si la comision de apertura es cero, dejamos el texto vacio. * parseamos por que el valor almacenado en calc es un string al habetr pasdado por el mapper ***/ if (parseFloat(openingFee) === 0){ return openingFeeText; } if (openingFeeType === "P"){ openingFeeText = texts.opening_fee_text_p; }else{ openingFeeText = texts.opening_fee_text_n; } return openingFeeText; } // funcion que remplaza los patrones function fReplaceTextToolTip(text, calc) { var openingFeeText = fGetOpeningFeeText(calc.raw.openingFeeType, calc.raw.openingFee); // preparamos objeto que mapea el reemplazo var mapObj = { "{&amount&}":calc.mapped.amount, "{&tin&}":calc.mapped.tin, "{&tae&}":calc.mapped.tae, "{&CA&}":calc.mapped.openingFee, "{&openingFeeText&}":openingFeeText, "{&totalam&}":calc.mapped.totalPayment, "{&CAFinanced&}": cFunctionalities.RoundToN(calc.raw.openingFee/calc.raw.term, 2).toLocaleString("es-ES",{minimumFractionDigits: 2}) }; // creamos expresion regular que pasaremos al replace gi = global insensitive replacment var replaceText = new RegExp(Object.keys(mapObj).join("|"),"gi"); // sustituimos los patrones por los valores correspondientes text = text.replace(replaceText, function (matched) { return mapObj[matched]; }); // Reemplazamos de nuevo para incluir variables que tienen variables text = text.replace(replaceText, function (matched) { return mapObj[matched]; }); return text; } // funcion para calclar el plazo maximo de la oferta comercial function fGetMaxTerm(amount, productType){ if (!productType) productType = 'STD'; function filterByProductType(offer) { return offer.product_type === productType; } var offers = commercialOffers; if(productType !== '*') offers = commercialOffers.filter(filterByProductType); var term = 0; for(var i = 0; i < offers.length; i++){ if (amount >= offers[i]["min_amount"] && amount <= offers[i]["max_amount"]) // si importe en rango entramos if (term < offers[i]["term"]){ term = offers[i]["term"]; } // nos quedamos con el plazo mas elevado } return term; } //funcion para obtener los datos de la oferta comercial de todos los tramos //access: el tipo de acceso a la oferta // - api: Realizar la llamada api // - red: Realizar el calculo con los datos redondeados function fGetCommercialOffer(amount, term, type){ var objRet = []; const productType = 'STD'; function filterByProductType(offer) { return offer.product_type === productType; } var offers = commercialOffers; if(productType !== '*') offers = commercialOffers.filter(filterByProductType); for(var i = 0; i < offers.length; i++){ objRet.push(fGetCommercialOfferTerm(amount, offers[i].term, type)); } return objRet; } //funcion para obtener los datos de la oferta comercial de un solo tramo //access: el tipo de acceso a la oferta // - api: Realizar la llamada api // - red: Realizar el calculo con los datos redondeados function fGetCommercialOfferTerm(amount, term, type, productType){ try{ if (!productType) productType = 'STD'; // convertimos a minusculas type = type.toLowerCase(); if(isNaN(amount)){ amount = 0.1; } var objRet = { payment: null, term: null, btnIncreaseTermEnabled: null, btnDecreaseTermEnabled: null, Information: null }; // validamos datos de entrada message = cFunctionalities.ValidateDataEntry("amount", amount); if (message !== null){ messages.push(message); } message = cFunctionalities.ValidateDataEntry("term", term); if (message !== null){ messages.push(message); } message = cFunctionalities.ValidateDataEntry("type", type); if (message !== null){ messages.push(message); } if (messages.length > 0){ cFunctionalities.ThrowJsException(messages, "fGetFinancialOffer"); } var vInformation = "", vBtnIncrease = true, vBtnDecrease = true, maxAmount = 0, minAmount = 0, maxTerm = 0, minTerm = 0; function filterByProductType(offer) { return offer.product_type === productType; } var offers = commercialOffers; if(productType !== '*') offers = commercialOffers.filter(filterByProductType); // alimentamos variables maximas y minimas y obtenemos el rango de plazos disponibles para el plazo data = cFunctionalities.MaxMinAmountTerm(amount, offers); maxAmount = data.maxAmount; minAmount = data.minAmount; maxTerm = data.maxTerm; minTerm = data.minTerm; termArray = data.termOffer; /*** * si no recibimos plazo, calculamos el maximo por defecto. * si el plazo recibido no esta entre los plazos disponibles para el importe, recalculamos el plazo maximo ***/ if (term === null || (term !== null && cFunctionalities.ExistsInArray(term, "term", termArray) === false)){ term = fGetMaxTerm(amount, productType); } // desahabilitamos los botones de +/- si alcanzamos los limites if (term >= maxTerm){ vBtnIncrease = false; } if (term <= minTerm){ vBtnDecrease = false; } // comprobacion si el importe esta entre el minimo y el maximo if (amount > maxAmount || amount < minAmount){ return objRet; } else{ // una vez aqui, llamamos a la calculadora var calc; if(type === 'api'){ //TODO Async calc = fCalculatorApi(amount, term); } else calc = fCalculator(amount, term); if (type !== "parcial"){ vInformation = fGetHTMLToolTipPopup(type, calc); } objRet.payment = calc.mapped.payment; objRet.term = term; objRet.btnIncreaseTermEnabled = vBtnIncrease; objRet.btnDecreaseTermEnabled = vBtnDecrease; objRet.Information = vInformation; return objRet; } } catch(error){ cFunctionalities.ThrowJsException(error, 'fGetCommercialOfferTerm'); } } // funcion para obtener los datos base function fGetFinancialOffer(amount, term, type){ try{ // convertimos a minusculas type = type.toLowerCase(); if(isNaN(amount)){ amount = 0.1; } var objRet = { payment: null, term: null, btnIncreaseTermEnabled: null, btnDecreaseTermEnabled: null, Information: null }; // validamos datos de entrada message = cFunctionalities.ValidateDataEntry("amount", amount); if (message !== null){ messages.push(message); } message = cFunctionalities.ValidateDataEntry("term", term); if (message !== null){ messages.push(message); } message = cFunctionalities.ValidateDataEntry("type", type); if (message !== null){ messages.push(message); } if (messages.length > 0){ cFunctionalities.ThrowJsException(messages, "fGetFinancialOffer"); } var vInformation = "", vBtnIncrease = true, vBtnDecrease = true, maxAmount = 0, minAmount = 0, maxTerm = 0, minTerm = 0; // alimentamos variables maximas y minimas y obtenemos el rango de plazos disponibles para el plazo data = cFunctionalities.MaxMinAmountTerm(amount, commercialOffers); maxAmount = data.maxAmount; minAmount = data.minAmount; maxTerm = data.maxTerm; minTerm = data.minTerm; termArray = data.termOffer; /*** * si no recibimos plazo, calculamos el maximo por defecto. * si el plazo recibido no esta entre los plazos disponibles para el importe, recalculamos el plazo maximo ***/ if (term === null || (term !== null && cFunctionalities.ExistsInArray(term, "term", termArray) === false)){ term = fGetMaxTerm(amount); } // desahabilitamos los botones de +/- si alcanzamos los limites if (term >= maxTerm){ vBtnIncrease = false; } if (term <= minTerm){ vBtnDecrease = false; } // comprobacion si el importe esta entre el minimo y el maximo if (amount > maxAmount || amount < minAmount){ return objRet; } else{ // una vez aqui, llamamos a la calculadora var calc = fCalculator(amount, term); if (type !== "parcial"){ vInformation = fGetHTMLToolTipPopup(type, calc); } objRet.payment = calc.mapped.payment; objRet.term = term; objRet.btnIncreaseTermEnabled = vBtnIncrease; objRet.btnDecreaseTermEnabled = vBtnDecrease; objRet.Information = vInformation; return objRet; } } catch(error){ cFunctionalities.ThrowJsException(error, 'fGetFinancialOffer'); } } // funcion para incrementar el plazo function fIncreaseTerm(amount, term, type, productType){ try{ var newTerm = term; if(!productType) productType = 'STD'; function filterByProductType(offer) { return offer.product_type === productType; } var offers = commercialOffers; if(productType !== '*') offers = commercialOffers.filter(filterByProductType); for (var i = 0; i < offers.length; i++){ if (term < offers[i]["term"] && amount >= offers[i]["min_amount"] && amount <= offers[i]["max_amount"]){ newTerm = offers[i]["term"]; break; } } return fGetCommercialOfferTerm(amount, newTerm, type, productType); } catch(error){ cFunctionalities.ThrowJsException(error, 'fIncreaseTerm'); } } // funcion para disminuir el plazo function fDecreaseTerm(amount, term, type, productType){ try{ var newTerm = term; if(!productType) productType = 'STD'; function filterByProductType(offer) { return offer.product_type === productType; } var offers = commercialOffers; if(productType !== '*') offers = commercialOffers.filter(filterByProductType); for (var i = offers.length; i != 0; i--){ if (term > offers[i-1]["term"] && amount >= offers[i-1]["min_amount"] && amount <= offers[i-1]["max_amount"]){ newTerm = offers[i - 1]["term"]; break; } } return fGetCommercialOfferTerm(amount, newTerm, type, productType); } catch(error){ cFunctionalities.ThrowJsException(error, 'fDecreaseTerm'); } } // funcion que llama distintos componenets para calcular los datos necesarios function fGetDataCalc(amount, term){ // inicializamos la clases var finData = pepperFinancialData().GetFinancialData(amount, term, commercialOffers); var finCalc = pepperFinancialCalc(); // calculamos tabla de amortizacion var amortTable = finCalc.AmortizationTable(amount, term, finData.interest, finData.openingFeeType, finData.openingFee, finData.firstPayment); // En caso de ser un primer pago se debe reducir el plazo en -1 if (finData.firstPayment) for(i = 0; i < amortTable.amortTable.length; i++) amortTable.amortTable[i][0]=amortTable.amortTable[i][0] - 1; // calculamos tir en base a la tabla de amortizacion var tir = 0.0; if (finData.interest > 0 || finData.openingFee > 0) tir = finCalc.CalcTir(amortTable); return { amount : amount, totalPayment : finCalc.GetTotalPayment(amortTable.amortTable), tae : finCalc.CalcTae(tir), payment : amortTable.instalment, openingFee : finData.openingFee, openingFeeType : finData.openingFeeType, interest : finData.interest, term : term }; } return { getCommercialOfferTerm:fGetCommercialOfferTerm, getCommercialOffer:fGetCommercialOffer, getFinancialOffer:fGetFinancialOffer, increaseTerm:fIncreaseTerm, decreaseTerm:fDecreaseTerm, getHTMLToolTip:fGetHTMLToolTip, getHTMLToolTipPepper: fGetHTMLToolTipPepper, availableFinance : fAvailableFinance, maxMinAmount : fMaxMinAmount }; } /*** * Funcion que mapea el resultado de la cacluladora al modelo que se necesita ***/ function pepperMapper(){ var ROUND_FINAL = 2; function fReturnDataMapper(dataCalc){ try{ var froundN = pepperFunctionalities().RoundToN; return { /*** * rendondeamos a 2 decimales todos los valores mediante la funcion fRoundToN * toLocaleString convierte al formato regional indicado (es-ES) comas para decimales y puntos para miles, * minimumFractionDigits indica el numero minimo de decimales que tiene que haber. * ¿posibles problemas de compatibilidad? ***/ amount: froundN(dataCalc.amount,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), payment: froundN(dataCalc.payment,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), totalPayment: froundN(dataCalc.totalPayment,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), firstPayment: froundN(dataCalc.payment,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), lastPayment: froundN(dataCalc.payment,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), tae: froundN(dataCalc.tae,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), tin: froundN(dataCalc.interest,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), openingFee: froundN(dataCalc.openingFee,ROUND_FINAL).toLocaleString("es-ES",{minimumFractionDigits: 2}), openingFeeType: dataCalc.openingFeeType }; }catch(error) { cFunctionalities.ThrowJsException(error, 'fReturnDataMapper'); } } return { ReturnDataMapper: fReturnDataMapper }; } /*** * funcion base que tendra funciones de obtencion de datos de caracter financiero ***/ function pepperFinancialData(){ /*** * funcion para obtener los datos financieros de la ofertaComercial segun el plazo e importe ***/ function fGetFinancialData(amount, term, commercialOffers){ var openingFee = 0; var openingFeePct = 0; var openingFeeType = "N"; // P = primera cuota, N = financiada var interest = 0; var commercialOfferId = ""; for(var i = 0; i= commercialOffers[i]["min_amount"] && amount <= commercialOffers[i]["max_amount"]){ interest = commercialOffers[i]["tin"]; openingFeeType = commercialOffers[i]["opening_fee_type"]; openingFeePct = commercialOffers[i]["opening_fee_percentage"]; openingFee = commercialOffers[i]["opening_fee_fix_amount"]; commercialOfferId = commercialOffers[i]["commercial_offer_id"]; } } if (openingFeePct !== 0 && openingFee === 0){ openingFee = (openingFeePct/100) * amount; } return { openingFee : openingFee, openingFeeType : openingFeeType, interest : interest, commercialOfferId : commercialOfferId, firstPayment : true }; } return { GetFinancialData: fGetFinancialData }; } /*** * funcion base que albergara los diferentes calculos financieros ***/ function pepperFinancialCalc(){ // inicializacion de clases externas // usaremos redondeo a 4 decimales para simular el tipo de dato Money de BBDD var ROUND_FLOAT = 8; var ROUND_MONEY = 4; var ROUND_FINAL = 2; var froundN = pepperFunctionalities().RoundToN; /*** * funcion para calcular la tabla de amortizacion ***/ function fAmortizationTable(amount, term, interest, openingFeeType, openingFee, firstPayment){ var disbursement = amount; if (openingFeeType === "F"){ // financiada + amount = froundN(amount + openingFee, ROUND_FINAL); } if (openingFeeType === "N"){ // financiada - amount = froundN(amount - openingFee, ROUND_FINAL); } var ani = firstPayment ? 1 + fCalcAni(term-1, interest):fCalcAni(term, interest); var instalment = froundN(amount / ani, ROUND_FINAL); var amortTable = []; // Se incluye calculo del carrete para calcular la tabla de amortizacion var aux_amount = amount; var carrete_amount = null; for (var i = 1; i <= term; i++){ carrete_amount = fCarreteTerm(i, instalment, aux_amount, interest); aux_amount = froundN(aux_amount - carrete_amount.instalment_principal,ROUND_FINAL); if ((i == 1) && (openingFeeType == "P")) amortTable.push([i,froundN(carrete_amount.instalment + openingFee, ROUND_FINAL)]); else amortTable.push([i,carrete_amount.instalment]); } return { amortTable:amortTable, amount:amount, disbursement: disbursement, instalment:instalment }; } /*** * Formula para calcular los datos de la siguiente cuota ***/ function fCarreteTerm(actual_term, instalment, amount_pending,interest ){ var new_instalment = 0; var interest_month = froundN(interest /1200, ROUND_FLOAT); var instalment_interest = froundN(amount_pending * interest_month, ROUND_FINAL); if (actual_term == 1) instalment_interest = 0; // si la pasta pendiente es menor que la cuota lo clavo todo if (instalment > amount_pending){ instalment_principal = amount_pending; } else { instalment_principal = froundN(instalment - instalment_interest, ROUND_FINAL); } var new_amount = froundN(amount_pending - instalment_principal, ROUND_FINAL); var instalment = froundN(instalment_principal + instalment_interest, ROUND_FINAL); return { i:actual_term, new_amount:new_amount, instalment_principal:instalment_principal, instalment_interest:instalment_interest, instalment:instalment }; } /*** * formula matematica financiera para calcular el coeficiente de la cuota ***/ function fCalcAni(term, interest){ var ani = 0; if (interest === 0){ ani = term; } else{ interest = interest / 1200; ani = (Math.pow(1 + interest, term) - 1) / (interest * Math.pow(1 + interest, term)); } return ani; } /*** * funcion que calclula el TIR dada una tabla de amortizacion y el importe ***/ function fCalcTir(amortizationTable){ var tir = 15; // valor inicial var monthlyTir = 0; var amortTable = amortizationTable.amortTable; var disbursement = amortizationTable.disbursement; var totalPayment = 0; var maxLim = 100; var minLim = 0; for (var i = 0; i<=30; i++){ // 30 vueltas para aproximarnos al valor totalPayment = 0; monthlyTir = tir/1200; for (var j = 0; j disbursement) { minLim = tir; } else{ maxLim = tir; } tir = minLim + ((maxLim - minLim) / 2); } return tir; } /*** * funcion que calcula el TAE a partir de TIR ***/ function fCalcTae(tir){ var tae = 0; tae = (Math.pow(1 + (tir / 1200), 12) - 1) * 100; return tae; } /*** * funcion que hace un sumatorio de todas las cuotas de la tabla de amortizacion ***/ function fGetTotalPayment(amortTable){ // funcion para sumar todas las cuotas de la tabla de amortizacion totalPayment = amortTable.map(function (v) { return v[1]; }).reduce(function (a, b) { return a + b; }); return totalPayment; } return{ AmortizationTable : fAmortizationTable, CalcTir: fCalcTir, CalcTae : fCalcTae, GetTotalPayment : fGetTotalPayment }; } function pepperFunctionalities(){ // funcion que redondea el numero pasado por parametro a N decimales pasado por parametros function fRoundToN(num, n){ if (num === 1.005){ //para este caso JS lo redondea a 1, niapa num = num + 0.00001; } var nRound = Math.pow(10, n); return Math.round(num * nRound) / nRound; } // funcion que busca el valoe "search" en la columna "column" en el array "array" function fExistsInArray(search,column,array){ var ret = false; for (var i = 0; i = amount){ var newTermOffer = {}; newTermOffer.term = commercialOffer[i]["term"]; newTermOffer.minAmount = commercialOffer[i]["min_amount"]; newTermOffer.maxAmount = commercialOffer[i]["max_amount"]; termOffer.push(newTermOffer); } } maxAmount = Math.max.apply(Math, termOffer.map(function(column) { return column.maxAmount; })); minAmount = Math.min.apply(Math, termOffer.map(function(column) { return column.minAmount; })); maxTerm = Math.max.apply(Math, termOffer.map(function (column) { return column.term; })); minTerm = Math.min.apply(Math, termOffer.map(function(column) { return column.term; })); return { maxAmount : maxAmount, minAmount : minAmount, maxTerm : maxTerm, minTerm : minTerm, termOffer :termOffer }; } function fMaxMinAmount(commercialOffer){ maxAmount = Math.max.apply(Math, commercialOffer.map(function(column) { return column.max_amount; })); minAmount = Math.min.apply(Math, commercialOffer.map(function(column) { return column.min_amount; })); return { maxAmount : maxAmount, minAmount : minAmount }; } // funcion que valida los diferentes valores que puede contener un tipo de parametro de entrada function fValidateDataEntry(type, value){ var message = null; switch (type){ case "amount": if (typeof value === "string"){ message = "Valor de \""+type+"\": {"+value+"} no es un valor numerico valido"; }else if (typeof value === "undefined" /*|| value === null*/){ message = "Valor de \""+type+"\": {"+value+"} no esta definido"; /*}else if (value === 0){ message = "Valor de \""+type+"\": {"+value+"} no es un valor admitido";*/ }else if (value < 0){ message = "Valor de \""+type+"\": {"+value+"} no puedes ser menor que 0"; } break; case "term": if (typeof value === "string"){ message = "Valor de \""+type+"\": {"+value+"} no es un valor numerico valido"; }else if (typeof value === "undefined"){ message = "Valor de \""+type+"\": {"+value+"} no esta definido"; }else if (value === 0){ message = "Valor de \""+type+"\": {"+value+"} no es un valor admitido"; }else if (value < 0){ message = "Valor de \""+type+"\": {"+value+"} no puedes ser menor que 0"; } break; case "type": if (value !== "parcial" && value !== "total" && value !== "pepper" && value !== "api"){ message = "Valor \""+type+"\": {"+value+"} no esta entre los valores permitidos"; } break; } return message; } function fThrowJsException(messages, process){ // asignamos valor a process si no esta definido if (typeof process === "undefined" || process === null || process === ""){ process = "N/A"; } var exception = []; if(Array.isArray(messages)){ for (var i = 0; i < messages.length; i++){ var newException = {}; newException.Message = messages[i]; newException.process = process; exception.push(newException); } }else{ exception.push({ Message: messages, process: process }); } throw exception; } return { RoundToN: fRoundToN, ExistsInArray: fExistsInArray, MaxMinAmountTerm: fMaxMinAmountTerm, MaxMinAmount: fMaxMinAmount, ValidateDataEntry: fValidateDataEntry, ThrowJsException: fThrowJsException }; }