feat(nakui): Fase 5 del ERP — tablero de KPIs

View::Dashboard: grilla de tarjetas de agregados. Metric Count/Sum/
GroupBy con filtro opcional (CardFilter), computado por compute_metric
en meta-runtime (MetricResult Scalar/Breakdown). meta-form render_dashboard
pinta cada tarjeta con el número grande formateado o un breakdown con
barras de texto. El CRM gana una vista «Panorama»: clientes,
oportunidades, pipeline, ganadas, y breakdowns por etapa y canal.

Tests de compute_metric; verificación del panorama en nakui-ui. Clippy
limpio en las libs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 19:29:27 +00:00
parent ab1cf9998a
commit ab2b8f6638
10 changed files with 386 additions and 12 deletions
+25
View File
@@ -432,10 +432,35 @@ mod tests {
"interaccion_form",
"cliente_detail",
"oportunidad_detail",
"panorama",
] {
assert!(m.views.contains_key(view), "falta la vista «{view}»");
}
// Fase 5: el tablero «panorama» con sus tarjetas de KPI.
let nahual_meta_schema::View::Dashboard(dash) = &m.views["panorama"] else {
panic!("panorama debe ser un tablero (dashboard)");
};
assert!(
dash.cards.len() >= 5,
"el panorama debe tener varias tarjetas"
);
let ganadas = dash
.cards
.iter()
.find(|c| c.label.contains("ganadas"))
.expect("tarjeta de oportunidades ganadas");
assert!(
ganadas.filter.is_some(),
"la tarjeta «ganadas» debe filtrar por etapa",
);
assert!(
dash.cards
.iter()
.any(|c| matches!(c.metric, nahual_meta_schema::Metric::GroupBy { .. })),
"el panorama debe tener al menos un breakdown",
);
// Fase 2: la lista de oportunidades resuelve `cliente_id` al
// label del cliente y formatea `monto` como moneda.
let nahual_meta_schema::View::List(lv) = &m.views["oportunidad_list"] else {