--- name: Sindicância completa mecanismo cobrança/boleto/NFSe 2026-04-17 description: Relatório consolidado do fluxo real de cobrança, pontos críticos e bugs encontrados type: project originSessionId: ff25db81-a051-4175-8cdc-bc6303f57bf0 --- # Sindicância completa - 2026-04-17 ## FLUXO ATUAL (como funciona hoje) ### 1. Contrato - Tabela `contratos` com status `ativo`/`encerrado`/`prorrogado`, `data_fim`, `dia_vencimento`, `valor_mensal` - Vigente = `status IN (ativo, prorrogado)` AND (`data_fim >= hoje` OR aditivo ativo) - Aditivos em `aditivos`: `contrato_id`, `data_inicio`, `data_fim`, `valor_mensal` - Aditivo sobrescreve o valor do contrato quando cobre a data do vencimento (fix de hoje) ### 2. Flag `gerar_boleto` (clientes.gerar_boleto) Respeitada em 3 caminhos: - CronCobrancaAutomatica linhas 93, 409, 1051 (ambos query e função) - Sicoob::gerarBoleto (manual) — fix adicionado hoje - Boleto::create → criarBoletoCliente — fix adicionado hoje ### 3. Regras de cobrança (CronCobrancaAutomatica) Fases `tipo_cobranca`: - **Antes**: 7_dias, 4_dias, 2_dias, vencimento (4 fases) - **Após**: 2_apos, 4_apos, 6_apos, 8_apos, 10_apos (5 fases) - **Protesto**: 11+ dias vencido = protesto_diario (envia todo dia) - Cadência: 1x por vencimento nas fases normais, diário no protesto - Envio consolidado: 1 mensagem WhatsApp + anexos PDF de TODOS os boletos pendentes ### 4. Regras de geração de boleto Validações (4 camadas): - Cliente status=ativo - Cliente gerar_boleto=1 - Contrato ativo/prorrogado - data_fim >= hoje OR aditivo vigente Regra nova (fix hoje): **só gera próximo mês se o do mês atual estiver pago** (antes gerava mesmo com vencido) ### 5. Ligações VoIP (Magnus) Tipos: vence_hoje (1x), vencido (2x/dia a cada 2 dias), protestado (2x/dia diariamente), boas_vindas Horário: 9h-20h Boleto vira protestado: 10+ dias vencido + 2+ notificações enviadas ### 6. Emissão NFSe (CronNfseAutomatica) Trigger: boleto status=pago + data_pagamento preenchida Bloqueios: cliente inativo, CNPJ vazio, contrato encerrado, data_fim passada sem aditivo, Sicoob não confirma (pula se ignorar_sync_sicoob=1) Serviço: busca `cliente_servicos` JOIN `nfse_servicos_config` por `servico_nome`. Se não achar → ERRO (fix hoje: antes pegava todos os 10) ### 7. Tratamento de telefone WhatsApp Função: `WhatsApp::formatarTelefoneDDD()`. DDD >= 31 + 9º dígito = remove o 9 Sessão financeira: `QLh063KG7xL0kmEY0U5EhH0x1Qt1mhI2thuPN` (5531849...) para cobranças Endpoint Baileys: `/rest/sendMessage/{key}/text` (msg) e `/document` (PDFs) --- ## PONTOS CRÍTICOS ATUAIS ### 🔴 CRÍTICO - Cron de ligação continua ligando mesmo com boleto pago Hoje JAC recebeu 5 ligações (14:48-16:30) mesmo com boleto 133 já marcado como `pago` às ~14:00. O cron `processarLigacoes` não revalida o status atual antes de ligar. **Evidência:** ``` id 395 | 14:48 nao_atendida | boleto_id=133 boleto_status=pago id 396 | 15:00 nao_atendida | boleto_id=133 boleto_status=pago id 397 | 15:30 nao_atendida | boleto_id=133 boleto_status=pago id 398 | 16:00 nao_atendida | boleto_id=133 boleto_status=pago id 399 | 16:30 disparada | boleto_id=133 boleto_status=pago ``` **Fix necessário**: em processarLigacoes, antes de disparar, requerer boleto ainda em status `pendente/gerado/vencido` ### 🔴 CRÍTICO - NFSe emitida em duplicata pelo cron - FAST TELECOM: NFSes 30 (01/04 08:00) e 32 (01/04 10:30) geradas no mesmo dia pro mesmo boleto, canceladas depois. Nota 39 (04/04) ficou. - G CLOSET: NFSes 31 e 33 mesmo dia, canceladas. Nota 42 ficou. - JAC: NFSes 35 (01/04), 44 (17/04), 45 (17/04) — 3 tentativas, 3 canceladas, 46 ficou **Fix necessário**: lock/mutex na query que seleciona boletos pendentes OU garantir dedup por (boleto_id, status != cancelada) dentro da transação ### 🟡 MÉDIO - DÉBORA FLORES TRIGUEIRO tem serviço sem config NFSe Cliente 41 tem 2 serviços: "Gestão de Redes Sociais" (ok) e "Ferramenta de Mensagem (Chat)" (sem match em `nfse_servicos_config`). Se o sistema escolher "Ferramenta de Mensagem" primeiro → erro. Depende da ordem de retorno do JOIN. **Fix**: cadastrar "Ferramenta de Mensagem (Chat)" em `nfse_servicos_config` OU garantir que busca prefere o 1º ativo com config ### 🟡 MÉDIO - Clientes ATIVOS com gerar_boleto=0 - DANIELA MARIA PINTO (cliente 21) - CLARICE TONET TAMBOSI (cliente 27) - JESIEL TELLES - TESTE (39, teste) - JANTAR EMPRESARIAL (40, R$1, teste?) **Ação**: confirmar se é intencional. Nenhum boleto será gerado pra eles até setar gerar_boleto=1. ### 🟡 MÉDIO - Telefone JSF SOLUCOES com DDD 93 (Pará) JSF: `93984226821` → com formatarTelefoneDDD vira `559384226821`. Regra atual remove 9º dígito pra DDD >= 31. Para DDD 93 (Pará/Santarém), isso pode não ser o correto (alguns DDDs >=31 mantêm o 9 no WhatsApp). **Ação**: validar com teste real se WhatsApp do JSF recebe. ### 🟢 BAIXO - Contrato JAC 10 `prorrogado` com data_fim 2026-01-01 passada Aditivo vigente cobre. Sistema respeita. ### 🟢 BAIXO - Tentativa de emissão NFSe em ~15min consecutivos (JAC 17/04) Múltiplas tentativas aconteceram por ações minhas de cancelar/reemitir durante debug. Normal no cenário, não é bug. --- ## CLIENTES ATIVOS ELEGÍVEIS PARA COBRANÇA (17 clientes) Clientes com contrato ativo + gerar_boleto=1: CARVA, CILENE, DÉBORA, FABIANE, FAST TELECOM, FORTINOX, G CLOSET, JAC, JSF, JULIANA, MARCIO, MISLENE, REGINALDO, ULTRASSONOGRAFIA, VALOR MOVÉIS (+ 2 com gerar_boleto=0: DANIELA, CLARICE) ## CLIENTES BLOQUEADOS (7 - não geram nada) NUTRIBOM (x2), SILVANA COLCHÕES, EDITORA SIMETRIA, COVER WITH PEEL, DOPP, IDALY — todos com status=inativo + contrato=encerrado --- ## FIXES DEPLOYADOS HOJE 1. CronBoletos: validar `situacaoBoleto=liquidado` + `LIQUIDAÇÃO` em listaHistorico (antes exigia valorPago>0) 2. CronCobranca: gera próximo mês SÓ se atual pago (antes: pago OU vencido) 3. `buscarAditivoAtivo` aceita `$dataCobertura` (antes só hoje) 4. Cron NFSe: fallback removido (sem cliente_servicos → erro, não pega todos) 5. `getNotaByBoleto` ignora canceladas (antes só erro) 6. `clienteContratoAtivo` bloqueia contrato vencido sem aditivo 7. Gerar boleto manual (Sicoob + Boleto::create) bloqueia cliente inativo, gerar_boleto=0, contrato encerrado, data_fim passada sem aditivo 8. CronNfseAutomatica bloqueia contrato encerrado/sem aditivo 9. Flag `ignorar_sync_sicoob` adicionada e respeitada em cron e NFSe 10. Endpoints diagnóstico: `/sicoob/diagnostico-boleto/{n}`, `/sicoob/cancelar-diagnostico/{n}`, `/nfse/cancelar-diagnostico/{id}` --- ## AÇÕES PENDENTES (decisão do usuário) 1. ~~Corrigir cron de ligação~~ ✓ FIXED (contador agora inclui nao_atendida - respeita 2x/dia) 2. Adicionar lock/dedup no cron NFSe pra evitar duplicatas (caso real: boleto 114 teve 1 auth + 2 canceladas) 3. ~~Cadastrar "Ferramenta de Mensagem (Chat)"~~ ✓ FIXED + auto-sync criado 4. Confirmar se DANIELA e CLARICE com gerar_boleto=0 é intencional 5. Testar envio WhatsApp pro JSF (DDD 93) pra validar regra 6. 4 boletos antigos sem NFSe retroativa: JAC 125, Daniela 99, Mislene 115, Marcio 113 ## FIX ADICIONAL: Auto-sync servico → nfse_servicos_config `ClienteServicoModel::salvarServicosCliente()` agora garante que todo servico marcado no cadastro do cliente existe em `nfse_servicos_config`. Cria automaticamente com codigo 170601 e aliquota 5% se faltar. Usuario pode ajustar codigo/aliquota depois na tela de config NFSe. Isso elimina o erro "cliente sem servico fiscal vinculado" por falta de cadastro. ## VERIFICACAO SEFIN (confirmacao das canceladas) Todas as 10 NFSes canceladas no banco tem registro de cancelamento SEFIN bem-sucedido: - log nfse_log acao=cancelamento_admin com http_status=201 (Created) para 60, 61, 67, 68, 80, 81, 82, 83, 94, 95 - Canceladas oficialmente na Receita Federal OBS: endpoint `/nfse/{chave}` retorna 404 para consulta (mesmo de autorizadas) - e bug do endpoint de consulta, nao do cancelamento. URL ADN/SEFIN possivelmente incorreta no codigo (nao investigado). Nao afeta emissao/cancelamento que funcionam. ## Mecanismo de protesto automatico - VALIDADO Logica em `CronCobrancaAutomatica::executarProtestoAutomaticoSicoob` (linha 1752): 1. Cliente + contrato ativos 2. Boleto vencido >= 10 dias 3. Pelo menos 2 notificacoes de atraso enviadas (2_apos, 4_apos, 6_apos, 8_apos, 10_apos) 4. Nao ja protestado 5. Protesto nao removido antes Se todas OK -> chama Sicoob::protestarBoleto, marca protestado=1, data_protesto. Chamado em 2 pontos (linha 1412 e 1434) quando `diasAteVencimento <= -10`. Validado no historico real: Fortinox boleto 62 (venc 10/03) foi protestado automaticamente em 20/03 14:30 (exatamente 10 dias apos vencimento, com 3 notificacoes de atraso ja enviadas). Estado atual dos candidatos a protesto: - Fortinox 53 (venc 10/04): 7 dias vencido, 3 notif. Sera protestado automaticamente em 20/04 se nao pagar. - Debora 2535 (venc 15/04): 2 dias, 1 notif. Falta ~8 dias. ## Aba "Protestados" adicionada em /boletos Criada aba dedicada na tela de boletos listando todos com `protestado=1` e `protesto_removido=0`, independente do status. Assim boletos cancelados apos protesto (como Fortinox 62) aparecem visualmente na lista, sem sumir em "Cancelados". Caso Fortinox 62: Sicoob deu BAIXA por protesto em 09/04 (padrao apos 20 dias do protesto). Protesto continua ativo no cartorio (CRA). Para negociar, gerar novo boleto e depois chamar Sicoob::removerProtesto. ## DECISOES CONFIRMADAS 17/04 - DANIELA MARIA PINTO com gerar_boleto=0 = intencional (usuario confirmou: "não é para emitir boleto pra ela") - 4 retroativas de fevereiro: deixar como esta - DEBORA servico "Ferramenta de Mensagem (Chat)" no cadastro = correto, o fix foi cadastrar em nfse_servicos_config