diff --git a/ci4/app/Config/Routes/ImportadoresRoutes.php b/ci4/app/Config/Routes/ImportadoresRoutes.php
index 5bf2caca..df3ffa12 100644
--- a/ci4/app/Config/Routes/ImportadoresRoutes.php
+++ b/ci4/app/Config/Routes/ImportadoresRoutes.php
@@ -9,7 +9,7 @@ $routes->group('importador', ['namespace' => 'App\Controllers\Importadores'], fu
/* Libros */
$routes->group('catalogo', ['namespace' => 'App\Controllers\Importadores'], function ($routes) {
/**======================
- * CRUD
+ * Tool
*========================**/
$routes->get('', 'ImportadorCatalogo::index', ['as' => 'importadorCatalogoTool']);
@@ -17,6 +17,7 @@ $routes->group('importador', ['namespace' => 'App\Controllers\Importadores'], fu
/**======================
* AJAX
*========================**/
+ $routes->post('validar-fila', 'ImportadorCatalogo::validarFila');
});
diff --git a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php
index 493fc4cb..7c82e02a 100644
--- a/ci4/app/Controllers/Importadores/ImportadorCatalogo.php
+++ b/ci4/app/Controllers/Importadores/ImportadorCatalogo.php
@@ -185,4 +185,53 @@ class ImportadorCatalogo extends BaseResourceController
+ public function validarFila()
+ {
+ $json = $this->request->getJSON();
+
+ if (!$json || !isset($json->fila[0])) {
+ return $this->response->setJSON([
+ 'apto' => false,
+ 'reason' => 'Datos inválidos'
+ ]);
+ }
+
+ $input = trim($json->fila[0]); // Asumimos que 'input' es el primer campo de la fila
+
+ if (empty($input)) {
+ return $this->response->setJSON([
+ 'apto' => false,
+ 'reason' => 'ISBN no proporiconado'
+ ]);
+ }
+
+ $catalogoModel = new CatalogoLibroModel();
+
+ // 1. Buscar por ISBN exacto
+ $libroPorIsbn = $catalogoModel->where('isbn', $input)->first();
+
+ if ($libroPorIsbn) {
+ return $this->response->setJSON([
+ 'apto' => true
+ ]);
+ }
+
+ // 2. Buscar por EAN sin guiones
+ $eanLimpio = str_replace('-', '', $input);
+
+ $libroPorEan = $catalogoModel->where('REPLACE(ean, "-", "")', $eanLimpio)->first();
+
+ if ($libroPorEan) {
+ return $this->response->setJSON([
+ 'apto' => true
+ ]);
+ }
+
+ // No encontrado
+ return $this->response->setJSON([
+ 'apto' => false,
+ 'reason' => 'No encontrado en catálogo'
+ ]);
+ }
+
}
diff --git a/ci4/app/Language/es/Importador.php b/ci4/app/Language/es/Importador.php
index 930fe61a..8d4d36dd 100644
--- a/ci4/app/Language/es/Importador.php
+++ b/ci4/app/Language/es/Importador.php
@@ -9,6 +9,8 @@ return [
'idlinea' => 'Ref. cliente',
'cnt_pedida' => 'Unidades',
'precio_compra' => 'Precio Compra',
+ 'importar' => 'Importar',
+ 'subirArchivo' => 'Cargar Excel proporcionado por RA-MA',
'libro' => 'libro',
'id' => 'ID',
diff --git a/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php b/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php
index e812993e..a7b2e8dc 100644
--- a/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php
+++ b/ci4/app/Views/themes/vuexy/form/importador/catalogo/viewImportadorCatalogoTool.php
@@ -10,47 +10,79 @@
-
- = view('themes/_commonPartialsBs/_alertBoxes'); ?>
-
-
+
+
+
+
+
+
+
+
+
+
+
+
= $this->endSection() ?>
diff --git a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js
index e72a8bfb..8fce7010 100644
--- a/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js
+++ b/httpdocs/assets/js/safekat/pages/importadores/catalogo/catalogo_tool.js
@@ -2,13 +2,21 @@ import Ajax from '../../../components/ajax.js';
document.addEventListener('DOMContentLoaded', function () {
- // Columnas que espera la tabla (en el orden de HTML)
const TABLE_COLUMNS = ["input", "idlinea", "descripcion", "cnt_pedida", "precio_compra"];
- let dataTable; // referencia al DataTable
+ let dataTable;
dataTable = $('#excelTable').DataTable({
orderCellsTop: true,
- fixedHeader: true
+ responsive: true,
+ scrollX: true,
+ lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500],
+ pageLength: 25,
+ lengthChange: true,
+ dom: 'lfrtip',
+ language: {
+ url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
+ },
+ order: [[1, 'asc']]
});
document.getElementById('excelFile').addEventListener('change', function (e) {
@@ -28,124 +36,156 @@ document.addEventListener('DOMContentLoaded', function () {
reader.readAsArrayBuffer(file);
});
- function validateAndLoadDataTable(data) {
+ async function validateAndLoadDataTable(data) {
if (data.length === 0) return;
const headers = data[0].map(h => h.toString().trim());
-
- // Crear un índice rápido de nombreColumna => posicion
const headerMap = {};
headers.forEach((name, idx) => {
- headerMap[name.toLowerCase()] = idx; // pasar todo a minúsculas para evitar errores
+ headerMap[name.toLowerCase()] = idx;
});
- // Verificar si todas las columnas requeridas existen
const missing = TABLE_COLUMNS.filter(col => !(col in headerMap));
if (missing.length > 0) {
Swal.fire({
title: 'Error',
- text: 'Faltan las siguientes columnas en el Excel: ' + missing.join(', '),
+ text: 'Faltan las siguientes columnas: ' + missing.join(', '),
icon: 'error',
confirmButtonText: 'Aceptar',
buttonsStyling: true,
- customClass: {
- confirmButton: 'btn btn-danger'
- }
+ customClass: { confirmButton: 'btn btn-danger' }
});
- dataTable.clear().draw(); // limpia tabla
+ dataTable.clear().draw();
return;
}
const rows = [];
for (let i = 1; i < data.length; i++) {
- const row = [];
+ const rowData = TABLE_COLUMNS.map(col => data[i][headerMap[col]] ?? '');
- TABLE_COLUMNS.forEach(col => {
- const idx = headerMap[col];
- row.push(data[i][idx] ?? '');
- });
+ // Llamar backend para validar la fila
+ const isValid = await validarFila(rowData);
- // Agregar botón al final
- row.push('');
+ let checkboxHtml = '';
+ let actionBtnsHtml = '';
- rows.push(row);
+ if (isValid) {
+ checkboxHtml = ``;
+
+ actionBtnsHtml = `
+
+
+
+
+ `;
+ } else {
+ checkboxHtml = ``;
+
+ actionBtnsHtml = `
+
+ No Apto
+
+
+ `;
+ }
+
+ rows.push([checkboxHtml, ...rowData, actionBtnsHtml]);
}
dataTable.clear().rows.add(rows).draw();
- // Agregar eventos dinámicos para eliminar
+ setupEventListeners();
+ }
+
+ async function validarFila(rowData) {
+ try {
+ const response = await fetch('/importador/catalogo/validar-fila', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-CSRF-TOKEN': '= csrf_hash() ?>'
+ },
+ body: JSON.stringify({ fila: rowData })
+ });
+
+ const result = await response.json();
+ return result.apto === true;
+ } catch (error) {
+ console.error('Error validando fila', error);
+ return false;
+ }
+ }
+
+ function setupEventListeners() {
$('#excelTable tbody').off('click', '.deleteRow').on('click', '.deleteRow', function () {
dataTable.row($(this).parents('tr')).remove().draw();
});
+
+ $('#excelTable tbody').off('click', '.importRow').on('click', '.importRow', function () {
+ const rowData = dataTable.row($(this).parents('tr')).data();
+ console.log('Importar esta fila:', rowData);
+ // Aquí podrías enviar sólo esta fila al servidor si quieres importar individualmente
+ });
}
- $('#excelTable thead tr:eq(1) th').each(function (i) {
- const title = $(this).text();
-
- if (title.trim() !== '') { // Solo si el th tiene título
- $(this).html('');
-
- $('input', this).on('keyup change', function () {
- if (dataTable.column(i).search() !== this.value) {
- dataTable
- .column(i)
- .search(this.value)
- .draw();
- }
- });
- }
- });
-
document.getElementById('importBtn').addEventListener('click', function () {
- const allData = dataTable.rows().data().toArray();
- const rowsToSend = allData.map(row => row.slice(0, -1)); // sin botón
-
- if (rowsToSend.length === 0) {
+ const selectedRows = [];
+
+ dataTable.rows().every(function () {
+ const data = this.data();
+ const checkboxHtml = $(data[0]).find('input.select-row');
+ if (checkboxHtml.length > 0 && checkboxHtml.is(':checked') && !checkboxHtml.is(':disabled')) {
+ selectedRows.push(data.slice(1, -1)); // sin checkbox ni botones
+ }
+ });
+
+ if (selectedRows.length === 0) {
Swal.fire({
title: 'Atención',
- text: 'No hay datos para importar.',
+ text: 'No hay filas aptas seleccionadas para importar.',
icon: 'warning',
confirmButtonText: 'Aceptar',
buttonsStyling: true,
- customClass: {
- confirmButton: 'btn btn-warning'
- }
+ customClass: { confirmButton: 'btn btn-warning' }
});
return;
}
-
+
fetch('/importar', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '= csrf_hash() ?>'
},
- body: JSON.stringify({ data: rowsToSend })
+ body: JSON.stringify({ data: selectedRows })
}).then(res => res.json())
- .then(response => {
- Swal.fire({
- title: 'Importación exitosa',
- text: response.message,
- icon: 'success',
- confirmButtonText: 'Aceptar',
- buttonsStyling: true,
- customClass: {
- confirmButton: 'btn btn-success'
- }
- });
- })
- .catch(error => {
- console.error(error);
- Swal.fire({
- title: 'Error',
- text: 'Hubo un problema al importar los datos.',
- icon: 'error',
- confirmButtonText: 'Aceptar',
- buttonsStyling: true,
- customClass: {
- confirmButton: 'btn btn-danger'
- }
- });
- });
+ .then(response => {
+ Swal.fire({
+ title: 'Importación exitosa',
+ text: response.message,
+ icon: 'success',
+ confirmButtonText: 'Aceptar',
+ buttonsStyling: true,
+ customClass: { confirmButton: 'btn btn-success' }
+ });
+ })
+ .catch(error => {
+ console.error(error);
+ Swal.fire({
+ title: 'Error',
+ text: 'Error importando datos.',
+ icon: 'error',
+ confirmButtonText: 'Aceptar',
+ buttonsStyling: true,
+ customClass: { confirmButton: 'btn btn-danger' }
+ });
+ });
});
-});
\ No newline at end of file
+
+});