> ## 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 é uma referência completa de todas as tags, filtros e operadores de template disponíveis no Reporter. Para uma introdução a templates e placeholders, veja [O que é o Reporter?](/pt/products/reporter/what-is-reporter).

## 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 | floatformat:2 }}   --> renders 123.45
```

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

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

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

### 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** -- Exibe 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" %}
```

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

### 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" }}
```

### contains

Verifica se um valor está parcialmente contido em outro. Ú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    | Exibe 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                |
| `contains`           | Função | Correspondência parcial de string          |
| `floatformat`        | Filtro | Formata casas decimais                     |

<h2 id="advanced-filtering">
  Filtragem avançada
</h2>

***

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 | `{ "nin": ["deleted", "archived"] }` |
