Lógica de Notificação Pré-Vencimento (1 Dia Antes)
Visão Geral
A notificação InvoicePreDueReminderNotification
envia lembretes 1 dia antes do vencimento efetivo de faturas, com tratamento inteligente de finais de semana e feriados.
Conceitos Fundamentais
1. Dia Útil vs Dia Não Útil
- Dia Útil: Segunda a sexta-feira, exceto feriados
- Dia Não Útil: Sábados, domingos e feriados (tabela
gk2_hollidays
)
2. Vencimento Original vs Vencimento Efetivo
- Vencimento Original: Data de vencimento registrada na fatura
- Vencimento Efetivo: Primeiro dia útil após o vencimento original (se cair em dia não útil)
Exemplo:
Vencimento Original: Domingo, 28/09/2025
Vencimento Efetivo: Segunda, 29/09/2025 (próximo dia útil)
Regras de Envio
A lógica possui duas regras que se aplicam dependendo do contexto:
Regra 1: Bloco de Dias Não Úteis (Sexta-feira e vésperas)
Quando aplicar:
- Hoje é dia útil
- Amanhã é dia não útil (sábado, domingo ou feriado)
Como funciona:
- Percorre todos os dias não úteis consecutivos a partir de amanhã
- Para cada dia no bloco, verifica se alguma fatura vence naquele dia
- Notifica hoje todas as faturas cujo vencimento original cai dentro desse bloco
Exemplo 1 - Fim de semana normal:
Hoje: Sexta, 26/09/2025 (dia útil)
Amanhã: Sábado, 27/09/2025 (não útil) ← gatilho da regra
Bloco: [Sábado 27, Domingo 28]
Faturas notificadas hoje (sexta):
- Fatura vence Sábado 27/09 ✅
- Fatura vence Domingo 28/09 ✅
- Fatura vence Segunda 29/09 ❌ (não está no bloco)
Exemplo 2 - Feriado prolongado:
Hoje: Quinta, 25/09/2025 (dia útil)
Amanhã: Sexta, 26/09/2025 (feriado) ← gatilho da regra
Bloco: [Sexta 26 (feriado), Sábado 27, Domingo 28]
Faturas notificadas hoje (quinta):
- Fatura vence Sexta 26/09 ✅
- Fatura vence Sábado 27/09 ✅
- Fatura vence Domingo 28/09 ✅
- Fatura vence Segunda 29/09 ❌
Regra 2: Dia Anterior Simples (Dias normais)
Quando aplicar:
- Hoje é dia útil
- Amanhã também é dia útil
Como funciona:
- Calcula o vencimento efetivo da fatura (normaliza para dia útil)
- Subtrai 1 dia do vencimento efetivo
- Se hoje == (vencimento efetivo - 1 dia), notifica
Exemplo 1 - Fatura vence em dia útil:
Hoje: Terça, 30/09/2025
Venc. Original: Quarta, 01/10/2025
Venc. Efetivo: Quarta, 01/10/2025 (já é dia útil)
Dia Anterior: Terça, 30/09/2025
Resultado: NOTIFICA ✅ (hoje == dia anterior)
Exemplo 2 - Fatura vence em domingo (mas amanhã é útil):
Hoje: Segunda, 29/09/2025
Venc. Original: Domingo, 05/10/2025 (próximo domingo)
Venc. Efetivo: Segunda, 06/10/2025 (normalizado)
Dia Anterior: Domingo, 05/10/2025
Resultado: NÃO NOTIFICA ❌ (hoje != dia anterior)
Fluxo de Decisão
┌─────────────────────────────┐ │ Hoje é dia útil? │ └──────────┬──────────────────┘ │ Não ├──────────> NÃO ENVIA │ │ Sim ▼ ┌─────────────────────────────┐ │ Amanhã é dia não útil? │ └──────────┬──────────────────┘ │ ┌────┴────┐ │ │ Sim Não │ │ ▼ ▼ ┌─────────┐ ┌──────────────────────┐ │ REGRA 1 │ │ REGRA 2 │ │ Bloco │ │ Simples 1 dia antes │ └─────────┘ └──────────────────────┘
Implementação Técnica
Estrutura de Arquivos
Helpers/ ├── InvoiceNotificationScheduler.php │ └── Lógica de dias úteis/feriados │ └── InvoicePreDueReminderScheduler.php └── Lógica de decisão de envio (Regra 1 + Regra 2) InvoicePreDueReminderNotification.php └── Busca faturas Unpaid e usa scheduler para decidir
Classe: InvoicePreDueReminderScheduler
Método Principal:
public function shouldNotifyOneDayBeforeEffective( DateTime $today, DateTime $originalDueDate ): bool
Pseudocódigo:
SE hoje NÃO é dia útil: RETORNA false amanhã = hoje + 1 dia SE amanhã NÃO é dia útil: // REGRA 1: Bloco cursor = amanhã ENQUANTO cursor não for dia útil: SE originalDueDate == cursor: RETORNA true cursor = cursor + 1 dia RETORNA false SENÃO: // REGRA 2: Simples efetivo = normalizeToBusinessDay(originalDueDate) diaAnterior = efetivo - 1 dia RETORNA (hoje == diaAnterior)
Classe: InvoicePreDueReminderNotification
Método getPayload():
1. Verifica se hoje é dia útil (se não, retorna []) 2. Busca faturas com status 'Unpaid' 3. Filtra por métodos de pagamento elegíveis (PIX/Boleto) 4. Para cada fatura: - Usa scheduler.shouldNotifyOneDayBeforeEffective() - Se true, adiciona ao payload 5. Retorna array de payloads para envio
Casos de Uso Detalhados
Caso 1: Sexta-feira antes do fim de semana
Contexto:
- Hoje: Sexta, 26/09/2025
- Fatura A: vence Sábado, 27/09/2025
- Fatura B: vence Domingo, 28/09/2025
- Fatura C: vence Segunda, 29/09/2025
Processamento:
Sexta (hoje): Amanhã = Sábado (não útil) ← REGRA 1 Bloco = [Sábado, Domingo] Fatura A (vence Sábado): Sábado está no bloco? SIM → NOTIFICA ✅ Fatura B (vence Domingo): Domingo está no bloco? SIM → NOTIFICA ✅ Fatura C (vence Segunda): Segunda está no bloco? NÃO → NÃO NOTIFICA ❌ Segunda (próxima rodada): Amanhã = Terça (útil) ← REGRA 2 Fatura C (vence Segunda): Efetivo = Segunda Dia anterior = Domingo Hoje (Segunda) == Domingo? NÃO → NÃO NOTIFICA ❌ (Obs: não notifica porque o vencimento efetivo já passou)
Caso 2: Quinta antes de feriado prolongado
Contexto:
- Hoje: Quinta, 10/09/2026
- Sexta, 11/09: Feriado
- Fatura D: vence Sexta, 11/09/2026 (feriado)
- Fatura E: vence Segunda, 14/09/2026
Processamento:
Quinta (hoje): Amanhã = Sexta (feriado, não útil) ← REGRA 1 Bloco = [Sexta (feriado), Sábado, Domingo] Fatura D (vence Sexta feriado): Sexta está no bloco? SIM → NOTIFICA ✅ Fatura E (vence Segunda): Segunda está no bloco? NÃO → NÃO NOTIFICA ❌ Segunda, 14/09: Amanhã = Terça (útil) ← REGRA 2 Fatura E (vence Segunda): Efetivo = Segunda, 14/09 Dia anterior = Domingo, 13/09 Hoje (Segunda) == Domingo? NÃO → NÃO NOTIFICA ❌
Caso 3: Terça normal
Contexto:
- Hoje: Terça, 30/09/2025
- Fatura F: vence Quarta, 01/10/2025
Processamento:
Terça (hoje): Amanhã = Quarta (útil) ← REGRA 2 Fatura F (vence Quarta): Efetivo = Quarta, 01/10 Dia anterior = Terça, 30/09 Hoje (Terça) == Terça? SIM → NOTIFICA ✅
Testes
Arquivo de Teste
modules/addons/lknhooknotification/src/Notifications/Custom/tests_pre_due_scheduler_instancias2.php
Como executar:
php modules/addons/lknhooknotification/src/Notifications/Custom/tests_pre_due_scheduler_instancias2.php
Configuração
Ativação da Notificação
- Acesse: Addons → Hook Notification → Notifications
- Localize:
InvoicePreDueReminderNotification
- Clique em + Setup template
- Configure o template com os parâmetros disponíveis
Parâmetros Disponíveis no Template
{invoice_id}
- ID da fatura{client_first_name}
- Primeiro nome do cliente{order_details_action}
- Payload completo para botão de pagamento (PIX/Boleto){invoice_pdf_url}
- URL do PDF da fatura{greetings}
- Saudação contextual (bom dia/tarde/noite)
Requisitos
- Métodos de pagamento suportados:
lknbbpix
(PIX)mmhospedagem_API_BS2
(Boleto)
- Faturas com status:
Unpaid
- Faturas com total > 0
- Execução: Hook
DailyCronJob
- : 1 dia DEPOIS do vencimento efetivo
- Status: Overdue (vencida)
- Objetivo: Cobrar faturas atrasadas
Observações Importantes
- Não envia em finais de semana/feriados: A notificação só roda em dias úteis
- Vencimento efetivo: Sempre considera o arrasto para o próximo dia útil
- Sem compensação na Regra 2: Se o "dia anterior" cair em não útil, não envia
- Compensação na Regra 1: Antecipa para o último dia útil antes do bloco
- Cache: O factory do addon descobre automaticamente novas notificações
- Helpers não são notificações: Schedulers na pasta
Helpers/
não aparecem como notificações