From be4cdb11c31530e385503ba61fe4b53ad5d979a7 Mon Sep 17 00:00:00 2001 From: marsalva Date: Sun, 8 Feb 2026 15:03:27 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 126 ++++++++++++++++++++---------------------------------- 1 file changed, 47 insertions(+), 79 deletions(-) diff --git a/server.js b/server.js index 4974b45..98f0aec 100644 --- a/server.js +++ b/server.js @@ -29,14 +29,14 @@ const pool = new Pool({ }); // ========================================== -// 🧠 AUTO-ACTUALIZACIÓN DB (REPARADOR DEEP) +// 🧠 AUTO-ACTUALIZACIÓN DB // ========================================== async function autoUpdateDB() { const client = await pool.connect(); try { console.log("🔄 Verificando salud de la base de datos..."); - // 1. DEFINICIÓN BASE (Para instalaciones nuevas) + // 1. CREAR TABLAS (Si no existen) await client.query(` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, @@ -137,89 +137,43 @@ async function autoUpdateDB() { ); `); - // 2. PARCHE DE REPARACIÓN MANUAL (AQUÍ ESTÁ LA SOLUCIÓN) - // Este bloque fuerza la creación de columnas si no existen + // 2. PARCHE DE REPARACIÓN await client.query(` DO $$ BEGIN -- Client ID - 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='client_id') THEN ALTER TABLE services ADD COLUMN client_id INT REFERENCES clients(id) ON DELETE SET NULL; END IF; -- Status ID - 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; - - -- 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; - + 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; + -- Guild & Assigned + 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 + 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; - + 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; + -- Schedule + 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; + 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_email_key; EXCEPTION WHEN OTHERS THEN NULL; END; END $$; `); - console.log("✅ DB Sincronizada y Reparada Exitosamente."); + console.log("✅ DB Sincronizada y Reparada."); } catch (e) { console.error("❌ Error DB:", e); } finally { @@ -301,7 +255,6 @@ 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.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 }); } }); -// OBTENER OPERARIOS POR GREMIO app.get("/operators", authMiddleware, async (req, res) => { try { const { guild_id } = req.query; @@ -353,11 +306,19 @@ app.put("/services/:id/status", authMiddleware, async (req, res) => { } catch (e) { await client.query('ROLLBACK'); res.status(500).json({ ok: false }); } finally { client.release(); } }); +// CREAR SERVICIO (SANITIZADO) app.post("/services", authMiddleware, async (req, res) => { const client = await pool.connect(); try { 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; const p = normalizePhone(phone); + + // SANITIZAR ENTEROS (Evitar error invalid input syntax for type integer: "") + const safeDuration = (duration === "" || duration === null) ? 30 : duration; + const safeCompanyId = (company_id === "" || company_id === null) ? null : company_id; + const safeGuildId = (guild_id === "" || guild_id === null) ? null : guild_id; + const safeAssignedTo = (assigned_to === "" || assigned_to === null) ? null : assigned_to; + await client.query('BEGIN'); let finalStatus = status_id; @@ -387,9 +348,9 @@ app.post("/services", authMiddleware, async (req, res) => { RETURNING id `, [ req.user.accountId, clientId, finalStatus, p, name, address, email, - description, scheduled_date || 'NOW()', scheduled_time || 'NOW()', duration || 30, is_urgent || false, - is_company || false, company_id || null, company_ref, internal_notes, client_notes, name + " - Svc", - guild_id || null, assigned_to || null + description, scheduled_date || 'NOW()', scheduled_time || 'NOW()', safeDuration, is_urgent || false, + is_company || false, safeCompanyId, company_ref, internal_notes, client_notes, name + " - Svc", + safeGuildId, safeAssignedTo ]); await client.query("INSERT INTO service_logs (service_id, user_id, new_status_id, comment) VALUES ($1, $2, $3, 'Servicio Creado')", [insert.rows[0].id, req.user.sub, finalStatus]); @@ -399,6 +360,7 @@ 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(); } }); +// EDITAR SERVICIO (SANITIZADO) app.put("/services/:id", authMiddleware, async (req, res) => { const client = await pool.connect(); try { @@ -410,6 +372,12 @@ app.put("/services/:id", authMiddleware, async (req, res) => { guild_id, assigned_to } = req.body; + // SANITIZAR ENTEROS + const safeDuration = (duration === "" || duration === null) ? 30 : duration; + const safeCompanyId = (company_id === "" || company_id === null) ? null : company_id; + const safeGuildId = (guild_id === "" || guild_id === null) ? null : guild_id; + const safeAssignedTo = (assigned_to === "" || assigned_to === null) ? null : assigned_to; + await client.query('BEGIN'); await client.query(` UPDATE services SET @@ -421,10 +389,10 @@ app.put("/services/:id", authMiddleware, async (req, res) => { WHERE id=$16 AND owner_id=$17 `, [ name, address, email, description, - scheduled_date, scheduled_time, duration, is_urgent, - is_company, company_id, company_ref, + scheduled_date, scheduled_time, safeDuration, is_urgent, + is_company, safeCompanyId, company_ref, internal_notes, client_notes, - guild_id, assigned_to, + safeGuildId, safeAssignedTo, req.params.id, req.user.accountId ]);