From cf0539d55c11a815bc96491684d81fdd9f9516cd Mon Sep 17 00:00:00 2001 From: marsalva Date: Sun, 1 Mar 2026 20:44:46 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/server.js b/server.js index 8c6313d..a8cd2bd 100644 --- a/server.js +++ b/server.js @@ -2085,22 +2085,22 @@ app.put("/articles/:id", authMiddleware, async (req, res) => { // --- PRESUPUESTOS --- app.get("/budgets", authMiddleware, async (req, res) => { try { - const q = await pool.query("SELECT * FROM budgets WHERE owner_id=$1 ORDER BY created_at DESC", [req.user.accountId]); + // MAGIA: Cruzamos los datos con scraped_services y service_statuses para saber + // exactamente en qué estado se encuentra el servicio que nació de este presupuesto. + const q = await pool.query(` + SELECT b.*, + s.status as linked_service_status, + st.name as linked_service_status_name + FROM budgets b + LEFT JOIN scraped_services s ON s.service_ref = 'PRE-' || b.id AND s.owner_id = b.owner_id + LEFT JOIN service_statuses st ON st.id::text = (s.raw_data->>'status_operativo')::text + WHERE b.owner_id=$1 + ORDER BY b.created_at DESC + `, [req.user.accountId]); res.json({ ok: true, budgets: q.rows }); } catch(e) { res.status(500).json({ok: false}); } }); -app.post("/budgets", authMiddleware, async (req, res) => { - try { - const { client_phone, client_name, client_address, items, subtotal, tax, total } = req.body; - await pool.query( - "INSERT INTO budgets (owner_id, client_phone, client_name, client_address, items, subtotal, tax, total) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", - [req.user.accountId, client_phone, client_name, client_address, JSON.stringify(items), subtotal, tax, total] - ); - res.json({ ok: true }); - } catch(e) { res.status(500).json({ok: false}); } -}); - // Borrar Presupuesto app.delete("/budgets/:id", authMiddleware, async (req, res) => { try { @@ -2109,9 +2109,22 @@ app.delete("/budgets/:id", authMiddleware, async (req, res) => { const status = q.rows[0].status; - // REGLA DE NEGOCIO: No se puede borrar si está aceptado o ya convertido a servicio - if (status === 'accepted' || status === 'converted') { - return res.status(400).json({ok: false, error: "Para poder borrar un presupuesto, primero debe estar anulado/rechazado."}); + // Comprobamos si el servicio vinculado está anulado + const sq = await pool.query(` + SELECT st.name as status_name + FROM scraped_services s + LEFT JOIN service_statuses st ON st.id::text = (s.raw_data->>'status_operativo')::text + WHERE s.service_ref = $1 AND s.owner_id = $2 + `, [`PRE-${req.params.id}`, req.user.accountId]); + + let isAnulado = false; + if (sq.rowCount > 0 && sq.rows[0].status_name && sq.rows[0].status_name.toLowerCase().includes('anulado')) { + isAnulado = true; + } + + // REGLA DE NEGOCIO: No se puede borrar si está aceptado o convertido (Y NO ESTÁ ANULADO) + if ((status === 'accepted' || status === 'converted') && !isAnulado) { + return res.status(400).json({ok: false, error: "Para poder borrar un presupuesto, el servicio primero debe estar anulado."}); } await pool.query("DELETE FROM budgets WHERE id=$1 AND owner_id=$2", [req.params.id, req.user.accountId]);