Encargos por atraso (multa + juros)
Política da plataforma para boletos reemitidos após o vencimento.
SSOT
Configuração global em public.configuracoes_cobranca (singleton). Editável apenas por administrador/especialista. Toda escola da plataforma compartilha a mesma política — não há override por escola nesta versão.
| Campo | Default | Limite | Descrição |
|---|---|---|---|
multa_atraso_percentual | 2.00 | 0 a 10 | % aplicado uma única vez sobre o principal |
juros_mora_mensal_percentual | 1.00 | 0 a 20 | % ao mês, pro-rata diário (dia × valor × % / 30) |
dias_uteis_novo_vencimento | 3 | 1 a 30 | Dias úteis para o novo vencimento do boleto reemitido |
ativo | true | bool | Quando false, fatura vencida volta a recusar reemissão |
Fórmulas
text
multa = valor_original × (multa_atraso_percentual / 100)
juros = valor_original × (juros_mora_mensal_percentual / 100) × (dias_atraso / 30)
total = valor_original + multa + juros
novo_vencimento = hoje_BRT + dias_uteis_novo_vencimento (pulando sáb/dom)Tudo arredondado em 2 casas decimais (centavos).
Exemplo numérico
Fatura R$ 2.909,50, vencida em 10/06/2026, hoje 18/06/2026 (8 dias de atraso):
text
multa = 2909,50 × 2% = 58,19
juros = 2909,50 × 1% × 8/30 = 7,76
total = 2975,45
novo vencimento = 23/06/2026 (3 dias úteis BRT, pulando fim de semana)Embasamento legal
- CDC art. 52 — multa de mora limitada a 2% sobre o valor da prestação para serviços de execução continuada.
- Lei 9.298/96 — reduziu o teto de 10% para 2% e proibiu cláusulas leoninas em contratos de consumo.
- Pro-rata diário — padrão de mercado para evitar questionamento no Procon (cobrar mês cheio por 1 dia de atraso é desproporcional).
Onde mora
- DDL:
supabase/migrations/<ts>_*configuracoes_cobranca*.sql - Helper SSOT (frontend):
src/lib/encargos-atraso.ts→calcularEncargos,calcularNovoVencimentoDiasUteis - Helper SSOT (edge):
supabase/functions/_shared/encargos-atraso.ts(paridade testada) - Branch de reemissão:
supabase/functions/mercadopago-boleto/index.ts§ handleGerar - UI:
src/components/admin-financeiro/confirmar-encargos-dialog.tsx(drawer admin) +src/components/pagamentos-escola.tsx(escola) - Snapshot na fatura:
escola_faturas.boleto_valor_cobrado,boleto_multa,boleto_juros,boleto_vencimento_original
Fluxo de reemissão
- UI chama
previewEncargos(faturaId)→ backend rodadry_run: true(sem chamar MP). - Se a fatura está vencida, backend retorna
{ requer_confirmacao: true, multa, juros, valor_total, novo_vencimento }. - UI abre
ConfirmarEncargosDialogcom breakdown completo. - Ao confirmar, UI chama
gerarBoleto({ confirmar_encargos: true }). - Backend recalcula encargos (zero-trust) e chama
createBoleto(valor_total, novo_vencimento). - Persiste em
escola_faturassnapshot dos encargos para conciliação contábil. - Loga
pagamento.boleto_emitido_com_encargoscom o breakdown completo.
Faturas no prazo continuam no fluxo direto (sem dialog).
Quem pode reemitir
- Administrador/especialista: qualquer fatura.
- Gestor da escola (
escola/escola_trial): somente faturas da própria escola — auto-atendimento.
Conciliação contábil
Quando o webhook do Mercado Pago confirma pagamento de boleto reemitido, sabemos com precisão:
text
escola_faturas.valor = principal (mensalidade)
escola_faturas.boleto_valor_cobrado = total cobrado no boleto
escola_faturas.boleto_multa = multa em R$
escola_faturas.boleto_juros = juros em R$
escola_faturas.boleto_vencimento_original = vencimento real da fatura
escola_faturas.boleto_expira_em = vencimento do boleto reemitidoO campo valor continua intacto (principal). O extra entra como receita de multa/juros.
Limitações conhecidas
- Feriados nacionais não são considerados no cálculo de
dias_uteis_novo_vencimento— hoje só pula sáb/dom. Risco: ~10-12 dias/ano em que D+3 cai em dia sem compensação bancária, gerando cobrança indevida de juros na régua D+3/D+10/D+17 (CDC §52). Roadmap P2 emmem://features/billing/feriados-dias-uteis-roadmap; triagem em boleto-manual.md §Roadmap pós-MVP. - Feriados estaduais/municipais variam por escola — fora do roadmap atual.
- Override de valor cobrado (desconto comercial, ajuste de erro) está gated por ADR-017 (status Proposed). Sem o ADR aprovado, a única forma de ajustar valor é UPDATE manual no banco.
Follow-up adicional
- Override de encargos por escola (caso jurídico peça contrato diferenciado).
- Recálculo retroativo de boletos já emitidos com valor antigo (não toca).
Alterar a política
sql
UPDATE public.configuracoes_cobranca
SET multa_atraso_percentual = 2.00,
juros_mora_mensal_percentual = 1.00,
dias_uteis_novo_vencimento = 3,
ativo = true,
atualizado_por = '<uuid_admin>';A mudança entra em vigor na próxima emissão. Não afeta boletos já gerados.