Actualizar server.js
This commit is contained in:
46
server.js
46
server.js
@@ -895,12 +895,12 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
if (agendaQ.rowCount > 0) {
|
||||
const ocupaciones = {};
|
||||
agendaQ.rows.forEach(r => {
|
||||
if(r.date && r.time && r.time.includes(':')) {
|
||||
if(!ocupaciones[r.date]) ocupaciones[r.date] = [];
|
||||
if (r.date && r.time && r.time.includes(':')) {
|
||||
if (!ocupaciones[r.date]) ocupaciones[r.date] = [];
|
||||
|
||||
// Calculamos la hora de fin exacta sumando la duración (Ej: 60, 120, 180 min)
|
||||
let [h, m] = r.time.split(':').map(Number);
|
||||
let dur = parseInt(r.duration || 60);
|
||||
let dur = parseInt(r.duration || 60, 10);
|
||||
let endMin = (h * 60 + m) + dur;
|
||||
let endH = String(Math.floor(endMin / 60) % 24).padStart(2, '0');
|
||||
let endM = String(endMin % 60).padStart(2, '0');
|
||||
@@ -912,8 +912,17 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
}
|
||||
});
|
||||
|
||||
const lineas = Object.keys(ocupaciones).map(d => `- Día ${d}:\n * ${ocupaciones[d].join("\n * ")}`);
|
||||
if(lineas.length > 0) {
|
||||
const lineas = Object.keys(ocupaciones).sort().map(d => {
|
||||
const [y, m, day] = d.split('-').map(Number);
|
||||
const fechaHumana = new Date(y, m - 1, day, 12, 0, 0).toLocaleDateString('es-ES', {
|
||||
weekday: 'long',
|
||||
day: 'numeric',
|
||||
month: 'long'
|
||||
});
|
||||
return `- Día ${fechaHumana} (${d}):\n * ${ocupaciones[d].join("\n * ")}`;
|
||||
});
|
||||
|
||||
if (lineas.length > 0) {
|
||||
agendaOcupadaTexto = "Ocupaciones actuales del técnico (Citas confirmadas, pendientes y bloqueos):\n" + lineas.join("\n") +
|
||||
"\n\n👉 IMPORTANTE: Todas las horas que NO se solapen con esos tramos exactos ESTÁN LIBRES." +
|
||||
"\n🚨 REGLA LOGÍSTICA ESTRICTA: El técnico necesita tiempo para viajar. Si el cliente actual es de una localidad distinta a la cita anterior o posterior (ej: Algeciras vs La Línea), ES OBLIGATORIO dejar un margen de al menos 45-60 minutos de viaje entre el final de una cita y el inicio de la siguiente. NUNCA ofrezcas horas pegadas si hay desplazamiento.";
|
||||
@@ -4054,10 +4063,27 @@ app.post("/webhook/evolution", async (req, res) => {
|
||||
// 🛡️ REGEX BLINDADO: Pilla la etiqueta aunque la IA meta espacios raros
|
||||
const matchPropuesta = respuestaIA.match(/\[PROPUESTA:\s*(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2})\]/i);
|
||||
|
||||
// 🧹 BORRAMOS EL TEXTO DEL CÓDIGO PARA QUE EL CLIENTE NO LO VEA NUNCA
|
||||
let textoLimpio = respuestaIA.replace(/\[PROPUESTA:.*?\]/gi, "").replace(/código:/gi, "").trim();
|
||||
|
||||
if (matchPropuesta) {
|
||||
const fechaSugerida = matchPropuesta[1];
|
||||
const horaSugerida = matchPropuesta[2];
|
||||
|
||||
// 🛡️ ESCUDO ANTI-SOLAPE: comprobamos antes de guardar la propuesta
|
||||
const disponibilidad = await comprobarDisponibilidad(
|
||||
ownerId,
|
||||
service.assigned_to,
|
||||
fechaSugerida,
|
||||
horaSugerida,
|
||||
60,
|
||||
service.id
|
||||
);
|
||||
|
||||
if (disponibilidad.choca) {
|
||||
console.log(`⛔ [DOBLE-BOOKING EVITADO] Exp ${service.service_ref} chocaba con ${disponibilidad.ref} a las ${disponibilidad.time}`);
|
||||
textoLimpio = "Uy, perdona, se me acaban de cruzar los cables y justo me han bloqueado ese hueco por el sistema interno. 😅 ¿Me dices otra hora que te venga bien?";
|
||||
} else {
|
||||
// 🚀 GUARDADO COMO PENDIENTE (Espera a que el Técnico la apruebe en la App o en la Oficina)
|
||||
await pool.query(`
|
||||
UPDATE scraped_services
|
||||
@@ -4068,13 +4094,13 @@ app.post("/webhook/evolution", async (req, res) => {
|
||||
) WHERE id = $3
|
||||
`, [fechaSugerida, horaSugerida, service.id]);
|
||||
}
|
||||
|
||||
// 🧹 BORRAMOS EL TEXTO DEL CÓDIGO PARA QUE EL CLIENTE NO LO VEA NUNCA
|
||||
const textoLimpio = respuestaIA.replace(/\[PROPUESTA:.*?\]/gi, "").replace(/código:/gi, "").trim();
|
||||
}
|
||||
|
||||
await sendWhatsAppAuto(telefonoCliente, textoLimpio, instanceName, true);
|
||||
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", textoLimpio]);
|
||||
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", textoLimpio]
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
candadosIA.delete(service.id);
|
||||
|
||||
Reference in New Issue
Block a user