From 71e70bf5511baa7521e075a3989140638371f2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Sat, 3 May 2025 12:06:25 +0200 Subject: [PATCH] =?UTF-8?q?terminando=20a=20falta=20del=20listado=20a?= =?UTF-8?q?=C3=B1adir=20etiquetas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ci4/app/Config/Routes.php | 8 ++ .../Logistica/EtiquetasTitulosController.php | 112 +++++++++++++++++ .../Logistica/LogisticaController.php | 13 ++ ...25-05-03-094500_CreateEtiquetasTitulos.php | 60 +++++++++ ci4/app/Entities/Etiquetas/EtiquetaTitulo.php | 17 +++ .../Etiquetas/EtiquetaTituloLinea.php | 10 ++ ci4/app/Language/es/Logistica.php | 9 ++ .../Etiquetas/EtiquetasTitulosLineasModel.php | 35 ++++++ .../Etiquetas/EtiquetasTitulosModel.php | 35 ++++++ ci4/app/Services/EtiquetasTitulosService.php | 107 ++++++++++++++++ ci4/app/Services/LogisticaService.php | 11 +- .../form/logistica/viewImpresionEtiquetas.php | 119 ++++++++++++++++++ .../form/logistica/viewPanelLogistica.php | 2 +- .../pages/logistica/impresionEtiquetas.js | 73 +++++++++++ 14 files changed, 605 insertions(+), 6 deletions(-) create mode 100644 ci4/app/Controllers/Logistica/EtiquetasTitulosController.php create mode 100644 ci4/app/Database/Migrations/2025-05-03-094500_CreateEtiquetasTitulos.php create mode 100644 ci4/app/Entities/Etiquetas/EtiquetaTitulo.php create mode 100644 ci4/app/Entities/Etiquetas/EtiquetaTituloLinea.php create mode 100644 ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php create mode 100644 ci4/app/Models/Etiquetas/EtiquetasTitulosModel.php create mode 100644 ci4/app/Services/EtiquetasTitulosService.php create mode 100644 ci4/app/Views/themes/vuexy/form/logistica/viewImpresionEtiquetas.php create mode 100644 httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 352a871e..5f952ada 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -818,6 +818,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi $routes->get('panel', 'LogisticaController::panel', ['as' => 'LogisticaPanel']); $routes->get('envios', 'LogisticaController::gestionEnvios', ['as' => 'gestionEnvios']); $routes->get('enviosFerros', 'LogisticaController::gestionEnviosFerros', ['as' => 'gestionEnviosFerros']); + $routes->get('etiquetasLogistica', 'LogisticaController::etiquetasLogistica', ['as' => 'etiquetasLogistica']); $routes->get('datatableEnvios', 'LogisticaController::datatable_envios'); $routes->get('datatableLineasEnvios/(:num)', 'LogisticaController::datatable_enviosEdit/$1'); $routes->get('envio/(:num)', 'LogisticaController::editEnvio/$1'); @@ -841,6 +842,13 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi }); +$routes->group('etiquetasTitulos', ['namespace' => 'App\Controllers\Logistica'], function ($routes) { + + $routes->get('otList', 'EtiquetasTitulosController::findOTs'); + $routes->get('addList', 'EtiquetasTitulosController::findAddresses'); + $routes->post('newEtiquetaTitulos', 'EtiquetasTitulosController::addEtiqueta'); +}); + /* * -------------------------------------------------------------------- * Translation diff --git a/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php b/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php new file mode 100644 index 00000000..15fc86ab --- /dev/null +++ b/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php @@ -0,0 +1,112 @@ +impresoraEtiquetaService = service('impresora_etiqueta'); + $this->locale = session()->get('lang'); + + $this->viewData['pageTitle'] = lang('Logistica.logistica'); + + // Breadcrumbs + $this->viewData['breadcrumb'] = [ + ['title' => lang("App.menu_logistica"), 'route' => route_to("LogisticaPanel"), 'active' => false], + ]; + + + parent::initController($request, $response, $logger); + } + + public function findOTs() + { + if ($this->request->isAJAX()) { + + $query = EtiquetasTitulosService::getOtsWithTitulos(); + + if ($this->request->getGet("q")) { + $query->groupStart() + ->orLike("ot.id", $this->request->getGet("q")) + ->orLike("pr.titulo)", $this->request->getGet("q")) + ->groupEnd(); + } + + + $result = $query->orderBy("id", "DESC")->get()->getResultObject(); + + return $this->response->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function findAddresses() + { + if ($this->request->isAJAX()) { + + $ot_id = $this->request->getGet("ot_id"); + + $query = EtiquetasTitulosService::getDireccionesOT($ot_id); + + if ($this->request->getGet("q")) { + $query->groupStart() + ->orLike("pd.direccion", $this->request->getGet("q")) + ->groupEnd(); + } + + + $result = $query->orderBy("pd.direccion", "ASC")->get()->getResultObject(); + + return $this->response->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function addEtiqueta() + { + if ($this->request->isAJAX()) { + + $data = []; + $data['user_id'] = auth()->user()->id; + $data['ot_id'] = $this->request->getPost('ot_id') ?? null; + $data['direccion'] = $this->request->getPost('direccion') ?? null; + $data['unidades_caja'] = $this->request->getPost('unidades_caja') ?? null; + + if( + $this->request->getPost('ot_id') == null || + $this->request->getPost('direccion') == null || + $this->request->getPost('unidades_caja') == null + ){ + return [ + 'status' => false, + 'message' => lang('Logistica.errorMissingData') + ]; + } + + $result = EtiquetasTitulosService::addEtiqueta($data); + + return $this->response->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } +} \ No newline at end of file diff --git a/ci4/app/Controllers/Logistica/LogisticaController.php b/ci4/app/Controllers/Logistica/LogisticaController.php index d8dade10..586bb83d 100755 --- a/ci4/app/Controllers/Logistica/LogisticaController.php +++ b/ci4/app/Controllers/Logistica/LogisticaController.php @@ -85,6 +85,19 @@ class LogisticaController extends BaseController return view(static::$viewPath . 'viewLogisticaSelectEnvios', $viewData); } + public function etiquetasLogistica() + { + $viewData = [ + 'currentModule' => static::$controllerSlug, + 'boxTitle' => lang('Logistica.etiquetasTitulos'), + 'usingServerSideDataTable' => true, + ]; + + $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class + + return view(static::$viewPath . 'viewImpresionEtiquetas', $viewData); + } + public function listAlbaranes(){ $viewData = [ 'currentModule' => static::$controllerSlug, diff --git a/ci4/app/Database/Migrations/2025-05-03-094500_CreateEtiquetasTitulos.php b/ci4/app/Database/Migrations/2025-05-03-094500_CreateEtiquetasTitulos.php new file mode 100644 index 00000000..18baa8a8 --- /dev/null +++ b/ci4/app/Database/Migrations/2025-05-03-094500_CreateEtiquetasTitulos.php @@ -0,0 +1,60 @@ +forge->addField([ + 'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true], + 'comentarios' => ['type' => 'TEXT', 'null' => true], + 'direccion' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => false], + 'att' => ['type' => 'VARCHAR', 'constraint' => 255, 'null' => false], + 'cliente_id' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + 'created_at' => ['type' => 'DATETIME', 'null' => true], + 'updated_at' => ['type' => 'DATETIME', 'null' => true], + 'deleted_at' => ['type' => 'DATETIME', 'null' => true], + 'user_created_at' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + 'user_updated_at' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + 'user_deleted_at' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + ]); + $this->forge->addKey('id', true); + $this->forge->addForeignKey('user_created_at', 'users', 'id', 'SET NULL', 'CASCADE'); + $this->forge->addForeignKey('user_updated_at', 'users', 'id', 'SET NULL', 'CASCADE'); + $this->forge->addForeignKey('user_deleted_at', 'users', 'id', 'SET NULL', 'CASCADE'); + $this->forge->addForeignKey('cliente_id', 'clientes', 'id', 'SET NULL', 'CASCADE'); + $this->forge->createTable('etiquetas_titulos'); + + // Tabla: etiquetas_titulos_lineas + $this->forge->addField([ + 'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true], + 'etiqueta_titulos_id' => ['type' => 'INT', 'unsigned' => true], + 'ot_id' => ['type' => 'INT', 'unsigned' => true], + 'unidades' => ['type' => 'INT', 'unsigned' => true], + 'numero_caja' => ['type' => 'INT', 'unsigned' => true], + 'created_at' => ['type' => 'DATETIME', 'null' => true], + 'updated_at' => ['type' => 'DATETIME', 'null' => true], + 'deleted_at' => ['type' => 'DATETIME', 'null' => true], + 'user_created_at' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + 'user_updated_at' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + 'user_deleted_at' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + ]); + $this->forge->addKey('id', true); + $this->forge->addForeignKey('etiqueta_titulos_id', 'etiquetas_titulos', 'id', 'CASCADE', 'CASCADE'); + $this->forge->addForeignKey('ot_id', 'ordenes_trabajo', 'id', 'CASCADE', 'CASCADE'); + $this->forge->addForeignKey('user_created_at', 'users', 'id', 'SET NULL', 'CASCADE'); + $this->forge->addForeignKey('user_updated_at', 'users', 'id', 'SET NULL', 'CASCADE'); + $this->forge->addForeignKey('user_deleted_at', 'users', 'id', 'SET NULL', 'CASCADE'); + $this->forge->createTable('etiquetas_titulos_lineas'); + } + + public function down() + { + $this->forge->dropTable('etiquetas_titulos_lineas', true); + $this->forge->dropTable('etiquetas_titulos', true); + } +} diff --git a/ci4/app/Entities/Etiquetas/EtiquetaTitulo.php b/ci4/app/Entities/Etiquetas/EtiquetaTitulo.php new file mode 100644 index 00000000..35168ebf --- /dev/null +++ b/ci4/app/Entities/Etiquetas/EtiquetaTitulo.php @@ -0,0 +1,17 @@ +where('etiqueta_titulos_id', $this->id)->findAll(); + } +} diff --git a/ci4/app/Entities/Etiquetas/EtiquetaTituloLinea.php b/ci4/app/Entities/Etiquetas/EtiquetaTituloLinea.php new file mode 100644 index 00000000..74ee95a6 --- /dev/null +++ b/ci4/app/Entities/Etiquetas/EtiquetaTituloLinea.php @@ -0,0 +1,10 @@ + 'Finalizar envío', 'finalizarEnvioYOTs' => 'Finalizar envío y OTS', + + 'id' => 'ID', + 'numeroCajas' => 'Nº Cajas', + 'listadoEtiquetas' => 'Listado de etiquetas', + 'nuevaEtiqueta' => 'Nueva etiqueta', + + 'errors' => [ 'noEnvio' => 'No se ha encontrado el envio', 'noEnvioLineas' => 'No se han encontrado líneas de envío', 'noDataToFind' => 'No se ha introducido ningún dato para buscar', 'notFound' => 'No se encuentra el pedido o ISBN, el pedido no está en producción o finalizado o no tiene envíos pendientes', 'noAddresses' => 'El pedido no tiene direcciones de envío', + 'errorMissingData' => 'Faltan datos para crear la etiqueta', + 'errorInsertarEtiqueta' => 'Error al insertar la etiqueta', ], 'success' => [ 'finalizado' => 'El envío se ha finalizado correctamente', diff --git a/ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php b/ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php new file mode 100644 index 00000000..01ee3db4 --- /dev/null +++ b/ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php @@ -0,0 +1,35 @@ +table('ordenes_trabajo ot') + ->select(" + ot.id AS id, + CONCAT('[', ot.id, '] - ', pr.titulo) AS name") + ->join('pedidos p', 'p.id = ot.pedido_id') + ->join('pedidos_linea pl', 'p.id = pl.pedido_id') + ->join('presupuestos pr', 'pr.id = pl.presupuesto_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'); + + return $builder; + } + + public static function getDireccionesOT($ot_id){ + + $db = \Config\Database::connect(); + + // 3. Subconsulta principal + $builder = $db->table('presupuesto_direcciones pd') + ->select(" + pd.id AS id, + pd.direccion AS name") + ->join('presupuestos pr', 'pr.id = pd.presupuesto_id') + ->join('pedidos_linea pl', 'pr.id = pl.presupuesto_id') + ->join('pedidos p', 'p.id = pl.pedido_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('ot.id', $ot_id); + + return $builder; + } + + public static function addEtiqueta($data) + { + $db = \Config\Database::connect(); + + $builder = $db->table('presupuesto_direcciones pd'); + $builder->select('pd.att, pd.direccion, pd.cantidad, pr.cliente_id'); + $builder->join('presupuestos pr', 'pr.id = pd.presupuesto_id'); + $builder->join('pedidos_linea pl', 'pr.id = pl.presupuesto_id'); + $builder->join('pedidos p', 'p.id = pl.pedido_id'); + $builder->join('ordenes_trabajo ot', 'ot.pedido_id = p.id'); + $builder->where('ot.id', $data['ot_id']); + $builder->where('pd.direccion', $data['direccion']); + + $result = $builder->get()->getRow(); + $data['att'] = $result->att; + $data['direccion'] = $result->direccion; + $data['cantidad'] = $result->cantidad; + $data['cliente_id'] = $result->cliente_id; + + $modelEtiquetasTitulos = model('App\Models\Etiquetas\EtiquetasTitulosModel'); + $modelEtiquetasTitulos->insert([ + 'direccion' => $data['direccion'], + 'att' => $data['att'], + 'cliente_id' => $data['cliente_id'], + 'user_created_at' => $data['user_id'], + ]); + $etiquetaId = $modelEtiquetasTitulos->getInsertID(); + + if($etiquetaId == null){ + return [ + 'status' => false, + 'message' => lang('Logistica.errorInsertarEtiqueta'), + ]; + } + + $cantidad_restante = intval($data['cantidad']); + $numero_caja = 1; + while($cantidad_restante > 0){ + $modelEtiquetasTitulosLineas = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel'); + $modelEtiquetasTitulosLineas->insert([ + 'etiqueta_titulos_id' => $etiquetaId, + 'ot_id' => $data['ot_id'], + 'unidades' => $cantidad_restante - intval($data['unidades_caja']) < 0 ? $cantidad_restante : intval($data['unidades_caja']), + 'numero_caja' => $numero_caja, + 'user_created_at' => $data['user_id'], + ]); + $cantidad_restante -= $data['unidades_caja']; + $numero_caja++; + } + + + return [ + 'status' => true, + 'etiqueta' => $etiquetaId, + ]; + } +} \ No newline at end of file diff --git a/ci4/app/Services/LogisticaService.php b/ci4/app/Services/LogisticaService.php index d2251313..cb4fb1b5 100644 --- a/ci4/app/Services/LogisticaService.php +++ b/ci4/app/Services/LogisticaService.php @@ -78,6 +78,7 @@ class LogisticaService return $builder; } + public static function findForNewEnvio() { $db = \Config\Database::connect(); @@ -576,11 +577,11 @@ class LogisticaService $data = [ "printer" => $printer->name, "header" => [ - "_FORMAT" => "E:PEDIDO.ZPL", - "_QUANTITY" => 1, - "_PRINBTERNAME" => $printer->name, - "_JOBNAME" => "LBL101" - ], + "_FORMAT" => "E:PEDIDO.ZPL", + "_QUANTITY" => 1, + "_PRINBTERNAME" => $printer->name, + "_JOBNAME" => "LBL101" + ], ]; foreach ($lineas as $linea) { diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewImpresionEtiquetas.php b/ci4/app/Views/themes/vuexy/form/logistica/viewImpresionEtiquetas.php new file mode 100644 index 00000000..8966d68f --- /dev/null +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewImpresionEtiquetas.php @@ -0,0 +1,119 @@ +include("themes/_commonPartialsBs/sweetalert") ?> +include('themes/_commonPartialsBs/datatables') ?> +include("themes/_commonPartialsBs/select2bs5") ?> +extend('themes/vuexy/main/defaultlayout') ?> + +section('content'); ?> +
+
+
+
+

+
+
+ + + +
+

+ +

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

+ +

+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+
+ +
+
+ endSection() ?> + + + section('css') ?> + + endSection() ?> + + section('additionalExternalJs') ?> + + + endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php b/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php index 150044b0..0788a3fc 100755 --- a/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php @@ -21,7 +21,7 @@ " alt="Envío de Ferros/Prototipos">
-
+
" alt="Etiquetas de títulos">
diff --git a/httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js b/httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js new file mode 100644 index 00000000..ffbefa59 --- /dev/null +++ b/httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js @@ -0,0 +1,73 @@ +import ClassSelect from '../../components/select2.js'; + +$(() => { + + const selectOts = new ClassSelect($('#buscadorPedidos'), '/etiquetasTitulos/otList', "", true); + selectOts.init(); + + const selectDirecciones = new ClassSelect($('#selectDirecciones'), '/etiquetasTitulos/addList', "", true, { + ot_id: () => selectOts.getVal() + }); + selectDirecciones.init(); + + selectOts.item.on('select2:open', () => { + $('.select-direcciones').addClass('d-none'); + $('.add-etiqueta').addClass('d-none'); + }) + selectOts.item.on('change', () => { + selectDirecciones.empty(); + $('.add-etiqueta').addClass('d-none'); + $('.select-direcciones').removeClass('d-none'); + }) + selectDirecciones.item.on('select2:open', () => { + $('.add-etiqueta').addClass('d-none'); + }) + + selectDirecciones.item.on('change', () => { + $('.add-etiqueta').removeClass('d-none'); + }) + + $('#btnAddEtiqueta').on('click', () => { + + Swal.fire({ + title: 'Unidades por caja', + text: 'Seleccione la cantidad de unidades por caja', + icon: 'info', + input: 'text', + inputLabel: 'Unidades/caja', + inputValue: 0, + showCancelButton: true, + confirmButtonColor: '#3085d6', + confirmButtonText: 'Aceptar', + cancelButtonText: 'Cancelar', + customClass: { + confirmButton: 'btn btn-primary me-1', + cancelButton: 'btn btn-secondary' + }, + buttonsStyling: false + }).then((result) => { + if (result.isConfirmed) { + const unidades_caja = result.value; + const url = '/etiquetasTitulos/newEtiquetaTitulos'; + const data = { + ot_id: selectOts.getVal(), + direccion: selectDirecciones.getText(), + unidades_caja: unidades_caja + }; + $.post( + url, + data, + function (response) { + if (response.status) { + // OK + } else { + popErrorAlert('Error en la respuesta'); + } + } + ).fail(function (xhr, status, error) { + popErrorAlert(error); + }); + } + }); + }) +})