diff --git a/server.js b/server.js index f1730de..f5b32e8 100644 --- a/server.js +++ b/server.js @@ -600,7 +600,10 @@ async function triggerHomeServeRobot(ownerId, serviceId, eventType) { const settings = userQ.rows[0]?.wa_settings?.robot_homeserve || {}; const rule = settings[eventType]; - if (!rule || !rule.enabled) return; // Si la regla está apagada, abortamos. + if (!rule || !rule.enabled) { + console.log(`🤖 [ROBOT HS] Regla '${eventType}' desactivada. Omitiendo.`); + return; + } const svcQ = await pool.query(` SELECT s.service_ref, s.raw_data, u.full_name as worker_name @@ -613,52 +616,69 @@ async function triggerHomeServeRobot(ownerId, serviceId, eventType) { const s = svcQ.rows[0]; const raw = s.raw_data || {}; - // 2. Calcular la fecha de Siguiente Acción + // 2. Calcular la fecha de Siguiente Acción (Formato exacto HomeServe DD/MM/YYYY) let targetDate = new Date(); + let formattedDate = ""; - if (eventType === 'date') { + if (eventType === 'date' && raw.scheduled_date) { // 🎯 SI ES "CITA", usamos estrictamente la fecha en la que se ha agendado - if (raw.scheduled_date) { - const [y, m, d] = raw.scheduled_date.split('-'); - targetDate = new Date(y, m - 1, d); - } + const [y, m, d] = raw.scheduled_date.split('-'); + formattedDate = `${d.padStart(2, '0')}/${m.padStart(2, '0')}/${y}`; } else { - // 📅 SI ES "ASIGNAR" o "NO LOCALIZADO", sumamos los días a partir de HOY saltando fines de semana - let added = 0; - while (added < (rule.days_next || 0)) { - targetDate.setDate(targetDate.getDate() + 1); - if (targetDate.getDay() !== 0 && targetDate.getDay() !== 6) { - added++; - } - } - } - - // Blindaje extra anti-fines de semana (por si la cita o el salto caen en Sábado o Domingo) - if (targetDate.getDay() === 6) targetDate.setDate(targetDate.getDate() + 2); - if (targetDate.getDay() === 0) targetDate.setDate(targetDate.getDate() + 1); + // 📅 SI ES "ASIGNAR" o "NO LOCALIZADO", sumamos los días a partir de HOY + const daysToAdd = parseInt(rule.days_next) || 0; + targetDate.setDate(targetDate.getDate() + daysToAdd); + + // Blindaje: Si la fecha resultante cae en fin de semana, la movemos al Lunes + if (targetDate.getDay() === 6) targetDate.setDate(targetDate.getDate() + 2); // Si es Sábado -> Suma 2 días (Lunes) + else if (targetDate.getDay() === 0) targetDate.setDate(targetDate.getDate() + 1); // Si es Domingo -> Suma 1 día (Lunes) - const formattedDate = `${String(targetDate.getDate()).padStart(2, '0')}/${String(targetDate.getMonth() + 1).padStart(2, '0')}/${targetDate.getFullYear()}`; + 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}`; + } // 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"); + const clientName = raw["Nombre Cliente"] || raw["CLIENTE"] || "Cliente"; + let clientPhone = raw["Teléfono"] || raw["TELEFONO"] || raw["TELEFONOS"] || ""; + clientPhone = extractValidPhone(clientPhone); + + // Formateo humano de la fecha para el texto de observaciones + 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 { + // Si no hay cita agendada (Ej: No localizado), usamos la fecha de hoy para el texto + 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); - let phone = raw["Teléfono"] || raw["TELEFONO"] || raw["TELEFONOS"] || ""; - let cleanPhone = extractValidPhone(phone); - text = text.replace(/{{TELEFONO}}/g, cleanPhone); + // Si no hay hora (ej: No localizado), ponemos la hora actual + const horaActual = `${String(new Date().getHours()).padStart(2, '0')}:${String(new Date().getMinutes()).padStart(2, '0')}`; + text = text.replace(/{{HORA}}/g, raw["scheduled_time"] || horaActual); + 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"); - // 4. Mandar la orden definitiva al Robot + // 4. ESCUDO ANTI-POPUP HOMESERVE (Mínimo 20 caracteres) + if (text.length < 25) { + text += " - Actualizado por el sistema."; + } + + // 5. 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})`); + console.log(`🤖 [ROBOT HS] Orden enviada a la cola para exp ${s.service_ref} (Regla: ${eventType}) | Fecha: ${formattedDate} | Obs: "${text}"`); } catch(e) { console.error("❌ Error en puente HomeServe:", e);