Actualizar server.js
This commit is contained in:
63
server.js
63
server.js
@@ -440,14 +440,19 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
if (!settings.wa_ai_enabled) return null;
|
if (!settings.wa_ai_enabled) return null;
|
||||||
|
|
||||||
const promptSistema = `
|
const promptSistema = `
|
||||||
Eres el asistente virtual de la empresa "${empresaNombre}". Tu objetivo es ayudar a los clientes con sus reparaciones de hogar de forma profesional, amable y MUY concisa.
|
Eres el asistente de "${empresaNombre}".
|
||||||
|
DATOS EXPEDIENTE #${datosExpediente.ref}:
|
||||||
DATOS REALES DEL EXPEDIENTE #${datosExpediente.ref}:
|
- Estado: ${datosExpediente.estado}
|
||||||
- Estado actual: ${datosExpediente.estado}
|
- Cita actual: ${datosExpediente.cita || 'Ninguna'}
|
||||||
- Técnico asignado: ${datosExpediente.operario || 'Estamos asignando al mejor técnico para su caso'}
|
Eres el asistente de "${empresaNombre}".
|
||||||
- Cita programada: ${datosExpediente.cita || 'Pendiente de coordinar'}
|
|
||||||
|
REGLA DE CITAS (CRÍTICA):
|
||||||
REGLAS DE ORO:
|
- Tú NO confirmas citas finales, solo recoges la preferencia del cliente.
|
||||||
|
- Si el cliente propone un día/hora, responde: "He recibido su preferencia para el [FECHA]. Voy a consultarlo con el técnico asignado y le confirmaremos por aquí en cuanto valide su agenda."
|
||||||
|
- Al final de esa respuesta, añade el código: [PROPUESTA:DD-MM-YYYY HH:mm]
|
||||||
|
- Si el cliente no propone nada, dile que nos diga qué mañanas o tardes le vienen mejor para que el técnico se organice.
|
||||||
|
|
||||||
|
REGLAS DE ORO:
|
||||||
1. Si el cliente pregunta "¿Cuándo venís?", responde con la "Fecha Cita" si existe. Si no existe, di que la oficina le llamará en breve para agendar.
|
1. Si el cliente pregunta "¿Cuándo venís?", responde con la "Fecha Cita" si existe. Si no existe, di que la oficina le llamará en breve para agendar.
|
||||||
2. NUNCA inventes precios ni presupuestos. Si preguntan coste, di que el técnico debe valorar el daño in situ.
|
2. NUNCA inventes precios ni presupuestos. Si preguntan coste, di que el técnico debe valorar el daño in situ.
|
||||||
3. Si el cliente está enfadado o usa lenguaje ofensivo, di: "Siento las molestias. He dado aviso urgente a mis compañeros de la oficina para que le llamen ahora mismo".
|
3. Si el cliente está enfadado o usa lenguaje ofensivo, di: "Siento las molestias. He dado aviso urgente a mis compañeros de la oficina para que le llamen ahora mismo".
|
||||||
@@ -3030,11 +3035,45 @@ app.post("/webhook/evolution", async (req, res) => {
|
|||||||
cita: service.cita
|
cita: service.cita
|
||||||
});
|
});
|
||||||
|
|
||||||
if (respuestaIA) {
|
if (respuestaIA) {
|
||||||
await sendWhatsAppAuto(telefonoCliente, respuestaIA, instanceName, true);
|
// 1. --- MAGIA: DETECTAR SI LA IA RECOGIÓ UNA PROPUESTA DE CITA ---
|
||||||
|
const matchPropuesta = respuestaIA.match(/\[PROPUESTA:(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2})\]/);
|
||||||
|
|
||||||
|
if (matchPropuesta) {
|
||||||
|
const fechaSugerida = matchPropuesta[1];
|
||||||
|
const horaSugerida = matchPropuesta[2];
|
||||||
|
|
||||||
|
console.log(`📅 PROPUESTA RECIBIDA: ${fechaSugerida} a las ${horaSugerida} para exp #${service.service_ref}`);
|
||||||
|
|
||||||
|
// Actualizamos el siniestro indicando que hay una propuesta pendiente (sin confirmar cita final)
|
||||||
|
await pool.query(`
|
||||||
|
UPDATE scraped_services
|
||||||
|
SET raw_data = raw_data || jsonb_build_object(
|
||||||
|
'propuesta_cliente_fecha', $1,
|
||||||
|
'propuesta_cliente_hora', $2,
|
||||||
|
'status_ia', 'esperando_confirmacion_humana'
|
||||||
|
)
|
||||||
|
WHERE id = $3
|
||||||
|
`, [fechaSugerida, horaSugerida, service.id]);
|
||||||
|
|
||||||
|
// Registramos el movimiento para que salga en el historial del servicio
|
||||||
|
await registrarMovimiento(
|
||||||
|
service.id,
|
||||||
|
null,
|
||||||
|
"Propuesta de Cita",
|
||||||
|
`El cliente solicita cita para el ${fechaSugerida} a las ${horaSugerida}. Pendiente de confirmación por el operario.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. --- LIMPIEZA Y ENVÍO ---
|
||||||
|
// Quitamos el código [PROPUESTA:...] del texto para que el cliente no lo vea
|
||||||
|
const textoLimpio = respuestaIA.replace(/\[PROPUESTA:.*?\]/, "").trim();
|
||||||
|
|
||||||
|
await sendWhatsAppAuto(telefonoCliente, textoLimpio, instanceName, true);
|
||||||
|
|
||||||
|
// 3. --- REGISTRO DEL CHAT ---
|
||||||
await pool.query(`INSERT INTO service_communications (scraped_id, owner_id, sender_name, sender_role, message) VALUES ($1, $2, $3, $4, $5)`,
|
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]);
|
[service.id, ownerId, "Asistente IA", "ia", textoLimpio]);
|
||||||
await registrarMovimiento(service.id, null, "Respuesta IA", `ChatGPT respondió automáticamente.`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
|
|||||||
Reference in New Issue
Block a user