From 8d33cc3f6a28a675928f0ed079a82160edc00dab Mon Sep 17 00:00:00 2001 From: marsalva Date: Sun, 1 Mar 2026 15:54:30 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/server.js b/server.js index d895353..682de41 100644 --- a/server.js +++ b/server.js @@ -2099,7 +2099,7 @@ app.patch("/budgets/:id/status", authMiddleware, async (req, res) => { // Convertir Presupuesto en Servicio Activo app.post("/budgets/:id/convert", authMiddleware, async (req, res) => { try { - const { date, time } = req.body; + const { date, time, guild_id, assigned_to, use_automation } = req.body; const bq = await pool.query("SELECT * FROM budgets WHERE id=$1 AND owner_id=$2", [req.params.id, req.user.accountId]); if (bq.rowCount === 0) return res.status(404).json({ok: false}); const budget = bq.rows[0]; @@ -2111,28 +2111,70 @@ app.post("/budgets/:id/convert", authMiddleware, async (req, res) => { "Dirección": budget.client_address, "Compañía": "Particular", "Descripción": "PRESUPUESTO ACEPTADO.\n" + budget.items.map(i => `${i.qty}x ${i.concept}`).join("\n"), - "scheduled_date": date, - "scheduled_time": time + "guild_id": guild_id || null, + "assigned_to": assigned_to || null, + "scheduled_date": date || "", + "scheduled_time": time || "" }; // 2. Insertamos en el Panel Operativo (Buzón) const insertSvc = await pool.query( - "INSERT INTO scraped_services (owner_id, provider, service_ref, status, automation_status, raw_data) VALUES ($1, 'particular', $2, 'pending', 'manual', $3) RETURNING id", - [req.user.accountId, `PRE-${budget.id}`, JSON.stringify(rawData)] + "INSERT INTO scraped_services (owner_id, provider, service_ref, status, automation_status, assigned_to, raw_data) VALUES ($1, 'particular', $2, 'pending', $3, $4, $5) RETURNING id", + [ + req.user.accountId, + `PRE-${budget.id}`, + use_automation ? 'manual' : 'manual', // Empezamos en manual siempre + assigned_to || null, + JSON.stringify(rawData) + ] ); + const newServiceId = insertSvc.rows[0].id; + // 3. Marcamos presupuesto como convertido y le enlazamos la ficha financiera por el total await pool.query("UPDATE budgets SET status='converted' WHERE id=$1", [budget.id]); await pool.query( "INSERT INTO service_financials (scraped_id, amount, payment_method) VALUES ($1, $2, 'Pendiente')", - [insertSvc.rows[0].id, budget.total] + [newServiceId, budget.total] ); - // 4. Mandamos WhatsApp de confirmación - if (budget.client_phone) { + // 4. Si pide automatización, la disparamos internamente simulando la llamada + if (use_automation && guild_id) { + // Buscamos código postal por si acaso para la automatización + const cpMatch = budget.client_address ? budget.client_address.match(/\b\d{5}\b/) : null; + const cp = cpMatch ? cpMatch[0] : "00000"; // Fallback si no hay CP + + // Reutilizamos la lógica de automatización (hacemos un fetch a nosotros mismos para aprovechar el motor existente) + const port = process.env.PORT || 3000; + const autoUrl = `http://localhost:${port}/providers/automate/${newServiceId}`; + + // Lo lanzamos sin esperar (asíncrono) para no bloquear la respuesta + fetch(autoUrl, { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${req.headers.authorization.split(' ')[1]}` }, + body: JSON.stringify({ guild_id, cp, useDelay: false }) + }).catch(e => console.error("Error lanzando automatización interna:", e)); + + // Si va a la bolsa, no avisamos al cliente de la fecha (aún no se sabe) + if (budget.client_phone) { + const msg = `✅ *PRESUPUESTO ACEPTADO*\n\nHola ${budget.client_name}, confirmamos la aceptación del presupuesto por un total de *${budget.total}€*.\n\nEn breve un técnico se pondrá en contacto contigo para agendar la cita. ¡Gracias por confiar en nosotros!`; + sendWhatsAppAuto(budget.client_phone, msg, `cliente_${req.user.accountId}`, false).catch(console.error); + } + } + // 5. Si se asigna manual con fecha + else if (budget.client_phone && date && time) { const [y, m, d] = date.split('-'); const msg = `✅ *PRESUPUESTO ACEPTADO*\n\nHola ${budget.client_name}, confirmamos la aceptación del presupuesto por un total de *${budget.total}€*.\n\nEl servicio ha sido agendado para el *${d}/${m}/${y} a las ${time}*. ¡Gracias por confiar en nosotros!`; sendWhatsAppAuto(budget.client_phone, msg, `cliente_${req.user.accountId}`, false).catch(console.error); + + // Forzar estado Asignado si hay un técnico + if (assigned_to) { + const statusQ = await pool.query("SELECT id FROM service_statuses WHERE owner_id=$1 AND name ILIKE '%asignado%' LIMIT 1", [req.user.accountId]); + if (statusQ.rowCount > 0) { + rawData.status_operativo = statusQ.rows[0].id; + await pool.query("UPDATE scraped_services SET raw_data = $1 WHERE id = $2", [JSON.stringify(rawData), newServiceId]); + } + } } res.json({ ok: true });