Actualizar server.js
This commit is contained in:
56
server.js
56
server.js
@@ -434,24 +434,29 @@ async function registrarMovimiento(serviceId, userId, action, details) {
|
|||||||
|
|
||||||
async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||||
try {
|
try {
|
||||||
const userQ = await pool.query("SELECT wa_settings, full_name FROM users WHERE id=$1", [ownerId]);
|
// 1. Extraemos TODO: nombre, settings y horarios reales de la ruta
|
||||||
const settings = userQ.rows[0]?.wa_settings || {};
|
const userQ = await pool.query("SELECT wa_settings, full_name, portal_settings FROM users WHERE id=$1", [ownerId]);
|
||||||
const empresaNombre = userQ.rows[0]?.full_name || "nuestra empresa";
|
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;
|
if (!settings.wa_ai_enabled) return null;
|
||||||
|
|
||||||
// 🕒 1. Sincronización de Fecha Real
|
|
||||||
const ahora = new Date();
|
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(`
|
const chatCheck = await pool.query(`
|
||||||
SELECT id FROM service_communications
|
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]);
|
`, [datosExpediente.dbId]);
|
||||||
const yaSeHaPresentado = chatCheck.rowCount > 0;
|
const yaSeHaPresentado = chatCheck.rowCount > 0;
|
||||||
|
|
||||||
// 📍 3. Inteligencia de Ruta (Buscar técnicos cerca)
|
// 📍 LOGÍSTICA: Buscar técnicos cerca
|
||||||
const poblacion = datosExpediente.poblacion || "";
|
const poblacion = datosExpediente.poblacion || "";
|
||||||
let fechasSugeridas = "";
|
let fechasSugeridas = "";
|
||||||
|
|
||||||
@@ -459,10 +464,8 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
const rutasCercanas = await pool.query(`
|
const rutasCercanas = await pool.query(`
|
||||||
SELECT raw_data->>'scheduled_date' as fecha
|
SELECT raw_data->>'scheduled_date' as fecha
|
||||||
FROM scraped_services
|
FROM scraped_services
|
||||||
WHERE owner_id = $1
|
WHERE owner_id = $1 AND raw_data->>'Población' ILIKE $2
|
||||||
AND raw_data->>'Población' ILIKE $2
|
AND raw_data->>'scheduled_date' > CURRENT_DATE::text AND id != $3
|
||||||
AND raw_data->>'scheduled_date' >= CURRENT_DATE::text
|
|
||||||
AND id != $3
|
|
||||||
GROUP BY fecha ORDER BY fecha ASC LIMIT 2
|
GROUP BY fecha ORDER BY fecha ASC LIMIT 2
|
||||||
`, [ownerId, poblacion, datosExpediente.dbId]);
|
`, [ownerId, poblacion, datosExpediente.dbId]);
|
||||||
|
|
||||||
@@ -475,29 +478,32 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const promptSistema = `
|
const promptSistema = `
|
||||||
Eres el Asistente IA de "${empresaNombre}".
|
Eres el Asistente Humano de "${empresaNombre}". Tienes que ser MUY natural, cercano y resolutivo. Nada de sonar robótico.
|
||||||
Hoy es ${fechaHoyTexto}. Estamos en el año 2026.
|
|
||||||
|
|
||||||
|
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}:
|
DATOS EXPEDIENTE #${datosExpediente.ref}:
|
||||||
- Estado: ${datosExpediente.estado}
|
- Estado: ${datosExpediente.estado}
|
||||||
- Población: ${poblacion}
|
- Población: ${poblacion}
|
||||||
- Cita actual: ${datosExpediente.cita || 'Ninguna'}
|
|
||||||
|
|
||||||
LÓGICA DE SALUDO:
|
LÓGICA DE SALUDO (MUY IMPORTANTE):
|
||||||
${!yaSeHaPresentado
|
${!yaSeHaPresentado
|
||||||
? `- Inicio de chat: Preséntate brevemente y menciona el expediente #${datosExpediente.ref}.`
|
? `- Es el inicio. Preséntate con empatía: "¡Hola! Soy el asistente de ${empresaNombre}. Te escribo sobre tu aviso #${datosExpediente.ref}..."`
|
||||||
: `- Conversación fluida: NO te presentes, NO digas hola, ve directo a la respuesta.`
|
: `- ⛔ 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
|
${fechasSugeridas
|
||||||
? `- Tenemos otros técnicos en ${poblacion} el ${fechasSugeridas}. SUGIERE estas fechas prioritariamente para optimizar la ruta.`
|
? `- Casualmente tenemos técnicos yendo a ${poblacion} el ${fechasSugeridas}. Sugiere esas fechas amigablemente para aprovechar el viaje.`
|
||||||
: `- No hay rutas previas en ${poblacion}. Pide al cliente su preferencia de mañana o tarde.`
|
: `- Pregúntale qué día de Lunes a Viernes le viene bien y si prefiere mañana o tarde.`
|
||||||
}
|
}
|
||||||
|
|
||||||
REGLA DE CITAS:
|
REGLA PARA GUARDAR LA CITA:
|
||||||
- Si el cliente propone algo, di que lo consultas y añade al final: [PROPUESTA:YYYY-MM-DD HH:mm]
|
- 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]
|
||||||
- Máximo 2 frases. Sé muy natural, no parezcas un robot.
|
- 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({
|
const completion = await openai.chat.completions.create({
|
||||||
@@ -506,7 +512,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
{ role: "system", content: promptSistema },
|
{ role: "system", content: promptSistema },
|
||||||
{ role: "user", content: mensajeCliente }
|
{ 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;
|
return completion.choices[0].message.content;
|
||||||
|
|||||||
Reference in New Issue
Block a user