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

# Referencia de plantillas

> Consulta cada tag, filtro y operador disponibles en Reporter — bucles, condicionales, placeholders y helpers de formato integrados.

Esta página es una referencia completa de todos los tags, filtros y operadores de plantillas disponibles en Reporter. Para una introducción a las plantillas y marcadores de posición, consulte [Qué es Reporter](/es/reporter/what-is-reporter).

## Construcción de plantillas

***

### Bloques comunes

* **Bucle**

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

* **Bucle con esquema explícito**

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

* **Condición simple**

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

* **Alcance temporal**

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

* **Formato de valores**

```
{{ field_name | floatformat:2 }}   --> renders 123.45
```

### Bloques condicionales

| Bloque                | Descripción                                           | Ejemplo                                                |
| --------------------- | ----------------------------------------------------- | ------------------------------------------------------ |
| If                    | Ejecuta el bloque si la condición es verdadera        | `{% if condition %}...{% endif %}`                     |
| If-else               | Ejecuta un bloque si es verdadero, otro si es falso   | `{% if condition %}...{% else %}...{% endif %}`        |
| If-else-if            | Permite múltiples verificaciones                      | `{% if a %}...{% elif b %}...{% else %}...{% endif %}` |
| Equal                 | Verifica si dos valores son iguales                   | `{% if a == b %}`                                      |
| Not equal             | Verifica si dos valores son diferentes                | `{% if a != b %}`                                      |
| Greater than          | Verifica si a es mayor que b                          | `{% if a > b %}`                                       |
| Less than             | Verifica si a es menor que b                          | `{% if a < b %}`                                       |
| Greater than or equal | Verifica si a es mayor o igual que b                  | `{% if a >= b %}`                                      |
| Less than or equal    | Verifica si a es menor o igual que b                  | `{% if a <= b %}`                                      |
| And                   | Retorna verdadero si ambas condiciones son verdaderas | `{% if a and b %}`                                     |
| Or                    | Retorna verdadero si al menos una es verdadera        | `{% if a or b %}`                                      |
| Not                   | Invierte el resultado booleano                        | `{% if not a %}`                                       |

## Referencia de tags

***

### Tags de agregación

**sum\_by** -- Suma valores numéricos de un campo en todos los elementos de una colección.

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

**Ejemplo:**

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

**count\_by** -- Cuenta el número de elementos en una colección.

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

**Ejemplo:**

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

**avg\_by** -- Calcula el promedio de valores numéricos en un campo.

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

**min\_by** -- Encuentra el valor numérico mínimo en un campo.

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

**max\_by** -- Encuentra el valor numérico máximo en un campo.

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

<Note>
  Todos los tags de agregación utilizan precisión decimal para evitar errores de redondeo de punto flotante. Los campos faltantes o no numéricos se omiten. Retorna `0` si ningún elemento coincide.
</Note>

### Tag de fecha y hora

**date\_time** -- Muestra la fecha y hora actual formateada según la cadena de formato proporcionada. La hora se genera en UTC.

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

**Códigos de formato:**

| Código | Significado             | Ejemplo |
| ------ | ----------------------- | ------- |
| `YYYY` | Año de 4 dígitos        | 2025    |
| `MM`   | Mes de 2 dígitos        | 01-12   |
| `dd`   | Día de 2 dígitos        | 01-31   |
| `HH`   | Hora de 2 dígitos (24h) | 00-23   |
| `mm`   | Minuto de 2 dígitos     | 00-59   |
| `ss`   | Segundo de 2 dígitos    | 00-59   |

**Ejemplos:**

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

### Tag aritmético

**calc** -- Evalúa expresiones matemáticas con soporte para variables del contexto de la plantilla.

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

**Operadores soportados:**

| Operador | Descripción              | Precedencia                    |
| -------- | ------------------------ | ------------------------------ |
| `**`     | Exponenciación           | Más alta (derecha a izquierda) |
| `*` `/`  | Multiplicación, división | Media                          |
| `+` `-`  | Suma, resta              | Más baja                       |
| `( )`    | Paréntesis               | Anula la precedencia           |

**Ejemplos:**

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

<Note>
  Las variables que no pueden resolverse toman el valor predeterminado `0`. La división por cero produce un error.
</Note>

### Tag de selección agrupada

**last\_item\_by\_group** -- Agrupa elementos por un campo y selecciona el elemento más reciente de cada grupo, ordenado por un campo de fecha (descendente). De forma opcional, filtra los elementos primero. Útil para reportes regulatorios que requieren el último registro por cuenta agrupado por categoría.

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

El resultado es una lista de elementos -- el más reciente de cada grupo -- almacenada en una variable sobre la que puedes iterar. Cada elemento es el registro original de la colección, así que accedes a sus propios 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` acepta una lista de campos separados por comas para agrupación compuesta. Tamaño máximo de la colección: 100,000 elementos. Los resultados se ordenan por el valor de `group_by` para una salida determinista.
</Note>

### Tags de contadores

**counter** -- Incrementa un contador nombrado en 1. No produce salida. Los contadores tienen alcance por renderizado.

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

**counter\_show** -- Muestra la suma de uno o más contadores nombrados.

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

**Ejemplo:**

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

## Referencia de filtros

***

### percent\_of

Calcula el porcentaje de un valor en relación con un total. Retorna una cadena formateada con 2 decimales.

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

Ejemplo: si `category.amount = "6.00"` y `total.expenses = "20.00"`:

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

### strip\_zeros

Elimina los ceros finales de un valor numérico sin redondear.

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

**Ejemplos:**

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

### slice

Extrae una subcadena usando índices de inicio y fin (basados en 0).

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

**Ejemplos:**

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

### replace

Reemplaza todas las ocurrencias de una cadena de búsqueda con una cadena de reemplazo. Formato: `"búsqueda:reemplazo"`.

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

**Ejemplos:**

```
{{ "01310-100" | replace:"-:" }}      --> 01310100   (elimina guiones)
{{ "1234.56" | replace:".:," }}       --> 1234,56    (punto a coma)
{{ "12.345.678/0001-99" | replace:".:" }}  --> 12345678/0001-99
```

### where

Filtra un arreglo de objetos por igualdad de campo. Soporta campos anidados mediante notación de punto.

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

**Ejemplos:**

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

Uso dentro de bucles:

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

### sum (filtro)

Suma valores numéricos de un campo en todos los elementos de un arreglo. Utiliza precisión decimal.

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

**Ejemplos:**

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

### count (filtro)

Cuenta los elementos de un arreglo donde un campo coincide con un valor. Soporta campos anidados.

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

**Ejemplos:**

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

### contains

Verifica si un valor está parcialmente incluido en otro. Útil cuando los datos incluyen prefijos o sufijos dinámicos.

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

**Ejemplo:**

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

Retorna `true` porque `@external/BRL` existe dentro del valor de origen.

## Resumen de operadores y filtros

***

| Nombre               | Tipo    | Descripción                                |
| -------------------- | ------- | ------------------------------------------ |
| `sum_by`             | Tag     | Suma valores por campo con filtro opcional |
| `count_by`           | Tag     | Cuenta elementos con filtro opcional       |
| `avg_by`             | Tag     | Calcula el promedio por campo              |
| `min_by`             | Tag     | Encuentra el valor mínimo                  |
| `max_by`             | Tag     | Encuentra el valor máximo                  |
| `date_time`          | Tag     | Formatea la fecha/hora actual              |
| `calc`               | Tag     | Evalúa expresiones aritméticas             |
| `last_item_by_group` | Tag     | Último elemento por grupo según la fecha   |
| `counter`            | Tag     | Incrementa un contador nombrado            |
| `counter_show`       | Tag     | Muestra el valor del contador              |
| `percent_of`         | Filtro  | Calcula porcentaje                         |
| `strip_zeros`        | Filtro  | Elimina ceros finales                      |
| `slice`              | Filtro  | Extrae subcadena                           |
| `replace`            | Filtro  | Reemplazo de cadenas                       |
| `where`              | Filtro  | Filtra arreglo por valor de campo          |
| `sum`                | Filtro  | Suma valores de campo del arreglo          |
| `count`              | Filtro  | Cuenta elementos coincidentes              |
| `contains`           | Función | Coincidencia parcial de cadenas            |
| `floatformat`        | Filtro  | Formatea decimales                         |

## Filtrado avanzado

***

Al generar un reporte, puede pasar filtros en el cuerpo de la solicitud para acotar los datos. Los filtros siguen una estructura de fuente de datos > tabla > campo:

**Esquema único (predeterminado):**

```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-esquema (clave explícita esquema.tabla):**

```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 soportados:**

| Operador  | Descripción                          | Ejemplo                              |
| --------- | ------------------------------------ | ------------------------------------ |
| `eq`      | Igual a                              | `{ "eq": ["active", "pending"] }`    |
| `gt`      | Mayor que                            | `{ "gt": [100] }`                    |
| `gte`     | Mayor o igual que                    | `{ "gte": ["2025-06-01"] }`          |
| `lt`      | Menor que                            | `{ "lt": [1000] }`                   |
| `lte`     | Menor o igual que                    | `{ "lte": ["2025-06-30"] }`          |
| `between` | El valor está dentro de un rango     | `{ "between": [100, 1000] }`         |
| `in`      | El valor está dentro de una lista    | `{ "in": ["active", "pending"] }`    |
| `nin`     | El valor no está dentro de una lista | `{ "nin": ["deleted", "archived"] }` |
