181 lines
6.7 KiB
JavaScript
181 lines
6.7 KiB
JavaScript
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;
|