'use strict' /** * reativacaoClientes.js — WPP-09 * * Job que roda periodicamente (padrão: 1× por dia às 10h) * para re-engajar clientes que não fazem pedidos há N dias. * * Fluxo: * 1. Lista clientes inativos (sem pedido nos últimos 60 dias) * 2. Para cada um, envia mensagem via NewWhats * 3. Registra envio na tabela wpp_reativacao_log * * Ativação: chamado em server.js via setInterval ou node-cron */ const { query, execute, queryOne } = require('../database/postgres') const DIAS_INATIVO = 60 // dias sem pedido para considerar inativo const BATCH_SIZE = 20 // máx clientes por execução const INTERVALO_MS = 24 * 60 * 60 * 1000 // 24h const JANELA_REATIVACAO = 30 // dias entre reativações do mesmo cliente async function getConfig() { try { const rows = await query(`SELECT key, value FROM plugin_configs WHERE plugin_id = 'newwhats'`) const cfg = {} for (const r of rows) cfg[r.key] = r.value return cfg } catch { return {} } } async function enviarWhatsApp(motorUrl, integKey, phone, mensagem) { if (!motorUrl || !integKey) return false try { const res = await fetch(`${motorUrl}/api/ext/v1/inbox/55${phone}/send`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-nw-key': integKey }, body: JSON.stringify({ text: mensagem }), }) return res.ok } catch { return false } } async function runReativacao() { console.log('[reativacao] Iniciando job de reativação de clientes...') const cfg = await getConfig() if (!cfg.newwhats_url || !cfg.integration_key) { console.warn('[reativacao] Motor não configurado — job pulado') return } if (cfg.auto_reply_mode === 'off') { console.log('[reativacao] auto_reply_mode=off — job pulado') return } try { // Lista clientes inativos que ainda não foram reativados recentemente const clientes = await query( `SELECT c.id AS cliente_id, c.nome, ct.numero AS telefone, MAX(p.created_at) AS ultimo_pedido FROM clientes c JOIN cliente_telefones ct ON ct.cliente_id = c.id AND ct.aceita_whatsapp = true LEFT JOIN pedidos p ON p.cliente_id = c.id WHERE c.status = 'ativo' AND c.id NOT IN ( SELECT cliente_id FROM wpp_reativacao_log WHERE enviada_em > NOW() - ($1 || ' days')::INTERVAL AND cliente_id IS NOT NULL ) GROUP BY c.id, c.nome, ct.numero HAVING MAX(p.created_at) < NOW() - ($2 || ' days')::INTERVAL OR MAX(p.created_at) IS NULL ORDER BY ultimo_pedido ASC NULLS FIRST LIMIT $3`, [JANELA_REATIVACAO, DIAS_INATIVO, BATCH_SIZE] ) console.log(`[reativacao] ${clientes.length} clientes inativos encontrados`) for (const cl of clientes) { const nome = cl.nome?.split(' ')[0] || 'Cliente' const telefone = cl.telefone.replace(/\D/g, '') const mensagem = `Olá, *${nome}*! 👋\nFaz um tempo que não vemos você por aqui no *Alemão Conveniências*.\n\nTemos novidades e promoções esperando por você! Bora fazer um pedido? 😊\n\nDigite *OI* para ver nossas ofertas do dia.` const enviado = await enviarWhatsApp(cfg.newwhats_url, cfg.integration_key, telefone, mensagem) if (enviado) { await execute( `INSERT INTO wpp_reativacao_log (cliente_id, chat_id, mensagem) VALUES ($1,$2,$3)`, [cl.cliente_id, `55${telefone}@s.whatsapp.net`, mensagem] ) console.log(`[reativacao] ✅ ${nome} (${telefone})`) } else { console.warn(`[reativacao] ⚠ Falha ao enviar para ${telefone}`) } // Pausa entre envios para não sobrecarregar await new Promise(r => setTimeout(r, 2000)) } console.log('[reativacao] Job concluído') } catch (err) { console.error('[reativacao] Erro inesperado:', err.message) } } /** * Inicia o job com agendamento automático. * @param {number} intervalMs — intervalo em ms (padrão 24h) * @param {number} initialDelayMs — atraso inicial antes do primeiro disparo (padrão 2min) */ function startReativacaoJob(intervalMs = INTERVALO_MS, initialDelayMs = 2 * 60 * 1000) { console.log(`[reativacao] Job agendado — intervalo: ${Math.round(intervalMs / 3600000)}h, delay inicial: ${initialDelayMs / 1000}s`) setTimeout(() => { runReativacao() setInterval(runReativacao, intervalMs) }, initialDelayMs) } module.exports = { startReativacaoJob, runReativacao }