Actualizar server.js
This commit is contained in:
47
server.js
47
server.js
@@ -857,14 +857,51 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
|||||||
|
|
||||||
let agendaOcupadaTexto = "El técnico tiene la agenda libre en horario laboral.";
|
let agendaOcupadaTexto = "El técnico tiene la agenda libre en horario laboral.";
|
||||||
if (datosExpediente.worker_id) {
|
if (datosExpediente.worker_id) {
|
||||||
const agendaQ = await pool.query("SELECT raw_data->>'scheduled_date' as date, raw_data->>'scheduled_time' as time, raw_data->>'Población' as pob FROM scraped_services WHERE assigned_to = $1 AND raw_data->>'scheduled_date' >= CURRENT_DATE::text AND status != 'archived' AND id != $2 ORDER BY date ASC, time ASC", [datosExpediente.worker_id, datosExpediente.dbId]);
|
// 🛑 NUEVO: Consulta avanzada que lee Duraciones, Bloqueos y Citas Pendientes
|
||||||
|
const agendaQ = await pool.query(`
|
||||||
|
SELECT
|
||||||
|
COALESCE(NULLIF(raw_data->>'scheduled_date', ''), raw_data->>'requested_date') as date,
|
||||||
|
COALESCE(NULLIF(raw_data->>'scheduled_time', ''), raw_data->>'requested_time') as time,
|
||||||
|
raw_data->>'duration_minutes' as duration,
|
||||||
|
raw_data->>'Población' as pob,
|
||||||
|
provider
|
||||||
|
FROM scraped_services
|
||||||
|
WHERE assigned_to = $1
|
||||||
|
AND status != 'archived'
|
||||||
|
AND id != $2
|
||||||
|
AND (
|
||||||
|
(raw_data->>'scheduled_date' IS NOT NULL AND raw_data->>'scheduled_date' >= CURRENT_DATE::text)
|
||||||
|
OR
|
||||||
|
(raw_data->>'appointment_status' = 'pending' AND raw_data->>'requested_date' >= CURRENT_DATE::text)
|
||||||
|
)
|
||||||
|
ORDER BY date ASC, time ASC
|
||||||
|
`, [datosExpediente.worker_id, datosExpediente.dbId]);
|
||||||
|
|
||||||
if (agendaQ.rowCount > 0) {
|
if (agendaQ.rowCount > 0) {
|
||||||
const ocupaciones = {};
|
const ocupaciones = {};
|
||||||
agendaQ.rows.forEach(r => { if(r.date && r.time) { if(!ocupaciones[r.date]) ocupaciones[r.date] = []; ocupaciones[r.date].push(`${r.time} (en ${r.pob || 'otra zona'})`); } });
|
agendaQ.rows.forEach(r => {
|
||||||
const lineas = Object.keys(ocupaciones).map(d => `- Día ${d}: Ocupado a las ${ocupaciones[d].join(", ")}`);
|
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 endMin = (h * 60 + m) + dur;
|
||||||
|
let endH = String(Math.floor(endMin / 60) % 24).padStart(2, '0');
|
||||||
|
let endM = String(endMin % 60).padStart(2, '0');
|
||||||
|
|
||||||
|
let tipo = r.provider === 'SYSTEM_BLOCK' ? 'BLOQUEO/AUSENCIA' : 'CITA';
|
||||||
|
let lugar = r.pob || 'Otra zona';
|
||||||
|
|
||||||
|
ocupaciones[r.date].push(`De ${r.time} a ${endH}:${endM} (${tipo} en ${lugar})`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const lineas = Object.keys(ocupaciones).map(d => `- Día ${d}:\n * ${ocupaciones[d].join("\n * ")}`);
|
||||||
if(lineas.length > 0) {
|
if(lineas.length > 0) {
|
||||||
agendaOcupadaTexto = "Citas actuales:\n " + lineas.join("\n ") +
|
agendaOcupadaTexto = "Ocupaciones actuales del técnico (Citas confirmadas, citas pendientes de aprobar y bloqueos):\n" + lineas.join("\n") +
|
||||||
"\n 👉 IMPORTANTE: Todas las demás horas (09:00, 11:00, 12:00, etc.) ESTÁN TOTALMENTE LIBRES. Ofrécelas sin miedo.";
|
"\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 entre el final de una cita y el inicio de la siguiente. NUNCA ofrezcas una hora que esté pegada a otra cita si hay desplazamiento.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user