feat(metabase): smartscalar KPI builders (sql + payload + dimension tag)
3 helpers puros para construir KPIs con display=smartscalar y comparacion vs n-1 sin que Metabase v0.59 pida breakout temporal. Replican el patron del dashboard Informe Lean (UNION ALL de 2 filas periodo/valor) y rellenan la firma exacta de template-tags que el frontend MBQL5 acepta. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
---
|
||||
name: metabase_smartscalar_kpi_sql
|
||||
kind: function
|
||||
lang: py
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "def metabase_smartscalar_kpi_sql(*, act_expr: str, n1_expr: str, body_sql: str, date_expr: str = 'MIN(fecha)') -> str"
|
||||
description: "Envuelve agregaciones actual+n-1 en el patron de 2 filas (periodo, valor) que el display smartscalar de Metabase v0.59 requiere para mostrar comparacion vs ano anterior sin pedir breakout temporal. Genera SQL nativo BigQuery con UNION ALL d_min/d_min-52w."
|
||||
tags: [metabase, smartscalar, kpi, sql, bigquery, pure, builder]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports: []
|
||||
params:
|
||||
- name: act_expr
|
||||
desc: "Expresion SQL de agregado para el periodo actual, ej. 'ROUND(SUM(v.venta_n), 2)' o 'SAFE_DIVIDE(SUM(a), NULLIF(SUM(b),0))'"
|
||||
- name: n1_expr
|
||||
desc: "Expresion SQL para el mismo agregado del ano anterior, ej. 'ROUND(SUM(v.venta_n1), 2)'"
|
||||
- name: body_sql
|
||||
desc: "Cuerpo SQL desde 'FROM' que define las tablas/CTEs y filtros con template-tags Metabase ([[AND {{tag}}]])"
|
||||
- name: date_expr
|
||||
desc: "Expresion para extraer la fecha minima del periodo; usada como periodo en la fila actual y ancla para DATE_SUB de la fila n-1. Default 'MIN(fecha)'"
|
||||
output: "string con SQL nativo BigQuery que devuelve 2 filas con columnas periodo (DATE) y valor (numero); fila 1 = periodo n-1, fila 2 = periodo actual"
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "python/functions/metabase/smartscalar.py"
|
||||
---
|
||||
|
||||
## Por que existe
|
||||
|
||||
El display ``smartscalar`` de Metabase v0.59.4 con ``previousValue`` requiere
|
||||
una serie temporal para mostrar comparacion. Si el query devuelve un solo
|
||||
numero el frontend muestra el error "Agrupa solo por un campo de tiempo para
|
||||
ver como ha cambiado con el tiempo".
|
||||
|
||||
El truco probado en el dashboard ``Informe Lean`` (cards 9340-9373) es
|
||||
producir 2 filas sinteticas: una para el periodo actual (``d_min``, ``act``)
|
||||
y otra para n-1 (``d_min - 52 weeks``, ``n1``). Smartscalar lo interpreta como
|
||||
serie de 2 puntos y compara naturalmente.
|
||||
|
||||
Esta funcion automatiza ese patron: el caller solo provee el cuerpo SQL con
|
||||
sus filtros y las dos expresiones de agregado.
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
body = """
|
||||
FROM `proj.ds.base_margenes_aa` `proj.ds.base_margenes_aa` v
|
||||
LEFT JOIN `proj.ds.Objeto_productos` p ON p.nav_id = v.prod_nav_id
|
||||
WHERE 1=1
|
||||
[[AND {{fecha}}]]
|
||||
[[AND {{categoria}}]]
|
||||
[[AND {{tipo}}]]
|
||||
"""
|
||||
|
||||
sql = metabase_smartscalar_kpi_sql(
|
||||
act_expr="ROUND(SUM(v.venta_n), 2)",
|
||||
n1_expr="ROUND(SUM(v.venta_n1), 2)",
|
||||
body_sql=body,
|
||||
date_expr="MIN(v.fecha)",
|
||||
)
|
||||
# sql tiene UNION ALL con periodo y valor
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
- Por convencion los template-tags estan envueltos en ``[[ ]]`` para que sean
|
||||
opcionales: si el dashboard no aplica el filtro la clausula desaparece.
|
||||
- Para que los field-filters de Metabase resuelvan correctamente las tablas
|
||||
dentro de CTEs, alias cada tabla con la cadena ``schema.table`` exacta que
|
||||
Metabase usa al expandir el template-tag (ej. ``\`proj.ds.tabla\` \`ds.tabla\``).
|
||||
- El SQL generado usa ``DATE_SUB(d_min, INTERVAL 52 WEEK)`` (BigQuery dialect).
|
||||
Para Postgres adaptar a ``d_min - INTERVAL '52 weeks'``.
|
||||
Reference in New Issue
Block a user