Añade envio de WhatsApp de bienvenida al crear un expediente nuevo

This commit is contained in:
2026-08-20 21:37:51 +00:00
parent 82738de6fa
commit c15a0fc41b

121
robot.js
View File

@@ -496,13 +496,121 @@ async function syncAndArchive(ownerId, provider, currentWebRefs) {
}
}
// ==========================================
// 👋 MENSAJE DE BIENVENIDA (WHATSAPP AL CLIENTE, SOLO EXPEDIENTES NUEVOS)
// ==========================================
const { EVOLUTION_BASE_URL, EVOLUTION_API_KEY } = process.env;
function extractValidPhoneRobot(rawPhone) {
if (!rawPhone) return "";
let str = String(rawPhone).replace(/\D/g, "");
if (str.startsWith("0034")) str = str.slice(4);
if (str.startsWith("34") && str.length >= 11) str = str.slice(2);
const match = str.match(/[6789]\d{8}/);
return match ? match[0] : (str.length >= 9 ? str.slice(-9) : str);
}
async function sendWhatsAppWelcomeText(phone, message, instanceName) {
if (!EVOLUTION_BASE_URL || !EVOLUTION_API_KEY) {
console.log("⚠️ [Bienvenida] Faltan EVOLUTION_BASE_URL / EVOLUTION_API_KEY en este robot. Se omite el envío.");
return false;
}
try {
const baseUrl = EVOLUTION_BASE_URL.replace(/\/$/, "");
const url = `${baseUrl}/message/sendText/${instanceName}`;
const response = await fetch(url, {
method: 'POST',
headers: { "Content-Type": "application/json", "apikey": EVOLUTION_API_KEY.trim() },
body: JSON.stringify({ number: phone, text: message, delay: 0 })
});
if (!response.ok) {
console.error("❌ [Bienvenida] Fallo enviando WhatsApp. Estado Evolution:", response.status);
return false;
}
return true;
} catch (e) {
console.error("❌ [Bienvenida] Error de red con Evolution API:", e.message);
return false;
}
}
const NOMBRE_COMPANIA_POR_PROVEEDOR = { multiasistencia: 'Multiasistencia', homeserve: 'HomeServe' };
// Réplica ligera de la lógica de triggerWhatsAppEvent('wa_evt_welcome') de server.js,
// pero autocontenida aquí porque el robot no pasa por el servidor (escribe directo a la BD).
async function sendWelcomeMessage(ownerId, provider, ref, data, serviceId) {
// 1. ¿Tiene la empresa activado el aviso de bienvenida?
const userQ = await pool.query("SELECT wa_settings FROM users WHERE id=$1", [ownerId]);
const settings = userQ.rows[0]?.wa_settings || {};
if (!settings.wa_evt_welcome) return;
// 2. ¿Existe la plantilla de bienvenida y tiene contenido?
const tplQ = await pool.query("SELECT content FROM message_templates WHERE owner_id=$1 AND type='welcome'", [ownerId]);
if (tplQ.rowCount === 0 || !tplQ.rows[0].content) return;
let text = tplQ.rows[0].content;
// 3. Teléfono válido
const cleanPhone = extractValidPhoneRobot(data['Teléfono']);
if (cleanPhone.length < 9) {
console.log(`⚠️ [Bienvenida] Expediente #${ref}: sin teléfono válido, no se envía.`);
return;
}
const finalPhone = "34" + cleanPhone;
// 4. Enlace al portal del cliente (por si la plantilla lo usa)
let enlace = "";
try {
const clientQ = await pool.query("SELECT portal_token FROM clients WHERE phone LIKE $1 AND owner_id=$2 LIMIT 1", [`%${cleanPhone}%`, ownerId]);
let token;
if (clientQ.rowCount > 0) {
token = clientQ.rows[0].portal_token;
} else {
const insertC = await pool.query(
"INSERT INTO clients (owner_id, full_name, phone, addresses) VALUES ($1, $2, $3, $4) RETURNING portal_token",
[ownerId, data['Nombre Cliente'] || "Asegurado", finalPhone, JSON.stringify([data['Dirección'] || ""])]
);
token = insertC.rows[0].portal_token;
}
enlace = `https://portal.integrarepara.es/?token=${token}&service=${serviceId}`;
} catch (e) {
console.error(`⚠️ [Bienvenida] No se pudo generar el enlace del portal para #${ref}:`, e.message);
}
// 5. Sustituir variables de la plantilla
text = text.replace(/{{NOMBRE}}/g, data['Nombre Cliente'] || "Cliente");
text = text.replace(/{{DIRECCION}}/g, data['Dirección'] || "su domicilio");
text = text.replace(/{{FECHA}}/g, "la fecha acordada");
text = text.replace(/{{HORA}}/g, "la hora acordada");
text = text.replace(/{{COMPANIA}}/g, NOMBRE_COMPANIA_POR_PROVEEDOR[provider] || "su Aseguradora");
text = text.replace(/{{REFERENCIA}}/g, ref);
text = text.replace(/{{ENLACE}}/g, enlace);
// 6. Enviar
const instanceName = `cliente_${ownerId}`;
const ok = await sendWhatsAppWelcomeText(finalPhone, text, instanceName);
if (ok) console.log(`👋 [Bienvenida] WhatsApp enviado a ${finalPhone} para el expediente #${ref}.`);
}
async function saveServiceToDB(ownerId, provider, ref, data) {
console.log(`💾 Guardando/Actualizando ${provider.toUpperCase()} ${ref}...`);
// Aquí está la solución al problema del tilde ("sí" vs "si") que te comenté antes
const isUrgent = (data['Urgente'] && (data['Urgente'].toLowerCase().trim() === 'sí' || data['Urgente'].toLowerCase().trim() === 'si')) ? true : false;
await pool.query(`
// 👋 NUEVO: Comprobamos ANTES de guardar si este expediente ya existía en el buzón,
// para saber si hay que disparar el WhatsApp de bienvenida (solo la primera vez que aparece).
let isNewRecord = false;
try {
const preCheck = await pool.query(
"SELECT id FROM scraped_services WHERE owner_id=$1 AND provider=$2 AND service_ref=$3",
[ownerId, provider, ref]
);
isNewRecord = preCheck.rowCount === 0;
} catch (e) {
console.error(`⚠️ [Bienvenida] No se pudo comprobar si ${ref} es nuevo:`, e.message);
}
const result = await pool.query(`
INSERT INTO scraped_services (owner_id, provider, service_ref, raw_data, status, is_urgent)
VALUES ($1, $2, $3, $4, 'pending', $5)
ON CONFLICT (owner_id, provider, service_ref)
@@ -517,7 +625,18 @@ async function saveServiceToDB(ownerId, provider, ref, data) {
WHEN scraped_services.status = 'imported' THEN 'imported'
ELSE 'pending'
END
RETURNING id
`, [ownerId, provider, ref, JSON.stringify(data), isUrgent]);
// 👋 NUEVO: Si es la primera vez que vemos este expediente, disparamos el WhatsApp de
// bienvenida en segundo plano (no bloquea ni puede romper el guardado de arriba).
if (isNewRecord && result.rows[0]) {
const newSvcId = result.rows[0].id;
console.log(`👋 [BIENVENIDA] Expediente #${ref} acaba de nacer. Disparando WhatsApp...`);
sendWelcomeMessage(ownerId, provider, ref, data, newSvcId).catch(e =>
console.error(`❌ [Bienvenida] Error inesperado para #${ref}:`, e.message)
);
}
}
main();