diff --git a/server.js b/server.js index 496a996..2043902 100644 --- a/server.js +++ b/server.js @@ -2981,59 +2981,77 @@ app.post("/services/:id/chat", authMiddleware, async (req, res) => { app.post("/webhook/evolution", async (req, res) => { try { const data = req.body; - // Solo procesamos si es un mensaje de texto entrante + + // 1. Filtrar solo mensajes de texto entrantes if (data.event !== "messages.upsert" || data.data.key.fromMe) return res.sendStatus(200); - const telefonoCliente = data.data.key.remoteJid.split("@")[0]; + const remoteJid = data.data.key.remoteJid; + const telefonoCliente = remoteJid.split("@")[0]; // Ej: 34666777888 const mensajeTexto = data.data.message?.conversation || data.data.message?.extendedTextMessage?.text; - const instanceName = data.instance; // ej: cliente_1 + const instanceName = data.instance; // Ej: cliente_1 if (!mensajeTexto) return res.sendStatus(200); - // 1. Identificar al dueño de la instancia (owner_id) - const ownerId = instanceName.split("_")[1]; + console.log(`📩 [WEBHOOK] Mensaje de ${telefonoCliente}: "${mensajeTexto}" (Instancia: ${instanceName})`); - // 2. Buscar si este teléfono tiene un servicio activo + // 2. Identificar al dueño (owner_id) + const ownerId = instanceName.split("_")[1]; + if (!ownerId) { + console.error("❌ [WEBHOOK] No se pudo determinar el ownerId de la instancia:", instanceName); + return res.sendStatus(200); + } + + // 3. Buscar siniestro por teléfono (Búsqueda ULTRA-FLEXIBLE en todo el JSON) + // Buscamos los últimos 9 dígitos para ignorar el +34 o 34 + const cleanPhone = telefonoCliente.slice(-9); + const svcQ = await pool.query(` - SELECT s.id, s.service_ref, s.assigned_to, u.full_name as worker_name, + SELECT s.id, s.service_ref, u.full_name as worker_name, st.name as status_name, s.raw_data->>'scheduled_date' as cita FROM scraped_services s LEFT JOIN users u ON s.assigned_to = u.id LEFT JOIN service_statuses st ON (s.raw_data->>'status_operativo')::text = st.id::text - WHERE s.owner_id = $1 AND s.raw_data->>'Teléfono' ILIKE $2 + WHERE s.owner_id = $1 + AND s.status != 'archived' + AND s.raw_data::text ILIKE $2 ORDER BY s.created_at DESC LIMIT 1 - `, [ownerId, `%${telefonoCliente.slice(-9)}%`]); + `, [ownerId, `%${cleanPhone}%`]); if (svcQ.rowCount > 0) { const service = svcQ.rows[0]; + console.log(`🔎 [IA] Siniestro localizado: #${service.service_ref}. Preparando respuesta...`); - // 3. Llamar a la IA + // 4. Llamar a la IA const respuestaIA = await procesarConIA(ownerId, mensajeTexto, { ref: service.service_ref, - estado: service.status_name, + estado: service.status_name || "En proceso", operario: service.worker_name, cita: service.cita }); if (respuestaIA) { - // 4. Enviar respuesta por WhatsApp + console.log(`🤖 [IA] Respondiendo: "${respuestaIA}"`); + // 5. Enviar respuesta por WhatsApp await sendWhatsAppAuto(telefonoCliente, respuestaIA, instanceName, true); - // 5. Registrar en el chat para que la oficina lo vea + // 6. Registrar en el chat y logs de trazabilidad await pool.query(` INSERT INTO service_communications (scraped_id, owner_id, sender_name, sender_role, message) VALUES ($1, $2, $3, $4, $5) `, [service.id, ownerId, "Asistente IA", "ia", respuestaIA]); - // 6. Registrar en el historial - await registrarMovimiento(service.id, null, "Respuesta IA", `ChatGPT respondió: ${respuestaIA}`); + await registrarMovimiento(service.id, null, "Respuesta IA", `ChatGPT respondió automáticamente al cliente.`); + } else { + console.log("ℹ️ [IA] ChatGPT no generó respuesta (Botón OFF o error interno)."); } + } else { + console.warn(`⚠️ [WEBHOOK] No hay siniestros activos para el teléfono ${cleanPhone} en la cuenta del admin ${ownerId}`); } res.sendStatus(200); } catch (e) { - console.error("Error Webhook IA:", e.message); - res.sendStatus(500); + console.error("❌ [WEBHOOK ERROR]:", e.message); + if (!res.headersSent) res.sendStatus(500); } });