Actualizar server.js

This commit is contained in:
2026-03-11 09:40:49 +00:00
parent b333b0d0dc
commit 2c1391bb38

143
server.js
View File

@@ -685,6 +685,91 @@ async function triggerHomeServeRobot(ownerId, serviceId, eventType) {
} }
} }
// ==========================================
// 🤖 PUENTE AUTOMÁTICO HACIA MULTIASISTENCIA
// ==========================================
async function triggerMultiRobot(ownerId, serviceId, eventType) {
try {
const userQ = await pool.query("SELECT wa_settings FROM users WHERE id=$1", [ownerId]);
const settings = userQ.rows[0]?.wa_settings?.robot_multi || {};
const rule = settings[eventType];
if (!rule || !rule.enabled) {
console.log(`🤖 [ROBOT MULTI] Regla '${eventType}' desactivada. Omitiendo.`);
return;
}
const svcQ = await pool.query(`
SELECT s.service_ref, s.raw_data, u.full_name as worker_name
FROM scraped_services s
LEFT JOIN users u ON s.assigned_to = u.id
WHERE s.id = $1
`, [serviceId]);
if (svcQ.rowCount === 0) return;
const s = svcQ.rows[0];
const raw = s.raw_data || {};
let targetDate = new Date();
let formattedDate = "";
let formattedTime = "";
if (eventType === 'date' && raw.scheduled_date) {
const [y, m, d] = raw.scheduled_date.split('-');
formattedDate = `${d.padStart(2, '0')}/${m.padStart(2, '0')}/${y}`;
formattedTime = raw.scheduled_time || "";
} else {
const daysToAdd = parseInt(rule.days_next) || 0;
targetDate.setDate(targetDate.getDate() + daysToAdd);
if (targetDate.getDay() === 6) targetDate.setDate(targetDate.getDate() + 2);
else if (targetDate.getDay() === 0) targetDate.setDate(targetDate.getDate() + 1);
const dd = String(targetDate.getDate()).padStart(2, '0');
const mm = String(targetDate.getMonth() + 1).padStart(2, '0');
const yyyy = targetDate.getFullYear();
formattedDate = `${dd}/${mm}/${yyyy}`;
const horaActual = `${String(new Date().getHours()).padStart(2, '0')}:${String(new Date().getMinutes()).padStart(2, '0')}`;
formattedTime = raw.scheduled_time || horaActual;
}
let text = rule.obs || "";
const clientName = raw["Nombre Cliente"] || raw["CLIENTE"] || "Cliente";
let clientPhone = raw["Teléfono"] || raw["TELEFONO"] || raw["TELEFONOS"] || "";
clientPhone = extractValidPhone(clientPhone);
let textoFechaCita = "hoy";
if (raw.scheduled_date) {
const [y, m, d] = raw.scheduled_date.split('-');
textoFechaCita = `${d.padStart(2, '0')}/${m.padStart(2, '0')}/${y}`;
} else {
const hoy = new Date();
textoFechaCita = `${String(hoy.getDate()).padStart(2, '0')}/${String(hoy.getMonth() + 1).padStart(2, '0')}/${hoy.getFullYear()}`;
}
text = text.replace(/{{NOMBRE}}/g, clientName);
text = text.replace(/{{FECHA}}/g, textoFechaCita);
text = text.replace(/{{HORA}}/g, formattedTime);
text = text.replace(/{{TELEFONO}}/g, clientPhone);
text = text.replace(/{{REFERENCIA}}/g, s.service_ref);
text = text.replace(/{{NOMBRE_OPERARIO}}/g, s.worker_name || "el técnico");
// Añadimos columna si no existe por si acaso
await pool.query(`ALTER TABLE robot_queue ADD COLUMN IF NOT EXISTS appointment_time TEXT;`).catch(() => {});
await pool.query(`
INSERT INTO robot_queue (owner_id, provider, service_number, new_status, appointment_date, appointment_time, observation, inform_client)
VALUES ($1, 'multiasistencia', $2, $3, $4, $5, $6, false)
`, [ownerId, s.service_ref, rule.status, formattedDate, formattedTime, text]);
console.log(`🤖 [ROBOT MULTI] Orden enviada a la cola para exp ${s.service_ref} (Regla: ${eventType}) | Fecha: ${formattedDate} | Hora: ${formattedTime}`);
} catch(e) {
console.error("❌ Error en puente Multiasistencia:", e);
}
}
// ========================================== // ==========================================
// 🕵️ ROBOT NOTARIO (TRAZABILIDAD TOTAL) // 🕵️ ROBOT NOTARIO (TRAZABILIDAD TOTAL)
@@ -1633,22 +1718,38 @@ app.put('/providers/scraped/:id', authMiddleware, async (req, res) => {
else triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_update').catch(console.error); else triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_update').catch(console.error);
} }
// 🚀 DISPARAR ROBOT HOMESERVE // 🚀 DISPARAR ROBOTS SEGÚN PROVEEDOR
const checkHs = await pool.query("SELECT provider FROM scraped_services WHERE id=$1", [id]); const checkProvider = await pool.query("SELECT provider FROM scraped_services WHERE id=$1", [id]);
if (checkHs.rows[0]?.provider === 'homeserve') { const providerName = checkProvider.rows[0]?.provider;
if (providerName === 'homeserve') {
if (statusChanged && isAsignado && finalAssignedTo) { if (statusChanged && isAsignado && finalAssignedTo) {
console.log("✅ [ADMIN] Disparando robot: ASIGNACIÓN"); console.log("✅ [ADMIN] Disparando robot HS: ASIGNACIÓN");
triggerHomeServeRobot(req.user.accountId, id, 'assign').catch(console.error); triggerHomeServeRobot(req.user.accountId, id, 'assign').catch(console.error);
} }
if (isCitado && (statusChanged || dateChanged) && newDate !== "" && newDate !== "null") { if (isCitado && (statusChanged || dateChanged) && newDate !== "" && newDate !== "null") {
console.log(`✅ [ADMIN] Disparando robot: CITA (${newDate})`); console.log(`✅ [ADMIN] Disparando robot HS: CITA (${newDate})`);
triggerHomeServeRobot(req.user.accountId, id, 'date').catch(console.error); triggerHomeServeRobot(req.user.accountId, id, 'date').catch(console.error);
} }
if (isNoLocalizado && statusChanged) { if (isNoLocalizado && statusChanged) {
console.log(`✅ [ADMIN] Disparando robot: NO LOCALIZADO`); console.log(`✅ [ADMIN] Disparando robot HS: NO LOCALIZADO`);
triggerHomeServeRobot(req.user.accountId, id, 'notfound').catch(console.error); triggerHomeServeRobot(req.user.accountId, id, 'notfound').catch(console.error);
} }
} }
else if (providerName === 'multiasistencia') {
if (statusChanged && isAsignado && finalAssignedTo) {
console.log("✅ [ADMIN] Disparando robot MULTI: ASIGNACIÓN");
triggerMultiRobot(req.user.accountId, id, 'assign').catch(console.error);
}
if (isCitado && (statusChanged || dateChanged) && newDate !== "" && newDate !== "null") {
console.log(`✅ [ADMIN] Disparando robot MULTI: CITA (${newDate})`);
triggerMultiRobot(req.user.accountId, id, 'date').catch(console.error);
}
if (isNoLocalizado && statusChanged) {
console.log(`✅ [ADMIN] Disparando robot MULTI: NO LOCALIZADO`);
triggerMultiRobot(req.user.accountId, id, 'notfound').catch(console.error);
}
}
res.json({ ok: true }); res.json({ ok: true });
} catch (error) { } catch (error) {
@@ -1772,32 +1873,45 @@ app.put("/services/set-appointment/:id", authMiddleware, async (req, res) => {
console.log(`🤖 [DEBUG APP-OP] Exp: ${id} | Estado: '${stName}' | statusChanged: ${statusChanged} | dateChanged: ${dateChanged}`); console.log(`🤖 [DEBUG APP-OP] Exp: ${id} | Estado: '${stName}' | statusChanged: ${statusChanged} | dateChanged: ${dateChanged}`);
const checkHs = await pool.query("SELECT provider FROM scraped_services WHERE id=$1", [id]); // 🚀 CAMBIO CLAVE: LEER PROVEEDOR REAL (HOME SERVE O MULTIASISTENCIA)
const isHomeServe = checkHs.rows[0]?.provider === 'homeserve'; const checkProv = await pool.query("SELECT provider FROM scraped_services WHERE id=$1", [id]);
const providerName = checkProv.rows[0]?.provider;
const isAsignado = stName.includes('asignado'); const isAsignado = stName.includes('asignado');
const isCitado = stName.includes('citado') || stName.includes('cita') || stName.includes('agendado'); const isCitado = stName.includes('citado') || stName.includes('cita') || stName.includes('agendado');
// --- ASIGNADO --- // --- ASIGNADO ---
if (statusChanged && isAsignado) { if (statusChanged && isAsignado) {
if (isHomeServe) triggerHomeServeRobot(req.user.accountId, id, 'assign').catch(console.error);
// Disparar Robot Inteligente
if (providerName === 'homeserve') triggerHomeServeRobot(req.user.accountId, id, 'assign').catch(console.error);
else if (providerName === 'multiasistencia') triggerMultiRobot(req.user.accountId, id, 'assign').catch(console.error);
// Notificar por WhatsApp y cambiar a Esperando al Cliente si tiene éxito
const waEnviadoExito = await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_assigned'); const waEnviadoExito = await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_assigned');
if (waEnviadoExito) { if (waEnviadoExito) {
const estadoEsperando = await pool.query("SELECT id FROM service_statuses WHERE owner_id=$1 AND name='Esperando al Cliente' LIMIT 1", [req.user.accountId]); const estadoEsperando = await pool.query("SELECT id FROM service_statuses WHERE owner_id=$1 AND name='Esperando al Cliente' LIMIT 1", [req.user.accountId]);
if (estadoEsperando.rowCount > 0) { if (estadoEsperando.rowCount > 0) {
updatedRawData.status_operativo = estadoEsperando.rows[0].id; updatedRawData.status_operativo = estadoEsperando.rows[0].id;
await pool.query('UPDATE scraped_services SET raw_data = $1 WHERE id = $2', [JSON.stringify(updatedRawData), id]); await pool.query('UPDATE scraped_services SET raw_data = $1 WHERE id = $2 AND owner_id = $3', [JSON.stringify(updatedRawData), id, req.user.accountId]);
} }
} }
} }
// --- CITADO (CONFIRMAR CITA) --- // --- CITADO (CONFIRMAR CITA) ---
else if (isCitado && (statusChanged || dateChanged)) { else if (isCitado && (statusChanged || dateChanged)) {
if (isHomeServe && newDate !== "") { if (newDate !== "") {
console.log(`✅ [APP-OP] Disparando robot: CITA (${newDate})`); // Disparar Robot Inteligente
triggerHomeServeRobot(req.user.accountId, id, 'date').catch(console.error); if (providerName === 'homeserve') {
console.log(`✅ [APP-OP] Disparando robot HS: CITA (${newDate})`);
triggerHomeServeRobot(req.user.accountId, id, 'date').catch(console.error);
} else if (providerName === 'multiasistencia') {
console.log(`✅ [APP-OP] Disparando robot MULTI: CITA (${newDate})`);
triggerMultiRobot(req.user.accountId, id, 'date').catch(console.error);
}
} }
// Notificar por WhatsApp
if (oldDate === "") await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_date'); if (oldDate === "") await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_date');
else if (oldDate !== newDate) await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_update'); else if (oldDate !== newDate) await triggerWhatsAppEvent(req.user.accountId, id, 'wa_evt_update');
} }
@@ -1818,9 +1932,6 @@ app.put("/services/set-appointment/:id", authMiddleware, async (req, res) => {
} }
}); });
// ==========================================
// 📞 RUTA PARA CLIENTE NO LOCALIZADO
// ==========================================
// ========================================== // ==========================================
// 📞 RUTA PARA CLIENTE NO LOCALIZADO // 📞 RUTA PARA CLIENTE NO LOCALIZADO