diff --git a/ci4/app/Config/Routes/ImportadoresRoutes.php b/ci4/app/Config/Routes/ImportadoresRoutes.php index 2706aa8c..f3e20ae5 100644 --- a/ci4/app/Config/Routes/ImportadoresRoutes.php +++ b/ci4/app/Config/Routes/ImportadoresRoutes.php @@ -32,6 +32,7 @@ $routes->group('importador', ['namespace' => 'App\Controllers\Importadores'], fu /**====================== * AJAX *========================**/ + $routes->post('validar-fila', 'ImportadorBubok::validarFila'); $routes->post('importar-fila', 'ImportadorBubok::importarFila'); }); diff --git a/ci4/app/Config/Routes/ScriptsRoutes.php b/ci4/app/Config/Routes/ScriptsRoutes.php index f7e994c9..d3744033 100644 --- a/ci4/app/Config/Routes/ScriptsRoutes.php +++ b/ci4/app/Config/Routes/ScriptsRoutes.php @@ -7,7 +7,7 @@ use CodeIgniter\Router\RouteCollection; /* Rutas para tarifas */ $routes->group('scripts', ['namespace' => 'App\Controllers\Scripts'], function ($routes) { - $routes->get('completar-identidades', 'UsersIntegrity::completarIdentidades'); + //$routes->get('completar-identidades', 'UsersIntegrity::completarIdentidades'); }); \ No newline at end of file diff --git a/ci4/app/Controllers/Importadores/ImportadorBubok.php b/ci4/app/Controllers/Importadores/ImportadorBubok.php index 33fcc4d5..27641c64 100644 --- a/ci4/app/Controllers/Importadores/ImportadorBubok.php +++ b/ci4/app/Controllers/Importadores/ImportadorBubok.php @@ -3,6 +3,7 @@ namespace App\Controllers\Importadores; use App\Controllers\BaseResourceController; use App\Controllers\Presupuestos\Presupuestocliente; +use App\Models\Presupuestos\PresupuestoModel; use App\Services\PresupuestoService; class ImportadorBubok extends BaseResourceController @@ -50,6 +51,73 @@ class ImportadorBubok extends BaseResourceController return view(static::$viewPath . 'viewImportadorBubokTool', $viewData); } + public function validarFila() + { + $json = $this->request->getJSON(); + + if (!$json || empty($json->producto) || empty($json->pedido)) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'Datos incompletos' + ]); + } + + $producto = $json->producto; + $pedido = $json->pedido; + + // Validar existencia de ID de producto + if (empty($producto->id)) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'ID de producto no proporcionado' + ]); + } + + $refCliente = $pedido->orderNumber . '-' . $producto->id; + + // Validar formato Ref. Cliente + if (strpos($refCliente, '-') === false || strlen($refCliente) < 5) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'Ref. cliente inválido' + ]); + } + + // 1. Verificar si ya fue importado + $presupuestoModel = new PresupuestoModel(); + $yaExiste = $presupuestoModel->where('referencia_cliente', $refCliente)->first(); + + if ($yaExiste) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => 'Referencia ya importada' + ]); + } + + // 2. Validación básica del producto (puedes expandir con más reglas si lo necesitas) + $errores = []; + + if (empty($producto->title)) + $errores[] = 'Falta título'; + if (empty($producto->body->pages)) + $errores[] = 'Faltan páginas'; + if (empty($producto->amount)) + $errores[] = 'Falta tirada'; + + if (!empty($errores)) { + return $this->response->setJSON([ + 'apto' => false, + 'reason' => implode(', ', $errores) + ]); + } + + // 3. Producto considerado apto + return $this->response->setJSON([ + 'apto' => true + ]); + } + + public function importarFila() { @@ -83,7 +151,7 @@ class ImportadorBubok extends BaseResourceController 'message' => 'Número de orden o ID del producto no reconocidos.' ]); } - $refCliente = "$orderNumber - $productId"; + $refCliente = "$orderNumber-$productId"; // Titulo $titulo = $producto->title ?? null; @@ -331,12 +399,12 @@ class ImportadorBubok extends BaseResourceController 'ivaReducido' => 1, ]; - return $this->respond([ + /*return $this->respond([ 'status' => 400, 'message' => $dataToImport, 'interiorTipo' => $interiorTipo, 'isColor' => $isColor - ]); + ]);*/ // 5. Guardar try { @@ -368,11 +436,11 @@ class ImportadorBubok extends BaseResourceController ]; } } - + // confirmar y crear pedido y ot $presupuestoModel->confirmarPresupuesto($response['sk_id']); - PresupuestoService::crearPedido($response['sk_id'],isImported:true); - + PresupuestoService::crearPedido($response['sk_id'], isImported: true); + if (!isset($response['sk_id'])) { return $this->respond([ diff --git a/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js b/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js index 76325766..b86902b1 100644 --- a/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js +++ b/httpdocs/assets/js/safekat/pages/importadores/bubok/bubok_tool.js @@ -1,8 +1,11 @@ document.addEventListener('DOMContentLoaded', function () { + let dataTable; let productosOriginales = []; let datosComunesPedido = {}; + document.getElementById('importBtn').disabled = true; + document.getElementById('xmlFile').addEventListener('change', function (e) { const file = e.target.files[0]; if (!file || !file.name.endsWith('.zip')) { @@ -10,10 +13,19 @@ document.addEventListener('DOMContentLoaded', function () { return; } + document.getElementById('importBtn').disabled = true; + const reader = new FileReader(); reader.onload = async function (event) { try { const zip = await JSZip.loadAsync(event.target.result); + + // Reset tabla y memoria de productos + if (dataTable) { + dataTable.clear().draw(); + } + productosOriginales = []; + const xmlFiles = Object.values(zip.files).filter(f => f.name.endsWith('.xml') && !f.name.startsWith('__MACOSX/') ); @@ -23,11 +35,20 @@ document.addEventListener('DOMContentLoaded', function () { return; } + Swal.fire({ + title: 'Procesando...', + text: 'Cargando XMLs...', + allowOutsideClick: false, + showDenyButton: false, + didOpen: () => Swal.showLoading() + }); + for (const file of xmlFiles) { const content = await file.async('text'); - parseXmlAndLoadTable(content); + await parseXmlAndLoadTable(content); } + Swal.close(); Swal.fire('Éxito', `${xmlFiles.length} archivos XML cargados.`, 'success'); } catch (err) { console.error(err); @@ -38,8 +59,8 @@ document.addEventListener('DOMContentLoaded', function () { reader.readAsArrayBuffer(file); }); - function parseXmlAndLoadTable(xmlText) { - let parser = new DOMParser(); + async function parseXmlAndLoadTable(xmlText) { + const parser = new DOMParser(); let xmlDoc; try { @@ -50,7 +71,7 @@ document.addEventListener('DOMContentLoaded', function () { return; } - datosComunesPedido = { + const pedidoActual = { orderNumber: xmlDoc.querySelector('orderNumber')?.textContent ?? '', shipping: { address: xmlDoc.querySelector('shippingData > address')?.textContent ?? '', @@ -65,13 +86,19 @@ document.addEventListener('DOMContentLoaded', function () { const products = Array.from(xmlDoc.getElementsByTagName('product')); const offset = productosOriginales.length; + const rows = []; - products.forEach((prod, idx) => { - productosOriginales.push({ index: offset + idx, data: prod }); - }); + for (let i = 0; i < products.length; i++) { + const product = products[i]; + const globalIndex = offset + i; + + // Asociar producto con su pedido + productosOriginales.push({ + index: globalIndex, + data: product, + pedido: { ...pedidoActual } + }); - const rows = products.map((product, index) => { - const globalIndex = offset + index; const id = product.querySelector('id')?.textContent ?? ''; const title = product.querySelector('title')?.textContent ?? ''; const pages = product.querySelector('body > pages')?.textContent ?? ''; @@ -97,40 +124,65 @@ document.addEventListener('DOMContentLoaded', function () { } }); - return [ - ``, - `${datosComunesPedido.orderNumber} - ${id}`, - title, - tamano, - pages, - tirada, - interior, - '', - ` - ` - ]; - }); + // Obtener referencia del pedido + const refCliente = `${pedidoActual.orderNumber}-${id}`; + + // Validar fila con su propio pedido + const result = await validarProductoXml(product, pedidoActual); + + let checkboxHtml = ''; + let notaHtml = ''; + let actionBtnsHtml = ''; + + if (result.apto) { + checkboxHtml = ``; + notaHtml = ''; + actionBtnsHtml = ` +