diff --git a/server.js b/server.js index f72a522..59448d0 100644 --- a/server.js +++ b/server.js @@ -1350,10 +1350,11 @@ app.get("/services/active", authMiddleware, async (req, res) => { }); // AÑADIDO: Ruta para fijar la cita o el estado operativo (CORREGIDA PARA NO PERDER LA FECHA) +// AÑADIDO: Ruta para fijar la cita o el estado operativo (CORREGIDA PARA NO PERDER LA FECHA Y ENVIAR BIEN EL WHATSAPP) app.put("/services/set-appointment/:id", authMiddleware, async (req, res) => { try { const { id } = req.params; - let { date, time, status_operativo, ...extra } = req.body; + let { date, time, status_operativo, skip_survey, ...extra } = req.body; const current = await pool.query('SELECT raw_data, assigned_to FROM scraped_services WHERE id = $1 AND owner_id = $2', [id, req.user.accountId]); if (current.rowCount === 0) return res.status(404).json({ ok: false, error: 'No encontrado' }); @@ -1361,7 +1362,6 @@ app.put("/services/set-appointment/:id", authMiddleware, async (req, res) => { const rawActual = current.rows[0].raw_data || {}; // --- MEJORA: MANTENER FECHA SI NO SE ENVÍA --- - // Si 'date' es undefined (no viene en el JSON), usamos la que ya tiene el servicio. let newDate = (date !== undefined) ? date : (rawActual.scheduled_date || ""); let newTime = (time !== undefined) ? time : (rawActual.scheduled_time || ""); @@ -1377,23 +1377,35 @@ app.put("/services/set-appointment/:id", authMiddleware, async (req, res) => { // --- REGLA ESTRICTA: BORRAR FECHAS SOLO SI SE ANULA O RETROCEDE A PENDIENTE --- if (stName.includes('pendiente') || stName.includes('desasignado') || stName.includes('asignado') || stName.includes('anulado') || stName.includes('esperando')) { - // Solo en estos casos reseteamos la fecha a vacío newDate = ""; newTime = ""; } - // --- MOTOR DE EVENTOS --- + // 1. PRIMERO GUARDAMOS EN BASE DE DATOS (Para que los motores puedan leer la info real) + const updatedRawData = { + ...rawActual, + ...extra, + "scheduled_date": newDate, + "scheduled_time": newTime, + "status_operativo": status_operativo + }; + + await pool.query('UPDATE scraped_services SET raw_data = $1, assigned_to = $2 WHERE id = $3 AND owner_id = $4', + [JSON.stringify(updatedRawData), finalAssignedTo, id, req.user.accountId] + ); + + // 2. DESPUÉS LANZAMOS LOS EVENTOS (Con la BBDD ya actualizada) if (stName.includes('asignado')) { const waEnviadoExito = await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_assigned'); if (waEnviadoExito) { const estadoEsperando = await pool.query("SELECT id FROM service_statuses WHERE owner_id=$1 AND name='Esperando al Cliente' LIMIT 1", [req.user.accountId]); if (estadoEsperando.rowCount > 0) { - status_operativo = estadoEsperando.rows[0].id; + updatedRawData.status_operativo = estadoEsperando.rows[0].id; + await pool.query('UPDATE scraped_services SET raw_data = $1 WHERE id = $2 AND owner_id = $3', [JSON.stringify(updatedRawData), id, req.user.accountId]); } } } else if (stName.includes('esperando') || stName.includes('pendiente de cita')) { - // NUEVO: Si forzamos "Esperando al cliente", le volvemos a disparar el WA con el link await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_assigned'); } else if (stName.includes('pendiente de asignar') || stName.includes('desasignado')) { @@ -1407,33 +1419,24 @@ app.put("/services/set-appointment/:id", authMiddleware, async (req, res) => { sendWhatsAppAuto(w.phone, msg, `cliente_${req.user.accountId}`, false).catch(console.error); } } - extra.assigned_to = null; - extra.assigned_to_name = null; + // Limpieza de datos si se desasigna + updatedRawData.assigned_to = null; + updatedRawData.assigned_to_name = null; finalAssignedTo = null; + await pool.query('UPDATE scraped_services SET raw_data = $1, assigned_to = null WHERE id = $2 AND owner_id = $3', [JSON.stringify(updatedRawData), id, req.user.accountId]); } else if (stName.includes('citado') && newDate !== "" && date !== undefined) { - // Solo disparamos el WA de cita si realmente estamos enviando una fecha nueva (date !== undefined) const oldDate = rawActual.scheduled_date || ""; if (oldDate === "") await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_date'); else if (oldDate !== newDate) await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_update'); } else if (stName.includes('camino')) { await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_onway'); } else if (stName.includes('finalizado') || stName.includes('terminado')) { - await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_survey'); + if (!skip_survey) { // Solo lo mandamos si el operario no dijo que NO + await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_survey'); + } } - const updatedRawData = { - ...rawActual, - ...extra, - "scheduled_date": newDate, - "scheduled_time": newTime, - "status_operativo": status_operativo - }; - - await pool.query('UPDATE scraped_services SET raw_data = $1, assigned_to = $2 WHERE id = $3 AND owner_id = $4', - [JSON.stringify(updatedRawData), finalAssignedTo, id, req.user.accountId] - ); - // --- INICIO TRAZABILIDAD --- let logDetalle = `Estado modificado a: ${stName.toUpperCase() || 'MODIFICADO'}.`; if (newDate) logDetalle += ` Cita para el ${newDate} a las ${newTime}.`;