> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Cálculos do Fees Engine

> Saiba como o Fees Engine calcula tarifas, lida com precisão decimal, divide valores entre contas e aplica isenções em períodos diários ou mensais.

## Valores numéricos (string)

***

Expresse todos os valores financeiros no **Fees Engine** como uma `string` do tipo `numeric`. Isso garante alta precisão decimal para ativos como BRL ou BTC. Também evita erros de arredondamento durante cálculos, divisões ou isenções.

**Exemplo:**

```
"value": "12.50"
```

## Períodos de faturamento

***

Ao acionar um cálculo de faturamento, você especifica a janela de tempo pelo campo `period`. O Fees Engine aceita três formatos:

| Formato | Exemplo      | Janela                                                                   |
| ------- | ------------ | ------------------------------------------------------------------------ |
| Diário  | `2026-03-15` | Início daquele dia → início do dia seguinte (UTC)                        |
| Semanal | `2026-W13`   | Segunda-feira 00:00 UTC da semana ISO → segunda-feira seguinte 00:00 UTC |
| Mensal  | `2026-03`    | Primeiro instante do mês → primeiro instante do mês seguinte (UTC)       |

O mecanismo usa o período para contar as transações qualificadas (para pacotes de volume) ou as contas ativas (para pacotes de manutenção) dentro dessa janela exata.

<Tip>
  Os períodos semanais seguem o [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Week_dates). A numeração das semanas vai de `W01` a `W52` (ou `W53` em anos com 53 semanas ISO). A semana sempre começa na segunda-feira.
</Tip>

Escolha a granularidade que corresponde ao seu ciclo de faturamento. Um produto de cartão pré-pago faturado diariamente usaria `2026-03-15`. Uma plataforma SaaS faturada mensalmente usaria `2026-03`. Um marketplace que liquida semanalmente usaria `2026-W13`.

## Regras de cálculo de tarifa

***

Cada tarifa usa uma `applicationRule` para definir como ela é calculada. Você pode escolher entre três tipos de regra:

* [maxBetweenTypes](#maxbetweentypes)
* [flatFee](#flatfee)
* [percentual](#percentual)

Você pode combinar regras diferentes em um único pacote para atender ao seu caso de uso.

Outros campos importantes:

* `isDeductibleFrom`: define se a tarifa é deduzida do remetente ou do destinatário.
* `referenceAmount`: `originalAmount` ou `afterFeesAmount`.
* `priority`: define a ordem de aplicação. A prioridade 1 deve sempre usar `originalAmount`.

### maxBetweenTypes

Aplica o que for maior: uma tarifa fixa ou uma tarifa percentual.

**Exemplo**

* Valor da tarifa fixa: R\$ 5.
* Tarifa percentual: 2%.
* Valor de referência: R\$ 1.000.

```
rate = 1000 * 0.02 = R$ 20.00
```

Como **R\$ 20 > R\$ 5**, o mecanismo aplica a tarifa percentual.

### flatFee

Aplica um valor de tarifa fixo. O comportamento depende de `isDeductibleFrom`.

**Exemplo**

* Tarifa fixa: R\$ 15.
* Valor de referência: R\$ 115.

| `isDeductibleFrom` | Fórmula                 | Tarifa Total |
| :----------------- | :---------------------- | :----------- |
| `false`            | `referenceAmount + fee` | R\$ 130,00   |
| `true`             | `referenceAmount - fee` | R\$ 100,00   |

### percentual

Aplica uma tarifa como percentual do valor de referência.

**Exemplo**

* Valor: 30%.
* Valor de referência: R\$ 389,50.

| `isDeductibleFrom` | Fórmula                                       | Tarifa Total |
| :----------------- | :-------------------------------------------- | :----------- |
| `false`            | `referenceAmount * value`                     | R\$ 116,85   |
| `true`             | `referenceAmount - (referenceAmount * value)` | R\$ 272,65   |

## Divisão de tarifas

***

Quando uma transação tem múltiplas contas de origem, o Fees Engine divide as tarifas proporcionalmente.

### Exemplo

* Valor total: R\$ 4.000,00
* Tarifa fixa: R\$ 15,00
* Imposto: 4%
* `isDeductibleFrom: false`

### Participação %

> **Fórmula**: (Valor da Conta ÷ Valor Total) × 100

| Conta     | Participação | Valor     |
| :-------- | :----------- | :-------- |
| @account1 | 25%          | R\$ 1.000 |
| @account2 | 25%          | R\$ 1.000 |
| @account3 | 40%          | R\$ 1.600 |
| @account4 | 10%          | R\$ 400   |

### Distribuição da tarifa fixa

> **Fórmula**: `fixed Fee × participation %`

| Conta     | Parte da Tarifa | Total        |
| :-------- | :-------------- | :----------- |
| @account1 | R\$ 3,75        | R\$ 1.003,75 |
| @account2 | R\$ 3,75        | R\$ 1.003,75 |
| @account3 | R\$ 6,00        | R\$ 1.606,00 |
| @account4 | R\$ 1,50        | R\$ 401,50   |

### Imposto proporcional

> **Fórmula**: `account amount × tax %`

| Conta     | Imposto   | Total c/ Imposto |
| :-------- | :-------- | :--------------- |
| @account1 | R\$ 40,00 | R\$ 1.040,00     |
| @account2 | R\$ 40,00 | R\$ 1.040,00     |
| @account3 | R\$ 64,00 | R\$ 1.664,00     |
| @account4 | R\$ 16,00 | R\$ 416,00       |

### Valor final por conta

> **Fórmula**: `principal + fee + tax`

| Conta     | Tarifa   | Imposto   | Total Final  |
| :-------- | :------- | :-------- | :----------- |
| @account1 | R\$ 3,75 | R\$ 40,00 | R\$ 1.043,75 |
| @account2 | R\$ 3,75 | R\$ 40,00 | R\$ 1.043,75 |
| @account3 | R\$ 6,00 | R\$ 64,00 | R\$ 1.670,00 |
| @account4 | R\$ 1,50 | R\$ 16,00 | R\$ 417,50   |

#### Validações

* Total das participações = 100%
* A divisão da tarifa corresponde à tarifa fixa
* Divisão do imposto = 4%
* Total enviado = R\$ 4.175,00

## Isenções de tarifa: regras e hierarquia

***

### Por valor da transação

Use `minimumAmount` e `maximumAmount` para definir a faixa em que **as tarifas se aplicam**.

> Por exemplo: se a faixa for R$ 0–300, uma transação de R$ 301 não aciona tarifas.

### Por conta

O sistema verifica `waivedAccounts`. Uma origem nessa lista é isenta de tarifas.

<Tip>
  **Hierarquia:** verificação da faixa de valor > depois isenção por conta
</Tip>

## Exemplo combinado: isenções de tarifa e divisão proporcional de tarifas

***

Este pacote inclui contas com isenções de tarifa e exige a divisão proporcional das tarifas.

### Cenário

Estamos processando uma transação de **R\$ 4.000**, que inclui:

* Uma **tarifa fixa** de **R\$ 16**.
* Apenas algumas contas estão sujeitas à tarifa fixa
* Um **imposto IOF** de **6%** a ser deduzido.

#### Divisão do lado da origem

| Conta de Origem | %   | Valor Proporcional |
| :-------------- | --- | :----------------- |
| @account1       | 15% | R\$ 600            |
| @account2       | 35% | R\$ 1.400          |
| @account3       | 40% | R\$ 1.600          |
| @account4       | 10% | R\$ 400            |

O mecanismo aplica a tarifa fixa apenas a `@account3` e `@account4`.

#### Resultado após a Tarifa Administrativa (proporcional)

| Conta     | Tarifa Administrativa | Total        |
| :-------- | :-------------------- | :----------- |
| @account1 | Isento                | R\$ 600      |
| @account2 | Isento                | R\$ 1.400    |
| @account3 | R\$ 12,80             | R\$ 1.612,80 |
| @account4 | R\$ 3,20              | R\$ 403,20   |

O valor total enviado aumenta para **R\$ 4.016**.

#### Dedução de IOF (destinatário)

| Destinatário | %   | Bruto     | IOF (6%) | Líquido |
| :----------- | --- | :-------- | :------- | :------ |
| @donation1   | 25% | R\$ 1.000 | R\$ 60   | R\$ 940 |
| @donation2   | 25% | R\$ 1.000 | R\$ 60   | R\$ 940 |
| @donation3   | 25% | R\$ 1.000 | R\$ 60   | R\$ 940 |
| @donation4   | 25% | R\$ 1.000 | R\$ 60   | R\$ 940 |

<Danger>
  O mecanismo credita as tarifas nas contas definidas no `creditAccount` de cada tarifa.
</Danger>

## Dízimas periódicas

***

Quando a divisão de uma tarifa gera uma dízima periódica (por exemplo, 0,3333...), o Fees Engine mantém cada trecho da tarifa com precisão total. Ele reconcilia o pequeno resto na tarifa da conta com o maior valor. Isso mantém o total exato, evita desvios de arredondamento e mantém seu ledger consistente.

<h2 id="billing-calculations">
  Cálculos de faturamento
</h2>

***

Os pacotes de faturamento usam um modelo de cálculo diferente dos pacotes de tarifas. Em vez de avaliar transações individuais, eles agregam dados ao longo de um período de faturamento e retornam payloads de cobrança para o seu orquestrador executar.

O faturamento aceita três formatos de período: mensal (`YYYY-MM`), semanal (`YYYY-Www`, por exemplo, `2026-W13`) e diário (`YYYY-MM-DD`).

### Cálculo de faturamento por volume

O faturamento por volume conta as transações que correspondem a um `eventFilter` (rota de transação + status) dentro do período de faturamento, e então aplica a precificação com base no modelo configurado.

O cálculo segue esta ordem:

1. **Conta** as transações qualificadas no período.
2. **Subtrai** a `freeQuota` da contagem total para obter a contagem faturável.
3. **Aplica a precificação** com base no `pricingModel` (`tiered` ou `fixed`).
4. **Aplica um desconto** de `discountTiers`, avaliado sobre a contagem **total** (antes de subtrair a cota gratuita).

O mecanismo mantém os valores com precisão decimal total durante todo o processo. O mecanismo não aplica arredondamento de escala do ativo.

#### Precificação em camadas

A precificação em camadas é **precificação por volume, não precificação graduada**. O mecanismo encontra a única camada cuja faixa de quantidade contém a contagem faturável, e então cobra **cada** unidade faturável pelo preço unitário dessa camada. Ele não precifica cada unidade dentro da sua própria faixa.

A faixa de uma camada é inclusiva nas duas pontas. Se você omitir o limite superior, a camada fica sem limite.

O mecanismo busca uma camada apenas quando a contagem faturável é positiva. Se a contagem faturável for positiva e nenhuma camada a cobrir, o cálculo falha para esse pacote. Uma contagem faturável igual a zero pula a busca de camada e produz um valor zero, então suas camadas não precisam cobrir o zero.

**Exemplo**: um pacote de faturamento para emissão de boleto com três camadas e uma cota gratuita de 50:

| Faixa     | Preço unitário |
| --------- | -------------- |
| 1–500     | R\$ 1,20       |
| 501–2.000 | R\$ 0,80       |
| 2.001+    | R\$ 0,45       |

Para um cliente que emitiu 1.800 boletos no mês:

* 50 isentos (cota gratuita) → 1.750 faturáveis
* 1.750 cai na camada 501–2.000, então **todas** as 1.750 unidades são precificadas a R\$ 0,80: R\$ 1.400,00 bruto
* O desconto se aplica sobre a contagem total de 1.800 (≥ 1.000 → 5%): −R\$ 70,00
* **Total líquido: R\$ 1.330,00**

#### Precificação fixa

Um único preço unitário se aplica a todas as transações faturáveis, independentemente do volume. O mecanismo ainda subtrai a cota gratuita antes do cálculo. A precificação fixa usa o preço unitário da **primeira camada** do pacote, então um pacote fixo ainda deve declarar pelo menos uma camada. Caso contrário, o cálculo falha.

**Exemplo**: R\$ 0,10 por Pix enviado, sem cota gratuita:

* 5.000 transações Pix × R\$ 0,10 = R\$ 500,00

#### Camadas de desconto

No máximo **uma** camada de desconto se aplica: a que tem o maior `minQuantity` que a contagem total atinge ou ultrapassa. O mecanismo aplica o percentual dela ao valor bruto. Os descontos são avaliados sobre a contagem total de transações, não sobre a contagem faturável.

#### Escopo da contagem

O cálculo de volume conta as transações **por rota de transação em todo o ledger**. A cota gratuita, as camadas e as camadas de desconto se aplicam a esse total no nível da rota. Para contar dois fluxos separadamente, crie um pacote por rota de transação.

### Cálculo de faturamento de manutenção

O faturamento de manutenção cobra um valor fixo por conta ativa no período de faturamento. O mecanismo resolve as contas-alvo, mantém apenas as ativas e gera um único payload de transação.

O resultado é uma transação N:1:

* Cada conta ativa aparece como um lançamento de débito (`source.from`) no valor configurado em `feeAmount`.
* A `maintenanceCreditAccount` recebe o total completo como um único lançamento de crédito (`distribute.to`).

O mecanismo mantém apenas as contas cujo código de status é `active` e exclui qualquer outro status. Se nenhuma conta for resolvida, o pacote retorna um payload vazio (`{}`) em vez de uma transação.

**Exemplo**: manutenção mensal de R\$ 9,90 para um segmento com 12.000 contas PF ativas:

* 12.000 lançamentos em `source.from`, cada um debitado em R\$ 9,90
* 1 lançamento em `distribute.to` creditado em R\$ 118.800,00

### Resultados com valor zero

Quando o valor líquido de um pacote é zero (por exemplo, quando a cota gratuita cobriu todas as transações), o mecanismo ainda retorna um resultado para esse pacote, mas com um payload de transação vazio (`{}`). Trate isso como "processado, nada a enviar".

Um uso totalmente isento chega a esse resultado sem buscar camada. A cota gratuita leva a contagem faturável a zero, o mecanismo pula a correspondência de camada e o valor é zero. Um pacote cujas camadas começam em 1 está correto para esse caso.

### Política de falha tudo ou nada

Se algum pacote de faturamento falhar durante uma chamada a `/billing/calculate`, a operação inteira falha. O mecanismo não retorna resultados parciais. A resposta indica qual pacote e recurso causou a falha, para você corrigir e executar novamente.

### Metadados de auditoria

Cada resultado de cálculo de faturamento carrega metadados estruturados para rastreabilidade. Os resultados de volume incluem o tipo de faturamento, o id e o rótulo do pacote, o período, as contagens total e faturável de eventos, a cota gratuita usada, o modelo de precificação, os valores bruto e líquido, e o detalhe do desconto (percentual, valor e `minQuantity`) quando aplicável. Os resultados de manutenção incluem o tipo de faturamento, o id e o rótulo do pacote, o período, a contagem total de contas e o valor da tarifa por conta.
