From 5c287ba38d3e43f2f5b74094b3db2631aa2f69bf Mon Sep 17 00:00:00 2001 From: marsalva Date: Sun, 8 Mar 2026 22:45:51 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 97 +++++++++++++------------------------------------------ 1 file changed, 23 insertions(+), 74 deletions(-) diff --git a/server.js b/server.js index 8417380..1942727 100644 --- a/server.js +++ b/server.js @@ -1591,59 +1591,7 @@ app.post("/providers/automate/:id", authMiddleware, async (req, res) => { } }); -// ========================================== -// 馃摑 ACTUALIZACI脫N DE EXPEDIENTES (Y ESCUDO ANTI-ARCHIVO) -// ========================================== -app.put('/providers/scraped/:id', authMiddleware, async (req, res) => { - const { id } = req.params; - let { automation_status, status, name, phone, address, cp, description, guild_id, assigned_to, assigned_to_name, internal_notes, client_notes, is_urgent, ...extra } = req.body; - - try { - // 1. Cambio de estado de automatizaci贸n - if (automation_status) { - await pool.query(`UPDATE scraped_services SET automation_status = $1 WHERE id = $2 AND owner_id = $3`, [automation_status, id, req.user.accountId]); - return res.json({ ok: true }); - } - - // 2. ESCUDO ANTI-ARCHIVO - if (status === 'archived') { - const checkQ = await pool.query(` - SELECT raw_data, assigned_to, service_ref, - (SELECT is_final FROM service_statuses WHERE id::text = raw_data->>'status_operativo') as is_final - FROM scraped_services WHERE id = $1 AND owner_id = $2 - `, [id, req.user.accountId]); - - if (checkQ.rowCount > 0) { - const row = checkQ.rows[0]; - const isFinal = row.is_final === true; - const hasWorker = row.assigned_to !== null; - let raw = row.raw_data || {}; - const serviceRef = row.service_ref || raw["Referencia"] || id; - - if (hasWorker && !isFinal) { - if (!raw.cerrado_proveedor) { - raw.cerrado_proveedor = true; - await pool.query(`UPDATE scraped_services SET raw_data = $1 WHERE id = $2 AND owner_id = $3`, [JSON.stringify(raw), id, req.user.accountId]); - await pool.query("INSERT INTO scraped_service_logs (scraped_id, user_name, action, details) VALUES ($1, $2, $3, $4)", [id, 'Sistema (Robot)', 'Intento de Cierre', 'La compa帽铆a ha cerrado el aviso, pero se mantiene vivo en IntegraRepara.']); - - const workerQ = await pool.query("SELECT full_name, phone FROM users WHERE id=$1", [row.assigned_to]); - if (workerQ.rowCount > 0) { - const w = workerQ.rows[0]; - const msg = `馃毃 *隆ALERTA URGENTE!* 馃毃\n\nHola ${w.full_name}, la compa帽铆a aseguradora acaba de *CERRAR/ANULAR* el expediente *#${serviceRef}* en su sistema.\n\n鈿狅笍 *NO ACUDAS NI REALICES EL TRABAJO* si no lo has hecho ya, porque no se va a cobrar.\n\nPor favor, contacta con la oficina.`; - sendWhatsAppAuto(w.phone, msg, `cliente_${req.user.accountId}`, false).catch(console.error); - await pool.query("INSERT INTO scraped_service_logs (scraped_id, user_name, action, details) VALUES ($1, $2, $3, $4)", [id, 'Sistema (Robot)', 'Alerta de Cancelaci贸n', `WhatsApp de emergencia enviado a ${w.full_name}.`]); - } - } - return res.json({ ok: true, note: "Protegido de archivo autom谩tico y operario alertado" }); - } - } - - await pool.query(`UPDATE scraped_services SET status = 'archived', automation_status = 'manual' WHERE id = $1 AND owner_id = $2`, [id, req.user.accountId]); - await pool.query("INSERT INTO scraped_service_logs (scraped_id, user_name, action, details) VALUES ($1, $2, $3, $4)", [id, 'Sistema', 'Archivado', 'El expediente se ha cerrado definitivamente y movido al hist贸rico.']); - return res.json({ ok: true }); - } - - // 3. ACTUALIZACI脫N MANUAL NORMAL +// 3. ACTUALIZACI脫N MANUAL NORMAL DE LA FICHA const current = await pool.query('SELECT raw_data, assigned_to, status, is_urgent FROM scraped_services WHERE id = $1 AND owner_id = $2', [id, req.user.accountId]); if (current.rows.length === 0) return res.status(404).json({ error: 'No encontrado' }); @@ -1654,8 +1602,14 @@ app.put('/providers/scraped/:id', authMiddleware, async (req, res) => { const oldWorkerId = current.rows[0].assigned_to || rawActual.assigned_to; let finalAssignedTo = assigned_to !== undefined ? (assigned_to === "" ? null : assigned_to) : oldWorkerId; + + // 馃憞 MAGIA: Detectamos si la fecha ha cambiado independientemente del estado + const oldDate = rawActual.scheduled_date || ""; + const newDate = extra.scheduled_date !== undefined ? extra.scheduled_date : oldDate; + const dateChanged = newDate !== "" && newDate !== oldDate; + const statusChanged = newStatus !== oldStatus; - // --- AVISO AL OPERARIO --- + // --- AVISO AL OPERARIO (ASIGNACI脫N NUEVA / DESASIGNACI脫N) --- if (finalAssignedTo !== oldWorkerId) { if (finalAssignedTo) { const workerQ = await pool.query("SELECT full_name, phone FROM users WHERE id=$1", [finalAssignedTo]); @@ -1679,10 +1633,12 @@ app.put('/providers/scraped/:id', authMiddleware, async (req, res) => { // --- L脫GICA DE ESTADOS Y WHATSAPP AL CLIENTE --- let stName = ""; - if (newStatus && newStatus !== oldStatus) { + if (newStatus) { const statusQ = await pool.query("SELECT name FROM service_statuses WHERE id=$1", [newStatus]); stName = (statusQ.rows[0]?.name || "").toLowerCase(); + } + if (statusChanged) { if ((stName.includes('pendiente') && !stName.includes('cita')) || stName.includes('desasignado') || stName.includes('asignado') || stName.includes('anulado') || stName.includes('esperando')) { if (!extra.scheduled_date) { extra.scheduled_date = ""; @@ -1703,11 +1659,12 @@ app.put('/providers/scraped/:id', authMiddleware, async (req, res) => { await registrarMovimiento(id, req.user.sub, "Robot WA", "WhatsApp de asignaci贸n fall贸 o est谩 desactivado."); } } - else if (stName.includes('citado') && extra.scheduled_date) { - const oldDate = rawActual.scheduled_date || ""; - if (oldDate === "") await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_date'); - else if (oldDate !== extra.scheduled_date) await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_update'); - } + } + + // 馃煝 NUEVO DISPARADOR WHATSAPP CITA (Se lanza si cambia el estado O la fecha) + if ((statusChanged && stName.includes('citado') && newDate !== "") || (dateChanged && stName.includes('citado'))) { + if (oldDate === "") await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_date'); + else if (oldDate !== newDate) await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_update'); } // 4. UNIFICAR DATOS FINALES @@ -1730,7 +1687,6 @@ app.put('/providers/scraped/:id', authMiddleware, async (req, res) => { let currentDbStatus = current.rows[0].status; const finalIsUrgent = is_urgent !== undefined ? is_urgent : current.rows[0].is_urgent; - // GUARDAMOS EN BASE DE DATOS await pool.query( `UPDATE scraped_services SET raw_data = $1, status = $2, is_urgent = $3, assigned_to = $4 WHERE id = $5 AND owner_id = $6`, [JSON.stringify(updatedRawData), currentDbStatus, finalIsUrgent, finalAssignedTo, id, req.user.accountId] @@ -1738,22 +1694,15 @@ app.put('/providers/scraped/:id', authMiddleware, async (req, res) => { await registrarMovimiento(id, req.user.sub, "Edici贸n / Asignaci贸n", "Expediente actualizado o asignado."); - // 5. 馃 DISPARAR ROBOT HOMESERVE (AHORA S脥, CON LA BBDD YA ACTUALIZADA) - if (newStatus && newStatus !== oldStatus) { - if (stName.includes('asignado') && finalAssignedTo) { - triggerHomeServeRobot(req.user.accountId, id, 'assign').catch(console.error); - } - else if (stName.includes('citado') && updatedRawData.scheduled_date) { - triggerHomeServeRobot(req.user.accountId, id, 'date').catch(console.error); - } + // 5. 馃 DISPARAR ROBOT HOMESERVE (AHORA S脥, LEE SI CAMBIA FECHA O ESTADO) + if (statusChanged && stName.includes('asignado') && finalAssignedTo) { + triggerHomeServeRobot(req.user.accountId, id, 'assign').catch(console.error); + } + if ((statusChanged && stName.includes('citado') && updatedRawData.scheduled_date) || (dateChanged && stName.includes('citado'))) { + triggerHomeServeRobot(req.user.accountId, id, 'date').catch(console.error); } res.json({ ok: true }); - } catch (error) { - console.error("Error actualizaci贸n manual:", error); - res.status(500).json({ error: 'Error' }); - } -}); // Validar si una referencia ya existe para este due帽o app.get("/services/check-ref", authMiddleware, async (req, res) => {