From e98352d53810a19da514a78a93465ef43415932f Mon Sep 17 00:00:00 2001 From: marsalva Date: Wed, 11 Feb 2026 08:10:13 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/server.js b/server.js index adc63d8..bc992a7 100644 --- a/server.js +++ b/server.js @@ -36,7 +36,6 @@ async function autoUpdateDB() { try { console.log("🔄 Verificando estructura DB..."); - // TABLAS PRINCIPALES (Usuarios, Clientes, Gremios...) await client.query(` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, @@ -101,10 +100,7 @@ async function autoUpdateDB() { is_final BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT NOW() ); - `); - - // TABLAS DE ZONAS (Versión simplificada, sin pueblos) - await client.query(` + CREATE TABLE IF NOT EXISTS zones ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, @@ -116,10 +112,7 @@ async function autoUpdateDB() { zone_id INT REFERENCES zones(id) ON DELETE CASCADE, PRIMARY KEY (user_id, zone_id) ); - `); - // TABLA SERVICIOS - await client.query(` CREATE TABLE IF NOT EXISTS services ( id SERIAL PRIMARY KEY, owner_id INT REFERENCES users(id) ON DELETE CASCADE, @@ -156,7 +149,7 @@ async function autoUpdateDB() { ); `); - // PARCHE DE REPARACIÓN (Mantenido por seguridad) + // PARCHE REPARACIÓN await client.query(` DO $$ BEGIN 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; @@ -204,12 +197,11 @@ app.post("/auth/reset-password", async (req, res) => { const client = await pool // ========================================== -// 🛠️ GESTIÓN DE ESTADOS (CRUD COMPLETO) +// 🛠️ GESTIÓN DE ESTADOS (CRUD SEGURO) // ========================================== app.get("/statuses", authMiddleware, async (req, res) => { try { let q = await pool.query("SELECT * FROM service_statuses WHERE owner_id=$1 ORDER BY id ASC", [req.user.accountId]); - // Si no hay estados, crea los default if (q.rowCount === 0) { const defaults = [{name:'Pendiente',c:'gray',d:true,f:false},{name:'En Proceso',c:'blue',d:false,f:false},{name:'Terminado',c:'green',d:false,f:true},{name:'Cancelado',c:'red',d:false,f:true}]; for (const s of defaults) await pool.query("INSERT INTO service_statuses (owner_id,name,color,is_default,is_final) VALUES ($1,$2,$3,$4,$5)", [req.user.accountId,s.name,s.c,s.d,s.f]); @@ -219,7 +211,6 @@ app.get("/statuses", authMiddleware, async (req, res) => { } catch (e) { res.status(500).json({ ok: false }); } }); -// NUEVO: CREAR ESTADO app.post("/statuses", authMiddleware, async (req, res) => { try { const { name, color } = req.body; @@ -229,12 +220,38 @@ app.post("/statuses", authMiddleware, async (req, res) => { } catch(e) { res.status(500).json({ ok: false }); } }); -// NUEVO: BORRAR ESTADO +// 🔥 BORRADO SEGURO DE ESTADOS 🔥 app.delete("/statuses/:id", authMiddleware, async (req, res) => { + const client = await pool.connect(); try { - await pool.query("DELETE FROM service_statuses WHERE id=$1 AND owner_id=$2", [req.params.id, req.user.accountId]); + const statusId = req.params.id; + const accountId = req.user.accountId; + + // 1. Comprobar si hay servicios usando este estado + const check = await client.query("SELECT COUNT(*) FROM services WHERE status_id = $1 AND owner_id = $2", [statusId, accountId]); + const usageCount = parseInt(check.rows[0].count); + + if (usageCount > 0) { + return res.status(400).json({ + ok: false, + error: `No se puede borrar: Este estado se usa en ${usageCount} servicios.` + }); + } + + // 2. Si no se usa, borrarlo + const del = await client.query("DELETE FROM service_statuses WHERE id=$1 AND owner_id=$2", [statusId, accountId]); + + if (del.rowCount === 0) { + return res.status(404).json({ ok: false, error: "Estado no encontrado o no autorizado" }); + } + res.json({ ok: true }); - } catch(e) { res.status(500).json({ ok: false }); } + } catch(e) { + console.error("Error borrando estado:", e); + res.status(500).json({ ok: false, error: "Error interno" }); + } finally { + client.release(); + } }); // CLIENTES, COMPAÑIAS, GREMIOS @@ -245,7 +262,7 @@ app.get("/companies", authMiddleware, async (req, res) => { try { const q = awai 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.delete("/companies/:id", authMiddleware, async (req, res) => { try { await pool.query("DELETE FROM companies WHERE id=$1 AND owner_id=$2", [req.params.id, req.user.accountId]); res.json({ ok: true }); } catch (e) { res.status(500).json({ ok: false }); } }); -// OBTENER OPERARIOS POR GREMIO +// OBTENER OPERARIOS app.get("/operators", authMiddleware, async (req, res) => { try { const { guild_id } = req.query;