Actualizar server.js
This commit is contained in:
57
server.js
57
server.js
@@ -460,7 +460,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
|
|
||||||
const esPrimerMensaje = historialChat.length === 0;
|
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.";
|
let agendaOcupadaTexto = "El técnico tiene la agenda libre. Puedes sugerir cualquier hora dentro del horario laboral.";
|
||||||
if (datosExpediente.worker_id) {
|
if (datosExpediente.worker_id) {
|
||||||
const agendaQ = await pool.query(`
|
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 = `
|
const promptSistema = `
|
||||||
Eres el asistente humano de "${empresaNombre}". Hablas de tú, de forma muy natural, corta y directa por WhatsApp.
|
Eres el asistente humano de "${empresaNombre}". Hablas de tú, de forma muy natural, corta y directa por WhatsApp.
|
||||||
|
|
||||||
CONTEXTO DE TRABAJO:
|
--- CONTEXTO Y HORARIOS ---
|
||||||
- Hoy es: ${fechaHoyTexto}. (Año 2026).
|
- Hoy es: ${fechaHoyTexto}.
|
||||||
- Horario L-V: Mañanas (${horarios.m_start}-${horarios.m_end}) y Tardes (${horarios.a_start}-${horarios.a_end}).
|
- 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}
|
- Estado: ${datosExpediente.estado}
|
||||||
- Población: ${datosExpediente.poblacion}
|
- Población: ${datosExpediente.poblacion}
|
||||||
- Urgencia: ${datosExpediente.is_urgent ? 'SÍ' : 'No'}
|
- Urgencia: ${datosExpediente.is_urgent ? 'SÍ (Prioridad)' : 'No'}
|
||||||
- Cita actual: ${datosExpediente.cita || 'Ninguna'}
|
- Cita Confirmada: ${datosExpediente.cita || 'Ninguna'}
|
||||||
|
- Cita Solicitada PENDIENTE: ${textoCitaPendiente}
|
||||||
|
|
||||||
⚠️ CALENDARIO DEL TÉCNICO ASIGNADO (CRÍTICO):
|
--- ⚠️ CALENDARIO DEL TÉCNICO Y RUTAS ---
|
||||||
${agendaOcupadaTexto}
|
${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:
|
--- 🛠️ MANUAL DE ACTUACIÓN (SIGUE EL ORDEN) ---
|
||||||
1. SI ES URGENCIA: No agendes. Di que el técnico contactará urgente.
|
1. 🚨 SI ES URGENCIA: No agendes. Di que al ser urgente, el técnico contactará y acudirá lo antes posible.
|
||||||
2. PARA AGENDAR:
|
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.
|
||||||
- Si no hay fecha: Sugiere tú una hora libre basándote en su calendario.
|
3. ✅ SI TIENE CITA CONFIRMADA: Recuérdale cuándo es, no agendes otra.
|
||||||
- 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].
|
4. 📅 PARA AGENDAR (Si no aplica lo anterior):
|
||||||
3. NUNCA TE PRESENTES si ya estáis conversando. Ve al grano.
|
- Sugiere un hueco libre (usando la Regla 2 de Rutas si es posible).
|
||||||
${esPrimerMensaje ? '4. Como es el primer mensaje, preséntate diciendo de qué empresa eres.' : ''}
|
- ⚠️ CIERRE: Si el cliente ACEPTA, dile que la anotas para pasársela al técnico y que cuando él la vea, se confirmará.
|
||||||
5. Sé breve (máximo 1 o 2 frases).
|
- ⚠️ OBLIGATORIO: En el momento del cierre, añade AL FINAL tu respuesta el código oculto: [PROPUESTA:YYYY-MM-DD HH:mm]
|
||||||
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.
|
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.
|
||||||
⚠️ 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.
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const mensajesParaIA = [
|
const mensajesParaIA = [
|
||||||
@@ -534,7 +536,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
const completion = await openai.chat.completions.create({
|
const completion = await openai.chat.completions.create({
|
||||||
model: "gpt-4o-mini",
|
model: "gpt-4o-mini",
|
||||||
messages: mensajesParaIA,
|
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;
|
return completion.choices[0].message.content;
|
||||||
@@ -3058,6 +3060,9 @@ app.post("/webhook/evolution", async (req, res) => {
|
|||||||
worker_id: service.assigned_to,
|
worker_id: service.assigned_to,
|
||||||
poblacion: service.poblacion || "", // 👈 CRÍTICO para buscar rutas en la misma zona
|
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
|
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) {
|
if (respuestaIA) {
|
||||||
|
|||||||
Reference in New Issue
Block a user