feat(herramientas): impresion de etiquetas QR y manifiesto HTML responsive para escaneo de cajas de herramientas
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const db = require('../config/db');
|
||||
const crypto = require('crypto');
|
||||
|
||||
class HerramientaSet {
|
||||
static async findAll(companyId) {
|
||||
@@ -27,10 +28,45 @@ class HerramientaSet {
|
||||
);
|
||||
if (!rows[0]) return null;
|
||||
const set = rows[0];
|
||||
|
||||
if (!set.qr_token) {
|
||||
set.qr_token = crypto.randomBytes(12).toString('hex');
|
||||
await db.query('UPDATE herramientas_sets SET qr_token = ? WHERE id = ?', [set.qr_token, set.id]);
|
||||
}
|
||||
|
||||
set.herramientas = await this.getItems(set.id);
|
||||
return set;
|
||||
}
|
||||
|
||||
static async findByToken(token) {
|
||||
if (!token) return null;
|
||||
const [rows] = await db.query(
|
||||
`SELECT hs.*, c.name as company_name, c.plan as company_plan
|
||||
FROM herramientas_sets hs
|
||||
INNER JOIN companies c ON hs.company_id = c.id
|
||||
WHERE hs.qr_token = ?`,
|
||||
[token]
|
||||
);
|
||||
if (!rows[0]) return null;
|
||||
const set = rows[0];
|
||||
set.herramientas = await this.getItems(set.id);
|
||||
|
||||
// Obtener asignación activa de custodia si existe
|
||||
const [custodia] = await db.query(
|
||||
`SELECT tha.*, u.nombre as tecnico_nombre, u.email as tecnico_email,
|
||||
tv.titulo as visita_titulo, tv.ticket_id, t.asunto as ticket_asunto
|
||||
FROM tecnico_herramientas_asignaciones tha
|
||||
INNER JOIN users u ON tha.tecnico_id = u.id
|
||||
LEFT JOIN ticket_visitas tv ON tha.ticket_visita_id = tv.id
|
||||
LEFT JOIN tickets t ON tv.ticket_id = t.id
|
||||
WHERE tha.set_id = ? AND tha.estado = 'asignado'
|
||||
ORDER BY tha.id DESC LIMIT 1`,
|
||||
[set.id]
|
||||
);
|
||||
set.custodia = custodia[0] || null;
|
||||
return set;
|
||||
}
|
||||
|
||||
static async getItems(setId) {
|
||||
const [items] = await db.query(
|
||||
`SELECT h.*, hsi.cantidad
|
||||
@@ -51,13 +87,16 @@ class HerramientaSet {
|
||||
descripcion = null,
|
||||
categoria = 'general',
|
||||
foto_url = null,
|
||||
qr_token = null,
|
||||
is_active = 1
|
||||
} = data;
|
||||
|
||||
const finalQrToken = qr_token || crypto.randomBytes(12).toString('hex');
|
||||
|
||||
const [res] = await db.query(
|
||||
`INSERT INTO herramientas_sets (company_id, nombre, codigo, descripcion, categoria, foto_url, is_active)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||
[company_id, nombre, codigo, descripcion, categoria, foto_url, is_active]
|
||||
`INSERT INTO herramientas_sets (company_id, nombre, codigo, qr_token, descripcion, categoria, foto_url, is_active)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[company_id, nombre, codigo, finalQrToken, descripcion, categoria, foto_url, is_active]
|
||||
);
|
||||
const setId = res.insertId;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user