From e6c433587263876a385a93a5963e0f0603b07e38 Mon Sep 17 00:00:00 2001 From: marsalva Date: Sun, 8 Mar 2026 19:58:22 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/server.js b/server.js index 57278ba..9e70919 100644 --- a/server.js +++ b/server.js @@ -577,6 +577,80 @@ app.post("/auth/verify", async (req, res) => { } }); +// ========================================== +// 🤖 PUENTE AUTOMÁTICO HACIA HOMESERVE +// ========================================== +async function triggerHomeServeRobot(ownerId, serviceId, eventType) { + try { + // 1. Obtener la configuración del robot y los datos del servicio + const userQ = await pool.query("SELECT wa_settings FROM users WHERE id=$1", [ownerId]); + const settings = userQ.rows[0]?.wa_settings?.robot_homeserve || {}; + + const rule = settings[eventType]; + if (!rule || !rule.enabled) return; // Si la regla está apagada, abortamos. + + 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 || {}; + + // 2. Calcular la fecha de Siguiente Acción (SALTANDO FINES DE SEMANA) + let targetDate = new Date(); + + if (eventType === 'date' && rule.days_next === 0 && raw.scheduled_date) { + // Si es "Cita" y pusiste 0 días, usa la fecha exacta de la cita + const [y, m, d] = raw.scheduled_date.split('-'); + targetDate = new Date(y, m - 1, d); + } else { + // Sumar días hábiles reales + let added = 0; + while (added < (rule.days_next || 0)) { + targetDate.setDate(targetDate.getDate() + 1); + if (targetDate.getDay() !== 0 && targetDate.getDay() !== 6) { + added++; + } + } + } + + // Blindaje extra: Si cae en sábado (6) o domingo (0), lo pasamos al lunes + if (targetDate.getDay() === 6) targetDate.setDate(targetDate.getDate() + 2); + if (targetDate.getDay() === 0) targetDate.setDate(targetDate.getDate() + 1); + + const formattedDate = `${String(targetDate.getDate()).padStart(2, '0')}/${String(targetDate.getMonth() + 1).padStart(2, '0')}/${targetDate.getFullYear()}`; + + // 3. Traducir variables personalizadas + let text = rule.obs || ""; + text = text.replace(/{{NOMBRE}}/g, raw["Nombre Cliente"] || raw["CLIENTE"] || "Cliente"); + text = text.replace(/{{FECHA}}/g, raw["scheduled_date"] ? raw["scheduled_date"].split('-').reverse().join('/') : "la fecha acordada"); + text = text.replace(/{{HORA}}/g, raw["scheduled_time"] || "la hora acordada"); + + let phone = raw["Teléfono"] || raw["TELEFONO"] || raw["TELEFONOS"] || ""; + let cleanPhone = String(phone).replace(/\D/g, ""); + if (cleanPhone.length > 9) cleanPhone = cleanPhone.slice(-9); + text = text.replace(/{{TELEFONO}}/g, cleanPhone); + + text = text.replace(/{{REFERENCIA}}/g, s.service_ref); + text = text.replace(/{{NOMBRE_OPERARIO}}/g, s.worker_name || "el técnico"); + + // 4. Mandar la orden definitiva al Robot + await pool.query(` + INSERT INTO robot_queue (owner_id, provider, service_number, new_status, appointment_date, observation, inform_client) + VALUES ($1, 'homeserve', $2, $3, $4, $5, $6) + `, [ownerId, s.service_ref, rule.status, formattedDate, text, rule.check_inform]); + + console.log(`🤖 [ROBOT HS] Orden enviada a la cola para exp ${s.service_ref} (Regla: ${eventType})`); + + } catch(e) { + console.error("❌ Error en puente HomeServe:", e); + } +} + // ========================================== // 🕵️ ROBOT NOTARIO (TRAZABILIDAD TOTAL)