feat(herramientas): impresion de etiquetas QR y manifiesto HTML responsive para escaneo de cajas de herramientas

This commit is contained in:
2026-11-01 09:13:39 -05:00
parent 83cbfcefa8
commit e71e531b51
15 changed files with 1252 additions and 22 deletions
+52 -3
View File
@@ -1,4 +1,5 @@
const db = require('../config/db');
const crypto = require('crypto');
class HerramientaAsignacion {
static async findAll(companyId, filtros = {}) {
@@ -70,6 +71,51 @@ class HerramientaAsignacion {
return rows[0] || null;
}
static async findByToken(token) {
if (!token) return null;
const [rows] = await db.query(
`SELECT tha.*,
u.nombre as tecnico_nombre,
u.email as tecnico_email,
c.name as company_name,
hs.nombre as set_nombre,
hs.codigo as set_codigo,
hs.foto_url as set_foto_url,
h.nombre as herramienta_nombre,
h.codigo as herramienta_codigo,
h.foto_url as herramienta_foto_url,
tv.titulo as visita_titulo,
tv.ticket_id,
t.asunto as ticket_asunto,
adm.nombre as asignado_por_nombre
FROM tecnico_herramientas_asignaciones tha
INNER JOIN users u ON tha.tecnico_id = u.id
INNER JOIN companies c ON tha.company_id = c.id
LEFT JOIN herramientas_sets hs ON tha.set_id = hs.id
LEFT JOIN herramientas h ON tha.herramienta_id = h.id
LEFT JOIN ticket_visitas tv ON tha.ticket_visita_id = tv.id
LEFT JOIN tickets t ON tv.ticket_id = t.id
LEFT JOIN users adm ON tha.asignado_por = adm.id
WHERE tha.qr_token = ?`,
[token]
);
if (!rows[0]) return null;
const asig = rows[0];
if (asig.set_id) {
const HerramientaSet = require('./HerramientaSet');
asig.herramientas = await HerramientaSet.getItems(asig.set_id);
} else if (asig.herramienta_id) {
const Herramienta = require('./Herramienta');
const tool = await Herramienta.findById(asig.herramienta_id, asig.company_id);
asig.herramientas = tool ? [tool] : [];
} else {
asig.herramientas = [];
}
return asig;
}
static async create(data) {
const {
company_id,
@@ -81,14 +127,17 @@ class HerramientaAsignacion {
fecha_asignacion = new Date(),
observaciones_entrega = null,
foto_entrega_url = null,
qr_token = null,
asignado_por = null
} = data;
const finalQrToken = qr_token || crypto.randomBytes(12).toString('hex');
const [res] = await db.query(
`INSERT INTO tecnico_herramientas_asignaciones
(company_id, tecnico_id, set_id, herramienta_id, ticket_visita_id, tipo_asignacion, fecha_asignacion, estado, observaciones_entrega, foto_entrega_url, asignado_por)
VALUES (?, ?, ?, ?, ?, ?, ?, 'asignado', ?, ?, ?)`,
[company_id, tecnico_id, set_id, herramienta_id, ticket_visita_id, tipo_asignacion, fecha_asignacion, observaciones_entrega, foto_entrega_url, asignado_por]
(company_id, tecnico_id, set_id, herramienta_id, ticket_visita_id, tipo_asignacion, qr_token, fecha_asignacion, estado, observaciones_entrega, foto_entrega_url, asignado_por)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'asignado', ?, ?, ?)`,
[company_id, tecnico_id, set_id, herramienta_id, ticket_visita_id, tipo_asignacion, finalQrToken, fecha_asignacion, observaciones_entrega, foto_entrega_url, asignado_por]
);
return res.insertId;
}