> ## 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

> Entenda como o Fees Engine calcula, distribui e isenta tarifas com regras rastreáveis e em conformidade para fluxos contábeis complexos.

## Valores numéricos (string)

***

Todos os valores financeiros no **Fees Engine** devem ser expressos como `string`, usando o tipo `numeric`. Isso garante o manuseio decimal de alta precisão para ativos como BRL ou BTC, e previne erros de arredondamento durante cálculos, divisões ou isenções.

<Danger>
  **Importante**

  * **Requerido**: Midaz v3.x.x (usa `numeric`).
  * **Incompatível**: Midaz v2.x.x (formato `amount` + `scale` descontinuado).

  Clientes usando Midaz v2.x.x devem atualizar para v3.x.x para garantir integração e funcionalidade adequadas com o Fees Engine.
</Danger>

**Exemplo:**

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

## Períodos de billing

***

Ao acionar um cálculo de billing, você especifica a janela de tempo através do campo `period`. O Fees Engine suporta três formatos:

| Formato | Exemplo      | Janela                                                                   |
| ------- | ------------ | ------------------------------------------------------------------------ |
| Diário  | `2026-03-15` | Início do 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 motor usa o período para contar transações qualificadas (para pacotes de volume) ou contas ativas (para pacotes de manutenção) dentro dessa janela exata.

<Tip>
  Períodos semanais seguem a [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 que possuem 53 semanas ISO). A semana sempre começa na segunda-feira.
</Tip>

Escolha a granularidade que corresponde ao seu ciclo de billing. Um produto de cartão pré-pago cobrado diariamente usaria `2026-03-15`; uma plataforma SaaS cobrada mensalmente usaria `2026-03`; um marketplace que faz liquidação semanal usaria `2026-W13`.

## Regras de cálculo de taxas

***

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

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

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

Outros campos importantes:

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

### maxBetweenTypes

Aplica o que for maior: uma taxa fixa ou uma taxa baseada em percentual.

**Exemplo**

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

```
rate = 1000 * 0.02 = R$ 20,00
```

Como **R\$ 20 > R\$ 5**, a taxa baseada em percentual é aplicada.

### flatFee

Aplica um valor fixo de taxa. O comportamento depende do `isDeductibleFrom`.

**Exemplo**

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

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

### percentual

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

**Exemplo**

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

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

## Divisão de taxas

***

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

### Exemplo

* Valor total: R\$4.000,00
* Taxa 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 taxa fixa

> **Fórmula**: `taxa fixa × participação %`

| Conta     | Parcela da Taxa | 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**: `valor da conta × % do imposto`

| 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 + taxa + imposto`

| Conta     | Taxa     | 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%
* Divisão da taxa corresponde à taxa fixa
* Divisão do imposto = 4%
* Total enviado = R\$ 4.175,00

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

***

### Por valor da transação

Use `minimumAmount` e `maximumAmount` para definir quando as **taxas devem ser aplicadas**.

> Por exemplo: Se a faixa é R\$ 0–300, uma transação de R\$ 301 não acionará taxas.

### Por conta

O sistema verifica `waivedAccounts`. Se a origem está listada, ela é isenta de taxas.

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

## Exemplo misto: isenções de taxas e divisão proporcional de taxas

***

Vamos ver um exemplo de um pacote que inclui contas com isenções de taxas e requer divisão proporcional das taxas.

### Cenário

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

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

#### Divisão no 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            |

Taxa fixa aplicada apenas a `@account3` e `@account4`.

#### Resultado após Taxa Administrativa (proporcional)

| Conta     | Taxa Admin | Total        |
| :-------- | :--------- | :----------- |
| @account1 | Isenta     | R\$ 600      |
| @account2 | Isenta     | 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>
  As taxas são creditadas nas contas definidas no `creditAccount` de cada taxa.
</Danger>

## Dízimas periódicas

***

Quando uma divisão de taxa resulta em dízimas periódicas (ex.: 0,3333...), o Fees Engine ajusta automaticamente o primeiro ou maior valor em um centavo para garantir que o total permaneça exato. Isso evita desvios de arredondamento e mantém seu ledger consistente.

## Cálculos de billing

***

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

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

### Cálculo de billing por volume

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

O cálculo segue esta ordem:

1. **Conta** as transações qualificadas no período.
2. **Subtrai** o `freeQuota` do total contado.
3. **Aplica preços** com base no `pricingModel` (`tiered` ou `fixed`).
4. **Aplica descontos** dos `discountTiers` se o volume total atingir algum limite.

#### Preço escalonado

Cada faixa define um intervalo de quantidade e um preço unitário. O motor aplica o preço correspondente para cada unidade dentro de cada intervalo.

**Exemplo**: Um pacote de billing para emissão de boletos com três faixas 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: 500 × R\$ 1,20 + 1.250 × R\$ 0,80 = R\$ 1.600,00
* Faixa de desconto aplicada (> 1.000 boletos → 5%): −R\$ 80,00
* **Total: R\$ 1.520,00**

#### Preço fixo

Um único preço unitário se aplica a todas as transações faturáveis, independentemente do volume. A cota gratuita ainda é subtraída antes do cálculo.

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

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

#### Modos de contagem

O campo `countMode` determina como as transações são agrupadas:

* **`perRoute`** — Conta todas as transações correspondentes na organização como um total único.
* **`perAccount`** — Conta transações por conta individual e aplica os preços independentemente para cada uma.

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

O billing de manutenção cobra um valor fixo por conta ativa no período de billing. O motor resolve as contas-alvo, filtra pelo status ativo e gera um único payload de transação.

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

* Cada conta ativa aparece como uma entrada de débito (`source.from`) pelo valor configurado em `feeAmount`.
* A `maintenanceCreditAccount` recebe o total completo como uma única entrada de crédito (`distribute.to`).

Contas inativas, encerradas ou suspensas são excluídas automaticamente.

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

* 12.000 entradas em `source.from`, cada uma debitada em R\$ 9,90
* 1 entrada em `distribute.to` creditada em R\$ 118.800,00

### Política de falha tudo-ou-nada

Se qualquer pacote de billing falhar durante uma chamada `/billing/calculate`, toda a operação falha. Nenhum resultado parcial é retornado. A resposta inclui qual pacote e recurso causou a falha, para que você possa corrigir e re-executar.

### Metadados de auditoria

Cada resultado de cálculo de billing inclui metadados estruturados com todos os parâmetros utilizados — modelo de preços, faixas aplicadas, cota gratuita subtraída, descontos aplicados e contagem de contas. Isso proporciona rastreabilidade completa para conciliação e auditoria.
