diff --git a/harvester-app/src/backend/casosUso/formulas/aplicarFormula.js b/harvester-app/src/backend/casosUso/formulas/aplicarFormula.js
index f8bf9f6b..5b776ce1 100644
--- a/harvester-app/src/backend/casosUso/formulas/aplicarFormula.js
+++ b/harvester-app/src/backend/casosUso/formulas/aplicarFormula.js
@@ -162,5 +162,8 @@ function indiceALetraColumna(indice) {
}
module.exports = {
- aplicarFormula
+ aplicarFormula,
+ encontrarColumnaVacia,
+ traducirFormulaEstructurada,
+ indiceALetraColumna,
};
diff --git a/harvester-app/src/backend/casosUso/formulas/filtrarDatos.js b/harvester-app/src/backend/casosUso/formulas/filtrarDatos.js
new file mode 100644
index 00000000..0c26c0b2
--- /dev/null
+++ b/harvester-app/src/backend/casosUso/formulas/filtrarDatos.js
@@ -0,0 +1,152 @@
+const { HyperFormula } = require('hyperformula');
+const { encontrarColumnaVacia } = require('./aplicarFormula.js')
+
+const opciones = {
+ licenseKey: 'gpl-v3',
+};
+
+/**
+ * Aplica una fórmula estructurada a una hoja de Excel almacenada en localStorage.
+ * @param {string} nombreFormula - Nombre de la fórmula a aplicar.
+ * @param {string} formulaEstructurada - Fórmula estructurada a aplicar.
+ * @param {string|null} tractorSeleccionado - Nombre de la hoja donde se aplicará la fórmula (opcional).
+ * @returns {Object} Resultado de la aplicación de la fórmula.
+ */
+
+function filtrarDatos(filtro, datosExcel, tractorSeleccionado){
+ if(filtro.length==0){
+ return { resultados: datosExcel };
+ }
+
+ // Lógica para filtrar los datos según el filtro
+
+ const hojas = datosExcel.hojas;
+
+ // Si no se especifica hoja, usar la primera disponible
+ let datos = [];
+ let tractorUsado = '';
+
+ if (tractorSeleccionado && hojas[tractorSeleccionado]) {
+ datos = hojas[tractorSeleccionado];
+ tractorUsado = tractorSeleccionado;
+ } else {
+ // Tomar la primera hoja disponible
+ tractorUsado = Object.keys(hojas)[0];
+ datos = hojas[tractorUsado];
+ }
+
+ // Verificar que datos sea un array
+ if (!Array.isArray(datos)) {
+ throw new Error('Formato de datos inválido: se esperaba un array');
+ }
+
+ if (datos.length === 0) {
+ throw new Error('No hay datos disponibles en la hoja seleccionada');
+ }
+
+ // Obtener encabezados
+ const encabezados = datos[0];
+
+ // Encontrar la primera columna vacía usando método seguro
+ const indiceColumnaVacio = encontrarColumnaVacia(datos);
+
+
+
+ const hyperFormulaInstance = HyperFormula.buildFromArray(datos, opciones);
+ const sheetId = hyperFormulaInstance.getSheetId('Sheet1');
+
+ const columnaCondicion = nombreColumnaAIndice(filtro[0].Datos, encabezados);
+ if(columnaCondicion.error) {
+ return { error: true, columnaNoEncontrada: columnaCondicion.columnaNoEncontrada };
+ }
+
+ const filas = datos.length;
+
+ const condicionFiltro = extraerCondicionFiltro(filtro[0].Datos);
+
+ for(let columna = indiceColumnaVacio; columna < indiceColumnaVacio*2+1; columna+=1) {
+ hyperFormulaInstance.setCellContents({ row: 0, col: columna, sheet: sheetId }, encabezados[columna-indiceColumnaVacio]);
+ const columnaLetra = numeroAColumnaExcel(columna-indiceColumnaVacio+1);
+ hyperFormulaInstance.setCellContents({ row: 1, col: columna, sheet: 0 }, `=FILTER(${columnaLetra}2:${columnaLetra}${filas}, ${columnaCondicion}2: ${columnaCondicion}${filas}${condicionFiltro})`);
+ }
+
+ const resultadosFiltrados = [];
+ for(let fila = 0; fila < filas; fila+=1) {
+ const resultadoColumna = [];
+ for(let columna = indiceColumnaVacio; columna < indiceColumnaVacio*2+1; columna+=1) {
+ const valorCelda = hyperFormulaInstance.getCellValue({ row: fila, col: columna, sheet: sheetId });
+ if (valorCelda != null && valorCelda != undefined) {
+ resultadoColumna.push(valorCelda);
+ }
+ }
+ if (resultadoColumna.length > 0) {
+ resultadosFiltrados.push(resultadoColumna);
+ }
+ }
+
+ const resultados = {
+ hojas: {
+ [tractorSeleccionado]: resultadosFiltrados
+ }
+ };
+
+
+ return {
+ resultados,
+ };
+
+}
+
+
+function numeroAColumnaExcel(num) {
+ let columna = '';
+ while (num > 0) {
+ const residuo = (num - 1) % 26;
+ columna = String.fromCharCode(65 + residuo) + columna;
+ num = Math.floor((num - 1) / 26);
+ }
+ return columna;
+}
+
+
+
+/**
+ * @function traducirFormulaEstructurada
+ * @param {string} formula - Fórmula estructurada a traducir.
+ * @param {Array} encabezados - Encabezados de la hoja de Excel.
+ * @param {number} filaActiva - Fila activa para la traducción.
+ * @returns {string} Fórmula traducida a formato clásico de Excel.
+ */
+
+function nombreColumnaAIndice(filtro, encabezados) {
+ // Buscar el primer match de [@NombreColumna]
+ const match = filtro.match(/\[@([^\]]+)\]/);
+ if (!match) {
+ return { error: true, columnasNoEncontradas: ['No se encontró ninguna columna en el filtro'] };
+ }
+ const nombreColumna = match[1];
+ const columna = encabezados.indexOf(nombreColumna);
+ if (columna === -1) {
+ return { error: true, columnaNoEncontrada: [nombreColumna] };
+ }
+ return numeroAColumnaExcel(columna + 1); // +1 porque A=1, B=2, etc.
+}
+
+
+/**
+ * Extrae la condición de una fórmula tipo =FILTER([@Columna]condición)
+ * @param {string} filtro - Fórmula tipo =FILTER([@Columna]condición)
+ * @returns {string|null} La condición (por ejemplo, '>1' o '="Muy rápido"'), o null si no se encuentra.
+ */
+function extraerCondicionFiltro(filtro) {
+ // Busca la referencia estructurada y lo que sigue después de ella, hasta el paréntesis de cierre
+ const match = filtro.match(/\[@[^\]]+\]([^)]+)/);
+ if (!match) return null;
+ return match[1].trim();
+}
+
+
+
+module.exports = {
+ filtrarDatos,
+}
\ No newline at end of file
diff --git a/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css b/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css
index 9d4b7041..ccdd6780 100644
--- a/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css
+++ b/harvester-app/src/framework/utils/css/paginas/analisis/generarReporte.css
@@ -564,7 +564,7 @@ body,
gap: 10px;
align-items: center;
justify-content: flex-start;
- height: 650px;
+ height: wrap-content;
position: relative;
}
diff --git a/harvester-app/src/framework/utils/css/paginas/inicio/moduloTractores.css b/harvester-app/src/framework/utils/css/paginas/inicio/moduloTractores.css
index 9146493f..4c94664b 100644
--- a/harvester-app/src/framework/utils/css/paginas/inicio/moduloTractores.css
+++ b/harvester-app/src/framework/utils/css/paginas/inicio/moduloTractores.css
@@ -55,6 +55,7 @@ input:focus {
flex-shrink: 0;
position: relative;
display: none;
+ height: 100%;
}
.secundario {
background: #e8e8e8;
@@ -96,10 +97,26 @@ input:focus {
border: none;
}
+
+.tractores-contenido{
+ height: 100%; /* Ajusta según lo que necesites */
+ max-height: 34.5em;
+ overflow-y: auto;
+ scrollbar-width: thin; /* Firefox */
+ scrollbar-color: #999 transparent; /* Firefox */
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ align-items: flex-start;
+ justify-content: flex-start;
+ align-self: stretch;
+ flex-shrink: 0;
+ position: relative;
+}
+
.distribuidores-contenido,
-.tractores-contenido,
.columnas-contenido {
- max-height: 300px; /* Ajusta según lo que necesites */
+ height: 40em; /* Ajusta según lo que necesites */
overflow-y: auto;
scrollbar-width: thin; /* Firefox */
scrollbar-color: #999 transparent; /* Firefox */
diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js
index 25119706..94907684 100644
--- a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js
+++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearCuadroFormulas.js
@@ -2,11 +2,12 @@ const { eliminarCuadroFormulas } = require('./eliminarCuadroFormulas');
const { mostrarAlerta } = require(`${rutaBase}/src/framework/vistas/includes/componentes/moleculas/alertaSwal/alertaSwal`);
const { filtrarYRenderizarFormulas, actualizarCaracteresBuscador } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/formulas/filtrarYRenderizarFormulas.js`);
const { aplicarFormula } = require(`${rutaBase}/src/backend/casosUso/formulas/aplicarFormula.js`);
-const { actualizarGraficaConColumna } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/actualizarGraficaConColumna.js`);
+const { filtrarDatos } = require(`${rutaBase}/src/backend/casosUso/formulas/filtrarDatos.js`);
const { procesarDatosUniversal } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/procesarDatosUniversal.js`);
const { obtenerParametrosTractor } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/formulas/obtenerParametrosTractor.js`);
const { retirarDatos } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/retirarDatos.js`);
-const { crearGrafica } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js`);
+const { crearMenuParametros } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js`);
+const { crearMenuFiltros } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js`);
const Chart = require('chart.js/auto');
/**
@@ -35,6 +36,11 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
mensajeInicial = 'No hay fórmulas disponibles.';
}
+ const filtrosDisponibles = formulasDisponibles.filter(formula => {
+ return formula.Datos.toLowerCase().includes('filter');
+ });
+
+
cuadroFormulas.innerHTML = `
Fórmulas
@@ -45,6 +51,11 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
+
+
Filtros
+
+
+
Aplicar Fórmula
@@ -64,12 +75,14 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
+
`;
- const contenedoesSeleccion = cuadroFormulas.querySelectorAll('.opciones-carta');
+ const contenedoresSeleccion = cuadroFormulas.querySelectorAll('.opciones-carta');
//ToDo: Escalar en número de variables dependiendo de las variables en las fórmulas
- crearMenuDesplegable(contenedoesSeleccion[0], 'A', columnasActualizadas, graficaId, datosOriginalesFormulas, tractorSeleccionado);
+ crearMenuParametros(contenedoresSeleccion[0], columnasActualizadas, graficaId, datosOriginalesFormulas, tractorSeleccionado, filtrosDisponibles, contenedoresSeleccion[1]);
+ crearMenuFiltros(contenedoresSeleccion[1], filtrosDisponibles, graficaId);
// Configurar búsqueda de fórmulas
const campoBusqueda = cuadroFormulas.querySelector('.search-section');
@@ -88,6 +101,10 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
botonAplicarFormula.addEventListener('click', () => {
+ const filtroAplicado = filtrosDisponibles.filter(filtro => {
+ return contenedoresSeleccion[1].querySelector('.opcion-texto').value == filtro.Nombre;
+ });
+
const textoAplicar = botonAplicarFormula.querySelector('div');
if (textoAplicar) {
textoAplicar.textContent = 'Aplicando...';
@@ -96,13 +113,21 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
const formulaSeleccionada = contenedorBusqueda.querySelector('.formula-seleccionada');
if (!formulaSeleccionada) {
mostrarAlerta('Error', 'Debes buscar y seleccionar una fórmula antes de aplicar.', 'error');
+ if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula';
return;
}
- // Verificar que hay datos disponibles
- const datosExcel = localStorage.getItem('datosFiltradosExcel');
- if (!datosExcel) {
+
+ const datosFiltrados = filtrarDatos(filtroAplicado, JSON.parse(localStorage.getItem('datosFiltradosExcel')), tractorSeleccionado);
+ if (datosFiltrados.error) {
+ mostrarAlerta(`Columna no encontrada: ${datosFiltrados.columnaNoEncontrada}`, 'Asegúrate de seleccionar todas las columnas necesarias para aplicar este filtro.', 'error');
+ if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula';
+ return;
+ }
+
+ if (!datosFiltrados) {
mostrarAlerta('Error', 'No hay datos de Excel cargados. Por favor, carga un archivo Excel primero.', 'error');
+ if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula';
return;
}
@@ -112,6 +137,7 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
if (!inputRadio) {
mostrarAlerta('Error', 'Error al obtener los datos de la fórmula seleccionada.', 'error');
+ if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula';
return;
}
@@ -122,6 +148,7 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
// Verificar que los datos están completos
if (!datosFormula || datosFormula.trim() === '') {
mostrarAlerta('Error', 'Los datos de la fórmula están vacíos o incompletos.', 'error');
+ if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula';
return;
}
@@ -131,15 +158,16 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
if (!graficaDiv) {
mostrarAlerta('Error', 'No se encontró la gráfica asociada.', 'error');
+ if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula';
return;
}
try {
let resultadoFormula;
if (tractorSeleccionado.length != 0) {
- resultadoFormula = aplicarFormula(nombreFormula, datosFormula, tractorSeleccionado, JSON.parse(datosExcel));
+ resultadoFormula = aplicarFormula(nombreFormula, datosFormula, tractorSeleccionado, datosFiltrados.resultados);
} else {
- resultadoFormula = aplicarFormula(nombreFormula, datosFormula, null, JSON.parse(datosExcel));
+ resultadoFormula = aplicarFormula(nombreFormula, datosFormula, null, datosFiltrados.resultados);
}
let contadorErrores = 0;
const resultados = resultadoFormula.resultados;
@@ -215,7 +243,7 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
if (textoAplicar) textoAplicar.textContent = 'Aplicar Fórmula';
}
}, 100);
- }
+ }
});
// Configurar evento de búsqueda (filtrado local)
@@ -251,51 +279,7 @@ async function crearCuadroFormulas(graficaId, formulasDisponibles, datosOriginal
return datosOriginalesFormulas;
}
-/**
- * Crea un menú desplegable para seleccionar columnas.
- * @param {HTMLDivElement} contenedor - Contenedor donde se agregará el menú desplegable.
- * @param {string} letra - Letra identificadora del menú.
- * @param {string[]} columnas - Lista de columnas disponibles.
- * @param {number} graficaId - ID de la gráfica asociada.
- * @returns {void}
- */
-function crearMenuDesplegable(contenedor, letra, columnas, graficaId, datosOriginalesFormulas, tractorSeleccionado) {
- const nuevoMenu = document.createElement('div');
- nuevoMenu.className = 'opcion';
- const seleccionValores = document.createElement('select');
- seleccionValores.className = 'opcion-texto';
- seleccionValores.innerHTML = ''
- columnas.forEach((texto) => {
- seleccionValores.innerHTML = `${seleccionValores.innerHTML}
- `
- });
-
- // Agregar evento de cambio para actualizar la gráfica
- seleccionValores.addEventListener('change', (evento) => {
- const columnaSeleccionada = evento.target.value;
- if (columnaSeleccionada && columnaSeleccionada !== '') {
- actualizarGraficaConColumna(graficaId, columnaSeleccionada, datosOriginalesFormulas, tractorSeleccionado);
- } else {
- // Si se deselecciona, resetear la gráfica a estado inicial
- const graficaDiv = document.getElementById(`previsualizacion-grafica-${graficaId}`);
- if (graficaDiv) {
- const canvas = graficaDiv.querySelector('canvas');
- const contexto = canvas.getContext('2d');
- const graficaExistente = Chart.getChart(contexto);
-
- if (graficaExistente) {
- graficaExistente.destroy();
- const nuevaGrafica = crearGrafica(contexto, 'line');
- nuevaGrafica.options.plugins.title.text = '';
- nuevaGrafica.update();
- }
- }
- }
- });
- nuevoMenu.appendChild(seleccionValores);
- contenedor.appendChild(nuevoMenu);
-}
module.exports = {
crearCuadroFormulas
diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js
new file mode 100644
index 00000000..448f3ccc
--- /dev/null
+++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuFiltros.js
@@ -0,0 +1,48 @@
+const Chart = require('chart.js/auto');
+const { crearGrafica } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js`);
+
+/**
+ * Crea un menú desplegable para seleccionar columnas.
+ * @param {HTMLDivElement} contenedor - Contenedor donde se agregará el menú desplegable.
+ * @param {string[]} filtros - Lista de filtros disponibles.
+ * @param {number} graficaId - ID de la gráfica asociada.
+ * @returns {void}
+ */
+function crearMenuFiltros(contenedor, filtros, graficaId) {
+ const nuevoMenu = document.createElement('div');
+ nuevoMenu.className = 'opcion';
+ const seleccionValores = document.createElement('select');
+ seleccionValores.className = 'opcion-texto';
+ seleccionValores.innerHTML = ''
+ filtros.forEach((filtro) => {
+ seleccionValores.innerHTML = `${seleccionValores.innerHTML}
+ `
+ });
+
+ // Agregar evento de cambio para actualizar la gráfica
+ seleccionValores.addEventListener('change', () => {
+ // Si se deselecciona, resetear la gráfica a estado inicial
+ const graficaDiv = document.getElementById(`previsualizacion-grafica-${graficaId}`);
+ if (graficaDiv) {
+ const canvas = graficaDiv.querySelector('canvas');
+ const contexto = canvas.getContext('2d');
+ const graficaExistente = Chart.getChart(contexto);
+
+ if (graficaExistente) {
+ const tipo = graficaExistente.config.type;
+ const titulo = graficaExistente.options.plugins.title.text;
+ graficaExistente.destroy();
+ const nuevaGrafica = crearGrafica(contexto, tipo);
+ nuevaGrafica.options.plugins.title.text = titulo;
+ nuevaGrafica.update();
+ }
+ }
+ });
+
+ nuevoMenu.appendChild(seleccionValores);
+ contenedor.appendChild(nuevoMenu);
+}
+
+module.exports = {
+ crearMenuFiltros,
+}
\ No newline at end of file
diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js
new file mode 100644
index 00000000..e0734732
--- /dev/null
+++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/crearMenuParametros.js
@@ -0,0 +1,63 @@
+const { actualizarGraficaConColumna } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/actualizarGraficaConColumna.js`);
+const { crearGrafica } = require(`${rutaBase}/src/framework/utils/scripts/paginas/analisis/graficas/crearGrafica.js`);
+const { filtrarDatos } = require(`${rutaBase}/src/backend/casosUso/formulas/filtrarDatos.js`);
+const Chart = require('chart.js/auto');
+
+/**
+ * Crea un menú desplegable para seleccionar columnas.
+ * @param {HTMLDivElement} contenedor - Contenedor donde se agregará el menú desplegable.
+ * @param {string[]} columnas - Lista de columnas disponibles.
+ * @param {number} graficaId - ID de la gráfica asociada.
+ * @returns {void}
+ */
+function crearMenuParametros(contenedor, columnas, graficaId, datosOriginalesFormulas, tractorSeleccionado, filtrosDisponibles, contenedorFiltros) {
+ const nuevoMenu = document.createElement('div');
+ nuevoMenu.className = 'opcion';
+ const seleccionValores = document.createElement('select');
+ seleccionValores.className = 'opcion-texto';
+ seleccionValores.innerHTML = ''
+ columnas.forEach((texto) => {
+ seleccionValores.innerHTML = `${seleccionValores.innerHTML}
+ `
+ });
+
+ // Agregar evento de cambio para actualizar la gráfica
+ seleccionValores.addEventListener('change', (evento) => {
+
+ const filtroAplicado = filtrosDisponibles.filter(filtro => {
+ return contenedorFiltros.querySelector('.opcion-texto').value == filtro.Nombre;
+ });
+
+ const datosFiltrados = filtrarDatos(filtroAplicado, JSON.parse(localStorage.getItem('datosFiltradosExcel')), tractorSeleccionado);
+
+ const columnaSeleccionada = evento.target.value;
+ if (columnaSeleccionada && columnaSeleccionada !== '') {
+ actualizarGraficaConColumna(graficaId, columnaSeleccionada, datosOriginalesFormulas, tractorSeleccionado, datosFiltrados.resultados);
+ } else {
+ // Si se deselecciona, resetear la gráfica a estado inicial
+ const graficaDiv = document.getElementById(`previsualizacion-grafica-${graficaId}`);
+ if (graficaDiv) {
+
+ const canvas = graficaDiv.querySelector('canvas');
+ const contexto = canvas.getContext('2d');
+ const graficaExistente = Chart.getChart(contexto);
+
+ if (graficaExistente) {
+ const tipo = graficaExistente.config.type;
+ const titulo = graficaExistente.options.plugins.title.text;
+ graficaExistente.destroy();
+ const nuevaGrafica = crearGrafica(contexto, tipo);
+ nuevaGrafica.options.plugins.title.text = titulo;
+ nuevaGrafica.update();
+ }
+ }
+ }
+ });
+
+ nuevoMenu.appendChild(seleccionValores);
+ contenedor.appendChild(nuevoMenu);
+}
+
+module.exports = {
+ crearMenuParametros,
+}
\ No newline at end of file
diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/filtrarYRenderizarFormulas.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/filtrarYRenderizarFormulas.js
index 7137e51b..380d6d66 100644
--- a/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/filtrarYRenderizarFormulas.js
+++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/formulas/filtrarYRenderizarFormulas.js
@@ -29,12 +29,19 @@ function filtrarYRenderizarFormulas(contenedor, terminoBusqueda = '', formulasDi
// Limpiar contenedor
contenedor.innerHTML = '';
+
+ formulasDisponibles = formulasDisponibles.filter(formula => {
+ return !formula.Datos.toLowerCase().includes('filter');
+ });
+
+
// Si no hay fórmulas cargadas, mostrar mensaje específico
if (formulasDisponibles.length === 0) {
contenedor.innerHTML = '
No hay fórmulas creadas. Ve al módulo de fórmulas para crear una.
';
return;
}
+
let formulasFiltradas = formulasDisponibles;
// Solo filtrar si hay un término de búsqueda válido
diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/actualizarGraficaConColumna.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/actualizarGraficaConColumna.js
index 26caa9c3..b8634da5 100644
--- a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/actualizarGraficaConColumna.js
+++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/actualizarGraficaConColumna.js
@@ -8,7 +8,7 @@ const { mostrarAlerta } = require(`${rutaBase}/src/framework/vistas/includes/com
* @param {string} nombreColumna - Nombre de la columna seleccionada.
* @returns {void}
*/
-function actualizarGraficaConColumna(graficaId, nombreColumna, datosOriginalesFormulas, tractorSeleccionado) {
+function actualizarGraficaConColumna(graficaId, nombreColumna, datosOriginalesFormulas, tractorSeleccionado, datosExcel) {
// Obtener la gráfica
const graficaDiv = document.getElementById(`previsualizacion-grafica-${graficaId}`);
if (!graficaDiv) {
@@ -28,7 +28,7 @@ function actualizarGraficaConColumna(graficaId, nombreColumna, datosOriginalesFo
}
// Obtener la hoja seleccionada del localStorage
- const datos = localStorage.getItem('datosFiltradosExcel');
+ const datos = datosExcel;//localStorage.getItem('datosFiltradosExcel');
if (!datos) {
mostrarAlerta('Error', 'No hay datos cargados para mostrar en la gráfica.', 'error');
@@ -39,7 +39,7 @@ function actualizarGraficaConColumna(graficaId, nombreColumna, datosOriginalesFo
let datosHoja = null;
// Parsear los datos del localStorage
- const datosParseados = JSON.parse(datos);
+ const datosParseados = datos;
// Determinar qué hoja usar
if (tractorSeleccionado && tractorSeleccionado.trim() !== '') {
diff --git a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/retirarDatos.js b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/retirarDatos.js
index 3adb9799..524d023e 100644
--- a/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/retirarDatos.js
+++ b/harvester-app/src/framework/utils/scripts/paginas/analisis/graficas/retirarDatos.js
@@ -56,22 +56,57 @@ function retirarDatos(graficaId, datosOriginalesFormulas) {
} else {
graficaExistente.options.plugins.title.text = 'Gráfica sin datos - Aplica una fórmula para ver resultados';
}
-
- graficaExistente.options.plugins.title.display = false;
-
- // Actualizar la gráfica
- graficaExistente.update();
-
- // Eliminar los datos originales del mapa
- datosOriginalesFormulas.delete(graficaId);
-
- // Restablecer los menús desplegables de parámetros si existen
- const cuadroFormulas = document.querySelector('.contenedor-formulas');
- if (cuadroFormulas) {
- const selectoresParametros = cuadroFormulas.querySelectorAll('.opcion-texto');
- selectoresParametros.forEach(selector => {
- selector.value = '';
- });
+
+ try {
+ // Verificar si hay datos originales para esta gráfica
+ const datosOriginales = datosOriginalesFormulas.get(graficaId);
+
+ if (!datosOriginales) {
+ mostrarAlerta('Información', 'Esta gráfica no tiene fórmula aplicada para retirar.', 'info');
+ return;
+ }
+
+ // Obtener el título actual del input de la tarjeta
+ const tarjetaGrafica = document.getElementById(graficaId.toString());
+ const tituloInput = tarjetaGrafica ? tarjetaGrafica.querySelector('.titulo-grafica') : null;
+ const tituloPersonalizado = tituloInput ? tituloInput.value : '';
+
+ // Restaurar gráfica a estado inicial
+ graficaExistente.data.labels = ['Sin datos'];
+ graficaExistente.data.datasets[0].data = [0];
+ graficaExistente.data.datasets[0].label = 'Datos';
+
+ // Restaurar título: usar el título personalizado del input o el mensaje por defecto
+ if (tituloPersonalizado && tituloPersonalizado.trim() !== '') {
+ graficaExistente.options.plugins.title.text = tituloPersonalizado;
+ } else {
+ graficaExistente.options.plugins.title.text = 'Gráfica sin datos - Aplica una fórmula para ver resultados';
+ }
+
+ // Configurar etiquetas: ocultar según el tipo de gráfica
+ const tipoActual = graficaExistente.config.type;
+ graficaExistente.options.plugins.datalabels.display = tipoActual !== 'line';
+ graficaExistente.options.plugins.title.display = true;
+
+ // Actualizar la gráfica
+ graficaExistente.update();
+
+ // Eliminar los datos originales del mapa
+ datosOriginalesFormulas.delete(graficaId);
+
+ // Restablecer los menús desplegables de parámetros si existen
+ const cuadroFormulas = document.querySelector('.contenedor-formulas');
+ if (cuadroFormulas) {
+ const selectoresParametros = cuadroFormulas.querySelectorAll('.opcion-texto');
+ selectoresParametros.forEach(selector => {
+ selector.value = '';
+ });
+ }
+
+ mostrarAlerta('Éxito', 'Los datos han sido retirados correctamente de la gráfica.', 'success');
+
+ } catch (error) {
+ mostrarAlerta('Error', `Error inesperado al retirar la fórmula: ${error.message}`, 'error');
}
mostrarAlerta('Éxito', 'Los datos han sido retirados correctamente de la gráfica.', 'success');
diff --git a/harvester-app/src/framework/utils/scripts/paginas/formulas/crearFormula.js b/harvester-app/src/framework/utils/scripts/paginas/formulas/crearFormula.js
index 66aff1a5..2168f169 100644
--- a/harvester-app/src/framework/utils/scripts/paginas/formulas/crearFormula.js
+++ b/harvester-app/src/framework/utils/scripts/paginas/formulas/crearFormula.js
@@ -1,5 +1,5 @@
-// RF67 Crear Fórmula - https://codeandco-wiki.netlify.app/docs/proyectos/tractores/documentacion/requisitos/RF67
-// RF69 Guardar Fórmula - https://codeandco-wiki.netlify.app/docs/proyectos/tractores/documentacion/requisitos/RF69
+// RF24 Crear Fórmula - https://codeandco-wiki.netlify.app/docs/proyectos/tractores/documentacion/requisitos/RF24
+// RF22 Guardar Fórmula - https://codeandco-wiki.netlify.app/docs/proyectos/tractores/documentacion/requisitos/RF22
const { LONGITUD_MAXIMA_FORMULA,
LONGITUD_MAXIMA_NOMBRE_FORMULA } = require(`${rutaBase}src/framework/utils/scripts/constantes.js`);
@@ -65,13 +65,13 @@ async function inicializarCrearFormula() {
if (nombreArchivo === null || nombreArchivo === undefined) {
const selectorAnidado = document.getElementById('main-function');
- const listaOpcionesEliminar = ['IF', 'IFERROR', 'VLOOKUP']
+ const listaOpcionesEliminar = ['IF', 'IFERROR']
listaOpcionesEliminar.forEach(elemento => {
const elemntoEliminar = selectorAnidado.querySelector(`option[value='${elemento}']`)
selectorAnidado.removeChild(elemntoEliminar)
});
- mostrarAlerta('No hay un archivo cargado.', 'No se podran crear fórmulas (SI, SI.ERROR y BUSCAV).', 'warning');
+ mostrarAlerta('No hay un archivo cargado.', 'No se podran crear fórmulas (SI, SI.ERROR).', 'warning');
return;
}
}
@@ -160,7 +160,7 @@ async function procesarFormula() {
btnGuardar.disabled = false;
return;
}
- const formula = cuadroTextoGenerado.split(':')[1].trim();
+ const formula = cuadroTextoGenerado.split('°')[2].trim();
try {
const respuesta = await guardarFormula(nombreFormula, formula);
@@ -217,11 +217,8 @@ function definirEstructura(elementoElegido, contenedor) {
agregarArgumento('Valor', 'iferror-value', contenedor, true);
agregarArgumento('Valor si error', 'iferror-iferror', contenedor, true);
break;
- case 'VLOOKUP':
- agregarArgumento('Valor buscado', 'vlookup-lookupvalue', contenedor, true);
- agregarArgumento('Matriz tabla', 'vlookup-tablearray', contenedor);
- agregarArgumento('Indicador de columnas', 'vlookup-colindexnum', contenedor);
- agregarArgumento('Coincidencia (0=exacta, 1=aproximada)', 'vlookup-rangelookup', contenedor);
+ case 'FILTER':
+ agregarCriterio('Condición', 'if-condition', contenedor);
break;
case 'ARITHMETIC':
agregarArgumento('Expresión', 'arithmetic-expression', contenedor);
@@ -346,7 +343,7 @@ function agregarFuncionAnidada(boton) {
-
+
`;
@@ -538,7 +535,7 @@ function generarFormulaCompleja() {
}
const formula = construirFormulaDesdeContenedor(contenedor, seleccionFuncionPrincipal.value);
- document.getElementById('resultado').innerText = `Fórmula generada (en inglés para HyperFormula):\n=${formula}`;
+ document.getElementById('resultado').innerText = `°Fórmula generada (en inglés para HyperFormula)°\n=${formula}`;
}
/**
@@ -576,11 +573,8 @@ function construirFormulaDesdeContenedor(contenedor, nombreFuncion) {
argumentos.push(procesarArgumento(elementosArgumentos[0]));
argumentos.push(procesarArgumento(elementosArgumentos[1]));
break;
- case 'VLOOKUP':
- argumentos.push(procesarArgumento(elementosArgumentos[0]));
- argumentos.push(obtenerValor(elementosArgumentos[1].querySelector('input')));
- argumentos.push(obtenerValor(elementosArgumentos[2].querySelector('input')));
- argumentos.push(obtenerValor(elementosArgumentos[3].querySelector('input')));
+ case 'FILTER':
+ argumentos.push(construirCondicion(elementosArgumentos[0], false));
break;
case 'ARITHMETIC':
return obtenerValor(elementosArgumentos[0].querySelector('input'));
@@ -673,7 +667,7 @@ function traducirFuncion(nombre) {
'CONTAR.SI': 'COUNTIF',
'CONTAR.SI.CONJUNTO': 'COUNTIFS',
'SI.ERROR': 'IFERROR',
- 'BUSCARV': 'VLOOKUP',
+ 'FILTRO': 'FILTER',
'ARITHMETIC': 'ARITHMETIC'
};
return map[nombre] || nombre;
diff --git a/harvester-app/src/framework/vistas/paginas/formulas/crearFormula.ejs b/harvester-app/src/framework/vistas/paginas/formulas/crearFormula.ejs
index 7c3fbf00..dd141c12 100644
--- a/harvester-app/src/framework/vistas/paginas/formulas/crearFormula.ejs
+++ b/harvester-app/src/framework/vistas/paginas/formulas/crearFormula.ejs
@@ -40,7 +40,7 @@
-
+
diff --git a/harvester-app/src/framework/vistas/paginas/iniciarSesion.ejs b/harvester-app/src/framework/vistas/paginas/iniciarSesion.ejs
index 4afe7d4b..8b79e3f1 100644
--- a/harvester-app/src/framework/vistas/paginas/iniciarSesion.ejs
+++ b/harvester-app/src/framework/vistas/paginas/iniciarSesion.ejs
@@ -41,8 +41,9 @@
Mas información
- Comunícate con el call center al 0800 266 1374 (gratuito) o por WhatsApp
- al 54 9 11 2034-1408 para consultar solicitudes o información.
+ Comunícate por télefono y WhatsApp
+ al 442 226 7458 o al correo jose.bravo@cnhmexico.com.mx
+ para consultar solicitudes o información.