Actualizar server.js
This commit is contained in:
59
server.js
59
server.js
@@ -913,6 +913,8 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
[ownerId]
|
||||
);
|
||||
|
||||
if (userQ.rowCount === 0) return null;
|
||||
|
||||
const userData = userQ.rows[0];
|
||||
const settings = userData?.wa_settings || {};
|
||||
const instruccionesExtra = settings.ai_custom_prompt || "";
|
||||
@@ -936,9 +938,8 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
day: "numeric"
|
||||
}).format(new Date());
|
||||
|
||||
// 👇 IMPORTANTE:
|
||||
// Aquí leemos el historial REAL, ya incluyendo el mensaje actual del cliente
|
||||
// que el webhook guardará antes de llamar a OpenAI.
|
||||
// Historial REAL del chat (ya incluye el último mensaje del cliente
|
||||
// si el webhook lo ha guardado antes de llamar a esta función)
|
||||
const historyQ = await pool.query(`
|
||||
SELECT sender_role, message
|
||||
FROM service_communications
|
||||
@@ -955,7 +956,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
content: row.message
|
||||
}));
|
||||
|
||||
// Si solo existe el mensaje actual del cliente, es primer mensaje
|
||||
// Si el historial solo tiene el mensaje actual del cliente, es primer contacto
|
||||
const esPrimerMensaje = historialRows.length <= 1;
|
||||
|
||||
let agendaOcupadaTexto = "✅ El técnico tiene la agenda libre en horario laboral.";
|
||||
@@ -988,11 +989,11 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
if (r.date && r.time && r.time.includes(':')) {
|
||||
if (!ocupaciones[r.date]) ocupaciones[r.date] = [];
|
||||
|
||||
let [h, m] = r.time.split(':').map(Number);
|
||||
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');
|
||||
const [h, m] = r.time.split(':').map(Number);
|
||||
const dur = parseInt(r.duration || 60, 10);
|
||||
const endMin = (h * 60 + m) + dur;
|
||||
const endH = String(Math.floor(endMin / 60) % 24).padStart(2, '0');
|
||||
const endM = String(endMin % 60).padStart(2, '0');
|
||||
|
||||
const tipo = r.provider === 'SYSTEM_BLOCK' ? 'BLOQUEO/AUSENCIA' : 'CITA';
|
||||
const lugar = r.pob || 'Otra zona';
|
||||
@@ -1008,6 +1009,7 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
day: 'numeric',
|
||||
month: 'long'
|
||||
});
|
||||
|
||||
return `- Día ${fechaHumana} (${d}):\n * ${ocupaciones[d].join("\n * ")}`;
|
||||
});
|
||||
|
||||
@@ -1021,21 +1023,27 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
}
|
||||
}
|
||||
|
||||
const hayCitaPendiente = datosExpediente.appointment_status === 'pending' && datosExpediente.cita_pendiente_fecha;
|
||||
const tieneCitaConfirmada = datosExpediente.cita && datosExpediente.cita !== 'Ninguna';
|
||||
const hayCitaPendiente =
|
||||
datosExpediente.appointment_status === 'pending' &&
|
||||
datosExpediente.cita_pendiente_fecha;
|
||||
|
||||
const tieneCitaConfirmada =
|
||||
datosExpediente.cita &&
|
||||
datosExpediente.cita !== 'Ninguna';
|
||||
|
||||
const esUrgencia = datosExpediente.is_urgent;
|
||||
|
||||
let tramoPendiente = datosExpediente.cita_pendiente_hora || "";
|
||||
if (tramoPendiente && tramoPendiente.includes(":")) {
|
||||
let [h, m] = tramoPendiente.split(':');
|
||||
let hEnd = String((parseInt(h) + 1) % 24).padStart(2, '0');
|
||||
const [h, m] = tramoPendiente.split(':');
|
||||
const hEnd = String((parseInt(h, 10) + 1) % 24).padStart(2, '0');
|
||||
tramoPendiente = `entre las ${h}:${m} y las ${hEnd}:${m} aprox`;
|
||||
}
|
||||
|
||||
let tramoConfirmado = datosExpediente.hora_cita || "";
|
||||
if (tramoConfirmado && tramoConfirmado.includes(":")) {
|
||||
let [h, m] = tramoConfirmado.split(':');
|
||||
let hEnd = String((parseInt(h) + 1) % 24).padStart(2, '0');
|
||||
const [h, m] = tramoConfirmado.split(':');
|
||||
const hEnd = String((parseInt(h, 10) + 1) % 24).padStart(2, '0');
|
||||
tramoConfirmado = `entre las ${h}:${m} y las ${hEnd}:${m} aprox`;
|
||||
} else {
|
||||
tramoConfirmado = 'una hora por confirmar';
|
||||
@@ -1049,7 +1057,9 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
if (citaTime < hoyTime) citaYaPaso = true;
|
||||
}
|
||||
|
||||
const esEstadoFinal = datosExpediente.estado && (
|
||||
const esEstadoFinal =
|
||||
datosExpediente.estado &&
|
||||
(
|
||||
datosExpediente.estado.toLowerCase().includes('finalizado') ||
|
||||
datosExpediente.estado.toLowerCase().includes('terminado') ||
|
||||
datosExpediente.estado.toLowerCase().includes('anulado')
|
||||
@@ -1062,17 +1072,25 @@ async function procesarConIA(ownerId, mensajeCliente, datosExpediente) {
|
||||
if (esEstadoFinal) {
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: SERVICIO CERRADO. Informa al cliente que el servicio por su avería (${datosExpediente.averia}) está finalizado. NO AGENDES NADA.`;
|
||||
} else if (noTieneTecnico) {
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: SIN TÉCNICO ASIGNADO.\nTU ÚNICO OBJETIVO: Informar al cliente que hemos recibido el aviso de su avería (${datosExpediente.averia}) y que estamos coordinando para asignarle un técnico en su zona.\n⛔ PROHIBICIÓN ABSOLUTA: NO ofrezcas citas, NO des horas, NO agendes nada hasta que se le asigne un técnico.`;
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: SIN TÉCNICO ASIGNADO.
|
||||
TU ÚNICO OBJETIVO: Informar al cliente que hemos recibido el aviso de su avería (${datosExpediente.averia}) y que estamos coordinando para asignarle un técnico en su zona.
|
||||
⛔ PROHIBICIÓN ABSOLUTA: NO ofrezcas citas, NO des horas, NO agendes nada hasta que se le asigne un técnico.`;
|
||||
} else if (citaYaPaso) {
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: LA CITA YA PASÓ (${datosExpediente.cita}). Informa que estamos tramitando su avería (${datosExpediente.averia}). NO AGENDES NADA.`;
|
||||
} else if (esUrgencia) {
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: URGENCIA. Tranquiliza al cliente sobre su avería (${datosExpediente.averia}) y dile que el técnico está avisado. NO PROPONGAS HORAS.`;
|
||||
} else if (hayCitaPendiente) {
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: CITA PENDIENTE DE APROBACIÓN.\n📅 Propuesta actual: El día ${datosExpediente.cita_pendiente_fecha} ${tramoPendiente}.\nTU OBJETIVO: Informar que esperamos confirmación del técnico para reparar su avería (${datosExpediente.averia}).\n⚠️ EXCEPCIÓN: Si el cliente pide CAMBIAR o CANCELAR, ofrécele un hueco nuevo.`;
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: CITA PENDIENTE DE APROBACIÓN.
|
||||
📅 Propuesta actual: El día ${datosExpediente.cita_pendiente_fecha} ${tramoPendiente}.
|
||||
TU OBJETIVO: Informar que esperamos confirmación del técnico para reparar su avería (${datosExpediente.averia}).
|
||||
⚠️ EXCEPCIÓN: Si el cliente pide CAMBIAR o CANCELAR, ofrécele un hueco nuevo.`;
|
||||
} else if (tieneCitaConfirmada) {
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: CITA CONFIRMADA para el ${datosExpediente.cita} ${tramoConfirmado}. Recuerda la cita para su avería (${datosExpediente.averia}).\n⚠️ EXCEPCIÓN: Si el cliente pide CAMBIARLA o CANCELARLA, ofrécele un hueco nuevo.`;
|
||||
directivaEstricta = `🛑 ESTADO ACTUAL: CITA CONFIRMADA para el ${datosExpediente.cita} ${tramoConfirmado}. Recuerda la cita para su avería (${datosExpediente.averia}).
|
||||
⚠️ EXCEPCIÓN: Si el cliente pide CAMBIARLA o CANCELARLA, ofrécele un hueco nuevo.`;
|
||||
} else {
|
||||
directivaEstricta = `🟢 ESTADO ACTUAL: PENDIENTE DE AGENDAR CITA.\nTU OBJETIVO: Acordar fecha y hora para reparar su avería (${datosExpediente.averia}). NUNCA ofrezcas horas ocupadas. Fines de semana solo URGENCIAS.\n⚠️ MUY IMPORTANTE: Cuando el cliente elija un hueco, NO le digas que la cita está confirmada. Dile que le pasas la nota al técnico para que él lo valide.`;
|
||||
directivaEstricta = `🟢 ESTADO ACTUAL: PENDIENTE DE AGENDAR CITA.
|
||||
TU OBJETIVO: Acordar fecha y hora para reparar su avería (${datosExpediente.averia}). NUNCA ofrezcas horas ocupadas. Fines de semana solo URGENCIAS.
|
||||
⚠️ MUY IMPORTANTE: Cuando el cliente elija un hueco, NO le digas que la cita está confirmada. Dile que le pasas la nota al técnico para que él lo valide.`;
|
||||
}
|
||||
|
||||
const promptSistema = `
|
||||
@@ -1124,6 +1142,7 @@ ${instruccionesExtra ? `6. Instrucción extra de la empresa: ${instruccionesExtr
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ==========================================
|
||||
// 📱 OTP PARA PORTAL DEL CLIENTE (ACCESO WEB)
|
||||
// ==========================================
|
||||
|
||||
Reference in New Issue
Block a user