Actualizar server.js

This commit is contained in:
2026-03-07 23:32:58 +00:00
parent ddf4310acd
commit aef383d7e5

View File

@@ -460,7 +460,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
const esPrimerMensaje = historialChat.length === 0;
// 🗓️ LECTURA DE AGENDA ANTI-SOLAPAMIENTOS (NUEVO)
// 🗓️ LECTURA DE AGENDA ANTI-SOLAPAMIENTOS
let agendaOcupadaTexto = "El técnico tiene la agenda libre. Puedes sugerir cualquier hora dentro del horario laboral.";
if (datosExpediente.worker_id) {
const agendaQ = await pool.query(`
@@ -489,40 +489,42 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
}
}
// 🚦 ESTADO PENDIENTE
const hayCitaPendiente = datosExpediente.appointment_status === 'pending' && datosExpediente.cita_pendiente_fecha;
const textoCitaPendiente = hayCitaPendiente
? `SÍ. El cliente solicitó cita para el ${datosExpediente.cita_pendiente_fecha} a las ${datosExpediente.cita_pendiente_hora || ''}. Está PENDIENTE de que el técnico la apruebe.`
: `NO.`;
const promptSistema = `
Eres el asistente humano de "${empresaNombre}". Hablas de tú, de forma muy natural, corta y directa por WhatsApp.
CONTEXTO DE TRABAJO:
- Hoy es: ${fechaHoyTexto}. (Año 2026).
--- CONTEXTO Y HORARIOS ---
- Hoy es: ${fechaHoyTexto}.
- Horario L-V: Mañanas (${horarios.m_start}-${horarios.m_end}) y Tardes (${horarios.a_start}-${horarios.a_end}).
- ⛔ FIN DE SEMANA CERRADO. Ofrece solo de lunes a viernes.
- ⛔ FIN DE SEMANA CERRADO. Ofrece solo de Lunes a Viernes.
DATOS DEL CLIENTE (Aviso #${datosExpediente.ref}):
--- DATOS DEL AVISO #${datosExpediente.ref} ---
- Estado: ${datosExpediente.estado}
- Población: ${datosExpediente.poblacion}
- Urgencia: ${datosExpediente.is_urgent ? 'SÍ' : 'No'}
- Cita actual: ${datosExpediente.cita || 'Ninguna'}
- Urgencia: ${datosExpediente.is_urgent ? 'SÍ (Prioridad)' : 'No'}
- Cita Confirmada: ${datosExpediente.cita || 'Ninguna'}
- Cita Solicitada PENDIENTE: ${textoCitaPendiente}
⚠️ CALENDARIO DEL TÉCNICO ASIGNADO (CRÍTICO):
--- ⚠️ CALENDARIO DEL TÉCNICO Y RUTAS ---
${agendaOcupadaTexto}
REGLA DE CALENDARIO: NUNCA sugieras ni aceptes una hora que ya esté ocupada en la lista anterior. Deja un margen de al menos 1 hora entre citas. Si el cliente pide una hora ocupada, dile que está cogida y ofrece una alternativa libre.
- REGLA 1 (ANTI-SOLAPAMIENTO): NUNCA sugieras ni aceptes una hora que ya esté ocupada en la lista anterior. Deja margen de al menos 1 hora entre citas.
- REGLA 2 (RUTAS): El cliente actual está en ${datosExpediente.poblacion}. Si el técnico ya va a ${datosExpediente.poblacion} un día concreto, PRIORIZA ofrecerle ese mismo día (en una hora libre) para aprovechar el viaje.
INSTRUCCIONES DE ACTUACIÓN:
1. SI ES URGENCIA: No agendes. Di que el técnico contactará urgente.
2. PARA AGENDAR:
- Si no hay fecha: Sugiere tú una hora libre basándote en su calendario.
- Si el cliente ACEPTA una hora libre, CIERRA LA CITA confirmándolo y añade OBLIGATORIAMENTE al final el código [PROPUESTA:YYYY-MM-DD HH:mm].
3. NUNCA TE PRESENTES si ya estáis conversando. Ve al grano.
${esPrimerMensaje ? '4. Como es el primer mensaje, preséntate diciendo de qué empresa eres.' : ''}
5. Sé breve (máximo 1 o 2 frases).
6. Cuando se confirma la cita, informar al cliente que se le va a informar al operario asignado de la cita elegida, y cuando la vea se le confirmara.
⚠️ CALENDARIO DEL TÉCNICO ASIGNADO (CRÍTICO):
${agendaOcupadaTexto}
REGLAS DE CALENDARIO Y OPTIMIZACIÓN DE RUTAS:
1. ANTI-SOLAPAMIENTO: NUNCA sugieras ni aceptes una hora que ya esté ocupada en la lista anterior.
2. OPTIMIZACIÓN DE RUTA (MUY IMPORTANTE): El cliente actual está en ${datosExpediente.poblacion}. Si ves en el calendario que el técnico ya tiene otra cita en ${datosExpediente.poblacion} un día concreto, tu prioridad absoluta es ofrecerle a este cliente ese mismo día (en una hora libre anterior o posterior) para aprovechar el viaje.
--- 🛠️ MANUAL DE ACTUACIÓN (SIGUE EL ORDEN) ---
1. 🚨 SI ES URGENCIA: No agendes. Di que al ser urgente, el técnico contactará y acudirá lo antes posible.
2. ⏳ SI TIENE CITA PENDIENTE: Dile que su propuesta ya ha sido enviada al técnico y que le avisaréis en cuanto él la confirme en su agenda. NO busques otra fecha.
3. ✅ SI TIENE CITA CONFIRMADA: Recuérdale cuándo es, no agendes otra.
4. 📅 PARA AGENDAR (Si no aplica lo anterior):
- Sugiere un hueco libre (usando la Regla 2 de Rutas si es posible).
- ⚠️ CIERRE: Si el cliente ACEPTA, dile que la anotas para pasársela al técnico y que cuando él la vea, se confirmará.
- ⚠️ OBLIGATORIO: En el momento del cierre, añade AL FINAL tu respuesta el código oculto: [PROPUESTA:YYYY-MM-DD HH:mm]
5. SALUDO: ${esPrimerMensaje ? 'Preséntate diciendo que eres de ' + empresaNombre + ' y da el nº de aviso.' : 'NO TE PRESENTES. Ya habéis hablado, ve al grano.'}
6. FORMATO: Máximo 2 frases. Corto y al pie.
`;
const mensajesParaIA = [
@@ -534,7 +536,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
const completion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: mensajesParaIA,
temperature: 0.2, // Mantenemos creatividad baja para que respete el horario estrictamente
temperature: 0.2, // Creatividad baja para obedecer reglas y horarios
});
return completion.choices[0].message.content;
@@ -3058,6 +3060,9 @@ app.post("/webhook/evolution", async (req, res) => {
worker_id: service.assigned_to,
poblacion: service.poblacion || "", // 👈 CRÍTICO para buscar rutas en la misma zona
is_urgent: service.is_urgent // 👈 CRÍTICO para que no pida cita en urgencias
appointment_status: service.appointment_status,
cita_pendiente_fecha: service.cita_pendiente_fecha,
cita_pendiente_hora: service.cita_pendiente_hora
});
if (respuestaIA) {