#!/usr/bin/env node /** * Script para Enviar Alertas Atrasados * * Este script envia manualmente alertas que não foram enviados * (para quando o cron não estava configurado) */ const { createClient } = require('@supabase/supabase-js'); const axios = require('axios'); const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); function question(query) { return new Promise(resolve => rl.question(query, resolve)); } // Configurações const SUPABASE_URL = process.env.SUPABASE_URL || 'https://ydhzylfnpqlxnzfcclla.supabase.co'; const SUPABASE_KEY = process.env.SUPABASE_SERVICE_KEY || process.env.SUPABASE_ANON_KEY; if (!SUPABASE_KEY) { console.error('❌ SUPABASE_KEY não configurado!'); process.exit(1); } const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); function formatarDataBR(data) { const d = new Date(data); return d.toLocaleDateString('pt-BR', { timeZone: 'America/Sao_Paulo' }); } function formatarMoeda(valor) { return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(valor); } async function enviarWhatsApp(telefone, mensagem, evolutionConfig) { try { const url = `${evolutionConfig.apiUrl}/message/sendText/${evolutionConfig.instanceName}`; const response = await axios.post(url, { number: telefone, textMessage: { text: mensagem } }, { headers: { 'apikey': evolutionConfig.apiKey, 'Content-Type': 'application/json' } }); return { success: true, data: response.data }; } catch (error) { return { success: false, error: error.message }; } } async function gerarPix(parcela, mercadoPagoToken) { try { const response = await axios.post('https://api.mercadopago.com/v1/payments', { transaction_amount: parseFloat(parcela.valor), description: `Parcela ${parcela.numero_parcela} - Venda #${parcela.venda_id}`, payment_method_id: 'pix', payer: { email: 'cliente@liberi.com.br' } }, { headers: { 'Authorization': `Bearer ${mercadoPagoToken}`, 'Content-Type': 'application/json' } }); return { success: true, qrCode: response.data.point_of_interaction?.transaction_data?.qr_code, qrCodeBase64: response.data.point_of_interaction?.transaction_data?.qr_code_base64, paymentId: response.data.id }; } catch (error) { return { success: false, error: error.message }; } } async function main() { console.log('\n🔔 ENVIO MANUAL DE ALERTAS ATRASADOS\n'); console.log('Este script enviará alertas que não foram enviados automaticamente.\n'); try { // Buscar configurações const { data: configData } = await supabase .from('configuracoes') .select('chave, valor') .in('chave', [ 'evolution_api_url', 'evolution_instance_name', 'evolution_api_key', 'mercadopago_access_token' ]); const config = {}; configData?.forEach(item => { config[item.chave] = item.valor; }); const evolutionConfig = { apiUrl: config.evolution_api_url, instanceName: config.evolution_instance_name, apiKey: config.evolution_api_key }; const mercadoPagoToken = config.mercadopago_access_token; // Buscar parcelas pendentes com vencimento hoje ou passado const hoje = new Date(); hoje.setHours(0, 0, 0, 0); const { data: parcelas, error } = await supabase .from('venda_parcelas') .select(` *, vendas ( id_venda, cliente_id, clientes ( nome_completo, whatsapp ) ) `) .eq('status', 'pendente') .lte('data_vencimento', hoje.toISOString()) .order('data_vencimento', { ascending: true }); if (error) throw error; if (!parcelas || parcelas.length === 0) { console.log('✅ Não há parcelas vencidas ou vencendo hoje.\n'); rl.close(); return; } console.log(`📦 Encontradas ${parcelas.length} parcela(s) vencida(s) ou vencendo hoje:\n`); parcelas.forEach((parcela, index) => { const cliente = parcela.vendas?.clientes; console.log(`${index + 1}. ${cliente?.nome_completo || 'N/A'} - Parcela ${parcela.numero_parcela}`); console.log(` Valor: ${formatarMoeda(parcela.valor)}`); console.log(` Vencimento: ${formatarDataBR(parcela.data_vencimento)}`); console.log(` WhatsApp: ${cliente?.whatsapp || 'N/A'}`); console.log(''); }); const resposta = await question('Deseja enviar alertas + PIX para essas parcelas? (s/N): '); if (!resposta.match(/^[Ss]$/)) { console.log('\n❌ Operação cancelada.\n'); rl.close(); return; } console.log('\n🚀 Iniciando envio...\n'); let enviados = 0; let erros = 0; for (const parcela of parcelas) { const cliente = parcela.vendas?.clientes; if (!cliente || !cliente.whatsapp) { console.log(`⚠️ Parcela ${parcela.numero_parcela}: Cliente sem WhatsApp`); erros++; continue; } const nomeCliente = cliente.nome_completo.split(' ')[0]; const valorFormatado = formatarMoeda(parcela.valor); // Gerar PIX console.log(`📱 Gerando PIX para ${cliente.nome_completo}...`); const pixResult = await gerarPix(parcela, mercadoPagoToken); let mensagem = `Olá ${nomeCliente}! 👋\n\n`; mensagem += `Você tem uma parcela no valor de ${valorFormatado} `; mensagem += `com vencimento em ${formatarDataBR(parcela.data_vencimento)}.\n\n`; if (pixResult.success && pixResult.qrCode) { mensagem += `📱 *PIX Copia e Cola:*\n\`\`\`${pixResult.qrCode}\`\`\`\n\n`; // Atualizar parcela com PIX await supabase .from('venda_parcelas') .update({ pix_payment_id: pixResult.paymentId, pix_qr_code: pixResult.qrCode, pix_qr_code_base64: pixResult.qrCodeBase64 }) .eq('id', parcela.id); console.log(` ✅ PIX gerado`); } else { mensagem += `Entre em contato para obter forma de pagamento.\n\n`; console.log(` ⚠️ Não foi possível gerar PIX`); } mensagem += `Agradecemos! 😊\n*Liberi Kids - Moda Infantil* 👗👕`; // Enviar mensagem console.log(`📤 Enviando para ${cliente.whatsapp}...`); const resultado = await enviarWhatsApp(cliente.whatsapp, mensagem, evolutionConfig); if (resultado.success) { enviados++; console.log(` ✅ Enviado com sucesso!\n`); // Registrar histórico await supabase .from('mensagens_whatsapp') .insert({ telefone_cliente: cliente.whatsapp, cliente_nome: cliente.nome_completo, mensagem: mensagem, tipo: 'enviada', status: 'enviada' }); } else { erros++; console.log(` ❌ Erro: ${resultado.error}\n`); } // Delay entre mensagens await new Promise(resolve => setTimeout(resolve, 2000)); } console.log('\n' + '='.repeat(50)); console.log('📊 RESUMO'); console.log('='.repeat(50)); console.log(`✅ Alertas enviados: ${enviados}`); console.log(`❌ Erros: ${erros}`); console.log(`📦 Total processado: ${parcelas.length}`); console.log('='.repeat(50) + '\n'); } catch (error) { console.error('\n💥 Erro:', error); } finally { rl.close(); } } main();