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

# Referência de templates

> Consulte cada tag, filtro e operador de template disponível no Reporter: loops, condicionais, placeholders e auxiliares de formatação integrados.

Esta página é a referência das tags, dos filtros e dos operadores de template no Reporter. Para uma introdução a templates e placeholders, veja [O que é o Reporter?](https://docs.lerian.studio/pt/products/reporter/what-is-reporter.md).

## Construindo templates

***

### Blocos comuns

* **Loop**

```
{% for <item> in <list> %}
  ...
{% endfor %}
```

* **Loop com schema explícito**

```
{% for order in external_db:sales.orders %}
  {{ order.id }} - {{ order.total }}
{% endfor %}
```

* **Condição simples**

```
{% if value_a == value_b %}
  ...
{% endif %}
```

* **Escopo temporário**

```
{% with <object> as <alias> %}
  ...
{% endwith %}
```

* **Formatação de valor**

```
{{ field_name | decimal:2 }}   --> renders 123.4 as 123.40
```

### Blocos condicionais

| Bloco | Descrição | Exemplo |
| - | - | - |
| Se | Executa o bloco se a condição for verdadeira | `{% if condition %}...{% endif %}` |
| Se-senão | Executa um bloco se verdadeiro, outro se falso | `{% if condition %}...{% else %}...{% endif %}` |
| Se-senão se | Permite várias checagens | `{% if a %}...{% elif b %}...{% else %}...{% endif %}` |
| Igual | Verifica se dois valores são iguais | `{% if a == b %}` |
| Diferente | Verifica se dois valores são diferentes | `{% if a != b %}` |
| Maior que | Verifica se a é maior que b | `{% if a > b %}` |
| Menor que | Verifica se a é menor que b | `{% if a < b %}` |
| Maior ou igual | Verifica se a é maior ou igual a b | `{% if a >= b %}` |
| Menor ou igual | Verifica se a é menor ou igual a b | `{% if a <= b %}` |
| E | Retorna verdadeiro se ambas as condições forem verdadeiras | `{% if a and b %}` |
| Ou | Retorna verdadeiro se pelo menos uma for verdadeira | `{% if a or b %}` |
| Não | Inverte o resultado booleano | `{% if not a %}` |

## Referência de tags

***

### Tags de agregação

**sum\_by** -- Soma valores numéricos de um campo em todos os itens de uma coleção.

```
{% sum_by <collection> by <field> %}
{% sum_by <collection> by <field> if <condition> %}
```

**Exemplo:**

```xml theme={null}
<Sum>
  {% sum_by transaction.operation by "amount" if accountAlias != "@external/BRL" %}
</Sum>
```

**count\_by** -- Conta o número de itens em uma coleção.

```
{% count_by <collection> %}
{% count_by <collection> if <condition> %}
```

**Exemplo:**

```xml theme={null}
<Count>
  {% count_by transaction.operation if accountAlias != "@external/BRL" %}
</Count>
```

**avg\_by** -- Calcula a média dos valores numéricos de um campo.

```
{% avg_by <collection> by <field> %}
{% avg_by <collection> by <field> if <condition> %}
```

**min\_by** -- Encontra o valor numérico mínimo de um campo.

```
{% min_by <collection> by <field> %}
{% min_by <collection> by <field> if <condition> %}
```

**max\_by** -- Encontra o valor numérico máximo de um campo.

```
{% max_by <collection> by <field> %}
{% max_by <collection> by <field> if <condition> %}
```

> [!NOTE]
>
> Todas as tags de agregação usam precisão decimal para evitar erros de arredondamento de ponto flutuante. Campos ausentes ou não numéricos são ignorados. Retorna `0` se nenhum item corresponder.

### Tag de data e hora

**date\_time** -- Retorna a data e a hora atuais no fuso horário local do runtime do Reporter, formatadas conforme a string de formato informada.

```
{% date_time "<format>" %}
```

**Códigos de formato:**

| Código | Significado | Exemplo |
| - | - | - |
| `YYYY` | Ano com 4 dígitos | 2025 |
| `MM` | Mês com 2 dígitos | 01-12 |
| `dd` | Dia com 2 dígitos | 01-31 |
| `HH` | Hora com 2 dígitos (24h) | 00-23 |
| `mm` | Minuto com 2 dígitos | 00-59 |
| `ss` | Segundo com 2 dígitos | 00-59 |

**Exemplos:**

```
{% date_time "YYYY-MM-dd" %}           --> 2025-02-06
{% date_time "dd/MM/YYYY HH:mm:ss" %} --> 06/02/2025 14:30:45
```

### Tag aritmética

**calc** -- Avalia expressões matemáticas com suporte a variáveis do contexto do template.

```
{% calc <expression> %}
```

**Operadores suportados:**

| Operador | Descrição | Precedência |
| - | - | - |
| `**` | Exponenciação | Mais alta (da direita para a esquerda) |
| `*` `/` | Multiplicação, divisão | Média |
| `+` `-` | Adição, subtração | Mais baixa |
| `( )` | Parênteses | Sobrepõe a precedência |

**Exemplos:**

```
{% calc 100 + 50 %}                                --> 150
{% calc balance.available * 0.5 %}                 --> calculated value
{% calc (balance.available + 1.2) * balance.on_hold - balance.available / 2 %}
```

> [!NOTE]
>
> Variáveis que não podem ser resolvidas usam `0` por padrão. Divisão por zero produz um erro.

### Tag de seleção agrupada

**last\_item\_by\_group** -- Agrupa itens por um campo e seleciona o item mais recente de cada grupo, ordenado por um campo de data (decrescente). Opcionalmente filtra os itens antes. Útil para relatórios regulatórios que exigem o registro mais recente por conta, agrupado por categoria.

```
{% last_item_by_group <collection> group_by "<group_field>" order_by "<date_field>" [if <condition>] as <result_var> %}
```

O resultado é uma lista de itens -- o mais recente de cada grupo -- armazenada em uma variável que você pode percorrer. Cada elemento é o registro original da coleção, então você acessa seus próprios campos:

```
{% last_item_by_group accounts group_by "cosif_code" order_by "created_at" as latest %}
{% for account in latest %}
  {{ account.cosif_code }}: {{ account.balance }}
{% endfor %}
```

> [!NOTE]
>
> `group_by` aceita uma lista de campos separados por vírgula para agrupamento composto. Tamanho máximo da coleção: 100.000 itens. Os resultados são ordenados pelo valor de `group_by` para uma saída determinística.

### Tags de contador

**counter** -- Incrementa um contador nomeado em 1. Não produz saída. Contadores têm escopo por renderização.

```
{% counter "<counter_name>" %}
```

**counter\_show** -- Mostra a soma de um ou mais contadores nomeados.

```
{% counter_show "<name1>" %}
{% counter_show "<name1>" "<name2>" "<name3>" %}
```

**Exemplo:**

```
{% for tx in ledger.transactions %}
  {% counter tx.type %}
{% endfor %}
Total credits: {% counter_show "credit" %}
Total debits: {% counter_show "debit" %}
Combined: {% counter_show "credit" "debit" %}
```

### Tag de parada

**fail** -- Interrompe o relatório de propósito. Coloque-a dentro de uma condição, para que ela rode só quando os dados quebrarem uma regra que o seu relatório não pode registrar.

```
{% fail "<explanation>" %}
```

O argumento é uma única string não vazia entre aspas. Qualquer outra coisa é um erro de sintaxe: a pré-visualização do template a recusa, e um relatório desse template termina com o status `Error`. Um ramo que não roda não tem efeito.

Quando a tag roda, a renderização para e o Reporter não grava nenhum arquivo. O relatório termina com status `Error` e `metadata.error_code` `report_generation_failed`, e o Reporter não tenta de novo. A pré-visualização do template responde com a explicação.

**Exemplo:**

```
{% if total_debit != total_credit %}
  {% fail "Debits and credits do not match." %}
{% endif %}
```

## Referência de filtros

***

### percent\_of

Calcula a porcentagem de um valor em relação a um total. Retorna uma string formatada com 2 casas decimais.

```
{{ value | percent_of: total }}
```

Exemplo: se `category.amount = "6.00"` e `total.expenses = "20.00"`:

```
{{ category.amount | percent_of: total.expenses }}  --> 30.00%
```

### strip\_zeros

Remove zeros à direita de um valor numérico sem arredondar.

```
{{ number | strip_zeros }}
```

**Exemplos:**

```
{{ "100.50000" | strip_zeros }}  --> 100.5
{{ "100.00" | strip_zeros }}     --> 100
{{ "99.990" | strip_zeros }}     --> 99.99
```

### decimal

Mostra um número com um número fixo de casas decimais, de 0 a 18.

```
{{ number | decimal:places }}
```

**Exemplos:**

```
{{ "100.5" | decimal:2 }}  --> 100.50
{{ 7 | decimal:0 }}        --> 7
```

Apenas `rjust`, `ljust` ou `center` podem vir depois de `decimal` na mesma expressão. O Reporter recusa um template que usa `decimal` dentro de uma tag `{% %}`.

### slice

Extrai uma substring usando índices de início e fim (baseados em 0).

```
{{ string | slice:"start:end" }}
```

**Exemplos:**

```
{{ "hello" | slice:"0:3" }}  --> hel
{{ "12345" | slice:"1:4" }}  --> 234
```

### replace

Substitui todas as ocorrências de uma string de busca por uma string de substituição. Formato: `"search:replacement"`.

```
{{ string | replace:"search:replacement" }}
```

**Exemplos:**

```
{{ "01310-100" | replace:"-:" }}      --> 01310100   (removes hyphens)
{{ "1234.56" | replace:".:," }}       --> 1234,56    (dot to comma)
{{ "12.345.678/0001-99" | replace:".:" }}  --> 12345678/0001-99
```

### where

Filtra um array de objetos por igualdade de campo. Aceita campos aninhados via notação de ponto.

```
{{ array | where:"field:value" }}
```

**Exemplos:**

```
{{ holders | where:"state:SP" }}
{{ holders | where:"address.state:SP" }}
```

Use dentro de loops:

```
{% for holder in holders|where:"state:SP" %}
  {{ holder.name }}
{% endfor %}
```

### sum (filtro)

Soma valores numéricos de um campo em todos os itens de um array. Usa precisão decimal.

```
{{ array | sum:"field" }}
```

**Exemplos:**

```
{{ operations | sum:"amount" }}
{{ items | sum:"price.value" }}
```

### count (filtro)

Conta elementos de um array em que um campo corresponde a um valor. Aceita campos aninhados.

```
{{ array | count:"field:value" }}
```

**Exemplos:**

```
{{ operations | count:"nat_oper:6" }}
{{ holders | count:"address.state:SP" }}
```

### add\_day

Adiciona um campo `dia` a cada linha de uma lista. O valor é o dia do campo de data indicado, como um número no formato `YYYYMMDD`. Use-o para agrupar ou comparar linhas por dia.

```
{{ list | add_day:"date_field" }}
```

### add\_signed

Adiciona um campo `signed` a cada linha de uma lista. O valor é o valor indicado, negativo quando o `direction` da linha é `debit`. Use-o para somar um saldo líquido.

```
{% with ops = midaz_transaction.operation|add_signed:"amount" %}
  {% sum_by ops by "signed" %}
{% endwith %}
```

### filter (função)

Retorna as linhas de uma lista cujo campo é igual a um valor.

```
{% for operation in filter(midaz_transaction.operation, "transaction_id", transaction.id) %}
```

### contains

Verifica se um valor está parcialmente contido em outro, sem diferenciar maiúsculas de minúsculas. Útil quando os dados incluem prefixos ou sufixos dinâmicos.

```
{% if contains(source_field, target_field) %}
```

**Exemplo:**

* Origem: `0#@external/BRL`
* Destino: `@external/BRL`

Retorna `true` porque `@external/BRL` existe dentro do valor de origem.

## Resumo de operadores e filtros

***

| Nome | Tipo | Descrição |
| - | - | - |
| `sum_by` | Tag | Soma valores por campo com filtro opcional |
| `count_by` | Tag | Conta itens com filtro opcional |
| `avg_by` | Tag | Calcula a média por campo |
| `min_by` | Tag | Encontra o valor mínimo |
| `max_by` | Tag | Encontra o valor máximo |
| `date_time` | Tag | Formata a data/hora atual |
| `calc` | Tag | Avalia expressões aritméticas |
| `last_item_by_group` | Tag | Item mais recente por grupo, por data |
| `counter` | Tag | Incrementa um contador nomeado |
| `counter_show` | Tag | Mostra o(s) valor(es) de contador |
| `percent_of` | Filtro | Calcula porcentagem |
| `strip_zeros` | Filtro | Remove zeros à direita |
| `slice` | Filtro | Extrai substring |
| `replace` | Filtro | Substituição de string |
| `where` | Filtro | Filtra array por valor de campo |
| `sum` | Filtro | Soma valores de campo do array |
| `count` | Filtro | Conta itens correspondentes |
| `decimal` | Filtro | Mostra casas decimais fixas |
| `add_day` | Filtro | Adiciona um campo numérico de dia a cada linha |
| `add_signed` | Filtro | Adiciona um campo de valor com sinal a cada linha |
| `filter` | Função | Linhas cujo campo é igual a um valor |
| `contains` | Função | Correspondência parcial de string, sem diferenciar maiúsculas de minúsculas |
| `floatformat` | Filtro | Arredonda para casas decimais |

## Filtragem avançada

***

Ao gerar um relatório, você pode enviar filtros no corpo da requisição para restringir os dados. Os filtros seguem uma estrutura de datasource > tabela > campo:

**Schema único (padrão):**

```json theme={null}
{
  "templateId": "00000000-0000-0000-0000-000000000000",
  "filters": {
    "midaz_onboarding": {
      "account": {
        "id": { "eq": ["123", "456"] },
        "createdAt": { "between": ["2023-01-01", "2023-01-31"] },
        "status": { "in": ["active", "pending"] }
      }
    }
  }
}
```

**Multi-schema (chave explícita schema.tabela):**

```json theme={null}
{
  "templateId": "00000000-0000-0000-0000-000000000000",
  "filters": {
    "external_db": {
      "sales.orders": {
        "total": { "gt": [100] },
        "created_at": { "gte": ["2025-01-01"] }
      },
      "finance.invoices": {
        "status": { "eq": ["paid"] }
      }
    }
  }
}
```

**Operadores suportados:**

| Operador | Descrição | Exemplo |
| - | - | - |
| `eq` | Igual a | `{ "eq": ["active", "pending"] }` |
| `gt` | Maior que | `{ "gt": [100] }` |
| `gte` | Maior ou igual a | `{ "gte": ["2025-06-01"] }` |
| `lt` | Menor que | `{ "lt": [1000] }` |
| `lte` | Menor ou igual a | `{ "lte": ["2025-06-30"] }` |
| `between` | O valor está dentro de um intervalo | `{ "between": [100, 1000] }` |
| `in` | O valor está dentro de uma lista | `{ "in": ["active", "pending"] }` |
| `nin` | O valor não está dentro de uma lista, ou o campo não tem valor | `{ "nin": ["deleted", "archived"] }` |
| `startsWith` | O texto começa com um dos prefixos | `{ "startsWith": ["1", "2"] }` |
| `notStartsWith` | O texto não começa com nenhum dos prefixos, ou o campo não tem valor | `{ "notStartsWith": ["7", "8"] }` |
| `isNull` | O campo não tem valor | `{ "isNull": true }` |
| `notNull` | O campo tem um valor | `{ "notNull": true }` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.