--- name: Cobranca WhatsApp - PDFs faltando ao enviar description: Bug recorrente onde cobrancas saem so com texto sem o PDF anexo. Causa raiz e fix preventivo aplicado em 2026-04-20. type: project originSessionId: cb486933-f159-41f1-8bb7-f110a95c9e0f --- ## Sintoma Clientes recebem WhatsApp de cobranca com o **texto** mas **sem o PDF** anexo. No log `cobranca_automatica_log` o status fica "enviado" (porque o texto saiu OK), nao gera erro visivel. ## Causa raiz (confirmada 2026-04-20) 1. Boletos novos as vezes ficam com `pdf_path = NULL` ou `pdf_path` populado mas **arquivo fisico nao existe** em `writable/uploads/boletos/` 2. Quando `CronCobrancaAutomatica::enviarBoletoWhatsapp()` roda, tenta: - PDF local → nao acha - API Sicoob `buscarSegundaViaDireta()` → falha (token expirado / timeout temporario) - Sem PDF: envia so texto, marca status "enviado" ## Fix preventivo aplicado (cron novo) Adicionado no crontab gotechbr: ``` 0 7-21/2 * * * wget -q -O /dev/null https://sistema.gotechbr.com.br/cron/boletos/corrigir-pdfs?token=58253... ``` 8x/dia (7h, 9h, 11h, ..., 21h) chama `/cron/boletos/corrigir-pdfs` que busca todos boletos com `pdf_path NULL` ou `''` e baixa via Sicoob. Garante PDFs prontos antes da cobranca rodar. ## Reenviar manualmente para um boleto especifico Endpoint que envia texto + PDF anexo: ``` POST https://sistema.gotechbr.com.br/cron/cobranca/enviar-boleto-whatsapp?token=58253... body: boleto_id=2523 ``` Retorna `{"success":true,"message":"1 boleto(s) enviados"}`. **Atencao tom da mensagem**: comeca com "Conforme solicitado na ligacao, seguem as informacoes:" — foi feito pro fluxo URA pos-ligacao. Para reenvio "normal" o texto fica esquisito mas funciona. ## Como auditar boletos com PDF faltando ```bash # boletos com pdf_path mas sem arquivo for path in $(mysql ... -BNe 'SELECT pdf_path FROM boletos WHERE pdf_path IS NOT NULL AND status IN ("gerado","pendente")'); do [ ! -f "writable/$path" ] && echo "FALTA: $path" done # boletos sem pdf_path mysql ... -e 'SELECT id, nosso_numero, status FROM boletos WHERE pdf_path IS NULL AND status IN ("gerado","pendente")' ``` ## Como rodar fix manual agora ``` curl 'https://sistema.gotechbr.com.br/cron/boletos/corrigir-pdfs?token=58253...' ``` Roda `CronBoletos::corrigirPdfs()` que itera boletos sem PDF e tenta Sicoob `buscarSegundaViaBoleto` + fallback `buscarSegundaViaDireta`.