terminada envio lineas

This commit is contained in:
2025-04-18 13:38:06 +02:00
parent 15f6d0d675
commit 0b04e6dabd
14 changed files with 1313 additions and 19 deletions

View File

@ -0,0 +1,598 @@
import ClassSelect from '../../components/select2.js';
import Ajax from '../../components/ajax.js';
class EnvioEdit {
constructor() {
this.tableCols = [
{ data: "rowSelected" },
{ data: "cajas", defaultContent: ""},
{ data: "pedido" },
{ data: "presupuesto" },
{ data: "titulo" },
{ data: "unidadesEnvio" },
{ data: "unidadesEnviadas" },
{ data: "unidadesTotal" },
{ data: "action" },
{ data: "id" },
{ data: "pesoUnidad" }
];
this.table = null;
this.buscarPedidos = new ClassSelect($("#buscadorPedidos"), '/logistica/selectAddLinea', "", true, { 'envio': $("#id").val() });
this.contadorCajas = parseInt($("#nextCaja").val()) || 1;
this.btnAddLinea = $("#btnAddLinea");
this.btnAddCaja = $("#btnAddCaja");
this.btnDeleteLinea = $("#btnEliminarLineas");
this.btnGuardarComentarios = $("#guardarComentarios");
}
init() {
this.table = $('#tableLineasEnvio').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": 'lrtip',
"ajax": {
"url": "/logistica/datatableLineasEnvios/" + $('#id').val(),
},
"columns": this.tableCols,
"language": {
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
},
rowGroup: {
dataSrc: 'cajas',
startRender: function (rows, group) {
const nombreGrupo = group === null || group === '' || group === 'null' || group.toUpperCase() === 'NO GROUP'
? 'SIN ASIGNAR'
: group;
let totalUnidades = 0;
let totalPeso = 0;
rows.data().each(function (row) {
const unidades = parseInt(row.unidadesEnvio) || 0;
totalUnidades += unidades;
totalPeso += parseFloat(row.pesoUnidad) * unidades || 0;
});
return `CAJA: ${nombreGrupo} [unidades: ${totalUnidades}, peso: <span class="peso-grupo" data-valor="${totalPeso}">${totalPeso.toFixed(1)}</span> kg]`;
}
},
"columnDefs": [
{
"targets": [0, 8],
"className": "text-center",
"orderable": false,
"searchable": false,
},
{
"targets": [2, 3, 5, 6, 7],
"className": "text-center",
},
{
targets: [1, 9, 10],
visible: false
}
],
"order": [[1, "asc"]],
"orderFixed": [ [1, 'asc'] ],
});
$('#tableLineasEnvio').on('draw.dt', () => {
const table = this.table;
this._aplicarDroppableEnGrupos(table);
// Aplica draggable a filas si aún no lo tienen
this.table.rows({ page: 'current' }).every(function () {
const $row = $(this.node());
if (!$row.hasClass('draggable-applied')) {
$row.addClass('draggable-applied');
$row.draggable({
helper: 'clone',
revert: 'invalid',
start: () => $row.css('opacity', 0.5),
stop: () => $row.css('opacity', 1)
});
}
});
document.querySelectorAll('.peso-grupo').forEach(el => {
const valor = parseFloat(el.getAttribute('data-valor')) || 0;
new AutoNumeric(el, valor, {
decimalPlaces: 1,
digitGroupSeparator: ',',
decimalCharacter: '.',
minimumValue: '0',
suffixText: '',
modifyValueOnWheel: false
});
});
});
$(document).on('click', '.btn-edit', (e) => {
const table = this.table;
const id = $(e.currentTarget).data('id');
const row = table.row($(e.currentTarget).closest('tr'));
const rowData = row.data();
Swal.fire({
title: 'Editar unidades a enviar',
input: 'number',
inputLabel: `Unidades actuales: ${rowData.unidadesEnvio}`,
inputValue: rowData.unidadesEnvio,
inputAttributes: {
min: 1
},
showCancelButton: true,
confirmButtonText: 'Guardar',
cancelButtonText: 'Cancelar',
inputValidator: (value) => {
if (!value || parseInt(value) <= 0) {
return 'Debes ingresar un valor mayor a 0';
}
},
customClass: {
confirmButton: 'btn btn-primary me-1',
cancelButton: 'btn btn-secondary'
},
buttonsStyling: false
}).then((result) => {
if (result.isConfirmed) {
const nuevasUnidades = parseInt(result.value);
$.post('/logistica/updateUnidadesEnvio', {
id: rowData.id,
unidades_envio: nuevasUnidades
}, function (response) {
if (response.status) {
table.draw(false);
} else {
Swal.fire({
title: 'Error',
text: response.message,
icon: 'error',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
}
}).fail(() => {
Swal.fire({
title: 'Error',
text: 'No se pudo actualizar el dato.',
icon: 'error',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
});
}
});
});
this.buscarPedidos.init();
this.btnAddLinea.on('click', this._addEnvioLinea.bind(this));
this.btnAddCaja.on('click', this._addCaja.bind(this));
this.btnDeleteLinea.on('click', this._deleteLineas.bind(this));
this.btnGuardarComentarios.on('click', () => {
$.post('/logistica/updateComentariosEnvio', {
id: $('#id').val(),
comentarios: $('#comentarios').val()
}, function (response) {
if (response.status) {
popSuccessAlert('Comentarios guardados correctamente');
} else {
popErrorAlert(response.message);
}
}).fail((error) => {
popErrorAlert(error.responseJSON.message);
});
});
}
_deleteLineas() {
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();
return rowData.id;
}
).toArray();
if (ids.length > 0) {
Swal.fire({
title: 'Eliminar líneas de envío',
text: '¿Está seguro de que desea eliminar 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/deleteLineasEnvio', {
ids: ids
}, function (response) {
if (response.status) {
table.draw(false);
}
else {
Swal.fire({
title: 'Error',
text: response.message,
icon: 'error',
showCancelButton: false,
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 eliminar la línea de envío.',
icon: 'error',
showCancelButton: false,
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',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
}
}
_addCaja() {
const table = this.table;
this.contadorCajas = this._calcularSiguienteNumeroCaja();
const contadorCajas = this.contadorCajas;
let moved = false;
// Recorremos todas las filas visibles
table.rows({ page: 'current' }).every(function () {
const $row = $(this.node());
const checkbox = $row.find('.checkbox-linea-envio');
if (checkbox.is(':checked')) {
const rowData = this.data();
$.post('/logistica/updateCajaLinea', {
id: rowData.id,
caja: contadorCajas
}, function (response) {
if (response.status) {
table.draw(false);
} else {
Swal.fire({
title: 'Error',
text: response.message,
icon: 'error',
showCancelButton: false,
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 actualizar el grupo.',
icon: 'error',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
table.ajax.reload();
});
moved = true;
}
});
if (moved) {
table.draw(false); // Redibuja sin cambiar de página
this.contadorCajas++;
} else {
Swal.fire({
title: 'Sin filas seleccionadas',
text: 'Marca al menos una línea para moverla a una nueva caja.',
icon: 'info',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
}
}
_aplicarDroppableEnGrupos(table) {
const self = this;
setTimeout(() => {
$('.dtrg-group').each(function () {
const $grupo = $(this);
let nombreGrupo = $grupo.text().toUpperCase().replace('CAJA:', '').trim();
if (nombreGrupo === 'SIN ASIGNAR') {
nombreGrupo = null;
}
// Evitar aplicar múltiples veces
if (!$grupo.hasClass('droppable-applied')) {
$grupo.addClass('droppable-applied');
$grupo.droppable({
accept: 'tr:not(.dtrg-group)',
hoverClass: 'table-primary',
drop: function (event, ui) {
const row = table.row(ui.draggable);
const rowData = row.data();
rowData.cajas = nombreGrupo;
row.data(rowData).invalidate();
$.post('/logistica/updateCajaLinea', {
id: rowData.id,
caja: nombreGrupo
}, function (response) {
if (response.status) {
self._reordenarCajas();
} else {
Swal.fire({
title: 'Error',
text: response.message,
icon: 'error',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
table.ajax.reload();
}
}).fail(() => {
Swal.fire({
title: 'Error filas seleccionadas',
text: 'No se pudo actualizar el grupo.',
icon: 'error',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
table.ajax.reload();
});
}
});
}
});
}, 50); // pequeño delay para asegurar que el DOM esté listo
}
_addEnvioLinea() {
if(!this.buscarPedidos.getVal()) {
Swal.fire({
title: 'Atención!',
text: 'Debe seleccionar un pedido antes de añadir una línea de envío.',
icon: 'info',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
return;
}
new Ajax('/logistica/addLineaEnvio', {
'envio_id': $('#id').val(),
'pedido_id': this.buscarPedidos.getVal(),
'direccion': $("#direccion").val()
}, {},
(response) => {
if (response.status) {
if (parseInt(response.data.total_unidades) > parseInt(response.data.unidades_envio)) {
const text = `<div style="text-align: left;">
Se ha añadido un nuevo envío parcial:\n
<ul>
<li>Unidades totales en pedido: {unidadesTotal}</li>
<li>Unidades añadidos: {unidadesEnvio}</li>
<li>Unidades enviadas: {unidadesEnviadas}</li>
<li>Unidades en envíos no finalizados: {unidadesPendientes}</li>
</ul>
</div>`;
const unidades_pendientes = parseInt(response.data.total_unidades) -
parseInt(response.data.unidades_enviadas) - parseInt(response.data.unidades_envio);
const textFinal = text.replace('{unidadesTotal}', response.data.total_unidades)
.replace('{unidadesEnvio}', response.data.unidades_envio)
.replace('{unidadesEnviadas}', response.data.unidades_enviadas)
.replace('{unidadesPendientes}', unidades_pendientes);
Swal.fire({
title: 'Atención!',
html: textFinal,
icon: 'info',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
}
this.table.draw();
this.buscarPedidos.empty();
} else {
Swal.fire({
title: 'Atención!',
text: response.message,
icon: 'info',
showCancelButton: false,
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
}
}, (error) => {
console.error(error);
}).get();
}
_calcularSiguienteNumeroCaja() {
const cajasUsadas = new Set();
this.table.rows().every(function () {
const data = this.data();
const caja = data.cajas;
if (caja !== null && caja !== '' && !isNaN(parseInt(caja))) {
cajasUsadas.add(parseInt(caja));
}
});
// Buscar el menor número libre empezando desde 1
let i = 1;
while (cajasUsadas.has(i)) {
i++;
}
return i;
}
_reordenarCajas() {
const table = this.table;
const mapaOriginalANuevo = {};
const cajasDetectadas = [];
// 1. Recolectar cajas distintas en orden
table.rows().every(function () {
const data = this.data();
const caja = data.cajas;
if (caja !== null && caja !== '' && !isNaN(parseInt(caja))) {
const cajaNum = parseInt(caja);
if (!cajasDetectadas.includes(cajaNum)) {
cajasDetectadas.push(cajaNum);
}
}
});
cajasDetectadas.sort((a, b) => a - b);
// 2. Construir mapa de renumeración
cajasDetectadas.forEach((valorOriginal, idx) => {
mapaOriginalANuevo[valorOriginal] = idx + 1;
});
// 3. Aplicar cambios si hace falta
table.rows().every(function () {
const data = this.data();
const original = parseInt(data.cajas);
const nuevo = mapaOriginalANuevo[original];
if (original !== nuevo) {
data.cajas = nuevo;
// Persistir en backend
$.post('/logistica/updateCajaLinea', {
id: data.id,
caja: nuevo
});
this.data(data).invalidate();
}
});
// 4. Actualizar contador interno
this.contadorCajas = cajasDetectadas.length + 1;
table.draw(false);
}
}
document.addEventListener('DOMContentLoaded', function () {
new EnvioEdit().init();
});
export default EnvioEdit;