From c7ae35e941a597860aca1cd212c726a74dc37857 Mon Sep 17 00:00:00 2001 From: marsalva Date: Fri, 20 Feb 2026 14:31:09 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 1f492a0..b90dcab 100644 --- a/server.js +++ b/server.js @@ -253,6 +253,11 @@ async function autoUpdateDB() { ALTER TABLE scraped_services ADD COLUMN is_urgent BOOLEAN DEFAULT FALSE; END IF; + -- AÑADIDO: Columna de palabras clave IA para los gremios + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='guilds' AND column_name='ia_keywords') THEN + ALTER TABLE guilds ADD COLUMN ia_keywords JSONB DEFAULT '[]'; + 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; @@ -1027,9 +1032,56 @@ app.delete("/admin/users/:id", authMiddleware, async (req, res) => { try { await app.get("/config/company", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT company_slug, full_name, plan_tier FROM users WHERE id=$1", [req.user.accountId]); res.json({ ok: true, slug: q.rows[0]?.company_slug, name: q.rows[0]?.full_name, plan: q.rows[0]?.plan_tier }); } catch (e) { res.status(500).json({ ok: false }); } }); app.post("/config/company", authMiddleware, async (req, res) => { const client = await pool.connect(); try { const { slug } = req.body; if (!slug || slug.length < 3) return res.status(400).json({ ok: false, error: "Mínimo 3 caracteres" }); const cleanSlug = slug.toLowerCase().replace(/[^a-z0-9-]/g, ""); if (cleanSlug !== slug) return res.status(400).json({ ok: false, error: "Carácteres inválidos" }); const check = await client.query("SELECT id FROM users WHERE company_slug=$1 AND id != $2", [cleanSlug, req.user.accountId]); if (check.rowCount > 0) return res.status(400).json({ ok: false, error: "Nombre en uso" }); await client.query("UPDATE users SET company_slug=$1 WHERE id=$2", [cleanSlug, req.user.accountId]); res.json({ ok: true, fullUrl: `https://${cleanSlug}.integrarepara.es` }); } catch (e) { res.status(500).json({ ok: false }); } finally { client.release(); } }); -app.get("/guilds", authMiddleware, async (req, res) => { try { const q = await pool.query("SELECT * FROM guilds WHERE owner_id=$1 ORDER BY name ASC", [req.user.accountId]); res.json({ ok: true, guilds: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } }); -app.post("/guilds", authMiddleware, async (req, res) => { try { const { name } = req.body; await pool.query("INSERT INTO guilds (name, owner_id) VALUES ($1, $2)", [name, req.user.accountId]); res.json({ ok: true }); } catch (e) { res.status(500).json({ ok: false }); } }); -app.delete("/guilds/:id", authMiddleware, async (req, res) => { try { await pool.query("DELETE FROM guilds 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 }); } }); + +// ========================================== +// 🛠️ RUTAS DE GREMIOS E INTELIGENCIA ARTIFICIAL +// ========================================== +app.get("/guilds", authMiddleware, async (req, res) => { + try { + // AHORA DEVOLVEMOS TAMBIÉN LAS PALABRAS CLAVE + const q = await pool.query("SELECT id, name, ia_keywords FROM guilds WHERE owner_id=$1 ORDER BY name ASC", [req.user.accountId]); + res.json({ ok: true, guilds: q.rows }); + } catch (e) { + res.status(500).json({ ok: false }); + } +}); + +app.post("/guilds", authMiddleware, async (req, res) => { + try { + const { name } = req.body; + await pool.query("INSERT INTO guilds (name, owner_id) VALUES ($1, $2)", [name, req.user.accountId]); + res.json({ ok: true }); + } catch (e) { res.status(500).json({ ok: false }); } +}); + +app.delete("/guilds/:id", authMiddleware, async (req, res) => { + try { + await pool.query("DELETE FROM guilds 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 }); } +}); + +// NUEVA RUTA: PARA GUARDAR LAS PALABRAS CLAVE DE LA IA +app.put("/guilds/:id/ia-rules", authMiddleware, async (req, res) => { + try { + const { keywords } = req.body; // Viene un array ["grifo", "fuga"] + const guildId = req.params.id; + + // Asegurarnos de que el array es válido + const safeKeywords = Array.isArray(keywords) ? keywords : []; + + await pool.query( + "UPDATE guilds SET ia_keywords = $1 WHERE id = $2 AND owner_id = $3", + [JSON.stringify(safeKeywords), guildId, req.user.accountId] + ); + + res.json({ ok: true }); + } catch (e) { + console.error("Error guardando IA:", e); + res.status(500).json({ ok: false, error: e.message }); + } +}); + app.get("/services", authMiddleware, async (req, res) => { try { const q = await pool.query(`SELECT s.*, st.name as status_name, st.color as status_color, c.name as company_name, g.name as guild_name, u.full_name as assigned_name FROM services s LEFT JOIN service_statuses st ON s.status_id = st.id LEFT JOIN companies c ON s.company_id = c.id LEFT JOIN guilds g ON s.guild_id = g.id LEFT JOIN users u ON s.assigned_to = u.id WHERE s.owner_id=$1 ORDER BY s.created_at DESC`, [req.user.accountId]); res.json({ ok: true, services: q.rows }); } catch (e) { res.status(500).json({ ok: false }); } }); app.get("/services/:id", authMiddleware, async (req, res) => { try { const q = await pool.query(`SELECT * FROM services WHERE id=$1 AND owner_id=$2`, [req.params.id, req.user.accountId]); res.json({ ok: true, service: q.rows[0] }); } catch (e) { res.status(500).json({ ok: false }); } });