Skip to content

REF-501-03: CreditBalance & CreditPolicy

ADR: ADR-501 — Service DeliveryEscopo: Reserva/consumo FIFO, granularidade, expiração, carência, limites, extrato de movimentações, CreditBalance ativo mesmo zerado


0. Entity Fields (CreditBalance)

CampoTipoDescrição
organization_idint (FK)Organization dona do saldo
balancedecimal(10,2)Saldo total disponível (nunca negativo)
reserveddecimal(10,2)Saldo reservado em ServiceRequests abertas
currencystringBRL | USD (segue billing_entity da Organization)
updated_atdatetimeÚltimo update do saldo

Invariante: balance - reserved >= 0 — sempre.

Rules:

  • 1 CreditBalance por Organization por currency
  • Auto-criado quando domínio Service habilitado (mesmo com saldo zero — §7)
  • Todas operações registradas em CreditBalanceTransaction (extrato — §6)

Operations:

OperaçãoDescrição
credit(amount, reason, reference_id)Adiciona ao balance (compra de créditos, reembolso)
reserve(amount)Move de balance → reserved (abertura de SR)
release(amount)Move de reserved → balance (SR cancelada)
confirm_debit(amount)Debita de reserved (SR completada)

1. Terminologia

ContextoTermoNota
Interno (código, banco, docs técnicos)UST (Unidade de Serviço Técnico)Nome permanente no sistema
Comercial (portal, cliente, negócio)Crédito / CreditUniversal PT/EN, padrão indústria
Cálculo1 crédito = 10 unidades internasMínimo por serviço: 1 crédito

2. Granularidade

RegraDetalhe
Crédito é inteiroNunca fracionário para o cliente
1 crédito = 10 un.Internamente, 10 unidades = 1 crédito
Mínimo por serviço1 crédito (nenhum serviço custa menos que 10 unidades)
Catálogo recalibradoServiços abaixo de 1 crédito sobem para 1

3. Reserva e Consumo (FIFO)

EtapaComportamento
Abertura de SRCréditos estimados reservados (soft-lock no saldo)
Conclusão de SRCréditos reais consumidos (débito efetivo). Diferença ajustada.
Cancelamento SRReserva liberada integralmente
FIFOCréditos mais antigos consumidos primeiro
AvulsosCréditos comprados avulso com CreditPolicy separada

Fluxo de Reserva

SR criada (ust_estimated = 4 créditos)

    ├── Saldo disponível ≥ 4?
    │   ├── SIM → Reservar 4 (soft-lock, FIFO)
    │   └── NÃO → Verificar CreditPolicy.block_on_limit_exceeded
    │       ├── false → SR continua (billing avulso na conclusão)
    │       └── true + threshold excedido → SR bloqueada

    ├── SR concluída (ust_actual = 5)
    │   ├── Consumir 4 da reserva + 1 adicional (FIFO)
    │   └── Se saldo insuficiente → billing avulso

    └── SR cancelada
        └── 4 créditos reservados liberados

4. Expiração (CreditPolicy)

CampoDefaultDescrição
expiration_months12Meses até expiração de créditos do plano
grace_before_days0Carência antes (antecipação com aprovação admin)
grace_after_days30Carência após expiração
avulso_expiration_months6Expiração de créditos comprados avulso

Cron diário verifica créditos expirados. Hook: middag_credit_expired.


5. Limites de Consumo

CampoDefaultDescrição
block_on_limit_exceededfalseBloquear SRs quando saldo negativo excede threshold
limit_threshold0Créditos negativos permitidos antes de bloqueio (0 = nenhum)

block=false: SRs continuam com saldo zero/negativo. Excedente cobrado como avulso. block=true + threshold: SRs bloqueadas quando negativo excede threshold. Admin pode override.


6. Extrato de Movimentações

CampoTipoDescrição
typeenumcredit / reserve / consume / release / expire
amountintQuantidade (positivo = entrada, negativo = saída)
sr_idFKServiceRequest relacionada (se aplicável)
balance_afterintSaldo após movimentação
created_atdatetimeTimestamp
notesstringDescrição (ex: "Reserva para SR-20260015")
TipoQuandoAmount
creditCréditos adicionados (plano ou avulso)+N
reserveSR aberta, créditos reservados-N (soft)
consumeSR concluída, débito efetivo-N
releaseSR cancelada, reserva devolvida+N
expireCréditos expiraram (cron)-N

7. CreditBalance Ativo Mesmo Zerado

CreditBalance criado automaticamente quando Service habilitado — mesmo com saldo zero.

CenárioComportamento
Service habilitadoCreditBalance criado (pode ter saldo 0)
Saldo = 0SRs continuam (billing avulso), extrato registra
Service desabilitadoCreditBalance preservado (dados não apagados)
PortalSe saldo = 0: "Créditos não incluídos no plano"

Justificativa: mensurar custo operacional real por Organization.


8. Alerta de Saldo Baixo

Saldo disponível < credit_low_threshold_pct (default: 20%) → hook middag_credit_balance_low. NotificationPolicy determina canais.