UNPKG

prg-function

Version:

Funciones genéricas utilizadas por Programamos SPA.

1,490 lines 65 kB
"use strict"; const U = require('prg-constant'); /** * Muestra un error por consola. * * @param {string} asMsg Mensaje a mostrar por consola. * @returns {string} Retorna string vacío. */ function fnLogError(asMsg) { console.error(asMsg); return ''; } /** * Muestra un mensaje por consola. * * @param {string} asMsg Mensaje a mostrar por consola. * @returns {string} Retorna string vacío. */ function fnLogInfo(asMsg) { console.info(asMsg); return ''; } /** * Retorna boolean indicando si un valor es nulo o undefined. * @param aoValue */ function novaluePure(aoValue) { return (aoValue === undefined || aoValue === null); } /** * Retorna boolean indicando si un valor es nulo o undefined. * @param aoValue */ function novalue(aoValue) { return novaluePure(aoValue) || aoValue === ''; } /** * Retorna indicador de fecha válida. * * @param {Date} aoDate Fecha. * @returns {boolean} Retorna true en caso de fecha válida, false en caso de fecha inválida. */ function fnIsValidDate(aoDate) { if (Object.prototype.toString.call(aoDate) === '[object Date]') { // it is a date if (isNaN(aoDate.getTime())) { // d.valueOf() could also work // date is not valid return false; } else { // date is valid return true; } } else { // not a date return false; } // return aoDate instanceof Date && !isNaN(aoDate.getTime()); } /** * Recibe un dato del tipo fecha. Retorna un string con formato: aaaa-mm-dd. * * @param {Date} aoDate Fecha. * @param {boolean} abHourMin Indica si se deben incluir horas y minutos. * @returns {string} Retorna un string con formato: aaaa-mm-dd. */ function fnGetDateString(aoDate, abHourMin) { if (aoDate === null || aoDate === undefined) { return ''; } if (!fnIsValidDate(aoDate)) { return ''; } let lsRet = ''; const lsSep = '-'; const llM = aoDate.getMonth() + 1; const llD = aoDate.getDate(); const llY = aoDate.getFullYear(); lsRet = llY + lsSep + llM + lsSep + llD; if (abHourMin) { lsRet += ` ${aoDate.getHours()}:${aoDate.getMinutes()}`; } return lsRet; } /** * Recibe un dato del tipo fecha. Retorna un string con formato: dd-mm-aaaa. * * @param {Date} aoDate Fecha. * @param {boolean} abHourMin Indica si se deben incluir horas y minutos. * @returns {string} Retorna un string con formato: aaaa-mm-dd. */ function fnGetDateStringChile(aoDate, abHourMin) { if (aoDate === null || aoDate === undefined) { return ''; } if (!fnIsValidDate(aoDate)) { return ''; } let lsRet = ''; const lsSep = '-'; const llM = aoDate.getMonth() + 1; const llD = aoDate.getDate(); const llY = aoDate.getFullYear(); lsRet = llD + lsSep + llM + lsSep + llY; if (abHourMin) { lsRet += ` ${aoDate.getHours()}:${aoDate.getMinutes()}`; } return lsRet; } /** * Sustituye caracteres en un texto. Si no recibe parámetros, cambia apóstrofe por un tilde (´). * * @param {string} asCharCambiar El caracter que se eliminará. * @param {string} asCharCambio El caracter que se agregará. * @param {string} asTxt Texto al cual se le modificarán caracteres. * @returns {string} Texto con el caracter modificado. Si es nulo on indefinido, retorna string vacío. */ function fnStrReplace(asCharCambiar, asCharCambio, asTxt) { if (asTxt === null || asTxt === undefined) { return ''; } if (asCharCambiar === null || asCharCambiar === undefined) { asCharCambiar = ''; } if (asCharCambio === null || asCharCambio === undefined) { asCharCambio = ''; } const lsType = typeof (asTxt); if (lsType === 'object') { if (Object.prototype.toString.call(asTxt) === '[object Date]') { const loDt = asTxt; const ldtFec = loDt; asTxt = fnGetDateString(ldtFec, false); } else { try { asTxt = JSON.stringify(asTxt); } catch (error) { fnLogError(`Error en fnStrReplace: ${error}.`); } } } if (lsType !== 'string') { asTxt += ''; } let lsRet = ''; for (let i = 0; i < asTxt.length; i++) { let lsAux = asTxt.charAt(i); if (lsAux === asCharCambiar) { lsAux = asCharCambio; } lsRet += lsAux; } return lsRet; } /** * Retorna el string de una expresión. Los objetos se convierten a string vacío. * * @param {*} aoValue Expresión que se convertirá a string. * @returns {string} Retorna el string de una expresión. Los objetos se convierten a string vacío. */ function fnToString(aoValue) { let lsRet = ''; try { if (novaluePure(aoValue)) { aoValue = ''; } if (typeof aoValue === 'number') { aoValue = aoValue.toString(); } if (typeof aoValue === 'boolean') { aoValue = aoValue === true ? '1' : '0'; } if (typeof aoValue !== 'string') { return ''; } lsRet = aoValue.trim(); } catch (error) { fnLogError(`Error en trim: ${error}.`); } return lsRet; } /** * Quita espacios a la izquierda y derecha de una expresión. * * @param {*} aoValue Expresión a la que se quitarán espacios. * @returns {string} Quita espacios a la izquierda y derecha de una expresión. */ function trim(aoValue) { return fnToString(aoValue).trim(); } /** * Retorna un número en formato Chile. Separador decimal coma. * Ejemplo: a) Recibe 1.5 y retorna '1,5' * b) Recibe 1,000,000 y retorna '1000000' * * @param {any} aoNumber Número que se convertirá a formato Chile. * @returns {string} Texto con el número en formato Chile. */ function fnToNumberChile(aoNumber) { let lsRet = ''; lsRet = trim(aoNumber); lsRet = fnStrReplace(',', '', lsRet); // Quita la coma separadora de miles. lsRet = fnStrReplace('.', ',', lsRet); // Cambia separador de decimales punto por coma. return lsRet; } /** * Reporta la posición de un string en otro. * * @param {string} asStr String en el cual se realizará la búsqueda. * @param {string} asSearch String que se buscará. * @param {number} [offset=0] Cantidad de caracteres desde los cuales se debe buscar <asSearch>, por defecto es cero. * @returns {number} Retorna la posición en la que está ubicado un string en otro. */ function fnStrpos(asStr, asSearch, offset = 0) { if (asStr === null || asStr === undefined) { return -1; } if (asSearch === null || asSearch === undefined) { return -1; } if (offset === null || offset === undefined) { offset = 0; } if (offset < 0) { offset = 0; } const lsType = typeof (asStr); if (lsType === 'object') { if (Object.prototype.toString.call(asStr) === '[object Date]') { const loDt = asStr; const ldtFec = loDt; asStr = fnGetDateString(ldtFec, false); } else { try { asStr = JSON.stringify(asStr); } catch (error) { fnLogError(`Error en fnStrpos: ${error}.`); } } } const i = (asStr + '').indexOf(asSearch, (offset || 0)); return i === -1 ? -1 : i; } /** * Retorna número entero representado por una expresión. * * @param {*} aoValue Expresión que será evaluada para obtener valor numérico entero. * @param {boolean} [abFtoChile=false] Indica si se debe interpretar la expresión como un número con formato chileno. * @returns {number} Retorna número entero representado por una expresión. */ function intval(aoValue, abFtoChile = false) { if (novalue(aoValue)) { aoValue = '0'; } if (typeof aoValue === 'object') { return 0; } if (typeof aoValue === 'boolean') { aoValue = aoValue === true ? 1 : 0; } let lsVal = aoValue + ''; if (abFtoChile) { // Es un formato de número con separador de decimales (coma) y signo peso. lsVal = fnStrReplace('$', '', lsVal); lsVal = fnStrReplace('.', '', lsVal); lsVal = fnStrReplace(',', '.', lsVal); } let llRet = parseInt(lsVal, 10); if (isNaN(llRet)) { llRet = 0; } return llRet; } /** * Retorna número decimal representado por una expresión. * * @param {*} aoValue Expresión que será evaluada para obtener valor numérico decimal. * @param {boolean} [abFtoChile=false] Indica si se debe interpretar la expresión como un número con formato chileno. * @returns {number} Retorna número decimal representado por una expresión. */ function floatval(aoValue, abFtoChile = false) { if (novalue(aoValue)) { aoValue = '0'; } if (typeof aoValue === 'object') { return 0; } if (typeof aoValue === 'boolean') { aoValue = aoValue === true ? 1 : 0; } let lsVal = aoValue + ''; if (abFtoChile) { // Es un formato de número con separador de decimales (coma) y signo peso. lsVal = fnStrReplace('$', '', lsVal); lsVal = fnStrReplace('.', '', lsVal); lsVal = fnStrReplace(',', '.', lsVal); } let llRet = parseFloat(lsVal); if (isNaN(llRet)) { llRet = 0; } return llRet; } /** * Retorna número decimal con un máximo de 2 posiciones decimales. * * @param {number} adValue Número decimal. * @returns {number} Retorna número decimal con un máximo de 2 posiciones decimales. */ function fnFixDec2(adValue) { adValue = floatval(adValue, false); const llF = 100; return Math.floor(adValue * llF) / llF; // Usa 2 decimales. } /** * Retorna boolean indicando si una expresión es un array o no. * * @param {*} aoArray * @returns {boolean} */ function fnIsArray(aoArray) { if (typeof aoArray !== 'object') { return false; } if (!Array.isArray(aoArray)) { return false; } return true; } /** * Elimina ítems de un objeto y retorna cantidad de eliminaciones. * * @param {*} aoObj Objeto al que elimina ítem. * @param {Array<string>} aoRemove Arreglo con nombres de campos que se eliminarán. * @returns {number} Retorna cantidad de campos eliminados. */ function fnArrRemoveItemObj(aoObj, aoRemove) { let llRet = 0; if (aoObj === undefined || aoObj === null || typeof aoObj !== 'object') { return llRet; } if (aoRemove === null || aoRemove === undefined || !fnIsArray(aoRemove) || aoRemove.length <= 0) { return llRet; } const lbAux = aoObj.length !== undefined; for (let i = 0; i < aoRemove.length; i++) { if (lbAux) { for (let j = 0; j < aoObj.length; j++) { if (aoObj[j].hasOwnProperty(aoRemove[i])) { delete aoObj[j][aoRemove[i]]; llRet++; } } } else { if (aoObj.hasOwnProperty(aoRemove[i])) { delete aoObj[aoRemove[i]]; llRet++; } } } return llRet; } /** * Retorna un substring de un string. * * @param {string} asString String que se va a recortar. * @param {number} [alStart=0] Caracter de inicio del recorte. Se usa base 0. * @param {number} [alLen=0] Cantidad de caracteres a recortar. * @returns {string} Retorna string recortado. */ function substr(asString, alStart = 0, alLen = 0) { asString = fnToString(asString); alStart = intval(alStart); alLen = intval(alLen); if (alStart > (asString.length - 1)) { return ''; } if (asString === '') { return asString; } if (alStart < 0) { alStart = 0; } if (alLen <= 0) { return ''; } const lsRet = asString.substring(alStart, alLen); return lsRet; } /** * Asigna un largo máximo para una variable. * * @param {string} asTexto El texto que se recortará. * @param {number} [alLength=0] El largo máximo que tendrá el texto. * @param {boolean} [abEscape=false] Indica si se debe aplicar 'escape' (addslashes) a caracteres especiales. * @returns {string} Retorna string recortado a <alLength> caracteres. */ function fnSetTxtLen(asTexto, alLength = 0, abEscape = false) { asTexto = trim(asTexto); // Quita espacios. alLength = intval(alLength); if (asTexto === '') { return ''; } if (alLength <= 0) { return ''; } if (fnToString(asTexto).length >= alLength) { asTexto = substr(asTexto, 0, alLength); // Si corresponde, recorta texto. } if (abEscape === true) { // asTexto = addslashes(asTexto); // Si corresponde, 'Escapa' caracteres especiales. } return asTexto; } /** * Recorta caracteres a la derecha de un string. * * @param {string} [asTexto=''] El texto que se recortará. * @param {number} [aiCharsCut=1] La cantidad de caracteres que se recortará, por defecto es 1. * @param {string} [asEndCharToCut=''] Retorna el string recortado a la derecha. * @returns {string} Retorna el string recortado a la derecha. */ function fnRightCut(asTexto = '', aiCharsCut = 1, asEndCharToCut = '') { asTexto = trim(asTexto); // Quita espacios. asEndCharToCut = trim(asEndCharToCut); // Quita espacios. aiCharsCut = intval(aiCharsCut); if (asTexto === '') { return ''; } // Si el string viene vacío retorna valor vacío. if (aiCharsCut <= 0) { return ''; } // No se requiere recortar nada. const liLen = fnToString(asTexto).length; // Determina largo del string. if (liLen < aiCharsCut) { return asTexto; // Se requiere recortar más caracteres de los que tiene el string. Retorna el mismo string. } if (asEndCharToCut !== '' && aiCharsCut === 1 && !(asTexto.endsWith(asEndCharToCut))) { return asTexto; // Se solicita que el texto termine con el caracter <asEndCharToCut> para recortar. De otro modo, sale sin recortar. } asTexto = substr(asTexto, 0, liLen - aiCharsCut); // Recorta caracter(es) de la derecha. return asTexto; } /** * Retorna un texto repetido una cierta cantidad de veces. * * @param {string} asString Texto que se repetirá. * @param {number} [alQty=1] Cantidad de repeticiones. * @returns {string} Retorna <asString> repetido <alQty> veces. */ function fnStrRepeat(asString, alQty = 1) { asString = fnToString(asString); if (asString === '') { return ''; } alQty = intval(alQty); if (alQty <= 1) { return asString; } const lsRet = new Array(alQty + 1).join(asString); return lsRet; } /** * Retorna los valores numéricos separados por coma desde un array o un string numérico. * * @param {Array<any>} aoArray Array o string con valores numéricos. * @param {boolean} [abAcceptZero=false] Indica si se deben aceptar valores iguales a cero. * @returns {string} Retorna un string de números separados por coma (sin coma final). */ function fnGetIdFromArray(aoArray, abAcceptZero = false) { if (aoArray === null || aoArray === undefined) { return ''; } let lsRet = ''; const lsType = typeof aoArray; if (lsType !== 'object' && lsType !== 'string' && lsType !== 'number') { // Sólo se admiten números, texto y objetos. return ''; } if (lsType === 'object' && !fnIsArray(aoArray)) { // Los objetos deben ser del tipo array. return ''; } if (!aoArray || typeof aoArray !== 'object') { // Es un string simple. const llAux = intval(aoArray); aoArray = [llAux]; } aoArray.forEach((loE) => { const llAux = intval(loE); if (llAux > 0 || abAcceptZero) { lsRet += `${llAux},`; } }); if (lsRet !== '') { lsRet = fnRightCut(lsRet, 1, ','); } return lsRet; } /** * Retorna los valores string separados por coma desde un array o un string. * * @param {Array<any>} aoArray Array o string con valores string. * @returns {string} Retorna un string de valores separados por coma (sin coma final). */ function fnGetStringFromArray(aoArray) { if (aoArray === null || aoArray === undefined) { return ''; } let lsRet = ''; const lsType = typeof aoArray; if (lsType !== 'object' && lsType !== 'string' && lsType !== 'number') { // Sólo se admiten números, texto y objetos. return ''; } if (lsType === 'object' && !fnIsArray(aoArray)) { // Los objetos deben ser del tipo array. return ''; } if (!aoArray || typeof aoArray !== 'object') { // Es un string simple. const llAux = trim(aoArray); aoArray = [llAux]; } aoArray.forEach((loE) => { const lsAux = trim(loE); lsRet += `${lsAux},`; }); if (lsRet !== '') { lsRet = fnRightCut(lsRet, 1, ','); } return lsRet; } /** * Rellena un string con caracteres (por defecto a la derecha). * * @param {string} [asTexto=''] El texto que se rellenará con datos. * @param {number} [aiQty=1] La cantidad de caracteres que se rellenará. * @param {string} [asChar=''] El caracter con el cual se rellenará. * @param {boolean} [abAddLeft=false] indica si el relleno se ubica a la izquierda del txto. * @returns {string} Retorna string rellenado. */ function fnStrFill(asTexto = '', aiQty = 1, asChar = '', abAddLeft = false) { asTexto = trim(asTexto); // Quita espacios. asChar = fnToString(asChar); if (asTexto === '') { return asTexto; // Si el string viene vacío retorna valor vacío. } if (asChar === '') { asChar = ' '; } aiQty = intval(aiQty); const liLen = fnToString(asTexto).length; // Determina largo del string. const liCan = aiQty - liLen; if (liCan <= 0) { return asTexto; // Se requiere rellenar el string con más caracteres de los que tiene. Retorna el mismo string. } let lsAux = ''; if (abAddLeft === true) { lsAux = fnStrRepeat(asChar, liCan) + asTexto; } else { lsAux = asTexto + fnStrRepeat(asChar, liCan); } return lsAux; } /** * Recorta caracteres a la izquierda de un string. * * @param {string} [asTexto=''] El texto que se recortará. * @param {number} [aiCharsCut=1] La cantidad de caracteres que se recortará, por defecto es 1. * @returns {string} Recorta caracteres a la izquierda de un string. */ function fnLeftCut(asTexto = '', aiCharsCut = 1) { asTexto = trim(asTexto); // Quita espacios. aiCharsCut = intval(aiCharsCut); if (asTexto === '' || asTexto.length <= aiCharsCut) { return ''; } // Si el string viene vacío retorna valor vacío. if (aiCharsCut <= 0) { return ''; } // No se requiere recortar nada. const liLen = fnToString(asTexto).length; // Determina largo del stirng. if (liLen < aiCharsCut) { return asTexto; // Se requiere recortar más caracteres de los que tiene el string. Retorna el mismo string. } asTexto = substr(asTexto, aiCharsCut, liLen - aiCharsCut); // Recorta caracter(es) de la derecha. return asTexto; } /** * Indica si un texto comienza con un valor determinado. * * @param {string} asText Texto donde buscar. * @param {string} [asStrSearch=''] Texto que se buscará. * @returns {boolean} Retorna bolean indicando si <asText> comenza con <asStrSearch>. */ function fnStartsWith(asText, asStrSearch = '') { asText = fnToString(asText); asStrSearch = fnToString(asStrSearch); if (asText === '') { return false; } if (asStrSearch === '') { return false; } return asText.startsWith(asStrSearch); } /** * Indica si un texto finaliza con un valor determinado. * * @param {string} asText Texto donde buscar. * @param {string} [asStrSearch=''] Texto que se buscará. * @returns {boolean} Retorna bolean indicando si <asText> finaliza con <asStrSearch>. */ function fnEndsWith(asText = '', asStrSearch = '') { asText = fnToString(asText); asStrSearch = fnToString(asStrSearch); if (asText === '') { return false; } if (asStrSearch === '') { return false; } return asText.endsWith(asStrSearch); } /** * Indica si un texto contiene un valor determinado. * * @param {string} asText Texto donde buscar. * @param {string} [asStrSearch=''] Texto que se buscará. * @returns {boolean} Retorna bolean indicando si <asText> contiene <asStrSearch>. */ function fnContains(asText = '', asStrSearch = '') { asText = fnToString(asText); asStrSearch = fnToString(asStrSearch); if (asText === '') { return false; } if (asStrSearch === '') { return false; } return asText.indexOf(asStrSearch) !== -1; } /** * Evalúa una expresión del tipo boolean. Retorna '0' para false ó '1' para true. * * @param {*} asTextBoolean Expresión del tipo boolean. * @returns {string} Retorna string '0' para falso y '1' para true. */ function fnBoolean(asTextBoolean) { let lsAux = '0'; if (typeof asTextBoolean === 'boolean') { lsAux = asTextBoolean ? '1' : '0'; } if (typeof asTextBoolean === 'number') { lsAux = asTextBoolean === 0 ? '0' : '1'; } if (typeof asTextBoolean === 'string') { const S = asTextBoolean.toUpperCase(); if (!(S === undefined || S === null || S === '')) { if (S === 'TRUE' || S === 'YES' || S === 'SI' || S === 'Y' || S === 'S' || S === '1' || S === 'ON') { lsAux = '1'; } if (S === 'FALSE' || S === 'NOT' || S === 'NO' || S === 'N' || S === '0' || S === 'OFF') { lsAux = '0'; } } } return lsAux; } /** * Evalúa un string y lo convierte a número entero. * * @param {*} asValue Expresión que se convertirá a entero. Se permiten números, boolean y string. * @returns {number} Retorna número obtenido de evaluar <asValue>. */ function fnLong(asValue) { let llRet = 0; if (asValue === null) { return llRet; } if (asValue === undefined) { return llRet; } try { if (typeof asValue === 'number') { return asValue; } // Es un número, retorna el mismo número. if (typeof asValue === 'boolean') { return asValue === true ? 1 : 0; } // Es un boolean, retorna 0 ó 1. if (typeof asValue !== 'string') { return 0; } // No es string, luego retorna 0. if (asValue === undefined || asValue === null || asValue === '') { return 0; } let lsAux = fnStrReplace('$', '', asValue); lsAux = fnStrReplace('.', '', lsAux); lsAux = fnStrReplace(',', '.', lsAux); llRet = floatval(lsAux); // Retorna un double. } catch (error) { fnLogError(`Error en fnLong: ${error}.`); } return llRet; // Retorna un double. } /** * Evalúa una expresión string del tipo DD-MM-YYYY. Retorna boolean indicando si es una fecha válida. * * @param {string} [asDate=''] Texto con expresión del tipo fecha. Formato: a) dd-mm-yyyy, b) dd/mm/yyyy, c) dd.mm.yyyy * @param {string} [asSeparator='-'] Separador de fecha. por defecto, asume guión. * @returns {boolean} Retorna true si la expresión es una fecha válida, false en caso contrario. */ function fnIsDate(asDate, asSeparator = '') { asDate = fnToString(asDate); asSeparator = fnToString(asSeparator); if (asDate === '') { return false; } const lsSep = '/'; if (asSeparator === '' || asSeparator === undefined || asSeparator === null) { asSeparator = lsSep; } // asDate = fnStrReplace(lsSep, asSeparator, asDate); // Cambia separador de campos slash. asDate = fnStrReplace('-', asSeparator, asDate); // Cambia separador de campos guión. asDate = fnStrReplace('.', asSeparator, asDate); // Cambia separador de campos punto. let aoDate = asDate.split(asSeparator); // separa en día, mes y año. if (aoDate.length !== 3) { // El arreglo debe tener 3 ítems. (d-m-y). return false; } let ms = 0; // Fecha en in milliseconds. let month = 0; let day = 0; let year = 0; // ; // (integer) month, day and year // Define mes, día y año desde el array (Se espera formato d/m/aaaa). day = intval(aoDate[0]) - 0; // Día. month = intval(aoDate[1]) - 1; // Mes. Resta 1. year = intval(aoDate[2]) - 0; // Año. if (year < 1000 || year > 9000) { // Asigna rango de fecha válidas. return false; } ms = (new Date(year, month, day)).getTime(); // Convierte fecha en milisegundos. aoDate = new Date(); // Inicializa fecha. Reusa variable. aoDate.setTime(ms); // compare input date and parts from Date() object, if difference exists then input date is not valid if (aoDate.getFullYear() !== year || aoDate.getMonth() !== month || aoDate.getDate() !== day) { return false; } return true; } /** * Retorna un número aleatorio entre un rango de números. * * @param {number} alMin Número desde. * @param {number} alMax Número hasta. * @returns {number} Retorna número aleatorio entre <alMin> y <alMax>. */ function fnRnd(alMin, alMax) { alMin = intval(alMin); alMax = intval(alMax); if (alMin === 0 && alMax === 0) { return 0; } return Math.floor(Math.random() * (alMax - alMin + 1)) + alMin; } /** * Retorna string para insertar fecha en base de datos. Para fecha inválidas retorna NULL. * * @param {Date} adtFec Fecha que se preparará para insertar en base de datos. * @returns {string} Retorna string para insertar fecha en base de datos. Para fecha inválidas retorna NULL. */ function fnGetDateToInsert(adtFec) { const lsNull = 'null'; if (adtFec === null || adtFec === undefined) { return lsNull; } if (!fnIsValidDate(adtFec)) { return lsNull; } const lsSep = '-'; const llD = adtFec.getDate(); const llM = adtFec.getMonth() + 1; const llY = adtFec.getFullYear(); const llHr = adtFec.getHours(); const llMn = adtFec.getMinutes(); const llSc = adtFec.getSeconds(); let lsFH = ''; if (llHr > 0 || llMn > 0 || llSc > 0) { lsFH = ` ${llHr}:${llMn}:${llSc}`; } return `'${llY}${lsSep}${llM}${lsSep}${llD}${lsFH}'`; } /** * Convierte un string a un array, de acuerdo a un separador. * * @param {string} [asText=''] Texto que se separará en un array. * @param {string} [asSeparator=','] Separador del texto. Por defcto es coma (,). * @returns {Array<string>} Retorna arreglo con datos separados desde un string. */ function fnSeparaComas(asText = '', asSeparator = ',') { const loRet = []; asText = fnToString(asText); if (asText === '' || asSeparator === '') { return loRet; } return asText.split(asSeparator); } /** * Convierte un string a mayúsculas. * * @param {string} asStr Texto que se convertirá a mayúsculas. * @returns {string} Retorna texto en mayúsculas. */ function strtoupper(asStr) { asStr = fnToString(asStr); if (asStr === '') { return ''; } return asStr.toUpperCase(); } /** * Ordena un arreglo de objetos por una clave específica y un tipo de orden determinado. * * @param {*} aoArray El arreglo que se va a ordenar. * @param {string} asSortKey El campo que se utilizará para el ordenamiento. * @param {boolean} [abDesc=false] Ordenar en forma descendente. Por defecto se ordena en forma ascendente. * @returns */ function sortByKey(aoArray, asSortKey, abDesc = false) { asSortKey = fnToString(asSortKey); if (asSortKey === '') { return []; } // No se indicó campo de ordenamiento, retorn arreglo sin modificar. if (!fnIsArray(aoArray)) { return []; } if (aoArray.length <= 0) { return []; } const liFac = (abDesc === true) ? -1 : 1; return aoArray.sort((a, b) => { let x = a[asSortKey]; let y = b[asSortKey]; if (typeof x === 'string') { x = x.toLowerCase(); } if (typeof y === 'string') { y = y.toLowerCase(); } return (((x < y) ? -1 : ((x > y) ? 1 : 0)) * liFac); }); } /** * Retorna una fecha con un formato determinado. Por defecto, asigna formato: YYYY-MM-DD. * Para fechas inválidas, indefinidas y nulas, retorna null. * * @param {Date} adtDate Fecha a la cual aplicar formato. * @param {string} asFormat Formato que se aplicará a la fecha. * @returns Retorna una fecha con un formato determinado. Por defecto, asigna formato: YYYY-MM-DD. * Para fechas inválidas, indefinidas y nulas, retorna null. */ function fnDateOnly(aoDate) { if (aoDate === null || aoDate === undefined || !fnIsValidDate(aoDate)) { return null; } return new Date(aoDate.getFullYear(), aoDate.getMonth(), aoDate.getDate()); } /** * Retorna la diferencia en días entre dos fechas. * * @param {Date} a Fecha desde. * @param {Date} b Fecha hasta. * @returns {number} Retorna la diferencia en días entre dos fechas. */ function dateDiffInDays(adtFecDesde, adtFecHasta) { if (adtFecDesde === null || adtFecDesde === undefined || adtFecHasta === null || adtFecHasta === undefined) { return 0; } if (!fnIsValidDate(adtFecDesde) || !fnIsValidDate(adtFecHasta)) { return 0; } const MS_PER_DAY = 1000 * 60 * 60 * 24; // Discard the time and time-zone information. const utc1 = Date.UTC(adtFecDesde.getFullYear(), adtFecDesde.getMonth(), adtFecDesde.getDate()); const utc2 = Date.UTC(adtFecHasta.getFullYear(), adtFecHasta.getMonth(), adtFecHasta.getDate()); return Math.floor((utc2 - utc1) / MS_PER_DAY); } /** * Retorna una fecha que se obtiene de sumar una cierta cantidad de días a una fecha. * * @param {Date} adtFec Fecha a la que se sumarán días. * @param {number} alDay Cantidad de dias que se sumarán a la fecha. * @returns {Date} Retorna una fecha que se obtiene de sumar una cierta cantidad de días a una fecha. */ function fnDateAddDays(adtFec, alDay) { if (adtFec === null || adtFec === undefined || !fnIsValidDate(adtFec)) { return adtFec; } alDay = intval(alDay); if (alDay === 0) { return adtFec; } const ldtRet = new Date(adtFec.getFullYear(), adtFec.getMonth(), adtFec.getDate()); ldtRet.setDate(ldtRet.getDate() + alDay); return ldtRet; } /** * Retorna una fecha que se obtiene de sumar una cierta cantidad de meses a una fecha. * * @param {Date} adtFec Fecha a la que se sumarán días. * @param {number} alDay Cantidad de dias que se sumarán a la fecha. * @returns {Date} Retorna una fecha que se obtiene de sumar una cierta cantidad de meses a una fecha. */ function fnDateAddMonth(adtFec, alMonth) { if (adtFec === null || adtFec === undefined || !fnIsValidDate(adtFec)) { return null; } alMonth = intval(alMonth); if (alMonth === 0) { return adtFec; } const ldtRet = new Date(adtFec.getFullYear(), adtFec.getMonth(), adtFec.getDate()); ldtRet.setMonth(ldtRet.getMonth() + alMonth); return ldtRet; } /** * Retorna el número de semana de una fecha. * * @param {Date} adtFec Fecha. * @returns {number} Retorna el número de semana de una fecha. */ function fnGetWeekDate(adtFec) { if (adtFec === null || adtFec === undefined || !fnIsValidDate(adtFec)) { return 0; } const ldtRet = new Date(adtFec.getFullYear(), adtFec.getMonth(), adtFec.getDate()); const date = ldtRet; // new Date(this.getTime()); date.setHours(0, 0, 0, 0); // Thursday in current week decides the year. date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); // January 4 is always in week 1. const week1 = new Date(date.getFullYear(), 0, 4); // Adjust to Thursday in week 1 and count number of weeks from date to week1. return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7); } /** * Aplica una máscara numérica a un número. Retorna un string con el número 'enmascarado'. * * @param {string} asNumber Texto con el número al cual se le va a aplicar la máscara. * @param {string} asType Tipo de máscara. * - <N> Número entero, aplica separador de miles. * - <M> Moneda, aplica signo pesos y separador de miles. * - <D1 - D8> Decimal, aplica separador de miles y separador de decimales (desde 1 hasta 8 decimales). * - <M1 - M8> Moneda, aplica signo pesos, separador de miles y separador de decimales * (desde 1 hasta 8 decimales). * @returns {string} Retorna string con máscara numérica aplicada. */ function formatMoney(asNumber, asType) { asType = fnToString(asType); if (asType === '') { return fnToString(asNumber); } // No se indicó formato, retorna el string original (convertido a string). const llVal = floatval(asNumber); if (llVal === 0) { return '0'; } const loMask = [ 'N', 'M', 'N1', 'N2', 'N3', 'N4', 'N5', 'N6', 'N7', 'N8', 'M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', ]; if (loMask.indexOf(asType) < 0) { // Máscara inválida. return fnToString(asNumber); // No se indicó formato válido, retorna el string original (convertido a string). } let lsType = 'N'; // Por defecto, agrega separador de miles. lsType = asType; const loA = (llVal + '').split('.'); // Crea arreglo con la parte entrera y parte decimal. const loVE = (loA[0]); let loVD = (loA[1]); let llA1 = 0; let lsA = ''; for (let i = loVE.length; i > 0; i--) { const lsL = loVE.charAt(i - 1); lsA = lsL + lsA; llA1++; if (llA1 === 3) { lsA = `.${lsA}`; llA1 = 0; } } if (lsA.charAt(0) === '.') { const lsB = lsA; lsA = lsB.substring(1, lsB.length); // Si corresponde, elimina el primer PUNTO. } if (lsType.startsWith('M')) { lsA = `$ ${lsA}`; } if (lsType.length > 1) { const lsB = lsType; const lsC = lsB.substring(1, lsB.length); // Recupera cantidad de dígitos. if (loVD === undefined || loVD === null) { loVD = '000000000'; } const liChars = parseInt(lsC); if (loVD.length < liChars) { loVD += '000000000'; } const lsD = loVD.substring(0, liChars); lsA = `${lsA},${lsD}`; } return lsA; } /** * Retorna string con formato numérico del lado del servidor. * * @param {string} asFormatType Tipo de formato que se aplica en servidor. * @returns {string} Retorna string con formato numérico del lado del servidor. */ function fnFormatServer(asFormatType) { const lsFM = '###,###,###,###,###,##0'; let lsF = ''; const lsFT = trim(asFormatType); if (lsFT === 'M') { lsF = `$${lsFM}`; } if (lsFT === 'M2') { lsF = `$${lsFM}.00`; } if (lsFT === 'M3') { lsF = `$${lsFM}.000`; } if (lsFT === 'M4') { lsF = `$${lsFM}.0000`; } if (lsFT === 'M5') { lsF = `$${lsFM}.00000`; } if (lsFT === 'M6') { lsF = `$${lsFM}.000000`; } if (lsFT === 'N') { lsF = `${lsFM}`; } if (lsFT === 'N2') { lsF = `${lsFM}.00`; } if (lsFT === 'N3') { lsF = `${lsFM}.000`; } if (lsFT === 'N4') { lsF = `${lsFM}.0000`; } if (lsFT === 'N5') { lsF = `${lsFM}.00000`; } if (lsFT === 'N6') { lsF = `${lsFM}.000000`; } return lsF; } /** * Retorna json utilizado como parámetro de retorno de funciones asíncronas. El formato es: { 'error': string, 'json': string, 's': number}. * * @param {*} asError Error ocurrido en la función. * @param {*} [aoData={}] Datos obtenidos en la función. * @param {number} alResponseCode Código https de respuesta. 200 para ok, 400 y 500 para errores, etc. * @returns {IParamRet} Retorna json utilizado como parámetro de retorno de funciones asíncronas. * el formato es: { 'error': string, 'json': string, 's': number}. */ function fnReturn(asError, aoData = {}, alResponseCode) { if (asError === undefined || asError === '') { asError = null; } if (typeof asError === 'number') { asError = asError.toString(); } if (aoData === undefined || asError) { aoData = null; } return { error: asError, json: aoData, s: alResponseCode }; } /** * Retorna objeto con estructura de datos para ejecutar SQL. La estructura de datos es: * { * 's' : Instrucción SQL, * 'a' : Exigir Filas Afectadas, * 'c' : Exigir Filas Modificadas, * 'ca': Cantidad de Filas Afectadas, * 'cc': Cantidad de Filas Modificadas, * 'ii': ID de registro insertado, * 'm' : Mensaje devuelto por la DB., * 'cf': Cantidad de registros, * 'cw': Cantidad de advertencias * } * * @param {string} asSql SQL que se ejecutará. * @param {boolean} [abAffected=false] Exigir que se afecte algún registro. Válido para INSERT, UPDATE, DELETE. * @param {boolean} [abChanged=false] Exigir que se modifique algún registro. Válido para UPDATE, DELETE. * @param {boolean} [abNoChange=false] Exigir que <NO> se afecte algún registro. Válido para UPDATE. * @returns {iSqlExec} Retorna objeto con estructura de datos para ejecutar SQL. La estructura de datos es: */ function fnSql(asSql, abAffected = false, abChanged = false, abNoChange = false) { asSql = fnToString(asSql); const loRet = { s: asSql, a: (abAffected === true), c: (abChanged === true), ct: (abNoChange === true), ca: 0, cc: 0, ii: 0, m: '', cf: 0, cw: 0, }; return loRet; } /** * Retorna un texto invertido. Ejemplo: UNO cambia a ONU. * * @param {string} asStr Texto que se invertirá. * @returns {string} Retorna un texto invertido. Ejemplo: UNO cambia a ONU. */ function fnStrReverse(asStr) { if (typeof asStr === 'number') { asStr = fnToString(asStr); } if (typeof asStr !== 'string') { return ''; } // Sólo se permiten números. if (asStr === '') { return ''; } // No hay texto para invertir. let x = asStr.length; let lsRet = ''; while (x >= 0) { lsRet += asStr.charAt(x); x--; } return lsRet; } /** * Retorna indicador de validez de rut. * * @param {number} alRut Parte numérica del rut. * @param {string} asDv Dígito verificador. * @returns {boolean} Retorna indicador de validez de rut. */ function fnVeriRut(alRut, asDv) { if (typeof alRut !== 'number' && typeof alRut !== 'string') { return false; } if (typeof asDv !== 'string') { return false; } alRut = intval(alRut); if (alRut <= 0 || alRut > 99999999) { return false; } asDv = fnToString(asDv); if (asDv === '') { return false; } let i = 2; let suma = 0; const lsRut = fnStrReverse(alRut); lsRut.split('').forEach((v) => { if (i === 8) { i = 2; } suma += intval(v) * i; i++; }); let lsDv = `${11 - (suma % 11)}`; if (lsDv === '11') { lsDv = '0'; } if (lsDv === '10') { lsDv = 'K'; } return lsDv === strtoupper(asDv); } /** * Retorna el dígito verificador de un rut. * * @param {number} alRut Rut para recuperar dígito verificador. * @returns {string} Retorna el dígito verificador de un rut. */ function fnGetRutDV(aoRut) { if (typeof aoRut !== 'string' && typeof aoRut !== 'number') { return ''; } const llRut = intval(aoRut); if (llRut <= 0) { return ''; } let i = 2; let suma = 0; const lsRut = fnStrReverse(llRut); lsRut.split('').forEach((v) => { if (i === 8) { i = 2; } suma += intval(v) * i; i++; }); let lsDv = `${11 - (suma % 11)}`; if (lsDv === '11') { lsDv = '0'; } if (lsDv === '10') { lsDv = 'K'; } return lsDv; } /** * Retorna un arreglo con rut y dígito verificador desde un string. Si el rut es incorrecto, retorna un arreglo vacío. * * @param {string} asRut Texto de tipo rut. Ejemplo: 11.111.111-1. * @returns {IRut} Retorna un arreglo con rut y dígito verificador desde un string. Si el rut es incorrecto, retorna un arreglo vacío. */ function fnGetRut(asRut) { const loRet = { r: 0, d: '', rut: '', rp: '', }; // Arreglo de retorno. if (novalue(asRut)) { return loRet; } // Se envía valor nulo o indefinido, retorna arreglo vacío. asRut = fnToString(asRut); if (asRut === '') { return loRet; } // Se envía valor vacío, retorna arreglo vacío. asRut = fnStrReplace('.', '', asRut); // Quita puntos, si corresponde. if (asRut.length <= 7) { return loRet; } // El rut debe tener, al menos 7 caracteres, retorna arreglo vacío. const lsC = '-'; if (asRut.indexOf(lsC) < 0) { // El rut no trae el guión separador de dígito verificador. const lsR = asRut.substring(0, asRut.length - 1); const lsD = asRut.charAt(asRut.length - 1); asRut = lsR + lsC + lsD; // Agrega el guión. } const loAux = asRut.split(lsC); if (loAux.length !== 2) { return loRet; // Hay más de un guión en el rut, retorna arreglo vacío. } if (fnVeriRut(loAux[0], loAux[1])) { // Verifica rut correcto. loRet.r = loAux[0]; loRet.d = loAux[1]; loRet.rut = `${loAux[0]}-${loAux[1]}`; loRet.rp = formatMoney(loAux[0] + '', 'N') + '-' + loAux[1]; } return loRet; } /** * Retorna la cantidad de coindicencias de un texto en otro. * * @param {string} asTextBuscar Texto donde buscar. * @param {string} asTextBuscado Texto que se buscará dentro de otro. * @param {number} [offset=0] Posición desde la cual se comenzará a contar. * @param {number} [length=0] ... * @returns {number} Retorna la cantidad de coindicencias de un texto en otro. */ function fnSubstringCount(asTextBuscar, asTextBuscado, alOffset = 0, alLength = 0) { if (typeof asTextBuscar !== 'string' && typeof asTextBuscar !== 'number') { return 0; } // Sólo para texto y número. if (typeof asTextBuscado !== 'string' && typeof asTextBuscado !== 'number') { return 0; } // Sólo para texto y número. asTextBuscar = fnToString(asTextBuscar); asTextBuscado = fnToString(asTextBuscado); if (asTextBuscar === '') { return 0; } if (asTextBuscado === '') { return 0; } alOffset = intval(alOffset); alLength = intval(alLength); if (alOffset < 0) { alOffset = 0; } if (alLength < 0) { alLength = 0; } let llCant = 0; if (isNaN(alOffset)) { alOffset = 0; } if (isNaN(alLength)) { alLength = 0; } if (asTextBuscado.length === 0) { return 0; } // { return false; } alOffset--; while ((alOffset = asTextBuscar.indexOf(asTextBuscado, alOffset + 1)) !== -1) { if (alLength > 0 && (alOffset + asTextBuscado.length) > alLength) { return 0; // return false; } llCant++; } return llCant; } function strstr(haystack, needle, bool = false) { let pos = 0; haystack += ''; pos = haystack.indexOf(needle); if (pos === -1) { return false; } if (bool) { return haystack.substr(0, pos); } return haystack.slice(pos); } function strrchr(haystack, needle) { let pos = 0; if (typeof needle !== 'string') { needle = String.fromCharCode(parseInt(needle, 10)); } needle = needle.charAt(0); pos = haystack.lastIndexOf(needle); if (pos === -1) { return ''; } const lsRet = haystack.substr(pos); return lsRet; } /** * Retorna indicador para determinar si un correo electrónico es correcto o no. * * @param {string} asEmail Correo electrónico que se evaluará. * @returns {boolean} Retorna indicador para determinar si un correo electrónico es correcto o no. */ function fnVeriEmail(asEmail) { asEmail = fnToString(asEmail); if (asEmail === '') { return false; } let lbMailOk = false; // let lsErr: string; // lsErr = ''; if ((fnToString(asEmail).length >= 6) && (fnSubstringCount(asEmail, '@') === 1) && (substr(asEmail, 0, 1) !== '@') && (substr(asEmail, fnToString(asEmail).length - 1, 1) !== '@')) { if ((!strstr(asEmail, "'")) && (!strstr(asEmail, '\"')) && (!strstr(asEmail, '\\')) && (!strstr(asEmail, '\$')) && (!strstr(asEmail, ' '))) { if (fnSubstringCount(asEmail, '.') >= 1) { // Valida si tiene caracter . (PUNTO). const term_dom = fnLeftCut(strrchr(asEmail, '.')); // Obtiene la terminacion del dominio. if (fnToString(term_dom).length > 1 && fnToString(term_dom).length < 5 && (!strstr(term_dom, '@'))) { const antes_dom = substr(asEmail, 0, fnToString(asEmail).length - fnToString(term_dom).length - 1); const caracter_ult = substr(antes_dom, fnToString(antes_dom).length - 1, 1); if (caracter_ult !== '@' && caracter_ult !== '.') { lbMailOk = true; } else { // lsErr = '4'; } } } else { // lsErr = '3.Sin.Punto.'; } } else { // lsErr = '2.Caracter.Especial.'; } } else { const p2 = fnSubstringCount(asEmail, '@'); if (p2 > 0) { // lsErr = 'Largo.'; } else { // lsErr = 'Falta arroba.'; } } return lbMailOk; } /** * Retorna un string con la primera letra en mayúsculas. Si el string contiene * varias palabras separadas por espacios aplica mayúscula a cada palabra. * * @param {string} asValue String para aplicar mayúsculas. * @returns {string} Retorna un string con la primera letra en mayúsculas. * Si el string contiene varias palabras separadas por espacios aplica mayúscula a cada palabra. */ function fnCapitalyze(asValue) { let lsRet = ''; asValue = trim(asValue); if (asValue === '') { return asValue; } const loAux = asValue.split(' '); loAux.forEach((loE) => { loE = trim(loE); const lsAux = loE.charAt(0).toUpperCase() + loE.slice(1); lsRet = lsRet + lsAux + ' '; }); lsRet = trim(lsRet); return lsRet; } function valStrParam(aoData, asField, asErrTxt = '', abNull = false, alLen = 1000, asErrBas = U.Err.Fld_Missing) { if (intval(trim(alLen)) <= 0) { // El largo es menor o igual a cero. Asigna valor por defecto. alLen = 1000; } const lsVal = substr(trim(aoData[asField]), 0, alLen); if (lsVal === '' && !abNull) { return `${asErrBas} ${asErrTxt}.`; } aoData[asField] = lsVal; return ''; } function valDateParam(aoData, asField, asErrTxt, abNull = false, asErrBas = U.Err.Fld_Missing, abN = true) { if (!aoData || !aoData[asField]) { return ''; //null; } // Valida tipo de dato Date. const lbF1 = aoData[asField] instanceof Date; const lbF2 = !isNaN(aoData[asField].valueOf()); if (lbF1 && lbF2) { return ''; } const lsFec = trim(aoData[asField]); if (lsFec === '') { if (!abNull) { if (trim(asErrBas) === '') { asErrBas = trim(U.Err.Fld_Missing); } return `${asErrBas} ${asErrTxt}.`; } if (abN) { aoData[asField] = null; // 'NULL'; } } if (lsFec !== '') { // Valida un string de fecha. const ldtFec = new Date(lsFec); if (ldtFec === null) { return asErrTxt; } aoData[asField] = ldtFec; } return ''; } function valNumParam(aoData, asField, asErrTxt = '', abNull = false, asErrBas = U.Err.Fld_Missing, abAllowNeg = false) { const llVal = floatval(aoData[asField]); const lbZero = llVal === 0; const lbNeg = llVal < 0 && !abAllowNeg; if ((lbZero || lbNeg) && !abNull) { return `${asErrBas} ${asErrTxt}.`; } aoData[asField] = llVal; return ''; } function valBoolParam(aoData, asField, asErrTxt = '', abNull = false, asErrBas = U.Err.Fld_Missing) { const lbVal = aoData[asField]; if ((lbVal === null || lbVal === undefined) && !abNull) { return `${asErrBas} ${asErrTxt}.`; } aoData[asField] = (lbVal === true); aoData['_' + asField] = (lbVal === true ? 1 : 0); aoData['_' + asField + '1'] = (lbVal === true ? 'SI' : 'NO'); return ''; } function fnGetMailParams(host, port, secure, user, pass, domain, key) { const loRet = { host: host, port: intval(port), secure: (fnBoolean(secure) === '1'), user: user, pass: pass, domainName: domain, }; return loRet; } function getDbParams() { return { host: trim(process.env.DB_HOST), user: trim(process.env.DB_USER), password: trim(process.env.DB_PASS), database: trim(process.env.DB_DATABASE), }; } function getPathTemp() { return trim(process.env.PATH_TEMP); } function getPathAssets() { return trim(process.env.PATH_ASSETS); } function getPathFiles() { return trim(process.env.PAT