Descontos de preço
Este guia é para a equipe da plataforma (papel platform_admin, com segundo fator). Um desconto altera só o valor cobrado de uma organização. Para liberar recursos sem mudar o preço, use as cortesias de Planos e entitlements.
O fluxo tem duas partes: o tipo de desconto (o modelo reutilizável) e a aplicação do tipo a uma organização.
Tipos de desconto
Em Administração › Tipos de desconto (/admin/discount-types) ficam os modelos. Cada tipo tem:
| Campo | Regra |
|---|---|
| Nome | De 3 a 80 caracteres, único entre os tipos ativos (sem diferenciar maiúsculas) |
| Descrição | Opcional, até 500 caracteres |
| Tipo | Percentual (de 1 a 100, até 2 casas) ou Valor fixo (em BRL, maior que zero, até 2 casas) |
| Alvo | Plano (linha de assinatura), Recurso medido (um ou mais recursos, por exemplo egress_gb) ou Fatura (subtotal) |
| Duração | Meses (de 1 a 60 períodos de cobrança), Até uma data (futura) ou Sem prazo |
| Acumulável | Se pode se combinar com outros descontos na mesma base |
Um valor fixo sobre um recurso medido aceita exatamente um recurso.
Editar um tipo cria uma nova versão: as versões antigas nunca mudam, e os descontos já aplicados continuam com a versão com que foram aplicados. Desativar impede novas aplicações sem tocar nas existentes.
Aplicar a uma organização
Na aba Descontos de /admin/orgs/{orgId}, escolha o tipo e informe:
- Motivo, de 10 a 500 caracteres. Fica visível só para a administração;
- Início: agora (padrão) ou a partir do próximo período de cobrança;
- Fim (opcional): sobrepõe o fim calculado pela duração do tipo, desde que seja posterior ao início.
O fim vem da duração: em Meses, é o início do período que contém o início do desconto mais N períodos; em Até uma data, a data do tipo; em Sem prazo, não há fim.
A aplicação é recusada quando:
- o tipo está desativado (409
discount.type_inactive); - o mesmo tipo já está vigente ou agendado na organização (409
discount.already_applied); - o tipo é de valor fixo e o preço vigente da organização não é em BRL (409
discount.currency_mismatch).
Remover um desconto o tira de todos os períodos ainda não fechados; faturas fechadas não mudam. Um job do worker marca como expirados os descontos cujo fim passou (a cada 5 minutos por padrão), mas o cálculo da fatura usa as datas e não depende dele.
A lista /admin/discounts mostra os descontos de todas as organizações e filtra os que vencem em até N dias e os sem prazo. A visão geral da administração destaca "Descontos que vencem em 7 dias" e "Descontos sem prazo".
Acumulação
O cálculo roda no fechamento do período, depois da fatura bruta, e é determinístico.
- Bases. Plano é a linha de assinatura; cada recurso é a sua linha de excedente; Fatura é o subtotal depois dos descontos de linha. Os descontos de plano e de recurso são calculados antes dos de fatura.
- Combinação por base. As alternativas são cada desconto não acumulável sozinho e o conjunto de todos os acumuláveis. Vence a alternativa mais vantajosa para o cliente; em empate, fica a aplicação mais antiga. Um desconto não acumulável nunca se combina com outro na mesma base.
- Ordem dos acumuláveis. Primeiro os percentuais, cada um sobre o que resta da base (10% e 10% resultam em 19%), depois os de valor fixo, na ordem de aplicação.
- Piso em zero. Cada valor é arredondado em 2 casas (half-even) e limitado ao que resta da base: nenhuma linha nem fatura fica negativa.
- Moeda. Percentuais valem em qualquer moeda. Valor fixo é em BRL e é ignorado em fatura de outra moeda.
Cada desconto que efetivamente abate algo vira uma linha Desconto: nome na fatura. Descontos que perderam na combinação não geram linha.
Auditoria e API
A auditoria registra discount_type.created, discount_type.updated, discount_type.deactivated, organization.discount_applied, organization.discount_removed e organization.discount_expired, com o tipo, a versão e o motivo.
| Rota | Uso |
|---|---|
GET/POST /api/v1/admin/discount-types | Listar e criar tipos |
GET/PUT /api/v1/admin/discount-types/{id} | Ler e criar nova versão (com If-Match) |
POST /api/v1/admin/discount-types/{id}/deactivate | Desativar |
GET/POST /api/v1/admin/orgs/{orgId}/discounts | Listar e aplicar |
DELETE /api/v1/admin/orgs/{orgId}/discounts/{discountId} | Remover |
GET /api/v1/admin/discounts | Lista entre organizações, com filtros |
Todas exigem platform_admin; os demais papéis recebem 403. O que a organização enxerga está em Descontos na fatura.