terminado

This commit is contained in:
2025-05-04 18:35:08 +02:00
parent 39639d9ff8
commit 7b645539e3
9 changed files with 589 additions and 74 deletions

View File

@ -856,6 +856,9 @@ $routes->group('etiquetasTitulos', ['namespace' => 'App\Controllers\Logistica'],
$routes->post('deleteLineas', 'EtiquetasTitulosController::deleteLineasEtiqueta');
$routes->post('updateLineas', 'EtiquetasTitulosController::updateLineasEtiqueta');
$routes->post('updateComentarios', 'EtiquetasTitulosController::updateComentarios');
$routes->post('updateOrdenCajas', 'EtiquetasTitulosController::updateOrdenCajas');
$routes->post('renumber', 'EtiquetasTitulosController::renumberCajas');
$routes->post('imprimirEtiquetas', 'EtiquetasTitulosController::imprimirEtiquetas');
});
/*

View File

@ -42,7 +42,7 @@ class EtiquetasTitulosController extends BaseController
if ($this->request->isAJAX()) {
$query = EtiquetasTitulosService::getOtsWithTitulos();
if ($this->request->getGet("q")) {
$query->groupStart()
->orLike("ot.id", $this->request->getGet("q"))
@ -66,7 +66,7 @@ class EtiquetasTitulosController extends BaseController
$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"))
@ -92,11 +92,11 @@ class EtiquetasTitulosController extends BaseController
$data['direccion'] = $this->request->getPost('direccion') ?? null;
$data['unidades_caja'] = $this->request->getPost('unidades_caja') ?? null;
if(
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')
@ -125,12 +125,12 @@ class EtiquetasTitulosController extends BaseController
$modelLineas = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');
$ids = $modelLineas->where('etiqueta_titulos_id', $id)->findColumn('id');
if($ids){
if ($ids) {
$modelLineas->delete($ids);
}
$model = model('App\Models\Etiquetas\EtiquetasTitulosModel');
$id = $model->where('id', $id)->findColumn('id');
if($id){
if ($id) {
$model->delete($id);
}
$result = [
@ -142,7 +142,7 @@ class EtiquetasTitulosController extends BaseController
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
@ -160,8 +160,8 @@ class EtiquetasTitulosController extends BaseController
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)
@ -193,7 +193,7 @@ class EtiquetasTitulosController extends BaseController
$q->groupEnd();
}
$result = DataTable::of($q)
$result = DataTable::of($q)
->add("action", callback: function ($q) {
return '
<div class="btn-group btn-group-sm">
@ -202,7 +202,7 @@ class EtiquetasTitulosController extends BaseController
</div>
';
});
return $result->toJson(returnAsObject: true);
}
@ -212,7 +212,7 @@ class EtiquetasTitulosController extends BaseController
$id = $this->request->getGet('id') ?? null;
$query = EtiquetasTitulosService::findOTsWithAddress($id);
if ($this->request->getGet("q")) {
$query->groupStart()
->orLike("name", $this->request->getGet("q"))
@ -229,9 +229,10 @@ class EtiquetasTitulosController extends BaseController
}
}
public function addLineasEtiqueta(){
public function addLineasEtiqueta()
{
if($this->request->isAJAX()){
if ($this->request->isAJAX()) {
$etiqueta_id = $this->request->getPost('etiqueta_id') ?? null;
$ot_id = $this->request->getPost('ot_id') ?? null;
@ -240,14 +241,14 @@ class EtiquetasTitulosController extends BaseController
$result = EtiquetasTitulosService::addLineasEtiqueta($etiqueta_id, $ot_id, $unidades, $cajas);
return $this->response->setJSON($result);
}
else {
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function datatableLineasEtiquetas($id = null){
public function datatableLineasEtiquetas($id = null)
{
$model = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');
@ -270,20 +271,22 @@ class EtiquetasTitulosController extends BaseController
return '<a href="' . base_url('produccion/ordentrabajo/edit/' . $row->ot) . '" target="_blank">' . $row->ot . '</a>';
}
)
->edit(
->edit(
"unidades",
function ($row, $meta) {
return '<input type="number" class="form-control input-lineas input-unidades text-center"
data-id="'. $row->id.'" data-name="unidades" value="' . $row->unidades . '">';
return '<input type="number" class="form-control input-lineas input-unidades text-center"
data-id="' . $row->id . '" data-name="unidades" value="' . $row->unidades . '">';
}
)
->edit(
"numero_caja",
function ($row, $meta) {
return '<input type="number" class="form-control input-lineas input-cajas text-center"
data-id="'. $row->id.'" data-name="numero_caja" value="' . $row->numero_caja . '">';
return '<input type="number" class="form-control input-lineas input-cajas text-center"
data-id="' . $row->id . '" data-name="numero_caja" value="' . $row->numero_caja . '">';
}
)
->add("unidades_raw", fn($row) => $row->unidades)
->add("pesoUnidad_raw", fn($row) => $row->pesoUnidad)
->add(
"action",
callback: function ($q) {
@ -311,10 +314,10 @@ class EtiquetasTitulosController extends BaseController
}
$model = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');
for( $i = 0; $i < count($ids); $i++){
for ($i = 0; $i < count($ids); $i++) {
$model->delete($ids[$i]);
}
$result = [
'status' => true,
@ -327,7 +330,8 @@ class EtiquetasTitulosController extends BaseController
}
}
public function updateLineasEtiqueta(){
public function updateLineasEtiqueta()
{
if ($this->request->isAJAX()) {
$id = $this->request->getPost('id') ?? null;
@ -355,7 +359,8 @@ class EtiquetasTitulosController extends BaseController
}
}
public function updateComentarios(){
public function updateComentarios()
{
if ($this->request->isAJAX()) {
$id = $this->request->getPost('id') ?? null;
@ -381,4 +386,82 @@ class EtiquetasTitulosController extends BaseController
return $this->failUnauthorized('Invalid request', 403);
}
}
public function updateOrdenCajas()
{
$rawInput = $this->request->getBody();
$data = json_decode($rawInput, true);
$orden = $data['orden'] ?? [];
if (!is_array($orden)) {
return $this->response->setJSON([
'status' => false,
'message' => 'Datos inválidos'
]);
}
$model = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');
foreach ($orden as $item) {
if (isset($item['id'], $item['numero_caja'])) {
$model->update($item['id'], [
'numero_caja' => $item['numero_caja'],
'updated_at' => date('Y-m-d H:i:s') // opcional
]);
}
}
return $this->response->setJSON([
'status' => true,
'message' => 'Orden de cajas actualizado correctamente'
]);
}
public function renumberCajas()
{
$id = $this->request->getPost('id') ?? null;
if ($id == null) {
return [
'status' => false,
'message' => lang('Logistica.errors.errorMissingData')
];
}
$result = EtiquetasTitulosService::reordenarCajas($id);
return $this->response->setJSON($result);
}
public function imprimirEtiquetas()
{
$etiqueta_id = $this->request->getPost('etiqueta_id') ?? null;
$ids = $this->request->getPost('ids') ?? [];
$impresora_id = $this->request->getPost('impresora_id') ?? null;
$modelImpresora = model('App\Models\Configuracion\ImpresoraEtiquetaModel');
$impresora = $modelImpresora->select('id, name, ip, port, user, pass')
->where('deleted_at', null)
->where('id', $impresora_id)
->orderBy('name', 'asc')
->first();
if ($impresora == null) {
return $this->response->setJSON([
'status' => false,
'message' => 'Impresora no válida'
]);
}
if ($etiqueta_id == null || $ids == []) {
return [
'status' => false,
'message' => lang('Logistica.errors.errorMissingData')
];
}
$result = EtiquetasTitulosService::imprimirEtiquetas($etiqueta_id, $ids, $impresora);
return $this->response->setJSON($result);
}
}

View File

@ -78,7 +78,7 @@ return [
'cliente' => 'Cliente',
'comentariosEtiqueta' => 'Comentarios etiqueta',
'addLineaEtiqueta' => 'Añadir líneas a la etiqueta',
'renumber' => 'Renumerar etiquetas',
'errors' => [
'noEnvio' => 'No se ha encontrado el envio',
@ -88,6 +88,8 @@ return [
'noAddresses' => 'El pedido no tiene direcciones de envío',
'errorMissingData' => 'Faltan datos para crear la etiqueta',
'errorInsertarEtiqueta' => 'Error al insertar la etiqueta',
'noEtiqueta' => 'No se ha encontrado la etiqueta',
'noEtiquetaLineas' => 'No se han encontrado líneas de etiqueta',
],
'success' => [
'finalizado' => 'El envío se ha finalizado correctamente',
@ -97,6 +99,8 @@ return [
'successDeleteLines' => 'Lineas de etiqueta eliminadas correctamente',
'successUpdateLine' => 'Linea de etiqueta actualizadas correctamente',
'comentariosUpdated' => 'Comentarios actualizados correctamente',
'successReordenarCajas' => 'Cajas reordenadas correctamente',
'imprimirEtiquetas' => 'Etiquetas impresas correctamente',
],
];

View File

@ -79,10 +79,12 @@ class EtiquetasTitulosLineasModel extends Model
$builder = $this->db->table('etiquetas_titulos_lineas etl')
->select('
etl.id as id,
etl.ot_id as ot,
pr.titulo as titulo,
etl.unidades as unidades,
etl.numero_caja as numero_caja,
etl.numero_caja as numero_caja_raw,
pd.cantidad as unidadesTotal,
etl.id as id,
etl.unidades as unidadesRaw,

View File

@ -165,12 +165,12 @@ class EtiquetasTitulosService
->selectMax('numero_caja')
->where('etiqueta_titulos_id', $etiqueta_id)
->first();
$next_caja = $next_caja->numero_caja ?? 0;
$next_caja = $next_caja->numero_caja ?? 0;
$next_caja++;
$user_id = auth()->user()->id;
while($unidades_restantes > 0){
while ($unidades_restantes > 0) {
$modelEtitquetaLinea->insert([
'etiqueta_titulos_id' => $etiqueta_id,
'ot_id' => $ot_id,
@ -188,4 +188,177 @@ class EtiquetasTitulosService
];
}
public static function reordenarCajas($etiqueta_id)
{
$model = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');
// 1. Obtener todas las líneas ordenadas por numero_caja e id
$lineas = $model
->where('etiqueta_titulos_id', $etiqueta_id)
->orderBy('numero_caja ASC')
->orderBy('id ASC')
->findAll();
// 2. Agrupar por caja
$grupos = [];
foreach ($lineas as $linea) {
$grupos[$linea->numero_caja][] = $linea;
}
// 3. Reasignar números de caja de forma consecutiva
$nuevoNumeroCaja = 1;
foreach ($grupos as $grupo) {
foreach ($grupo as $linea) {
$model->update($linea->id, ['numero_caja' => $nuevoNumeroCaja]);
}
$nuevoNumeroCaja++;
}
return [
'status' => true,
'message' => lang('Logistica.success.successReordenarCajas'),
];
}
public static function imprimirEtiquetas($etiqueta_id = null, $ids = [], $printer = null){
$model = model('App\Models\Etiquetas\EtiquetasTitulosModel');
$modelLineas = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');
if ($etiqueta_id) {
$etiquetas = $model->where('id', $etiqueta_id)->first();
$etiquetas_lineas = $modelLineas->whereIn('id', $ids)->orderBy('numero_caja', 'ASC')->findAll();
}
// buscar el maximo numero_cajas en el array de objetos etiquetas_lineas
$max_num_cajas = 0;
foreach ($etiquetas_lineas as $linea) {
if ($linea->numero_caja > $max_num_cajas) {
$max_num_cajas = $linea->numero_caja;
}
}
// se obtienen los numero_caja diferentes en un array
$numero_cajas = [];
foreach ($etiquetas_lineas as $linea) {
if (!in_array($linea->numero_caja, $numero_cajas)) {
$numero_cajas[] = $linea->numero_caja;
}
}
if (empty($etiquetas)) {
return [
'status' => false,
'message' => lang('Logistica.errors.noEtiqueta'),
];
}
if (empty($etiquetas_lineas)) {
return [
'status' => false,
'message' => lang('Logistica.errors.noEtiquetaLineas'),
];
}
$data = [
"printer" => $printer->name,
"header" => [
"_FORMAT" => "E:MULTI.ZPL",
"_QUANTITY" => 1,
"_PRINBTERNAME" => $printer->name,
"_JOBNAME" => "LBL101"
],
'direccion' => $etiquetas->direccion,
'grupos' => [],
'notas' => $etiquetas->comentarios,
'nombre' => $etiquetas->att,
];
$index_etiqueta = 0;
foreach ($numero_cajas as $caja) {
array_push($data['grupos'], [
]);
$prefix = 1;
$lineas = array_filter($etiquetas_lineas, function ($linea) use ($caja) {
return $linea->numero_caja == $caja;
});
$lineaCounter = 0;
foreach($lineas as $linea){
if($lineaCounter >= 5){
$lineaCounter = 0;
$index_etiqueta++;
array_push($data['grupos'], []);
}
$modelPresupuestos = model('App\Models\OrdenTrabajo\OrdenTrabajoModel');
$datos_etiqueta = $modelPresupuestos->select('
pr.titulo as titulo,
pr.isbn as isbn,
pr.referencia_cliente as referencia_cliente,
p.id as id_pedido,
ordenes_trabajo.total_tirada as total_tirada,')
->join('pedidos p', 'p.id = ordenes_trabajo.pedido_id')
->join('pedidos_linea pl', 'pl.pedido_id = p.id')
->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
->where('ordenes_trabajo.id',$linea->ot_id)->first();
$data['grupos'][$index_etiqueta][] = [
'prefix' => $caja,
'titulo' => mb_substr($datos_etiqueta->titulo, 0, 40),
'cantidad' => $linea->unidades,
'tirada' => $datos_etiqueta->total_tirada,
'ean' => str_replace('-', '', $datos_etiqueta->isbn),
'npedido' => $datos_etiqueta->id,
'refcliente' => $datos_etiqueta->referencia_cliente,
];
$lineaCounter++;
}
$index_etiqueta++;
}
$servicioImpresora = new ImpresoraEtiquetaService();
$xml = $servicioImpresora->createEtiquetaTitulos($data);
if ($xml == null) {
return [
'status' => false,
'message' => lang('Logistica.errors.noEtiquetas'),
];
}
$sk_environment = getenv('SK_ENVIRONMENT');
if ($sk_environment == 'production') {
$status = $servicioImpresora->sendToImpresoraEtiqueta("ETIQUETA", $xml, $printer);
if ($status) {
return [
'status' => true,
'message' => lang('Logistica.success.imprimirEtiquetas'),
];
} else {
return [
'status' => false,
'message' => lang('Logistica.errors.noEtiquetas'),
];
}
} else {
return [
'status' => true,
'message' => lang('Logistica.success.imprimirEtiquetas'),
'data' => $xml
];
}
}
}

View File

@ -24,9 +24,9 @@ class ImpresoraEtiquetaService extends BaseService
"labels" => [
[
"cliente" => "Cliente Potencial",
"titulo" => "[1234] TEST OLIVEROS",
"titulo" => "[1234] TEST OLIVEROS",
"cantidad" => 100,
"tirada" => 50,
"tirada" => 50,
"cajas" => 1,
"ean" => null,
"nombre" => "___Nombre___",
@ -76,6 +76,66 @@ class ImpresoraEtiquetaService extends BaseService
$xml->appendChild($labels);
return $xml->saveXML();
}
public function createEtiquetaTitulos(array $data_label = []): ?string
{
$xml = new DOMDocument('1.0', 'utf-8');
// Crear nodo raíz "labels"
$labels = $xml->createElement("labels");
// Establecer atributos de "labels" desde "header"
foreach ($data_label["header"] as $key => $value) {
$labels->setAttribute($key, $value);
}
// Recorrer grupos de etiquetas
foreach ($data_label["grupos"] as $grupo) {
$labelChild = $xml->createElement('label');
// Crear variables específicas del grupo
foreach ($grupo as $libro) {
$prefix = $libro['prefix'];
$variables = [
"titulo$prefix" => $libro['titulo'],
"tirada$prefix" => $libro['tirada'],
"ean$prefix" => $libro['ean'],
"npedido$prefix" => $libro['npedido'],
"refcliente$prefix" => $libro['refcliente'],
"textpedido$prefix" => 'Pedido',
"textcantidad$prefix" => 'Cantidad:',
"textref$prefix" => 'Ref:',
"textean$prefix" => 'ISBN',
];
foreach ($variables as $varName => $varValue) {
$variableChild = $xml->createElement('variable');
$variableChild->setAttribute("name", $varName);
$variableChild->appendChild($xml->createTextNode((string) $varValue));
$labelChild->appendChild($variableChild);
}
}
// Variables comunes del grupo
$nombreVariable = $xml->createElement('variable', htmlspecialchars($data_label['nombre']));
$nombreVariable->setAttribute('name', 'nombre');
$labelChild->appendChild($nombreVariable);
$direccionVariable = $xml->createElement('variable', htmlspecialchars($data_label['direccion']));
$direccionVariable->setAttribute('name', 'direccion');
$labelChild->appendChild($direccionVariable);
$labels->appendChild($labelChild);
}
$xml->appendChild($labels);
return $xml->saveXML();
}
public function sendToImpresoraEtiqueta(string $name, string $content, ImpresoraEtiquetaEntity $impresoraEtiqueta): bool
{
$tmpFile = tmpfile();
@ -84,8 +144,8 @@ class ImpresoraEtiquetaService extends BaseService
rewind($tmpFile);
$tmpMetaData = stream_get_meta_data($tmpFile);
$conn = @ftp_connect($impresoraEtiqueta->ip,$impresoraEtiqueta->port);
if(!$conn){
$conn = @ftp_connect($impresoraEtiqueta->ip, $impresoraEtiqueta->port);
if (!$conn) {
throw new Exception('Error al establecer conexión FTP');
}
$isLoginSuccess = @ftp_login($conn, $impresoraEtiqueta->user, $impresoraEtiqueta->pass);
@ -99,10 +159,10 @@ class ImpresoraEtiquetaService extends BaseService
if (ftp_put($conn, $name, $tmpMetaData['uri'], FTP_ASCII) === FALSE) {
$status = false;
ftp_close($conn);
}else{
} else {
$status = true;
}
return $status;
}
}

View File

@ -143,6 +143,21 @@
</button>
</div>
<div class="col-sm-2 px-3">
<button id="btnRenumber" name="btnRenumber" tabindex="1"
class="btn btn-success w-100">
<?= lang("Logistica.renumber") ?>
<i class="ti ti-box"></i>
</button>
</div>
<div class="col-sm-2 px-3">
<button id="btnImprimirEtiquetas" name="btnImprimirEtiquetas" tabindex="1"
class="btn btn-info w-100">
<?= lang("Logistica.imprimirEtiquetas") ?>
<i class="ti ti-printer"></i>
</button>
</div>
<div class="col-sm-2 px-3 d-flex flex-column justify-content-end">
<div class="d-flex flex-column justify-content-end h-100">
<label for="impresoraEtiquetas" class="form-label">
@ -179,13 +194,14 @@
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th colspan="10">
<th colspan="11">
<div class="text-end">
<?= lang("Logistica.unidadesTotalesFooter") ?>
<span id="footer-unidades-envio"></span>
@ -193,7 +209,7 @@
</th>
</tr>
<tr>
<th colspan="10">
<th colspan="11">
<div class="text-end">
<?= lang("Logistica.peso") ?>
<span id="footer-peso"></span>
@ -221,12 +237,13 @@
<link rel="stylesheet" href="https://cdn.datatables.net/rowreorder/1.4.1/css/rowReorder.dataTables.min.css">
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<link rel="stylesheet" href="<?= site_url("/themes/vuexy/vendor/libs/flatpickr/flatpickr.css") ?>">
<link rel="stylesheet" href="https://cdn.datatables.net/rowreorder/1.4.1/css/rowReorder.dataTables.min.css">
<?= $this->endSection() ?>
<?= $this->section('additionalExternalJs') ?>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
<script src="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.js') ?>"></script>
<script src="https://cdn.datatables.net/rowgroup/1.3.1/js/dataTables.rowGroup.min.js"></script>
<script src="https://cdn.datatables.net/rowreorder/1.4.1/js/dataTables.rowReorder.min.js"></script>
<script type="module" src="<?= site_url("assets/js/safekat/pages/logistica/etiquetaEdit.js") ?>"></script>
<?= $this->endSection() ?>

View File

@ -16,7 +16,9 @@ class EtiquetaEdit {
{ data: "id" },
{ data: "pesoUnidad" },
{ data: "unidadesRaw" },
{ data: "action" }
{ data: "action" },
{ data: "numero_caja_raw" }
];
this.table = null;
@ -25,6 +27,9 @@ class EtiquetaEdit {
this.addLineas = $('#btnAddLinea');
this.btnEliminarLineas = $('#btnEliminarLineas');
this.btbnGuardarComentarios = $('#guardarComentarios');
this.btnSelectAll = $('#btnSelectAll');
this.btnRenumber = $('#btnRenumber');
this.btnImprimirEtiquetas = $('#btnImprimirEtiquetas');
this.buscador = new ClassSelect($('#buscadorPedidos'), '/etiquetasTitulos/findOts', '', true, { 'id': $('#id').val() });
}
@ -41,10 +46,88 @@ class EtiquetaEdit {
$(document).on('change', '.input-lineas', this._updateLinea.bind(this));
this.btnEliminarLineas.on('click', this._deleteLinea.bind(this));
this.btbnGuardarComentarios.on('click', this._guardarComentarios.bind(this));
this.btnSelectAll.on('click', this._selectAll.bind(this));
this.btnRenumber.on('click', this._renumber.bind(this));
this.btnImprimirEtiquetas.on('click', this._imprimirEtiquetas.bind(this));
}
_imprimirEtiquetas() {
const self = this;
const ids = [];
this.table.rows().every(function (rowIdx, tableLoop, rowLoop) {
const node = this.node(); // DOM del tr
const checkbox = $(node).find('.checkbox-linea-envio');
if (checkbox.is(':checked')) {
const data = this.data();
ids.push(data.id);
}
});
$.post(
'/etiquetasTitulos/imprimirEtiquetas',
{
etiqueta_id: $('#id').val(),
ids: ids,
impresora_id: $('#impresoraEtiquetas').val()
},
function (response) {
if (response.status) {
popSuccessAlert(response.message);
if(response.data) {
// show xml in new tab
const blob = new Blob([response.data], { type: 'application/xml' });
const url = URL.createObjectURL(blob);
const newTab = window.open(url, '_blank');
if (newTab) {
newTab.onload = function () {
// Revoke the object URL after the new tab has loaded
URL.revokeObjectURL(url);
};
} else {
popErrorAlert('Error abriendo la pestaña');
}
}
} else {
popErrorAlert('Error imprimiendo las etiquetas');
}
}
).fail(function (xhr, status, error) {
popErrorAlert(error);
});
}
_renumber() {
const self = this;
$.post(
'/etiquetasTitulos/renumber',
{
id: $('#id').val()
},
function (response) {
if (response.status) {
self.table.ajax.reload();
popSuccessAlert(response.message);
} else {
popErrorAlert('Error renumerando las lineas');
}
}
).fail(function (xhr, status, error) {
popErrorAlert(error);
});
}
_selectAll() {
const checkboxes = this.table.$('input[type="checkbox"]');
const allChecked = checkboxes.length === checkboxes.filter(':checked').length;
checkboxes.prop('checked', !allChecked);
}
_initDatatable() {
const self = this;
this.table = $('#tableLineasEtiqueta').DataTable({
processing: true,
serverSide: true,
@ -52,54 +135,137 @@ class EtiquetaEdit {
responsive: true,
scrollX: true,
orderCellsTop: true,
orderable: false,
order: [[7, 'asc']],
lengthMenu: [5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500],
rowId: 'id',
order: [[10, 'asc']],
rowGroup: {
dataSrc: 'numero_caja_raw',
startRender: function (rows, group) {
let totalUnidades = 0;
let totalPeso = 0;
rows.data().each(function (row) {
const unidades = parseFloat(row.unidadesRaw) || 0;
const pesoUnidad = parseFloat(row.pesoUnidad) || 0;
totalUnidades += unidades;
totalPeso += unidades * pesoUnidad;
});
const groupId = 'grupo-caja-' + group;
return $('<tr/>')
.attr('data-group', groupId)
.addClass('group-header bg-light fw-bold')
.css('cursor', 'pointer')
.append(
`<td colspan="11">
📦 CAJA ${group} UNIDADES: ${totalUnidades} PESO: ${totalPeso.toFixed(2)} kg
</td>`
);
}
},
rowReorder: {
dataSrc: 'numero_caja_raw',
update: false,
selector: 'td:not(.dt-no-reorder)' // evita inputs
},
lengthMenu: [5, 10, 25, 50, 100],
pageLength: 50,
"dom": 'lrtip',
"ajax": {
"url": "/etiquetasTitulos/datatableLineas/" + $('#id').val(),
"data": function (d) {
ajax: {
url: "/etiquetasTitulos/datatableLineas/" + $('#id').val(),
data: function (d) {
d.direccion = $('#direccion').val();
d.id = $('#id').val();
},
},
"columns": this.tableCols,
"language": {
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 <tfoot>
$('#footer-unidades-envio').text(totalUnidades);
$('#footer-peso').text(totalPeso.toFixed(2));
},
"columnDefs": [
columnDefs: [
{
"targets": [0, 9],
"className": "text-center",
"orderable": false,
"searchable": false,
targets: [0, 9],
className: "text-center dt-no-reorder",
orderable: false,
searchable: false
},
{
"targets": [1, 2, 4, 5, 6],
"className": "text-center",
targets: [3, 4],
className: "text-center dt-no-reorder"
},
{
targets: [6, 7, 8],
targets: [1, 2, 4, 5, 6],
className: "text-center"
},
{
targets: [6, 7, 8, 10],
visible: false
}
]
});
$('#tableLineasEtiqueta tbody').on('click', 'tr.group-header', function () {
const group = $(this).data('group');
const table = $('#tableLineasEtiqueta').DataTable();
const icon = $(this).find('.group-toggle-icon');
let visible = true;
table.rows().every(function () {
const row = this.node();
const data = this.data();
if ('numero_caja' in data && ('grupo-caja-' + data.numero_caja) === group) {
if (!$(row).hasClass('group-header')) {
$(row).toggle();
visible = !$(row).is(':visible');
}
}
});
// Cambiar el icono
icon.text(visible ? '▼' : '►');
});
this.table.on('row-reorder', function (e, diff, edit) {
if (!diff.length || !edit.triggerRow) return;
const table = self.table;
const movedRowData = table.row(edit.triggerRow).data();
if (!movedRowData?.id) return;
const movedItem = diff.find(d => {
const rowData = table.row(d.node).data();
return rowData?.id === movedRowData.id;
});
if (!movedItem) return;
const payload = {
id: movedRowData.id,
numero_caja: movedItem.newData
};
$.ajax({
url: '/etiquetasTitulos/updateOrdenCajas',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({ orden: [payload] }),
success: function (response) {
if (response.status) {
setTimeout(() => {
self.table.ajax.reload(null, false);
}, 100);
} else {
popErrorAlert('Error actualizando el orden');
}
},
error: function () {
popErrorAlert('Error en la solicitud AJAX');
}
});
});
}
_addLineas() {
@ -185,7 +351,7 @@ class EtiquetaEdit {
}
});
}
else{
else {
ids.push($(e.currentTarget).attr('data-id'));
}
Swal.fire({
@ -241,13 +407,16 @@ class EtiquetaEdit {
if (!response.status) {
popErrorAlert('Error actualizando la linea');
}
else {
self.table.ajax.reload();
}
}
).fail(function (xhr, status, error) {
popErrorAlert(error);
});
}
_guardarComentarios(){
_guardarComentarios() {
const self = this;
const id = $('#id').val();
const comentarios = $('#comentarios').val();
@ -263,7 +432,7 @@ class EtiquetaEdit {
if (!response.status) {
popErrorAlert('Error actualizando comentarios');
}
else{
else {
popSuccessAlert(response.message);
}
}

View File

@ -139,4 +139,8 @@
.dtrg-group.ui-droppable-hover {
background-color: #d1ecf1 !important;
cursor: move;
}
.dt-no-reorder {
cursor: auto !important;
}