From decdcf3703f97e41ffcd76e3d29a857ff731fa4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Thu, 15 May 2025 23:55:09 +0200 Subject: [PATCH 1/2] trabajando en la lista de envios proximos --- ci4/app/Config/Routes.php | 1 + .../Logistica/LogisticaController.php | 19 + ci4/app/Language/es/Logistica.php | 4 + ci4/app/Language/es/Produccion.php | 1 + ci4/app/Models/Logistica/EnvioLineaModel.php | 3 +- ci4/app/Services/LogisticaService.php | 38 +- .../form/logistica/viewEnvioEditForm.php | 437 ++++++++++-------- .../maquinista/viewMaquinistaMaquinaTarea.php | 3 + .../maquinista/maquinistaTareaView.js | 47 ++ .../js/safekat/pages/logistica/envioEdit.js | 113 ++++- 10 files changed, 453 insertions(+), 213 deletions(-) diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 03ad8f11..4e1c1a81 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -871,6 +871,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi $routes->get('selectForNewEnvio', 'LogisticaController::findForNewEnvio'); $routes->get('selectDireccionForEnvio', 'LogisticaController::selectDireccionForEnvio'); $routes->post('imprimirEtiquetas', 'LogisticaController::imprimirEtiquetas'); + $routes->post('ficharEmbalaje', 'LogisticaController::ficharEmbalaje'); $routes->get('listAlbaranes', 'LogisticaController::listAlbaranes', ['as' => 'albaranesList']); }); diff --git a/ci4/app/Controllers/Logistica/LogisticaController.php b/ci4/app/Controllers/Logistica/LogisticaController.php index b69b0f4c..4ffd0733 100755 --- a/ci4/app/Controllers/Logistica/LogisticaController.php +++ b/ci4/app/Controllers/Logistica/LogisticaController.php @@ -132,6 +132,8 @@ class LogisticaController extends BaseController $result = $query->orderBy("name", "asc")->get()->getResultObject(); + $query = model('App\Models\Logistica\EnvioModel')->db->getLastQuery(); + return $this->response->setJSON($result); } else { return $this->failUnauthorized('Invalid request', 403); @@ -392,6 +394,17 @@ class LogisticaController extends BaseController } } + public function ficharEmbalaje() + { + if ($this->request->isAJAX()) { + + $ids = $this->request->getPost('ids') ?? []; + $result = LogisticaService::ficharEmbalaje($ids); + return $this->response->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } public function datatable_enviosEdit($idEnvio) { @@ -406,6 +419,12 @@ class LogisticaController extends BaseController return ''; } ) + ->edit( + "ordenTrabajo", + function ($row, $meta) { + return '' . $row->ordenTrabajo . ''; + } + ) ->edit( "pedido", function ($row, $meta) { diff --git a/ci4/app/Language/es/Logistica.php b/ci4/app/Language/es/Logistica.php index 0ef3e713..be9a91d8 100755 --- a/ci4/app/Language/es/Logistica.php +++ b/ci4/app/Language/es/Logistica.php @@ -44,6 +44,7 @@ return [ 'totales' => 'Totales', 'cajas' => 'Cajas', + 'ordenTrabajo' => 'OT', 'pedido' => 'Pedido', 'presupuesto' => 'Presupuesto', 'unidadesEnvio' => 'Unidades envío', @@ -62,6 +63,7 @@ return [ 'codigoSeguimiento' => 'Código de seguimiento', 'empresaMensajería' => 'Empresa de mensajería', + 'ficharEmbalaje' => 'Fichar embalaje', 'finalizarEnvio' => 'Finalizar envío', 'finalizarEnvioYOTs' => 'Finalizar envío y OTS', @@ -90,6 +92,7 @@ return [ 'errorInsertarEtiqueta' => 'Error al insertar la etiqueta', 'noEtiqueta' => 'No se ha encontrado la etiqueta', 'noEtiquetaLineas' => 'No se han encontrado líneas de etiqueta', + 'noLineas' => 'No se ha seleccionado ninguna línea', ], 'success' => [ 'finalizado' => 'El envío se ha finalizado correctamente', @@ -101,6 +104,7 @@ return [ 'comentariosUpdated' => 'Comentarios actualizados correctamente', 'successReordenarCajas' => 'Cajas reordenadas correctamente', 'imprimirEtiquetas' => 'Etiquetas impresas correctamente', + 'successFicharEmbalaje' => 'Embalaje fichado correctamente', ], ]; \ No newline at end of file diff --git a/ci4/app/Language/es/Produccion.php b/ci4/app/Language/es/Produccion.php index 728920c0..3d990871 100755 --- a/ci4/app/Language/es/Produccion.php +++ b/ci4/app/Language/es/Produccion.php @@ -182,6 +182,7 @@ return [ 'duplicate_estado_tarea_progress' => "Último estado de la tarea repetido", 'task_already_finished' => "La tarea se ha marcado como finalizada.", 'print_label' => "Imprimir etiqueta", + 'fichar_embalaje' => "Fichar embalaje", 'click_init' => "Clicks al inicio", 'click_end' => "Clicks al final", "comentarios" => "Comentarios", diff --git a/ci4/app/Models/Logistica/EnvioLineaModel.php b/ci4/app/Models/Logistica/EnvioLineaModel.php index a50709d3..76ae7b9b 100644 --- a/ci4/app/Models/Logistica/EnvioLineaModel.php +++ b/ci4/app/Models/Logistica/EnvioLineaModel.php @@ -35,7 +35,7 @@ class EnvioLineaModel extends Model $builder = $this->db ->table($this->table . " t1") ->select( - "t1.id, t1.pedido_id as pedido, t3.id as presupuesto, + "t1.id, t1.pedido_id as pedido, t3.id as presupuesto, t4.id as ordenTrabajo, t3.titulo as titulo, t1.unidades_envio as unidadesEnvio, t1.unidades_envio as unidadesEnvioRaw, t1.unidades_total as unidadesTotal, t2.tipo_envio as tipo_envio, IFNULL(( @@ -59,6 +59,7 @@ class EnvioLineaModel extends Model ); $builder->join("envios t2", "t1.envio_id = t2.id", "left"); $builder->join("presupuestos t3", "t1.presupuesto_id = t3.id", "left"); + $builder->join("ordenes_trabajo t4", "t1.pedido_id = t4.pedido_id", "left"); $builder->where("t1.envio_id", $envio_id); diff --git a/ci4/app/Services/LogisticaService.php b/ci4/app/Services/LogisticaService.php index cb4fb1b5..6d5f91b9 100644 --- a/ci4/app/Services/LogisticaService.php +++ b/ci4/app/Services/LogisticaService.php @@ -57,7 +57,8 @@ class LogisticaService ->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id') ->whereIn('pr.id', $presupuestoIds) ->whereIn('p.estado', ['finalizado', 'produccion']) - ->where('ot_dates.embalaje_at IS NOT NULL') + ->where('p.fecha_encuadernado IS NOT NULL') + ->where('DATE(p.fecha_encuadernado) <=', date('Y-m-d')) ->where("NOT EXISTS ( SELECT 1 FROM envios_lineas el @@ -103,16 +104,15 @@ class LogisticaService ->join('presupuestos pr', 'pr.id = pl.presupuesto_id') ->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id') ->join('ordenes_trabajo ot', 'ot.pedido_id = p.id') - ->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id') ->whereIn('p.estado', ['finalizado', 'produccion']) - ->where('ot_dates.embalaje_at IS NOT NULL') + ->where('p.fecha_encuadernado IS NOT NULL') + ->where('DATE(p.fecha_encuadernado) <=', date('Y-m-d')) ->groupBy('pl.id'); // 4. Envolver y filtrar por unidades pendientes $builder = $db->table("({$subBuilder->getCompiledSelect(false)}) AS sub"); $builder->select('id, name'); $builder->where('cantidad > unidades_enviadas'); - $builder->orderBy('name', 'ASC'); return $builder; } @@ -539,6 +539,13 @@ class LogisticaService $ot = $otModel->where('pedido_id', $linea->pedido_id) ->first(); $ps = (new ProductionService())->init($ot->id); + $date = $ps->getOrdenTrabajo()->dates()->embalaje_at; + if (is_null($date) || empty($date)) { + $ps->updateOrdenTrabajoDate([ + "name" => "embalaje_at", + "embalaje_at" => date('Y-m-d H:i:s') + ]); + } $ps->updateOrdenTrabajoDate([ "name" => "envio_at", "envio_at" => date('Y-m-d H:i:s') @@ -572,6 +579,29 @@ class LogisticaService return $data_return; } + public static function ficharEmbalaje($ids = null) + { + + if (is_null($ids) || empty($ids) || count($ids) == 0) { + return [ + 'status' => false, + 'message' => lang('Logistica.errors.noLineas'), + ]; + } + + for ($index = 0; $index < count($ids); $index++) { + $ps = (new ProductionService())->init($ids[$index]); + $ps->updateOrdenTrabajoDate([ + "name" => "embalaje_at", + "embalaje_at" => date('Y-m-d') + ]); + } + return [ + 'status' => true, + 'message' => lang('Logistica.success.successFicharEmbalaje'), + ]; + } + public static function generateEtiquetasTitulos($envio, $lineas, $printer, $cajas) { $data = [ diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php index 7c63bd17..27eecf8c 100644 --- a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php @@ -10,7 +10,7 @@

- tipo_envio == 'ferro_prototipo') ? 'FERRO':'' ?> + tipo_envio == 'ferro_prototipo') ? 'FERRO' : '' ?> finalizado == 0) ? '' : 'FINALIZADO' ?>

@@ -114,7 +114,7 @@
- finalizado == 0 && $envioEntity->tipo_envio=='estandar'): ?> + finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?>

@@ -130,6 +130,7 @@

+
-
-
- - - +
- -
-
-

- -

- -
-
-
-

-
-
-
- -
- finalizado == 0 && $envioEntity->tipo_envio=='estandar'): ?> -
- -
- -
- -
-
- -
- -
-
- - +
+
Java
+
PHP
+
Lua
+
SQL
+
Java
+
PHP
+
Lua
+
SQL
+
Java
+
PHP
+
Lua
+
SQL
+
Java
+
PHP
+
Lua
+
SQL
+
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
-
- - -
-
-
- - -
-
- -
- - - -
-
+ -
- -
-

- -

- -
-
- - -
- -
-
-

- +

-
-
- - finalizado == 0) ? '' : 'readonly' ?> - value="codigo_seguimiento)) ?>"> -
-
- - finalizado == 0): ?> - - - - -
- finalizado == 0): ?> -
- +
+
+
+

- tipo_envio=='estandar'): ?> -
- +
+
+ +
+ finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?> +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+
+ + +
+
+
- - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+ + +
+
+
+ + +
+
+ +
+ + + +
+
+
-
+
+ +
+

+ +

+ +
+
+ + +
+ +
+
+
+ +
+
+

+ +

+ +
+
+ + finalizado == 0) ? '' : 'readonly' ?> + value="codigo_seguimiento)) ?>"> +
+
+ + finalizado == 0): ?> + + + + +
+ finalizado == 0): ?> +
+ +
+ tipo_envio == 'estandar'): ?> +
+ +
+ + +
+
+
+ +
-
-endSection() ?> + endSection() ?> -section('css') ?> - - - -"> + section('css') ?> + + + + "> + " /> -endSection() ?> + endSection() ?> -section('additionalExternalJs') ?> - - - - -endSection() ?> \ No newline at end of file + section('additionalExternalJs') ?> + + + + + endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php b/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php index 66d37d4d..73c261f1 100644 --- a/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php +++ b/ci4/app/Views/themes/vuexy/form/produccion/maquinista/viewMaquinistaMaquinaTarea.php @@ -48,6 +48,9 @@
+
+ +
diff --git a/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js b/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js index 82d2e321..574b9b32 100644 --- a/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js +++ b/httpdocs/assets/js/safekat/pages/configuracion/maquinista/maquinistaTareaView.js @@ -14,6 +14,7 @@ class MaquinistaTareaView { this.tareaCardClass = '.tarea-card-action-block' this.inputClick = $('.ot-tarea-click') this.btnPrintLabels = this.item.find('#btn-print-labels') + this.btnFicharEmbalaje = this.item.find('#btn-fichar-embalaje') } init() { this.actionButtons.on('click', this.eventActionButton.bind(this)) @@ -22,6 +23,7 @@ class MaquinistaTareaView { this.handleGetTareaProgress(); this.inputClick.on('input', this.handleUpdateClickInput.bind(this)) this.btnPrintLabels.on('click', this.handlePrintLabels.bind(this)) + this.btnFicharEmbalaje.on('click', this.handleFicharEmbalaje.bind(this)) } eventActionButton(event) { @@ -301,6 +303,51 @@ class MaquinistaTareaView { }); } + handleFicharEmbalaje() { + const ot_id = [$('#otId').html()]; + $.post('/logistica/ficharEmbalaje', { + ids: ot_id, + }, function (response) { + if (response.status) { + Swal.fire({ + text: response.message, + icon: 'success', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + } else { + Swal.fire({ + title: 'Error', + text: response.message, + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + } + }).fail(() => { + Swal.fire({ + title: 'Error', + text: 'No se pudo realizar el fichaje.', + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + }); + } } export default MaquinistaTareaView; \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js index 4faf0457..63c6c3e3 100644 --- a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js +++ b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js @@ -7,6 +7,7 @@ class EnvioEdit { constructor() { this.tableCols = [ { data: "rowSelected" }, + { data: "ordenTrabajo" }, { data: "pedido" }, { data: "presupuesto" }, { data: "titulo" }, @@ -42,6 +43,12 @@ class EnvioEdit { this.proveedor.init(); } + if ($("#proximosEnvios").length) { + new PerfectScrollbar(document.getElementById('proximosEnvios'), { + wheelPropagation: false + }); + } + this.table = $('#tableLineasEnvio').DataTable({ processing: true, serverSide: true, @@ -84,11 +91,11 @@ class EnvioEdit { "searchable": false, }, { - "targets": [1, 2, 4, 5, 6], + "targets": [1, 2, 4, 5, 6, 7], "className": "text-center", }, { - targets: [7, 8, 9], + targets: [8, 9, 10], visible: false } ] @@ -121,7 +128,7 @@ class EnvioEdit { } const idEnvio = $('#id').val(); let num_cajas = this.cajas.val(); - if(ids.length != table.rows().count()){ + if (ids.length != table.rows().count()) { // se preguntará el numero de cajas en un swal con un input para obtener el valor Swal.fire({ title: 'Atención!', @@ -146,7 +153,7 @@ class EnvioEdit { } }); } - else{ + else { this._imprimirEtiquetas(idEnvio, ids, num_cajas); } }); @@ -485,9 +492,14 @@ class EnvioEdit { }); }); + $('#ficharEmbalaje').on('click', (e) => { + this._ficharEmbalajeLineas(); + }); + this._getAlbaranes(); } + _imprimirEtiquetas(envio_id, ids, num_cajas) { $.post('/logistica/imprimirEtiquetas', { @@ -510,7 +522,7 @@ class EnvioEdit { }, buttonsStyling: false }).then(() => { - if(response.data){ + if (response.data) { // show xml in a new tab const blob = new Blob([response.data], { type: 'application/xml' }); const url = URL.createObjectURL(blob); @@ -520,7 +532,7 @@ class EnvioEdit { a.click(); URL.revokeObjectURL(url); a.remove(); - + } }); } @@ -671,6 +683,95 @@ class EnvioEdit { }); } + + _ficharEmbalajeLineas() { + const table = this.table; + const selectedRows = table.rows({ page: 'current' }).nodes().filter((node) => { + const checkbox = $(node).find('.checkbox-linea-envio'); + return checkbox.is(':checked'); + }); + const ids = selectedRows.map((node) => { + const rowData = table.row(node).data(); + const parser = new DOMParser(); + const doc = parser.parseFromString(rowData.ordenTrabajo, 'text/html'); + return doc.body.textContent.trim(); // extrae solo el texto dentro del + }).toArray(); + + if (ids.length > 0) { + Swal.fire({ + title: 'Fichar embalaje', + text: '¿Está seguro de fichar el embalaje de las líneas seleccionadas?', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Sí', + cancelButtonText: 'Cancelar', + customClass: { + confirmButton: 'btn btn-danger me-1', + cancelButton: 'btn btn-secondary' + }, + buttonsStyling: false + }).then((result) => { + if (result.isConfirmed) { + $.post('/logistica/ficharEmbalaje', { + ids: ids + }, function (response) { + if (response.status) { + Swal.fire({ + text: response.message, + icon: 'success', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + } else { + Swal.fire({ + title: 'Error', + text: response.message, + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + } + }).fail(() => { + Swal.fire({ + title: 'Error', + text: 'No se pudo realizar el fichaje.', + icon: 'error', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + table.ajax.reload(); + }); + } + }); + } else { + Swal.fire({ + title: 'Sin filas seleccionadas', + text: 'Marca al menos una línea para eliminarla.', + icon: 'info', + confirmButtonColor: '#3085d6', + confirmButtonText: 'Ok', + customClass: { + confirmButton: 'btn btn-primary me-1', + }, + buttonsStyling: false + }); + } + } + + _deleteLineas() { const table = this.table; const selectedRows = table.rows({ page: 'current' }).nodes().filter((node) => { From 438000ebad7ee46c2e651939fbae44e1e0dea303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Mon, 19 May 2025 18:41:48 +0200 Subject: [PATCH 2/2] hecho lo de proximos envios --- ci4/app/Config/Routes.php | 2 + .../Logistica/LogisticaController.php | 58 ++- ci4/app/Language/es/Logistica.php | 1 + .../Models/OrdenTrabajo/OrdenTrabajoModel.php | 21 + ci4/app/Services/LogisticaService.php | 73 +++ .../form/logistica/viewEnvioEditForm.php | 473 +++++++++--------- .../js/safekat/pages/logistica/envioEdit.js | 47 +- 7 files changed, 423 insertions(+), 252 deletions(-) diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 4e1c1a81..f94097e3 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -765,6 +765,7 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func $routes->get('tareas/datatable/(:num)', 'Ordentrabajo::tareas_datatable/$1', ['as' => 'datatableTareasOrdenTrabajo']); $routes->get('maquinas/ots/datatable/(:num)','Ordentrabajo::datatable_maquina_ordenes_trabajo/$1'); $routes->get('maquinas/ots/(:num)','Ordentrabajo::get_maquina_ots/$1'); + /**====================== * UPDATES *========================**/ @@ -872,6 +873,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi $routes->get('selectDireccionForEnvio', 'LogisticaController::selectDireccionForEnvio'); $routes->post('imprimirEtiquetas', 'LogisticaController::imprimirEtiquetas'); $routes->post('ficharEmbalaje', 'LogisticaController::ficharEmbalaje'); + $routes->get('datatableProximosEnvios/(:num)', 'LogisticaController::datatable_proximosEnvios/$1'); $routes->get('listAlbaranes', 'LogisticaController::listAlbaranes', ['as' => 'albaranesList']); }); diff --git a/ci4/app/Controllers/Logistica/LogisticaController.php b/ci4/app/Controllers/Logistica/LogisticaController.php index 4ffd0733..23c4d3de 100755 --- a/ci4/app/Controllers/Logistica/LogisticaController.php +++ b/ci4/app/Controllers/Logistica/LogisticaController.php @@ -98,7 +98,8 @@ class LogisticaController extends BaseController return view(static::$viewPath . 'viewImpresionEtiquetas', $viewData); } - public function listAlbaranes(){ + public function listAlbaranes() + { $viewData = [ 'currentModule' => static::$controllerSlug, 'boxTitle' => lang('Albaran.albaranes'), @@ -117,7 +118,7 @@ class LogisticaController extends BaseController $tipo_envio = $this->request->getGet('tipo_envio') ?? 'estandar'; - if($tipo_envio == 'ferro_prototipo'){ + if ($tipo_envio == 'ferro_prototipo') { $query = LogisticaService::findForNewEnvioFerro(); } else { $query = LogisticaService::findForNewEnvio(); @@ -140,16 +141,17 @@ class LogisticaController extends BaseController } } - public function selectDireccionForEnvio(){ + public function selectDireccionForEnvio() + { if ($this->request->isAJAX()) { $ot = $this->request->getGet('ot_id'); - if($ot == null || $ot == 0){ + if ($ot == null || $ot == 0) { return []; } $searchVal = $this->request->getGet("q") ?? ""; $result = LogisticaService::findDireccionesNewEnvio($ot, $searchVal); - + return $this->response->setJSON($result); } else { return $this->failUnauthorized('Invalid request', 403); @@ -187,12 +189,12 @@ class LogisticaController extends BaseController public function imprimirEtiquetas() { if ($this->request->isAJAX()) { - $envio_id = $this->request->getPost('envio_id'); + $envio_id = $this->request->getPost('envio_id'); $ids = $this->request->getPost('envio_lineas'); $cajas = $this->request->getPost('cajas'); $printer_id = $this->request->getPost('printer_id'); - if($cajas == null || $cajas == 0){ + if ($cajas == null || $cajas == 0) { return $this->response->setJSON([ 'status' => false, 'message' => 'Cajas no válidas' @@ -204,7 +206,7 @@ class LogisticaController extends BaseController ->join('clientes', 'clientes.id = envios.cliente_id', 'left') ->where('envios.id', $envio_id) ->first(); - if($envio == null){ + if ($envio == null) { return $this->response->setJSON([ 'status' => false, 'message' => 'Envio no válido' @@ -215,7 +217,7 @@ class LogisticaController extends BaseController $lineas = $model->select('envios_lineas.*, presupuestos.titulo as titulo, presupuestos.referencia_cliente as referencia_cliente') ->join('presupuestos', 'presupuestos.id = envios_lineas.presupuesto_id', 'left') ->whereIn('envios_lineas.id', $ids)->findAll(); - if($lineas == null){ + if ($lineas == null) { return $this->response->setJSON([ 'status' => false, 'message' => 'Lineas no válidas' @@ -228,7 +230,7 @@ class LogisticaController extends BaseController ->where('id', $printer_id) ->orderBy('name', 'asc') ->first(); - if($impresora == null){ + if ($impresora == null) { return $this->response->setJSON([ 'status' => false, 'message' => 'Impresora no válida' @@ -332,14 +334,14 @@ class LogisticaController extends BaseController if (empty($envioEntity)) { return redirect()->to(base_url('logistica/selectEnvios/simple'))->with('error', lang('Logistica.errors.noEnvio')); } - + $modelProveedor = model('App\Models\Compras\ProveedorModel'); $proveedor = $modelProveedor->select('id, nombre') ->where('deleted_at', null) ->where('id', $envioEntity->proveedor_id) ->orderBy('nombre', 'asc') ->first(); - if(!empty($proveedor)){ + if (!empty($proveedor)) { $envioEntity->proveedor_nombre = $proveedor->nombre; } @@ -386,7 +388,7 @@ class LogisticaController extends BaseController $id = $this->request->getPost('id') ?? null; $finalizar_ots = $this->request->getPost('finalizar_ots') ?? false; - + $result = LogisticaService::finalizarEnvio($id, $finalizar_ots); return $this->response->setJSON($result); } else { @@ -439,17 +441,35 @@ class LogisticaController extends BaseController )->edit( "unidadesEnvio", function ($row, $meta) { - if($row->finalizado == 1 || $row->tipo_envio == 'ferro_prototipo'){ + if ($row->finalizado == 1 || $row->tipo_envio == 'ferro_prototipo') { return $row->unidadesEnvio; } return ''; + data-id="' . $row->id . '" data-name="unidades_envio" value="' . $row->unidadesEnvio . '">'; } ); return $result->toJson(returnAsObject: true); } + public function datatable_proximosEnvios($envio_id = null) + { + $q = LogisticaService::findNextEnvios($envio_id); + + $result = DataTable::of($q) + ->edit( + "ot", + function ($row, $meta) { + return '' . $row->ot . ''; + } + ); + + $result = $result->toJson(returnAsObject: true); + $query = model('App\Models\Logistica\EnvioModel')->db->getLastQuery(); + return $result; + + } + public function setCajaLinea() { @@ -490,7 +510,7 @@ class LogisticaController extends BaseController $fieldName = $this->request->getPost('name'); $fieldValue = $this->request->getPost('value'); - if (!$id || !$fieldName || ($fieldName=='unidades_envio' && !$fieldValue)) { + if (!$id || !$fieldName || ($fieldName == 'unidades_envio' && !$fieldValue)) { return $this->response->setJSON([ 'status' => false, 'message' => 'Datos inválidos' @@ -499,7 +519,7 @@ class LogisticaController extends BaseController $model = model('App\Models\Logistica\EnvioLineaModel'); $updated = $model->update($id, [ - "" . $fieldName => $fieldValue==""? null: $fieldValue, + "" . $fieldName => $fieldValue == "" ? null : $fieldValue, ]); return $this->response->setJSON([ @@ -522,7 +542,7 @@ class LogisticaController extends BaseController $model = model('App\Models\Logistica\EnvioModel'); $updated = $model->update($id, [ - "codigo_seguimiento" => $fieldValue==""? null: $fieldValue, + "codigo_seguimiento" => $fieldValue == "" ? null : $fieldValue, ]); return $this->response->setJSON([ @@ -545,7 +565,7 @@ class LogisticaController extends BaseController $model = model('App\Models\Logistica\EnvioModel'); $updated = $model->update($id, [ - "proveedor_id" => $fieldValue==""? null: $fieldValue, + "proveedor_id" => $fieldValue == "" ? null : $fieldValue, ]); return $this->response->setJSON([ diff --git a/ci4/app/Language/es/Logistica.php b/ci4/app/Language/es/Logistica.php index be9a91d8..4213a476 100755 --- a/ci4/app/Language/es/Logistica.php +++ b/ci4/app/Language/es/Logistica.php @@ -60,6 +60,7 @@ return [ 'selectAll' => 'Seleccionar todo', 'peso' => 'Peso (kg): ', 'unidadesTotalesFooter' => 'Unidades:', + 'fechaEncuadernado' => 'Fecha encuadernado', 'codigoSeguimiento' => 'Código de seguimiento', 'empresaMensajería' => 'Empresa de mensajería', diff --git a/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php b/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php index e28a7e1b..5c81a5ab 100755 --- a/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php +++ b/ci4/app/Models/OrdenTrabajo/OrdenTrabajoModel.php @@ -143,4 +143,25 @@ class OrdenTrabajoModel extends Model ->groupBy('orden_trabajo_tareas.id'); return $query; } + + public function queryProximosEnvios() + { + $query = $this->builder() + ->select([ + 'ordenes_trabajo.id as ot', + 'orden_trabajo_dates.encuadernacion_at as fechaEncuadernado', + ]) + ->join('pedidos', 'pedidos.id = ordenes_trabajo.pedido_id', 'left') + ->join('pedidos_linea', 'pedidos.id = pedidos_linea.pedido_id', 'left') + ->join('presupuestos', 'presupuestos.id = pedidos_linea.presupuesto_id', 'left') + ->join('presupuesto_direcciones', 'presupuestos.id = presupuesto_direcciones.presupuesto_id', 'left') + ->join('orden_trabajo_dates', 'orden_trabajo_dates.orden_trabajo_id = ordenes_trabajo.id', 'left') + ->where('ordenes_trabajo.deleted_at', null) + ->where('orden_trabajo_dates.encuadernacion_at !=', null) + + //->where('orden_trabajo_dates.fecha_encuadernado_at >=', 0) + //->where('ordenes_trabajo.fecha_entrega_warning >=', date("Y-m-d H:i:s")) + ->groupBy('ordenes_trabajo.id'); + return $query; + } } diff --git a/ci4/app/Services/LogisticaService.php b/ci4/app/Services/LogisticaService.php index 6d5f91b9..5e2fe8e1 100644 --- a/ci4/app/Services/LogisticaService.php +++ b/ci4/app/Services/LogisticaService.php @@ -79,6 +79,79 @@ class LogisticaService return $builder; } + public static function findNextEnvios(int $envio_id) + { + $db = \Config\Database::connect(); + + // 1. Dirección del envío actual + $envio = $db->table('envios')->select('direccion')->where('id', $envio_id)->get()->getRow(); + if (!$envio) { + return $db->table('(SELECT NULL AS id, NULL AS name) AS empty')->where('1 = 0'); + } + + $direccionNormalizada = str_replace(' ', '', strtolower(trim($envio->direccion))); + $direccionSQL = $db->escape($direccionNormalizada); + + // 2. Obtener presupuestos con esa dirección + $presupuestosConEsaDireccion = $db->table('presupuesto_direcciones') + ->select('presupuesto_id') + ->where("REPLACE(LOWER(TRIM(direccion)), ' ', '') = $direccionSQL", null, false) + ->get() + ->getResultArray(); + + $presupuestoIds = array_column($presupuestosConEsaDireccion, 'presupuesto_id'); + if (empty($presupuestoIds)) { + return $db->table('(SELECT NULL AS id, NULL AS name) AS empty')->where('1 = 0'); + } + + $hoy = date('Y-m-d'); + $sieteDiasDespues = date('Y-m-d', strtotime('+7 days')); + + // 3. Subconsulta principal + $subBuilder = $db->table('pedidos_linea pl') + ->select(" + ot.id AS ot, + DATE(p.fecha_encuadernado) as fechaEncuadernado, + ( + SELECT IFNULL(SUM(el.unidades_envio), 0) + FROM envios_lineas el + JOIN envios e ON e.id = el.envio_id + WHERE el.pedido_id = p.id + AND el.presupuesto_id = pr.id + AND REPLACE(LOWER(TRIM(e.direccion)), ' ', '') = $direccionSQL + AND (e.finalizado = 1 OR e.id = $envio_id) + ) AS unidades_enviadas, + pd.cantidad AS cantidad + ") + ->join('pedidos p', 'p.id = pl.pedido_id') + ->join('presupuestos pr', 'pr.id = pl.presupuesto_id') + ->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id') + ->join('ordenes_trabajo ot', 'ot.pedido_id = p.id') + ->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id') + ->whereIn('pr.id', $presupuestoIds) + ->whereIn('p.estado', ['finalizado', 'produccion']) + ->where('p.fecha_encuadernado IS NOT NULL') + ->where('DATE(p.fecha_encuadernado) >=', $hoy) + ->where('DATE(p.fecha_encuadernado) <=', $sieteDiasDespues) + ->where("NOT EXISTS ( + SELECT 1 + FROM envios_lineas el + WHERE el.envio_id = $envio_id + AND el.pedido_id = p.id + AND el.presupuesto_id = pr.id + GROUP BY el.pedido_id, el.presupuesto_id + HAVING SUM(el.unidades_envio) >= pd.cantidad + )", null, false) + ->groupBy('pl.id'); + + // 4. Envolver y filtrar por unidades pendientes + $builder = $db->table("({$subBuilder->getCompiledSelect(false)}) AS sub"); + $builder->select('ot, fechaEncuadernado'); + $builder->where('cantidad > unidades_enviadas'); + + return $builder; + } + public static function findForNewEnvio() { diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php index 27eecf8c..c90fe1e5 100644 --- a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php @@ -130,7 +130,7 @@
- +
-
- - +
-
-
-

- -

+
+

+ +

+
+
+ + + + + + + + + + +
+ +
+ +
-
-
-
-

-
-
-
- -
- finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?> -
-
- -
- -
-
- -
-
- -
- -
-
- - -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
-
- - -
-
-
- - -
-
- -
- -
+
-
+ -
- -
-

- -

- -
-
- - -
- -
-
-

- +

-
-
- - finalizado == 0) ? '' : 'readonly' ?> - value="codigo_seguimiento)) ?>"> -
-
- - finalizado == 0): ?> - - - - -
- finalizado == 0): ?> -
- +
+
+
+

- tipo_envio == 'estandar'): ?> -
-
- - + finalizado == 0 && $envioEntity->tipo_envio == 'estandar'): ?> +
+ +
+ +
+ +
+
+ +
+
+ +
+ +
+
+ + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+ + +
+
+
+ + +
+
+ +
+ + + +
+
+
-
+
+ +
+

+ +

+ +
+
+ + +
+ +
+
+
+ +
+
+

+ +

+ +
+
+ + finalizado == 0) ? '' : 'readonly' ?> + value="codigo_seguimiento)) ?>"> +
+
+ + finalizado == 0): ?> + + + + +
+ finalizado == 0): ?> +
+ +
+ tipo_envio == 'estandar'): ?> +
+ +
+ + +
+
+
+ +
- - endSection() ?> + endSection() ?> - section('css') ?> - - - - "> - " /> + section('css') ?> + + + + "> + " /> - endSection() ?> + endSection() ?> - section('additionalExternalJs') ?> - - - - - endSection() ?> \ No newline at end of file + section('additionalExternalJs') ?> + + + + + endSection() ?> \ No newline at end of file diff --git a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js index 63c6c3e3..71c300f9 100644 --- a/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js +++ b/httpdocs/assets/js/safekat/pages/logistica/envioEdit.js @@ -20,6 +20,7 @@ class EnvioEdit { ]; this.table = null; + this.tableProximosEnvios = null; this.buscarPedidos = new ClassSelect($("#buscadorPedidos"), '/logistica/selectAddLinea', "", true, { 'envio': $("#id").val() }); @@ -43,12 +44,6 @@ class EnvioEdit { this.proveedor.init(); } - if ($("#proximosEnvios").length) { - new PerfectScrollbar(document.getElementById('proximosEnvios'), { - wheelPropagation: false - }); - } - this.table = $('#tableLineasEnvio').DataTable({ processing: true, serverSide: true, @@ -101,6 +96,46 @@ class EnvioEdit { ] }); + this.tableProximosEnvios = $('#tableProximosEnvios').DataTable({ + processing: true, + serverSide: true, + autoWidth: true, + responsive: true, + scrollX: true, + orderCellsTop: true, + orderable: false, + order: [[1, 'asc']], + lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500], + pageLength: 5, + "dom": 'tp', + "ajax": { + "url": "/logistica/datatableProximosEnvios/" + $('#id').val(), + }, + "columns": [ + {data: 'ot'}, + {data: 'fechaEncuadernado'} + ], + "language": { + url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" + }, + "columnDefs": [ + { + "targets": [0, 1], + "className": "text-center", + }, + ], + drawCallback: function(){ + $(this.api().table().container()).find('table').css('width', '100%'); + this.api().columns.adjust(); + } + }); + + $('#proximosEnviosTip' + this.id).on('shown.bs.collapse', () => { + if (this.tableProximosEnvios) { + this.tableProximosEnvios.columns.adjust().draw(false); + } + }); + $('#btnImprimirEtiquetas').on('click', () => { const table = this.table; const selectedRows = table.rows({ page: 'current' }).nodes().filter((node) => {