Skip to content

Jobs CRON ​

Registry centralizado em supabase/functions/_shared/cron-jobs.ts (SSOT)


1. Visão Geral ​

JobSchedule (BRT)Schedule (UTC)CronEdge Function
Gerar FaturasÚltimo dia do mês 03:0006:000 6 28-31 * *faturamento-cron
Lembrete D-5Diário 06:0009:000 9 * * *faturamento-cron
Marcar VencidasDiário 04:3007:3030 7 * * *faturamento-cron
Régua de CobrançaDiário 09:0012:000 12 * * *faturamento-cron
ManutençãoDiário 04:0007:000 7 * * *maintenance-cron
Health CheckA cada 6h00:00, 06:00, 12:00, 18:000 */6 * * *healthcheck-cron

2. Gerar Faturas Mensal ​

Ação: gerar_faturas
Quando: Último dia de cada mês às 03:00 BRT
Function: faturamento-cron

Parâmetros (body JSON) ​

CampoTipoObrigatórioDescrição
actionstringSimgerar_faturas
manualbooleanNãotrue para execução manual (bypassa guard de último dia do mês)
referencia_messtringNãoYYYY-MM-01. Quando presente e manual: true, usa esse mês em vez de calcularProximoMes(). Permite processar meses retroativos.
triggered_bystringNãoUUID do usuário que disparou
triggered_by_namestringNãoNome do usuário

Tarefas ​

  1. Busca escolas com assinatura ativa
  2. Completa faturas skeleton ou cria novas para o mês de referência
  3. Cria link de pagamento (MercadoPago Checkout Pro)
  4. Emite boleto bancário (bolbradesco) em background via EdgeRuntime.waitUntil — best-effort, não bloqueia o cron nem aborta a geração das demais faturas. PDF fica disponível em escola_faturas.boleto_pdf_url para download imediato pela escola. Skip silencioso quando escola não tem CNPJ ou endereço completo.
  5. Envia mensagem WhatsApp com link para gestores

Ações de Log ​

AçãoTipo
faturamento.gerar_faturas_startedInício
faturamento.gerar_faturas_executadoSucesso
faturamento.link_geradoLink individual
faturamento.sms_enviadoMensagem individual
faturamento.erroErro individual
faturamento.cron_erroErro fatal
faturamento.cron_alertaAlerta (2 falhas)
faturamento.cron_criticoCrítico (3 falhas)
faturamento.alerta_faturas_sem_linkAlerta de saúde (0 processadas)

Métricas Extraídas ​

  • links_gerados — Total de links criados
  • sms_enviados — Total de mensagens enviadas

3. Lembrete D-5 Diário ​

Ação: lembrete_d5
Quando: Diariamente às 06:00 BRT
Function: faturamento-cron

Tarefas ​

  1. Busca faturas com vencimento em 5 dias
  2. Filtra faturas pendentes sem lembrete enviado
  3. Envia mensagem WhatsApp de lembrete
  4. Cria notificação in-app

Ações de Log ​

AçãoTipo
faturamento.lembrete_d5_startedInício
faturamento.lembrete_d5_executadoSucesso

Métricas Extraídas ​

  • lembretes_enviados — Total de lembretes
  • sms_enviados — Total de mensagens

3.1 Marcar Vencidas Diário ​

Ação: marcar_vencidasQuando: Diariamente às 04:30 BRT (antes da régua, para que o estado esteja fresco) Function: faturamento-cronpg_cron jobid: 11 — marcar-vencidas-diario (cron 30 7 * * * UTC, agendado em 2026-05-06)

Tarefas ​

  1. Busca faturas com status_pagamento = 'pendente' e vencimento_em definido.
  2. Filtra com isPastDateBRT() (BRT canônico, UTC−3 fixo — proibido new Date() cru).
  3. UPDATE em lote: status_pagamento = 'vencido', marcada_vencida_em = now() (filtro defensivo status_pagamento = 'pendente').

Ações de Log ​

AçãoTipo
faturamento.marcar_vencidas_startedInício
faturamento.marcar_vencidas_executadoSucesso
faturamento.fatura_marcada_vencidaLote (até 50 IDs no detalhe)

Métricas Extraídas ​

  • marcadas_vencidas — Total de faturas que transitaram de pendente→vencido.

3.2 Régua de Cobrança Diária ​

Ação: regua_cobrancaQuando: Diariamente às 09:00 BRT (após marcar_vencidas) Function: faturamento-cronpg_cron jobid: 12 — regua-cobranca-diario (cron 0 12 * * * UTC, agendado em 2026-05-06) SSOT dos gatilhos: _shared/cobranca-regua.ts (espelha src/lib/cobranca-regua.ts).

Gatilhos ​

RéguaDias de atrasoTom
d33Aviso após compensação (boleto compensa em até D+3 — primeiro toque seguro)
d1010Cobrança firme
d1717Aviso de bloqueio iminente

Demais atrasos (1..2, 4..9, 11..16, >17) são ignorados (sem reenvio).

Por que D+3 em vez de D+1? Boletos bancários podem levar até 3 dias úteis para compensar na conta da empresa após o pagamento. Disparar lembrete em D+1 gera ruído com clientes que pagaram na data certa — D+3 elimina esse falso-positivo. Régua antiga (d1/d7/d15) mantida como template histórico (não é mais usada pelo cron).

Idempotência ​

Garantida pelo índice único parcial uq_fatura_cobrancas_regua_auto em (fatura_id, regua_dia) WHERE origem='regua_auto' AND status IN ('enviado','entregue','lido'). Race entre workers é tratada como sucesso silencioso.

Tarefas ​

  1. Carrega faturas vencido + dados da escola (escolas.nome).
  2. Para cada uma calcula diasAtraso (BRT) e mapeia para régua via calcularReguaParaDiasAtraso.
  3. Renderiza template cobranca_d{3|10|17} (_shared/sms-templates.ts).
  4. Envia via helper enviarCobranca({ origem: 'regua_auto', ... }) — Wasender→Twilio, log estruturado em fatura_cobrancas.

Ações de Log ​

AçãoTipo
faturamento.regua_cobranca_startedInício
faturamento.regua_cobranca_executadoSucesso
faturamento.cobranca_envio_automaticoEnvio individual OK
faturamento.cobranca_noopIdempotência (já enviada)
faturamento.cobranca_falhaFalha individual

Métricas Extraídas ​

  • cobrancas_disparadas — Envios bem-sucedidos
  • cobrancas_skip — Sem destinatário ou já enviada (noop)
  • cobrancas_falhas — Falhas (ambos providers caíram)

Rate-limit ​

Bulk respeita o atraso default de 6s entre envios do Wasender (skipDelay=false).


Ação: manutencao
Quando: Diariamente às 04:00 BRT
Function: maintenance-cron

10 Tarefas de Cleanup ​

#TarefaAção de LogCritério
1OTPs do sistemamanutencao.cleanup_login_otps> 24 horas
2OTPs do portalmanutencao.cleanup_portal_otps> 24 horas
3Tentativas de login (portal)manutencao.cleanup_portal_tentativas> 7 dias
4Notificações antigasmanutencao.cleanup_notificacoes> 7 dias
5Tokens de cadastromanutencao.cleanup_cadastro_tokensExpirados
6Check sessão WhatsAppmanutencao.check_whatsapp_sessionDiário
7Token blacklistmanutencao.cleanup_token_blacklistExpirados
8Métricas rate limit portalmanutencao.cleanup_portal_rate_metrics> 30 dias
9Cooldown alertasmanutencao.cleanup_alert_cooldown> 24 horas
10Anonimização IPs (LGPD)manutencao.anonimizar_ips_lgpd> 6 meses

Check de Sessão WhatsApp ​

  • Verifica status da sessão Wasender via API
  • Se sessão desconectada → alerta push ntfy para admins
  • Cooldown: 24h entre alertas de sessão

Métricas Extraídas ​

  • total_removidos — Total de registros limpos

5. Health Check Periódico ​

Ação: healthcheck
Quando: A cada 6 horas (00:00, 06:00, 12:00, 18:00 UTC)
Function: healthcheck-cron

Probes ​

  1. Write probes — Testa operações de escrita (INSERT/DELETE) em fluxos críticos (faturamento, inscrições, portais). Dados de teste isolados (ano_edicao = 1900) para evitar colisões.
  2. Schema probes — Verifica integridade do schema (tabelas, colunas, constraints)
  3. Dependency probes — Valida conectividade com serviços externos (Wasender, MercadoPago, ntfy)

Ações de Log ​

AçãoTipo
healthcheck.executadoSucesso
healthcheck.falhaFalha em um ou mais probes
healthcheck.degradadoProbes OK mas com latência alta ou erro parcial
healthcheck.erroErro fatal na execução

Métricas Extraídas ​

  • Resultado por probe (sucesso/falha/latência)

6. Política de Retry e Escalação ​

Aplica-se a Gerar Faturas e Manutenção:

EtapaCondiçãoAção
RetryFalhaTenta novamente em 15 minutos
Alerta2 falhas consecutivasNotificação in-app para admins
Crítico3 falhas consecutivasMensagem WhatsApp para admins + alerta push ntfy.sh + status CRÍTICO

Alertas Push (ntfy.sh) ​

Complementar ao WhatsApp, alertas push são enviados via ntfy.sh para a equipe técnica em:

  • CRON falha crítica (3x consecutivas) — prioridade urgent
  • Sessão WhatsApp desconectada — prioridade urgent
  • Token revogado reutilizado — prioridade high

Ver detalhes: ALERTAS_PUSH.md

Cooldown de Mensagens ​

  • Manutenção: 2 horas entre mensagens de alerta
  • Faturamento: Sem cooldown adicional (cada ciclo é mensal)

7. Tabela cron_status ​

Referência de saúde dos jobs:

CampoTipoDescrição
job_nameTEXTNome do job
statusTEXToperacional, alerta, critico
ultima_execucaoTIMESTAMPTZÚltimo run
ultima_execucao_sucessoTIMESTAMPTZÚltimo sucesso
ultimo_erroTEXTMensagem de erro
ultimo_erro_emTIMESTAMPTZTimestamp do último erro
tentativas_consecutivasINTContador de falhas
proximo_retryTIMESTAMPTZPróxima tentativa
sms_critico_enviado_emTIMESTAMPTZÚltima mensagem de alerta
atualizado_emTIMESTAMPTZÚltima atualização do registro

8. Trigger Manual (NOC) ​

Disponível no Monitor CRON (admin-cron-monitor):

  1. Admin seleciona job
  2. Confirma execução manual
  3. Edge Function é chamada com action do registry
  4. Resultado refletido em cron_status e logs_transacoes

⚠️ Aviso: Triggers manuais enviam mensagens reais (WhatsApp) para usuários das escolas.


9. Registry — Fonte da Verdade ​

O arquivo supabase/functions/_shared/cron-jobs.ts é a única fonte da verdade (SSOT):

  • Plug & Play: Para adicionar novo job, basta adicionar entrada no registry
  • Zero alterações em admin-cron-monitor, useAdminCronMonitor ou componentes
  • Tipos derivados: CronJobName, CronJobAction
  • Funções utilitárias: mapLogActionToJobName(), classifyLogType(), getJobActions()

Referências ​

  • supabase/functions/_shared/cron-jobs.ts — Registry SSOT
  • supabase/functions/faturamento-cron/index.ts — Faturas + Lembrete
  • supabase/functions/maintenance-cron/index.ts — Manutenção
  • supabase/functions/healthcheck-cron/index.ts — Health Check
  • supabase/functions/_shared/health-probes.ts — Probes de saúde
  • src/components/admin-cron-monitor.tsx — UI de monitoramento
  • src/hooks/useAdminCronMonitor.ts — Hook do monitor