feat(grid): export_dataframe scopable par base_where_sql/base_params (#41)

This commit is contained in:
Colin Maudry
2026-07-13 09:44:24 +02:00
parent 9e0aa71910
commit 495fe153b1
2 changed files with 34 additions and 3 deletions
+14 -3
View File
@@ -68,17 +68,28 @@ def fetch_grid_page(
return rows, total, total_unique
def export_dataframe(filter_model, sort_model, hidden_columns) -> pl.DataFrame:
def export_dataframe(
filter_model,
sort_model,
hidden_columns,
base_where_sql: str = "TRUE",
base_params: tuple = (),
) -> pl.DataFrame:
"""Renvoie les lignes filtrées/triées pour l'export Excel.
Colonnes masquées exclues, valeurs brutes (non post-traitées HTML).
`base_where_sql`/`base_params` scopent l'export à un sous-ensemble (ex. un
acheteur/titulaire) — combinés en `(base) AND (filtre)`, comme
`fetch_grid_page`. Par défaut `TRUE` → comportement inchangé pour tableau.py.
"""
ast = filtermodel_to_ast(filter_model, schema)
filter_sql, params = ast_to_sql(ast, schema)
filter_sql, filter_params = ast_to_sql(ast, schema)
where_sql = f"({base_where_sql}) AND ({filter_sql})"
params = [*base_params, *filter_params]
order_by = sort_model_to_sql(sort_model, schema) or None
visible = [c for c in schema.names() if c not in set(hidden_columns or [])]
return query_marches(
where_sql=filter_sql,
where_sql=where_sql,
params=params,
columns=visible,
order_by=order_by,
+20
View File
@@ -92,6 +92,26 @@ def test_export_dataframe_applies_filter():
assert df.height == 0
def test_export_dataframe_applies_base_scope():
"""base_where_sql restreint l'export à un sous-ensemble (ex. un acheteur),
en plus du filterModel — utilisé par acheteur.py/titulaire.py (#41)."""
# Récupère un acheteur_id présent dans le jeu de test.
unscoped = export_dataframe(None, None, hidden_columns=[])
assert unscoped.height > 0
an_acheteur = unscoped["acheteur_id"][0]
scoped = export_dataframe(
None,
None,
hidden_columns=[],
base_where_sql="acheteur_id = ?",
base_params=(an_acheteur,),
)
assert scoped.height > 0
assert scoped.height <= unscoped.height
assert set(scoped["acheteur_id"].to_list()) == {an_acheteur}
def test_get_rows_tableau_tracks_search_once_per_filter_not_per_scroll_block():
"""Régression revue finale #41 : AG Grid envoie une getRowsRequest par bloc
de défilement infini, avec le même filterModel tant que le filtre ne