feat(fsm): implementar gestion y asignacion de sets de herramientas a tecnicos

This commit is contained in:
2026-10-31 17:07:30 -05:00
parent 06ef042538
commit c07162c375
13 changed files with 1793 additions and 9 deletions
+214
View File
@@ -5,6 +5,9 @@ const { isCompanyAdmin } = require('../middleware/auth');
const User = require('../models/User');
const Department = require('../models/Department');
const Ticket = require('../models/Ticket');
const Herramienta = require('../models/Herramienta');
const HerramientaSet = require('../models/HerramientaSet');
const HerramientaAsignacion = require('../models/HerramientaAsignacion');
router.get('/dashboard', isCompanyAdmin, async (req, res) => {
try {
@@ -150,4 +153,215 @@ router.post('/departments/delete/:id', isCompanyAdmin, async (req, res) => {
}
});
// ==========================================
// GESTIÓN DE HERRAMIENTAS Y SETS / KITS FSM
// ==========================================
router.get('/herramientas', isCompanyAdmin, async (req, res) => {
try {
const companyId = req.session.user.company_id;
const [herramientas, sets, asignaciones, stats, allUsers] = await Promise.all([
Herramienta.findAll(companyId),
HerramientaSet.findAll(companyId),
HerramientaAsignacion.findAll(companyId),
Herramienta.countByEstado(companyId),
User.findAll(companyId)
]);
const tecnicos = allUsers.filter(u => u.rol === 'agent' || u.rol === 'admin');
res.render('admin/herramientas', {
title: 'Herramientas & Sets',
herramientas,
sets,
asignaciones,
stats,
tecnicos
});
} catch (error) {
console.error('Error al cargar herramientas:', error);
req.flash('error_msg', 'Error al cargar gestión de herramientas');
res.redirect('/admin/dashboard');
}
});
// Crear Herramienta Individual
router.post('/herramientas/create', isCompanyAdmin, async (req, res) => {
const { nombre, codigo, numero_serie, categoria, marca, modelo, estado, ubicacion_bodega, notas } = req.body;
if (!nombre) {
req.flash('error_msg', 'El nombre de la herramienta es obligatorio');
return res.redirect('/admin/herramientas');
}
try {
await Herramienta.create({
company_id: req.session.user.company_id,
nombre,
codigo: codigo || null,
numero_serie: numero_serie || null,
categoria: categoria || 'general',
marca: marca || null,
modelo: modelo || null,
estado: estado || 'operativo',
ubicacion_bodega: ubicacion_bodega || null,
notas: notas || null
});
req.flash('success_msg', `Herramienta "${nombre}" registrada correctamente`);
res.redirect('/admin/herramientas#tab-herramientas');
} catch (error) {
console.error('Error al crear herramienta:', error);
req.flash('error_msg', 'Error al registrar la herramienta: ' + error.message);
res.redirect('/admin/herramientas');
}
});
// Editar Herramienta Individual
router.post('/herramientas/edit/:id', isCompanyAdmin, async (req, res) => {
const { nombre, codigo, numero_serie, categoria, marca, modelo, estado, ubicacion_bodega, notas } = req.body;
try {
await Herramienta.update(req.params.id, req.session.user.company_id, {
nombre,
codigo,
numero_serie,
categoria,
marca,
modelo,
estado,
ubicacion_bodega,
notas
});
req.flash('success_msg', 'Herramienta actualizada exitosamente');
res.redirect('/admin/herramientas#tab-herramientas');
} catch (error) {
console.error('Error al actualizar herramienta:', error);
req.flash('error_msg', 'Error al actualizar herramienta: ' + error.message);
res.redirect('/admin/herramientas');
}
});
// Eliminar Herramienta Individual
router.post('/herramientas/delete/:id', isCompanyAdmin, async (req, res) => {
try {
await Herramienta.delete(req.params.id, req.session.user.company_id);
req.flash('success_msg', 'Herramienta eliminada');
res.redirect('/admin/herramientas#tab-herramientas');
} catch (error) {
console.error('Error al eliminar herramienta:', error);
req.flash('error_msg', 'Error al eliminar herramienta');
res.redirect('/admin/herramientas');
}
});
// Crear Set / Kit de Herramientas
router.post('/herramientas/sets/create', isCompanyAdmin, async (req, res) => {
const { nombre, codigo, descripcion, categoria, herramientas_ids } = req.body;
if (!nombre) {
req.flash('error_msg', 'El nombre del Set / Kit es obligatorio');
return res.redirect('/admin/herramientas');
}
try {
let items = [];
if (Array.isArray(herramientas_ids)) {
items = herramientas_ids;
} else if (herramientas_ids) {
items = [herramientas_ids];
}
await HerramientaSet.create({
company_id: req.session.user.company_id,
nombre,
codigo: codigo || null,
descripcion: descripcion || null,
categoria: categoria || 'general'
}, items);
req.flash('success_msg', `Kit de herramientas "${nombre}" creado con ${items.length} instrumentos.`);
res.redirect('/admin/herramientas#tab-sets');
} catch (error) {
console.error('Error al crear set de herramientas:', error);
req.flash('error_msg', 'Error al crear set: ' + error.message);
res.redirect('/admin/herramientas');
}
});
// Editar Set / Kit de Herramientas
router.post('/herramientas/sets/edit/:id', isCompanyAdmin, async (req, res) => {
const { nombre, codigo, descripcion, categoria, is_active, herramientas_ids } = req.body;
try {
let items = null;
if (herramientas_ids !== undefined) {
items = Array.isArray(herramientas_ids) ? herramientas_ids : (herramientas_ids ? [herramientas_ids] : []);
}
await HerramientaSet.update(req.params.id, req.session.user.company_id, {
nombre,
codigo,
descripcion,
categoria,
is_active: is_active === '1' || is_active === 1 ? 1 : 0
}, items);
req.flash('success_msg', 'Set / Kit actualizado exitosamente');
res.redirect('/admin/herramientas#tab-sets');
} catch (error) {
console.error('Error al actualizar set:', error);
req.flash('error_msg', 'Error al actualizar set: ' + error.message);
res.redirect('/admin/herramientas');
}
});
// Eliminar Set / Kit de Herramientas
router.post('/herramientas/sets/delete/:id', isCompanyAdmin, async (req, res) => {
try {
await HerramientaSet.delete(req.params.id, req.session.user.company_id);
req.flash('success_msg', 'Set / Kit eliminado');
res.redirect('/admin/herramientas#tab-sets');
} catch (error) {
console.error('Error al eliminar set:', error);
req.flash('error_msg', 'Error al eliminar set');
res.redirect('/admin/herramientas');
}
});
// Asignar Set de Herramientas a Técnico (Dotación Fija)
router.post('/herramientas/asignar', isCompanyAdmin, async (req, res) => {
const { tecnico_id, set_id, herramienta_id, tipo_asignacion, observaciones_entrega } = req.body;
if (!tecnico_id || (!set_id && !herramienta_id)) {
req.flash('error_msg', 'Debe seleccionar un técnico y al menos un set o herramienta');
return res.redirect('/admin/herramientas');
}
try {
await HerramientaAsignacion.create({
company_id: req.session.user.company_id,
tecnico_id: parseInt(tecnico_id),
set_id: set_id ? parseInt(set_id) : null,
herramienta_id: herramienta_id ? parseInt(herramienta_id) : null,
tipo_asignacion: tipo_asignacion || 'dotacion_fija',
observaciones_entrega: observaciones_entrega || 'Asignación administrativa de equipamiento',
asignado_por: req.session.user.id
});
req.flash('success_msg', 'Equipamiento asignado al técnico exitosamente');
res.redirect('/admin/herramientas#tab-asignaciones');
} catch (error) {
console.error('Error al asignar herramientas:', error);
req.flash('error_msg', 'Error al asignar equipamiento: ' + error.message);
res.redirect('/admin/herramientas');
}
});
// Registrar Devolución de Herramientas
router.post('/herramientas/devolver/:id', isCompanyAdmin, async (req, res) => {
const { observaciones_devolucion, estado } = req.body;
try {
await HerramientaAsignacion.devolver(req.params.id, req.session.user.company_id, {
observaciones_devolucion: observaciones_devolucion || 'Devuelto conforme a bodega',
estado: estado || 'devuelto'
});
req.flash('success_msg', 'Devolución de herramientas registrada correctamente');
res.redirect('/admin/herramientas#tab-asignaciones');
} catch (error) {
console.error('Error al registrar devolución:', error);
req.flash('error_msg', 'Error al registrar devolución');
res.redirect('/admin/herramientas');
}
});
module.exports = router;