actas: unidades HBOX completas seleccionables (desde ensamble aprobado) + revisión de daño por componente

This commit is contained in:
Leopoldo Rodríguez 2026-09-30 11:10:29 -06:00
parent 71c825b992
commit a6f4a4c943
3 changed files with 30 additions and 4 deletions

View File

@ -96,6 +96,7 @@
grupos[g].forEach(u => og.append($('option', { value: u.serie, text: u.etiqueta || (u.serie + (u.maquina ? ' · ' + u.maquina : '')) }))); grupos[g].forEach(u => og.append($('option', { value: u.serie, text: u.etiqueta || (u.serie + (u.maquina ? ' · ' + u.maquina : '')) })));
serieSel.append(og); serieSel.append(og);
}); });
if (!cfg.sinEnsambladas) cargarEnsambladas();
serieSel.append($('option', { value: '__OTRA__', text: '➕ Otra unidad (no está en la lista)' })); serieSel.append($('option', { value: '__OTRA__', text: '➕ Otra unidad (no está en la lista)' }));
serieSel.append($('option', { value: 'CAMPO-PRUEBA', text: '⚙ PRUEBA (no cuenta)' })); serieSel.append($('option', { value: 'CAMPO-PRUEBA', text: '⚙ PRUEBA (no cuenta)' }));
const dS = $('div'); dS.append($('label', { text: cfg.etiquetaSerie || 'Unidad' }), serieSel, serieOtra, fichaUnidad); const dS = $('div'); dS.append($('label', { text: cfg.etiquetaSerie || 'Unidad' }), serieSel, serieOtra, fichaUnidad);
@ -140,7 +141,10 @@
if (cfg.tipo === 'dano') return; if (cfg.tipo === 'dano') return;
// En un acta compuesta (ensamble, integración) se revisa CADA módulo elegido, no solo // En un acta compuesta (ensamble, integración) se revisa CADA módulo elegido, no solo
// la unidad calculada: una tarjeta con corto no debe poder entrar a un ensamble. // la unidad calculada: una tarjeta con corto no debe poder entrar a un ensamble.
const series = compuesta ? Object.values(seleccion()).filter(v => v) : [serieActual()]; // Una unidad HBOX completa también se revisa pieza por pieza (tarjeta, ArduSimple, módem).
const u = compuesta ? null : unidadSel();
const series = compuesta ? Object.values(seleccion()).filter(v => v)
: [serieActual()].concat(u && u.componentes ? Object.values(u.componentes) : []);
const aRevisar = series.filter(v => v && !esPrueba(v)); const aRevisar = series.filter(v => v && !esPrueba(v));
if (!aRevisar.length) return; if (!aRevisar.length) return;
const avisos = []; const avisos = [];
@ -163,6 +167,28 @@
}).join('<hr style="border:0;border-top:1px solid currentColor;opacity:.3;margin:8px 0">'); }).join('<hr style="border:0;border-top:1px solid currentColor;opacity:.3;margin:8px 0">');
} }
// Unidades HBOX completas: salen de las actas de ensamble aprobadas y van primero en la lista,
// para que envío, recepción, daño, banco… puedan elegir la unidad entera y no solo sus piezas.
async function cargarEnsambladas() {
let j = null;
try { j = await (await fetch('/api/actas', { cache: 'no-store' })).json(); } catch (e) { return; }
const vistas = new Set(cfg.unidades.map(u => u.serie));
const us = (j && j.actas || []).filter(a => a.tipo === 'ensamble' && a.resultado === 'OK' && a.serie
&& !esPrueba(a.serie) && !vistas.has(a.serie) && vistas.add(a.serie));
if (!us.length) return;
const og = $('optgroup', { label: 'Unidades HBOX completas' });
us.sort((x, y) => x.serie < y.serie ? -1 : 1).forEach(a => {
const c = a.componentes || {};
const piezas = Object.values(c).filter(Boolean).join(' · ');
const u = { serie: a.serie, terminal: 'Unidades HBOX completas', componentes: c,
etiqueta: a.serie + (piezas ? ' (' + piezas + ')' : ''),
nota: 'Unidad completa' + (piezas ? ': ' + piezas : '') + '.' };
cfg.unidades.push(u);
og.append($('option', { value: u.serie, text: u.etiqueta }));
});
serieSel.insertBefore(og, serieSel.children[1] || null);
}
// selección actual de componentes -> {clave: valor} // selección actual de componentes -> {clave: valor}
function seleccion() { const s = {}; for (const k in compSel) s[k] = compSel[k].value; return s; } function seleccion() { const s = {}; for (const k in compSel) s[k] = compSel[k].value; return s; }
function unidadSel() { function unidadSel() {
@ -645,7 +671,7 @@
if (flota) { if (flota) {
serieOtra.style.display = serieSel.value === '__OTRA__' ? '' : 'none'; serieOtra.style.display = serieSel.value === '__OTRA__' ? '' : 'none';
const u = unidadSel(); const u = unidadSel();
fichaUnidad.innerHTML = u fichaUnidad.innerHTML = u && u.componentes ? u.nota : u
? '<b>' + (u.maquina || '—') + '</b> · ' + (u.terminal || '—') + (u.nota ? '<br>' + u.nota : '') ? '<b>' + (u.maquina || '—') + '</b> · ' + (u.terminal || '—') + (u.nota ? '<br>' + u.nota : '')
: ''; : '';
} }

View File

@ -21,7 +21,7 @@ Acta.render({
tecnicoDesdeUsuario: true, tecnicoDesdeUsuario: true,
nombres: { alan: 'Alán Basurto', daniel: 'Daniel Martínez', leo: 'Leo Rodríguez' }, nombres: { alan: 'Alán Basurto', daniel: 'Daniel Martínez', leo: 'Leo Rodríguez' },
unidades: window.SERIES, unidades: window.SERIES,
etiquetaSerie: 'Unidad que se envía', etiquetaSerie: 'Unidad HBOX o componente que se envía',
titulo: 'Acta de envío', titulo: 'Acta de envío',
subtitulo: 'Se llena al cerrar la caja. Procedimiento: Ciclo de vida §6.', subtitulo: 'Se llena al cerrar la caja. Procedimiento: Ciclo de vida §6.',
intro: 'Fija cómo salió la unidad (firmware, SIM, contenido, fotos). La recepción se compara contra esta acta.', intro: 'Fija cómo salió la unidad (firmware, SIM, contenido, fotos). La recepción se compara contra esta acta.',

View File

@ -24,7 +24,7 @@ Acta.render({
tecnicoDesdeUsuario: true, tecnicoDesdeUsuario: true,
nombres: { alan: 'Alán Basurto', daniel: 'Daniel Martínez', leo: 'Leo Rodríguez' }, nombres: { alan: 'Alán Basurto', daniel: 'Daniel Martínez', leo: 'Leo Rodríguez' },
unidades: window.SERIES, unidades: window.SERIES,
etiquetaSerie: 'Unidad que se recibe', etiquetaSerie: 'Unidad HBOX o componente que se recibe',
titulo: 'Acta de recepción e inspección', titulo: 'Acta de recepción e inspección',
subtitulo: 'Una por unidad, al abrir la caja y antes de entrar al puerto. Procedimiento: Ciclo de vida §7.', subtitulo: 'Una por unidad, al abrir la caja y antes de entrar al puerto. Procedimiento: Ciclo de vida §7.',
textoOK: 'LISTA PARA ENTRAR', textoOK: 'LISTA PARA ENTRAR',