Actualizar server.js

This commit is contained in:
2026-02-08 14:59:32 +00:00
parent 9e2ac9e072
commit 6fcc2efe44

131
server.js
View File

@@ -29,14 +29,14 @@ const pool = new Pool({
}); });
// ========================================== // ==========================================
// 🧠 AUTO-ACTUALIZACIÓN DB // 🧠 AUTO-ACTUALIZACIÓN DB (REPARADOR DEEP)
// ========================================== // ==========================================
async function autoUpdateDB() { async function autoUpdateDB() {
const client = await pool.connect(); const client = await pool.connect();
try { try {
console.log("🔄 Verificando salud de la base de datos..."); console.log("🔄 Verificando salud de la base de datos...");
// 1. CREAR TABLAS (Estructura Base) // 1. DEFINICIÓN BASE (Para instalaciones nuevas)
await client.query(` await client.query(`
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
@@ -106,8 +106,8 @@ async function autoUpdateDB() {
owner_id INT REFERENCES users(id) ON DELETE CASCADE, owner_id INT REFERENCES users(id) ON DELETE CASCADE,
client_id INT REFERENCES clients(id) ON DELETE SET NULL, client_id INT REFERENCES clients(id) ON DELETE SET NULL,
status_id INT REFERENCES service_statuses(id) ON DELETE SET NULL, status_id INT REFERENCES service_statuses(id) ON DELETE SET NULL,
guild_id INT REFERENCES guilds(id) ON DELETE SET NULL, -- NUEVO guild_id INT REFERENCES guilds(id) ON DELETE SET NULL,
assigned_to INT REFERENCES users(id) ON DELETE SET NULL, -- NUEVO assigned_to INT REFERENCES users(id) ON DELETE SET NULL,
title TEXT, title TEXT,
description TEXT, description TEXT,
contact_phone TEXT, contact_phone TEXT,
@@ -137,40 +137,94 @@ async function autoUpdateDB() {
); );
`); `);
// 2. PARCHE DE REPARACIÓN // 2. PARCHE DE REPARACIÓN MANUAL (AQUÍ ESTÁ LA SOLUCIÓN)
// Este bloque fuerza la creación de columnas si no existen
await client.query(` await client.query(`
DO $$ DO $$
BEGIN BEGIN
-- Nuevas columnas Asignación -- Client ID
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='guild_id') THEN ALTER TABLE services ADD COLUMN guild_id INT REFERENCES guilds(id) ON DELETE SET NULL; END IF; IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='client_id') THEN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='assigned_to') THEN ALTER TABLE services ADD COLUMN assigned_to INT REFERENCES users(id) ON DELETE SET NULL; END IF; ALTER TABLE services ADD COLUMN client_id INT REFERENCES clients(id) ON DELETE SET NULL;
END IF;
-- Reparaciones anteriores -- Status ID
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='email') THEN ALTER TABLE services ADD COLUMN email TEXT; END IF; IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='status_id') THEN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='address') THEN ALTER TABLE services ADD COLUMN address TEXT; END IF; ALTER TABLE services ADD COLUMN status_id INT REFERENCES service_statuses(id) ON DELETE SET NULL;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='description') THEN ALTER TABLE services ADD COLUMN description TEXT; END IF; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='title') THEN ALTER TABLE services ADD COLUMN title TEXT; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='client_id') THEN ALTER TABLE services ADD COLUMN client_id INT REFERENCES clients(id) ON DELETE SET NULL; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='status_id') THEN ALTER TABLE services ADD COLUMN status_id INT REFERENCES service_statuses(id) ON DELETE SET NULL; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='contact_phone') THEN ALTER TABLE services ADD COLUMN contact_phone TEXT; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='contact_name') THEN ALTER TABLE services ADD COLUMN contact_name TEXT; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='scheduled_date') THEN ALTER TABLE services ADD COLUMN scheduled_date DATE DEFAULT CURRENT_DATE; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='scheduled_time') THEN ALTER TABLE services ADD COLUMN scheduled_time TIME DEFAULT CURRENT_TIME; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='duration_minutes') THEN ALTER TABLE services ADD COLUMN duration_minutes INT DEFAULT 30; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='company_id') THEN ALTER TABLE services ADD COLUMN company_id INT REFERENCES companies(id) ON DELETE SET NULL; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='is_company') THEN ALTER TABLE services ADD COLUMN is_company BOOLEAN DEFAULT FALSE; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='company_ref') THEN ALTER TABLE services ADD COLUMN company_ref TEXT; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='internal_notes') THEN ALTER TABLE services ADD COLUMN internal_notes TEXT; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='client_notes') THEN ALTER TABLE services ADD COLUMN client_notes TEXT; END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='is_urgent') THEN ALTER TABLE services ADD COLUMN is_urgent BOOLEAN DEFAULT FALSE; END IF;
-- Guild ID & Assigned To
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='guild_id') THEN
ALTER TABLE services ADD COLUMN guild_id INT REFERENCES guilds(id) ON DELETE SET NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='assigned_to') THEN
ALTER TABLE services ADD COLUMN assigned_to INT REFERENCES users(id) ON DELETE SET NULL;
END IF;
-- Contact Info
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='contact_phone') THEN
ALTER TABLE services ADD COLUMN contact_phone TEXT;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='contact_name') THEN
ALTER TABLE services ADD COLUMN contact_name TEXT;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='address') THEN
ALTER TABLE services ADD COLUMN address TEXT;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='email') THEN
ALTER TABLE services ADD COLUMN email TEXT;
END IF;
-- Details
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='title') THEN
ALTER TABLE services ADD COLUMN title TEXT;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='description') THEN
ALTER TABLE services ADD COLUMN description TEXT;
END IF;
-- Scheduling
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='scheduled_date') THEN
ALTER TABLE services ADD COLUMN scheduled_date DATE DEFAULT CURRENT_DATE;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='scheduled_time') THEN
ALTER TABLE services ADD COLUMN scheduled_time TIME DEFAULT CURRENT_TIME;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='duration_minutes') THEN
ALTER TABLE services ADD COLUMN duration_minutes INT DEFAULT 30;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='is_urgent') THEN
ALTER TABLE services ADD COLUMN is_urgent BOOLEAN DEFAULT FALSE;
END IF;
-- Company & Notes
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='company_id') THEN
ALTER TABLE services ADD COLUMN company_id INT REFERENCES companies(id) ON DELETE SET NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='is_company') THEN
ALTER TABLE services ADD COLUMN is_company BOOLEAN DEFAULT FALSE;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='company_ref') THEN
ALTER TABLE services ADD COLUMN company_ref TEXT;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='internal_notes') THEN
ALTER TABLE services ADD COLUMN internal_notes TEXT;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='services' AND column_name='client_notes') THEN
ALTER TABLE services ADD COLUMN client_notes TEXT;
END IF;
-- Clean up old constraints
BEGIN ALTER TABLE users DROP CONSTRAINT IF EXISTS users_phone_key; EXCEPTION WHEN OTHERS THEN NULL; END; BEGIN ALTER TABLE users DROP CONSTRAINT IF EXISTS users_phone_key; EXCEPTION WHEN OTHERS THEN NULL; END;
BEGIN ALTER TABLE users DROP CONSTRAINT IF EXISTS users_email_key; EXCEPTION WHEN OTHERS THEN NULL; END; BEGIN ALTER TABLE users DROP CONSTRAINT IF EXISTS users_email_key; EXCEPTION WHEN OTHERS THEN NULL; END;
END $$; END $$;
`); `);
console.log("✅ DB Lista."); console.log("✅ DB Sincronizada y Reparada Exitosamente.");
} catch (e) { console.error("❌ Error DB:", e); } finally { client.release(); } } catch (e) {
console.error("❌ Error DB:", e);
} finally {
client.release();
}
} }
// HELPERS // HELPERS
@@ -247,16 +301,11 @@ app.get("/clients/search", authMiddleware, async (req, res) => {
app.get("/companies", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT * FROM companies WHERE owner_id=$1 ORDER BY name ASC", [req.user.accountId]); res.json({ ok: true, companies: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } }); app.get("/companies", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT * FROM companies WHERE owner_id=$1 ORDER BY name ASC", [req.user.accountId]); res.json({ ok: true, companies: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } });
app.post("/companies", authMiddleware, async (req, res) => { try { const { name } = req.body; await pool.query("INSERT INTO companies (name, owner_id) VALUES ($1, $2)", [name, req.user.accountId]); res.json({ ok: true }); } catch (e) { res.status(500).json({ ok: false }); } }); app.post("/companies", authMiddleware, async (req, res) => { try { const { name } = req.body; await pool.query("INSERT INTO companies (name, owner_id) VALUES ($1, $2)", [name, req.user.accountId]); res.json({ ok: true }); } catch (e) { res.status(500).json({ ok: false }); } });
// NUEVO: OBTENER OPERARIOS FILTRADOS POR GREMIO // OBTENER OPERARIOS POR GREMIO
app.get("/operators", authMiddleware, async (req, res) => { app.get("/operators", authMiddleware, async (req, res) => {
try { try {
const { guild_id } = req.query; const { guild_id } = req.query;
let query = ` let query = `SELECT u.id, u.full_name FROM users u JOIN user_guilds ug ON u.id = ug.user_id WHERE u.owner_id = $1 AND u.role = 'operario'`;
SELECT u.id, u.full_name
FROM users u
JOIN user_guilds ug ON u.id = ug.user_id
WHERE u.owner_id = $1 AND u.role = 'operario'
`;
const params = [req.user.accountId]; const params = [req.user.accountId];
if (guild_id) { query += ` AND ug.guild_id = $2`; params.push(guild_id); } if (guild_id) { query += ` AND ug.guild_id = $2`; params.push(guild_id); }
query += ` GROUP BY u.id ORDER BY u.full_name ASC`; query += ` GROUP BY u.id ORDER BY u.full_name ASC`;
@@ -307,14 +356,7 @@ app.put("/services/:id/status", authMiddleware, async (req, res) => {
app.post("/services", authMiddleware, async (req, res) => { app.post("/services", authMiddleware, async (req, res) => {
const client = await pool.connect(); const client = await pool.connect();
try { try {
const { const { phone, name, address, email, description, scheduled_date, scheduled_time, duration, is_urgent, is_company, company_id, company_ref, internal_notes, client_notes, status_id, guild_id, assigned_to } = req.body;
phone, name, address, email, description,
scheduled_date, scheduled_time, duration, is_urgent,
is_company, company_id, company_ref,
internal_notes, client_notes, status_id,
guild_id, assigned_to // NUEVOS CAMPOS
} = req.body;
const p = normalizePhone(phone); const p = normalizePhone(phone);
await client.query('BEGIN'); await client.query('BEGIN');
@@ -357,7 +399,6 @@ app.post("/services", authMiddleware, async (req, res) => {
} catch (e) { await client.query('ROLLBACK'); console.error(e); res.status(500).json({ ok: false, error: e.message }); } finally { client.release(); } } catch (e) { await client.query('ROLLBACK'); console.error(e); res.status(500).json({ ok: false, error: e.message }); } finally { client.release(); }
}); });
// EDITAR (Con asignación)
app.put("/services/:id", authMiddleware, async (req, res) => { app.put("/services/:id", authMiddleware, async (req, res) => {
const client = await pool.connect(); const client = await pool.connect();
try { try {
@@ -366,7 +407,7 @@ app.put("/services/:id", authMiddleware, async (req, res) => {
scheduled_date, scheduled_time, duration, is_urgent, scheduled_date, scheduled_time, duration, is_urgent,
is_company, company_id, company_ref, is_company, company_id, company_ref,
internal_notes, client_notes, internal_notes, client_notes,
guild_id, assigned_to // NUEVOS CAMPOS guild_id, assigned_to
} = req.body; } = req.body;
await client.query('BEGIN'); await client.query('BEGIN');