const express = require('express'); const { authRequired } = require('../middleware/auth'); const { requireRole } = require('../middleware/rbac'); const { getCentralPool } = require('../db/central'); const { provisionTenant } = require('../services/tenantProvision'); const { getTenantPool } = require('../db/tenant'); const { hashPassword } = require('../utils/password'); const { getParticipationSummary } = require('../services/participationService'); const router = express.Router(); router.get('/companies', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const central = getCentralPool(); const [rows] = await central.query('SELECT id, name, code, status, start_date, end_date, db_host, db_port, db_name, created_at FROM companies ORDER BY id DESC'); res.json(rows); } catch (err) { next(err); } }); router.post('/companies', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const { name, code, start_date, end_date, db_name, db_host, db_port, db_user, db_pass, admin_name, admin_email, admin_password } = req.body; if (!name || !code || !db_name || !db_host || !db_user || !db_pass || !admin_name || !admin_email || !admin_password) { return res.status(400).json({ error: 'Faltan campos requeridos' }); } if (!start_date || !end_date) { return res.status(400).json({ error: 'Fecha inicio y fin son obligatorias' }); } if (start_date > end_date) { return res.status(400).json({ error: 'Fecha inicio no puede ser mayor que fecha fin' }); } await provisionTenant({ name, code, dbName: db_name, dbHost: db_host, dbPort: db_port || 3306, dbUser: db_user, dbPass: db_pass, adminName: admin_name, adminEmail: admin_email, adminPassword: admin_password, startDate: start_date, endDate: end_date }); res.json({ ok: true }); } catch (err) { next(err); } }); router.patch('/companies/:id/status', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const { status } = req.body; if (!['active', 'suspended'].includes(status)) { return res.status(400).json({ error: 'Estado inválido' }); } const central = getCentralPool(); await central.query('UPDATE companies SET status = ? WHERE id = ?', [status, req.params.id]); res.json({ ok: true }); } catch (err) { next(err); } }); router.patch('/companies/:id/dates', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const { start_date, end_date } = req.body; if (!start_date || !end_date) { return res.status(400).json({ error: 'Fecha inicio y fin son obligatorias' }); } if (start_date > end_date) { return res.status(400).json({ error: 'Fecha inicio no puede ser mayor que fecha fin' }); } const central = getCentralPool(); await central.query('UPDATE companies SET start_date = ?, end_date = ? WHERE id = ?', [ start_date || null, end_date || null, req.params.id ]); res.json({ ok: true }); } catch (err) { next(err); } }); router.get('/companies/:id/participation', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const central = getCentralPool(); const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]); if (!company) return res.status(404).json({ error: 'Empresa no encontrada' }); const tenantPool = getTenantPool(company); const participation = await getParticipationSummary(tenantPool); res.json({ company_id: company.id, participation }); } catch (err) { next(err); } }); router.delete('/companies/:id', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const central = getCentralPool(); const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]); if (!company) return res.status(404).json({ error: 'Empresa no encontrada' }); const tenantPool = getTenantPool(company); const [[{ periods }]] = await tenantPool.query('SELECT COUNT(*) AS periods FROM survey_periods'); const [[{ responses }]] = await tenantPool.query('SELECT COUNT(*) AS responses FROM responses'); if (periods > 0 || responses > 0) { return res.status(400).json({ error: 'No se puede eliminar: existen encuestas registradas' }); } await central.query('DROP DATABASE IF EXISTS `' + company.db_name + '`'); await central.query('DELETE FROM companies WHERE id = ?', [company.id]); res.json({ ok: true }); } catch (err) { next(err); } }); router.post('/companies/:id/admins', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const { name, email, password } = req.body; if (!name || !email || !password) { return res.status(400).json({ error: 'Nombre, email y password requeridos' }); } const central = getCentralPool(); const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]); if (!company) return res.status(404).json({ error: 'Empresa no encontrada' }); const tenantPool = getTenantPool(company); const passwordHash = await hashPassword(password); await tenantPool.query( 'INSERT INTO admins (name, email, password_hash, role, status) VALUES (?, ?, ?, "admin", "active")', [name, email, passwordHash] ); res.json({ ok: true }); } catch (err) { next(err); } }); router.get('/companies/:id/admins', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const central = getCentralPool(); const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]); if (!company) return res.status(404).json({ error: 'Empresa no encontrada' }); const tenantPool = getTenantPool(company); const [rows] = await tenantPool.query('SELECT id, name, email, status, created_at FROM admins ORDER BY id DESC'); res.json(rows); } catch (err) { next(err); } }); router.patch('/companies/:id/admins/:adminId/status', authRequired, requireRole('superadmin'), async (req, res, next) => { try { const { status } = req.body; if (!['active', 'inactive'].includes(status)) { return res.status(400).json({ error: 'Estado inválido' }); } const central = getCentralPool(); const [[company]] = await central.query('SELECT * FROM companies WHERE id = ?', [req.params.id]); if (!company) return res.status(404).json({ error: 'Empresa no encontrada' }); const tenantPool = getTenantPool(company); await tenantPool.query('UPDATE admins SET status = ? WHERE id = ?', [status, req.params.adminId]); res.json({ ok: true }); } catch (err) { next(err); } }); module.exports = router;