diff --git a/server.js b/server.js index 3697e48..42440af 100644 --- a/server.js +++ b/server.js @@ -434,24 +434,29 @@ async function registrarMovimiento(serviceId, userId, action, details) { async function procesarConIA(ownerId, mensajeCliente, datosExpediente) { try { - const userQ = await pool.query("SELECT wa_settings, full_name FROM users WHERE id=$1", [ownerId]); - const settings = userQ.rows[0]?.wa_settings || {}; - const empresaNombre = userQ.rows[0]?.full_name || "nuestra empresa"; + // 1. Extraemos TODO: nombre, settings y horarios reales de la ruta + const userQ = await pool.query("SELECT wa_settings, full_name, portal_settings FROM users WHERE id=$1", [ownerId]); + const userData = userQ.rows[0]; + const settings = userData?.wa_settings || {}; + const empresaNombre = userData?.full_name || "nuestra empresa"; + // Si no hay horario configurado, usa un estándar lógico + const horarios = userData?.portal_settings || { m_start: "09:00", m_end: "14:00", a_start: "16:00", a_end: "19:00" }; if (!settings.wa_ai_enabled) return null; - // 🕒 1. Sincronización de Fecha Real const ahora = new Date(); - const fechaHoyTexto = ahora.toLocaleDateString('es-ES', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); + const opciones = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; + const fechaHoyTexto = ahora.toLocaleDateString('es-ES', opciones); - // 🧠 2. Memoria de Conversación (Evitar saludos repetitivos) + // 🧠 MEMORIA: Evita parecer tonto const chatCheck = await pool.query(` SELECT id FROM service_communications - WHERE scraped_id = $1 AND created_at > NOW() - INTERVAL '60 minutes' LIMIT 1 + WHERE scraped_id = $1 + AND created_at > NOW() - INTERVAL '60 minutes' LIMIT 1 `, [datosExpediente.dbId]); const yaSeHaPresentado = chatCheck.rowCount > 0; - // 📍 3. Inteligencia de Ruta (Buscar técnicos cerca) + // 📍 LOGÍSTICA: Buscar técnicos cerca const poblacion = datosExpediente.poblacion || ""; let fechasSugeridas = ""; @@ -459,10 +464,8 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) { const rutasCercanas = await pool.query(` SELECT raw_data->>'scheduled_date' as fecha FROM scraped_services - WHERE owner_id = $1 - AND raw_data->>'Población' ILIKE $2 - AND raw_data->>'scheduled_date' >= CURRENT_DATE::text - AND id != $3 + WHERE owner_id = $1 AND raw_data->>'Población' ILIKE $2 + AND raw_data->>'scheduled_date' > CURRENT_DATE::text AND id != $3 GROUP BY fecha ORDER BY fecha ASC LIMIT 2 `, [ownerId, poblacion, datosExpediente.dbId]); @@ -475,29 +478,32 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) { } const promptSistema = ` - Eres el Asistente IA de "${empresaNombre}". - Hoy es ${fechaHoyTexto}. Estamos en el año 2026. + Eres el Asistente Humano de "${empresaNombre}". Tienes que ser MUY natural, cercano y resolutivo. Nada de sonar robótico. + CONTEXTO Y HORARIOS: + - Hoy es: ${fechaHoyTexto}. Año 2026. + - HORARIO DE TRABAJO: Lunes a Viernes. Mañanas de ${horarios.m_start} a ${horarios.m_end}. Tardes de ${horarios.a_start} a ${horarios.a_end}. + - ⛔ LOS FINES DE SEMANA NO SE TRABAJA. Si el cliente pide un Sábado o Domingo, dile amablemente que descansamos el fin de semana y ofrécele un Viernes o Lunes dentro del horario. + DATOS EXPEDIENTE #${datosExpediente.ref}: - Estado: ${datosExpediente.estado} - Población: ${poblacion} - - Cita actual: ${datosExpediente.cita || 'Ninguna'} - LÓGICA DE SALUDO: + LÓGICA DE SALUDO (MUY IMPORTANTE): ${!yaSeHaPresentado - ? `- Inicio de chat: Preséntate brevemente y menciona el expediente #${datosExpediente.ref}.` - : `- Conversación fluida: NO te presentes, NO digas hola, ve directo a la respuesta.` + ? `- Es el inicio. Preséntate con empatía: "¡Hola! Soy el asistente de ${empresaNombre}. Te escribo sobre tu aviso #${datosExpediente.ref}..."` + : `- ⛔ YA HABÉIS HABLADO RECIENTEMENTE. PROHIBIDO decir "Hola" o volver a presentarte. Ve DIRECTO a la respuesta como harías en un chat real con un amigo.` } - ESTRATEGIA DE RUTA (LOGÍSTICA): + ESTRATEGIA DE RUTA: ${fechasSugeridas - ? `- Tenemos otros técnicos en ${poblacion} el ${fechasSugeridas}. SUGIERE estas fechas prioritariamente para optimizar la ruta.` - : `- No hay rutas previas en ${poblacion}. Pide al cliente su preferencia de mañana o tarde.` + ? `- Casualmente tenemos técnicos yendo a ${poblacion} el ${fechasSugeridas}. Sugiere esas fechas amigablemente para aprovechar el viaje.` + : `- Pregúntale qué día de Lunes a Viernes le viene bien y si prefiere mañana o tarde.` } - REGLA DE CITAS: - - Si el cliente propone algo, di que lo consultas y añade al final: [PROPUESTA:YYYY-MM-DD HH:mm] - - Máximo 2 frases. Sé muy natural, no parezcas un robot. + REGLA PARA GUARDAR LA CITA: + - Si el cliente confirma un día y hora válidos (L-V), dile que lo dejas anotado para que el técnico lo confirme y añade AL FINAL tu respuesta este código oculto: [PROPUESTA:YYYY-MM-DD HH:mm] + - Ejemplo: "Perfecto, te dejo anotado para el viernes a las 10:00. El técnico te confirmará en breve. [PROPUESTA:2026-03-13 10:00]" `; const completion = await openai.chat.completions.create({ @@ -506,7 +512,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) { { role: "system", content: promptSistema }, { role: "user", content: mensajeCliente } ], - temperature: 0.4, // Más preciso, menos creativo + temperature: 0.4, // Controlado para no divagar }); return completion.choices[0].message.content;