Añade envio de WhatsApp de bienvenida al crear un expediente nuevo
This commit is contained in:
135
robot.js
135
robot.js
@@ -496,28 +496,147 @@ 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) {
|
async function saveServiceToDB(ownerId, provider, ref, data) {
|
||||||
console.log(`💾 Guardando/Actualizando ${provider.toUpperCase()} ${ref}...`);
|
console.log(`💾 Guardando/Actualizando ${provider.toUpperCase()} ${ref}...`);
|
||||||
|
|
||||||
// Aquí está la solución al problema del tilde ("sí" vs "si") que te comenté antes
|
// 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;
|
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)
|
INSERT INTO scraped_services (owner_id, provider, service_ref, raw_data, status, is_urgent)
|
||||||
VALUES ($1, $2, $3, $4, 'pending', $5)
|
VALUES ($1, $2, $3, $4, 'pending', $5)
|
||||||
ON CONFLICT (owner_id, provider, service_ref)
|
ON CONFLICT (owner_id, provider, service_ref)
|
||||||
DO UPDATE SET
|
DO UPDATE SET
|
||||||
-- 🛡️ EL ESCUDO: Fusiona todo, pero si ya había un gremio guardado, lo blinda para que el robot no lo pise
|
-- 🛡️ EL ESCUDO: Fusiona todo, pero si ya había un gremio guardado, lo blinda para que el robot no lo pise
|
||||||
raw_data = (scraped_services.raw_data || EXCLUDED.raw_data) ||
|
raw_data = (scraped_services.raw_data || EXCLUDED.raw_data) ||
|
||||||
jsonb_build_object('guild_id', COALESCE(scraped_services.raw_data->'guild_id', EXCLUDED.raw_data->'guild_id')),
|
jsonb_build_object('guild_id', COALESCE(scraped_services.raw_data->'guild_id', EXCLUDED.raw_data->'guild_id')),
|
||||||
|
|
||||||
is_urgent = EXCLUDED.is_urgent,
|
is_urgent = EXCLUDED.is_urgent,
|
||||||
status = CASE
|
status = CASE
|
||||||
WHEN scraped_services.status = 'archived' THEN 'archived'
|
WHEN scraped_services.status = 'archived' THEN 'archived'
|
||||||
WHEN scraped_services.status = 'imported' THEN 'imported'
|
WHEN scraped_services.status = 'imported' THEN 'imported'
|
||||||
ELSE 'pending'
|
ELSE 'pending'
|
||||||
END
|
END
|
||||||
|
RETURNING id
|
||||||
`, [ownerId, provider, ref, JSON.stringify(data), isUrgent]);
|
`, [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();
|
main();
|
||||||
Reference in New Issue
Block a user