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:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user