diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 5f952ada..ec81df6c 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -847,6 +847,10 @@ $routes->group('etiquetasTitulos', ['namespace' => 'App\Controllers\Logistica'], $routes->get('otList', 'EtiquetasTitulosController::findOTs'); $routes->get('addList', 'EtiquetasTitulosController::findAddresses'); $routes->post('newEtiquetaTitulos', 'EtiquetasTitulosController::addEtiqueta'); + $routes->get('datatable', 'EtiquetasTitulosController::datatable'); + $routes->post('delete', 'EtiquetasTitulosController::deleteEtiqueta'); + $routes->get('edit/(:num)', 'EtiquetasTitulosController::edit/$1'); + $routes->get('datatableLineas/(:num)', 'EtiquetasTitulosController::datatableLineasEtiquetas/$1'); }); /* diff --git a/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php b/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php index 15fc86ab..229a720b 100644 --- a/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php +++ b/ci4/app/Controllers/Logistica/EtiquetasTitulosController.php @@ -17,13 +17,14 @@ class EtiquetasTitulosController extends BaseController protected string $locale; protected array $viewData; - protected static $controllerSlug = 'logistica'; + protected static $controllerSlug = 'etiquetas_titulos'; protected static $viewPath = 'themes/vuexy/form/logistica/'; public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) { $this->impresoraEtiquetaService = service('impresora_etiqueta'); $this->locale = session()->get('lang'); + $this->model = model('App\Models\Etiquetas\EtiquetasTitulosModel'); $this->viewData['pageTitle'] = lang('Logistica.logistica'); @@ -109,4 +110,141 @@ class EtiquetasTitulosController extends BaseController return $this->failUnauthorized('Invalid request', 403); } } + + public function deleteEtiqueta($id = null) + { + if ($this->request->isAJAX()) { + $id = $this->request->getPost('id') ?? null; + + if ($id == null) { + return [ + 'status' => false, + 'message' => lang('Logistica.errorMissingData') + ]; + } + + $modelLineas = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel'); + $ids = $modelLineas->where('etiqueta_titulos_id', $id)->findColumn('id'); + if($ids){ + $modelLineas->delete($ids); + } + $model = model('App\Models\Etiquetas\EtiquetasTitulosModel'); + $id = $model->where('id', $id)->findColumn('id'); + if($id){ + $model->delete($id); + } + $result = [ + 'status' => true, + 'message' => lang('Logistica.success.jhnresponse->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + + } + + + public function edit($id = null) + { + + if (empty($id)) { + return redirect()->to(base_url('logistica/selectEnvios/simple'))->with('error', lang('Logistica.errors.noEnvio')); + } + $model = model('App\Models\Etiquetas\EtiquetasTitulosModel'); + $etiquetaEntity = $model->select('etiquetas_titulos.*, clientes.nombre as cliente') + ->join('clientes', 'clientes.id = etiquetas_titulos.cliente_id', 'left') + ->where('etiquetas_titulos.id', $id) + ->first(); + if (empty($etiquetaEntity)) { + return redirect()->to(base_url('logistica/etiquetasLogistica'))->with('error', lang('Logistica.errors.noEnvio')); + } + + + $modelImpresora = model('App\Models\Configuracion\ImpresoraEtiquetaModel'); + $impresoras = $modelImpresora->select('id, name') + ->where('deleted_at', null) + ->where('tipo', 1) + ->orderBy('name', 'asc') + ->findAll(); + $etiquetaEntity->impresoras = $impresoras; + + $viewData = [ + 'currentModule' => static::$controllerSlug, + 'boxTitle' => '' . ' ' . lang('Logistica.EtiquetasTitulos') . ' [' . $etiquetaEntity->id . ']: ' . $etiquetaEntity->direccion, + 'usingServerSideDataTable' => true, + 'etiquetaEntity' => $etiquetaEntity, + ]; + + $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class + + return view(static::$viewPath . 'viewEtiquetasTitulosEdit', $viewData); + } + + + public function datatable() + { + $q = $this->model->getEtiquetasTitulos(); + + if (!empty($otsFilter)) { + $q->groupStart(); + $q->like('etl.ot_id', $otsFilter); + $q->groupEnd(); + } + + $result = DataTable::of($q) + ->add("action", callback: function ($q) { + return ' +
+ + +
+ '; + }); + + return $result->toJson(returnAsObject: true); + } + + public function datatableLineasEtiquetas($id = null){ + + $model = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel'); + + $id = $this->request->getGet('id') ?? null; + $direccion = $this->request->getGet('direccion') ?? null; + + $q = $model->getDatatableQuery($id, $direccion); + + + $result = DataTable::of($q) + ->add( + "rowSelected", + callback: function ($q) { + return ''; + } + ); + /*->edit( + "pedido", + function ($row, $meta) { + return '' . $row->pedido . ''; + } + ) + ->edit( + "presupuesto", + function ($row, $meta) { + return '' . $row->presupuesto . ''; + } + )->edit( + "unidadesEnvio", + function ($row, $meta) { + if($row->finalizado == 1 || $row->tipo_envio == 'ferro_prototipo'){ + return $row->unidadesEnvio; + } + return ''; + } + );*/ + + return $result->toJson(returnAsObject: true); + } } \ No newline at end of file diff --git a/ci4/app/Language/es/Logistica.php b/ci4/app/Language/es/Logistica.php index 6253266c..c3353c4a 100755 --- a/ci4/app/Language/es/Logistica.php +++ b/ci4/app/Language/es/Logistica.php @@ -66,10 +66,18 @@ return [ 'finalizarEnvioYOTs' => 'Finalizar envío y OTS', + 'EtiquetasTitulos' => 'Etiquetas de títulos', 'id' => 'ID', + 'otId' => 'OT ID', + 'num_caja' => 'Nº Caja', + 'unidadesTotalesOt' => 'Unidades totales OT', 'numeroCajas' => 'Nº Cajas', + 'unidadesEnCaja' => 'Unidades en caja', 'listadoEtiquetas' => 'Listado de etiquetas', 'nuevaEtiqueta' => 'Nueva etiqueta', + 'cliente' => 'Cliente', + 'comentariosEtiqueta' => 'Comentarios etiqueta', + 'addLineaEtiqueta' => 'Añadir líneas a la etiqueta', 'errors' => [ @@ -84,6 +92,7 @@ return [ 'success' => [ 'finalizado' => 'El envío se ha finalizado correctamente', 'finalizadoOTs' => 'El envío se ha finalizado correctamente.\nSe han creado las OTs siguientes OTs: {ots}', + 'successDeleteEtiqueta' => 'Etiqueta eliminada correctamente', ], ]; \ No newline at end of file diff --git a/ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php b/ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php index 01ee3db4..51be469a 100644 --- a/ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php +++ b/ci4/app/Models/Etiquetas/EtiquetasTitulosLineasModel.php @@ -32,4 +32,50 @@ class EtiquetasTitulosLineasModel extends Model protected $validationRules = []; protected $validationMessages = []; protected $skipValidation = false; + + protected $beforeDelete = ['addUserDeleted']; + + protected function addUserDeleted(array $data) + { + $userId = auth()->user()->id; + + if (!isset($data['data'])) { + $data['data'] = []; + } + + if (!empty($data['id'])) { + $builder = $this->builder(); + $builder->whereIn($this->primaryKey, (array) $data['id']) + ->update(['user_deleted_at' => $userId]); + } + return $data; + } + + public function getDatatableQuery($etiqueta_id, $direccion = null){ + + $direccionNormalizada = str_replace(' ', '', strtolower(trim($direccion))); + $direccionSQL = $this->db->escape($direccionNormalizada); + + + + $builder = $this->db->table('etiquetas_titulos_lineas etl') + ->select('etl.ot_id as ot, pr.titulo as titulo, etl.unidades as unidades, etl.numero_caja as numero_caja, + pd.cantidad as unidadesTotal, etl.id as id, etl.unidades as unidadesRaw, + (SELECT ROUND(SUM(peso)/1000, 2) + FROM presupuesto_linea + WHERE presupuesto_id = pr.id) AS pesoUnidad') + ->join('etiquetas_titulos et', 'et.id = etl.etiqueta_titulos_id') + ->join('ordenes_trabajo ot', 'ot.id = etl.ot_id') + ->join('pedidos p', 'p.id = ot.pedido_id') + ->join('pedidos_linea pl', 'pl.pedido_id = p.id') + ->join('presupuestos pr', 'pr.id = pl.presupuesto_id') + ->join('presupuesto_linea plinea', 'pr.id = plinea.presupuesto_id') + ->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id') + ->where('etl.deleted_at IS NULL') + ->where('et.id', $etiqueta_id) + ->where("REPLACE(LOWER(TRIM(pd.direccion)), ' ', '') = $direccionSQL", null, false) + ->groupBy('etl.numero_caja'); + + return $builder; + } } diff --git a/ci4/app/Models/Etiquetas/EtiquetasTitulosModel.php b/ci4/app/Models/Etiquetas/EtiquetasTitulosModel.php index 919e6ade..f253051a 100644 --- a/ci4/app/Models/Etiquetas/EtiquetasTitulosModel.php +++ b/ci4/app/Models/Etiquetas/EtiquetasTitulosModel.php @@ -32,4 +32,34 @@ class EtiquetasTitulosModel extends Model protected $validationRules = []; protected $validationMessages = []; protected $skipValidation = false; + + + protected $beforeDelete = ['addUserDeleted']; + + protected function addUserDeleted(array $data) + { + $userId = auth()->user()->id; + + if (!isset($data['data'])) { + $data['data'] = []; + } + + if (!empty($data['id'])) { + $builder = $this->builder(); + $builder->whereIn($this->primaryKey, (array) $data['id']) + ->update(['user_deleted_at' => $userId]); + } + return $data; + } + + public function getEtiquetasTitulos() + { + return $this->db->table('etiquetas_titulos et') + ->select('et.id, GROUP_CONCAT(DISTINCT etl.ot_id ORDER BY etl.ot_id ASC SEPARATOR ", ") as lista_ots') + ->select('COUNT(DISTINCT etl.numero_caja) as cajas, et.att, et.direccion') + ->join('etiquetas_titulos_lineas etl', 'etl.etiqueta_titulos_id = et.id') + ->where('et.deleted_at IS NULL') + ->where('etl.deleted_at IS NULL') + ->groupBy('et.id, et.att, et.direccion'); + } } diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewEtiquetasTitulosEdit.php b/ci4/app/Views/themes/vuexy/form/logistica/viewEtiquetasTitulosEdit.php new file mode 100644 index 00000000..fa3dabe5 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewEtiquetasTitulosEdit.php @@ -0,0 +1,231 @@ +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/viewImpresionEtiquetas.php b/ci4/app/Views/themes/vuexy/form/logistica/viewImpresionEtiquetas.php index 8966d68f..911f3dfc 100644 --- a/ci4/app/Views/themes/vuexy/form/logistica/viewImpresionEtiquetas.php +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewImpresionEtiquetas.php @@ -67,15 +67,15 @@
- +
- - - + + + - + diff --git a/httpdocs/assets/js/safekat/pages/logistica/etiquetaEdit.js b/httpdocs/assets/js/safekat/pages/logistica/etiquetaEdit.js new file mode 100644 index 00000000..b0aa0aa4 --- /dev/null +++ b/httpdocs/assets/js/safekat/pages/logistica/etiquetaEdit.js @@ -0,0 +1,112 @@ +import ClassSelect from '../../components/select2.js'; +import Ajax from '../../components/ajax.js'; +import AlbaranComponent from '../../components/albaranComponent.js'; + +class EtiquetaEdit { + + constructor() { + + this.tableCols = [ + { data: "rowSelected" }, + { data: "ot" }, + { data: "titulo" }, + { data: "numero_caja" }, + { data: "unidades" }, + { data: "unidadesTotal" }, + { data: "id" }, + { data: "pesoUnidad" }, + { data: "unidadesRaw" } + ]; + + this.table = null; + + this.direccion = $('#direccion'); + } + + init() { + this.initDatatable(); + } + + initDatatable() { + + this.table = $('#tableLineasEtiqueta').DataTable({ + processing: true, + serverSide: true, + autoWidth: true, + responsive: true, + scrollX: true, + orderCellsTop: true, + orderable: false, + order: [[7, 'asc']], + lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500], + pageLength: 50, + "dom": 'lrtip', + "ajax": { + "url": "/etiquetasTitulos/datatableLineas/" + $('#id').val(), + "data": function (d) { + d.direccion = $('#direccion').val(); + d.id = $('#id').val(); + }, + }, + "columns": this.tableCols, + "language": { + url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" + }, + footerCallback: function (row, data, start, end, display) { + let totalUnidades = 0; + let totalPeso = 0; + + data.forEach(row => { + const unidades = parseFloat(row.unidadesEnvioRaw) || 0; + const pesoUnidad = parseFloat(row.pesoUnidad) || 0; + totalUnidades += unidades; + totalPeso += unidades * pesoUnidad; + }); + + // Mostrar en spans personalizados del + $('#footer-unidades-envio').text(totalUnidades); + $('#footer-peso').text(totalPeso.toFixed(2)); + }, + "columnDefs": [ + { + "targets": [0], + "className": "text-center", + "orderable": false, + "searchable": false, + }, + { + "targets": [1, 2, 4, 5, 6], + "className": "text-center", + }, + { + targets: [6, 7, 8], + visible: false + } + ] + }); + + } +} + +document.addEventListener('DOMContentLoaded', function () { + /*const dropdown = document.querySelector(".dropdown-language"); + const activeItem = dropdown.querySelector(".dropdown-menu .dropdown-item"); + let locale = 'es'; + if (activeItem) { + locale = activeItem.getAttribute("data-language"); + } + + new Ajax('/translate/getTranslation', { locale: locale, translationFile: [] }, {}, + function (translations) { + window.language = JSON.parse(translations); + new EtiquetaEdit().init(); + }, + function (error) { + console.log("Error getting translations:", error); + } + ).post(); + */ + new EtiquetaEdit().init(); +}); + +export default EtiquetaEdit; diff --git a/httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js b/httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js index ffbefa59..0a8ae3c8 100644 --- a/httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js +++ b/httpdocs/assets/js/safekat/pages/logistica/impresionEtiquetas.js @@ -2,6 +2,8 @@ import ClassSelect from '../../components/select2.js'; $(() => { + let otsFilter = ''; + const selectOts = new ClassSelect($('#buscadorPedidos'), '/etiquetasTitulos/otList', "", true); selectOts.init(); @@ -26,7 +28,7 @@ $(() => { selectDirecciones.item.on('change', () => { $('.add-etiqueta').removeClass('d-none'); }) - + $('#btnAddEtiqueta').on('click', () => { Swal.fire({ @@ -59,7 +61,9 @@ $(() => { data, function (response) { if (response.status) { - // OK + tableEtiquetas.ajax.reload(); + // open the new etiqueta in a new tab + window.open(`${window.location.origin}/etiquetasTitulos/edit/${response.etiqueta}`, '_blank'); } else { popErrorAlert('Error en la respuesta'); } @@ -70,4 +74,104 @@ $(() => { } }); }) + + const tableEtiquetas = $('#tableOfEquiquetas').DataTable({ + processing: true, + serverSide: true, + autoWidth: true, + responsive: true, + scrollX: true, + orderCellsTop: true, + lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500], + pageLength: 50, + "dom": 'lBrtip', + "ajax": { + "url": "/etiquetasTitulos/datatable", + "data": function (d) { + d.otsFilter = otsFilter; + } + }, + "columns": [ + { "data": "id" }, + { "data": "lista_ots" }, + { "data": "cajas" }, + { "data": "att" }, + { "data": "direccion" }, + { "data": "action" } + + ], + "language": { + url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json" + }, + "columnDefs": [ + { + orderable: false, + searchable: false, + targets: [5] + }, + ], + "order": [[0, "desc"]], + }); + + $(document).on('click', '.btn-edit', function (e) { + window.location.href = '/etiquetasTitulos/edit/' + $(this).attr('data-id'); + }); + + $(document).on('click', '.btn-delete', function (e) { + Swal.fire({ + title: '¿Está seguro de eliminar la etiqueta?', + text: "No podrá revertir esta acción", + 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( + '/etiquetasTitulos/delete', + { + id: $(this).attr('data-id') + }, + function (response) { + if (response.status) { + tableEtiquetas.ajax.reload(); + popSuccessAlert(response.message); + } else { + popErrorAlert('Error borrando la etiqueta'); + } + } + ).fail(function (xhr, status, error) { + popErrorAlert(error); + }); + } + }) + + }); + + $(document).on("keyup", ".envio-filter", (event) => { + let columnName = $(event.currentTarget).attr("name"); + let columnIndex = $('#tableOfEquiquetas').DataTable().columns().eq(0).filter(function (index) { + return $('#tableOfEquiquetas').DataTable().column(index).dataSrc() === columnName; + })[0]; + $('#tableOfEquiquetas').DataTable().column(columnIndex).search($(event.currentTarget).val()).draw() + }) + + + $(document).on("keyup", ".envio-filter-ots", (event) => { + otsFilter = $(event.currentTarget).val(); + $('#tableOfEquiquetas').DataTable().ajax.reload(); + }) + + $(document).on("change", ".envio-filter-select", (event) => { + let columnName = $(event.currentTarget).attr("name"); + let columnIndex = $('#tableOfEquiquetas').DataTable().columns().eq(0).filter(function (index) { + return $('#tableOfEquiquetas').DataTable().column(index).dataSrc() === columnName; + })[0]; + $('#tableOfEquiquetas').DataTable().column(columnIndex).search($(event.currentTarget).val()).draw(); + }); })