taotanapol commited on
Commit
53dd0c1
Β·
verified Β·
1 Parent(s): 72a5e30

Make KPI card in Inventory tab filter by the item selected in the table

Browse files
Files changed (1) hide show
  1. streamlit_app.py +42 -4
streamlit_app.py CHANGED
@@ -2386,13 +2386,51 @@ with tab_inv:
2386
  & (inv_filt["Date"].dt.month == _m_sel)
2387
  ]
2388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2389
  # ── KPI tiles β€” total Value_Used in the month + per-customer rate
2390
  # Customers for the same month come from kpi_daily, filtered by
2391
  # the same sidebar Restaurant / Branch filters so the ratio is
2392
  # consistent with whichever scope the user is viewing.
2393
  _value_used_total = (
2394
- float(latest_rows["Value_Used"].sum())
2395
- if "Value_Used" in latest_rows.columns else 0.0
2396
  )
2397
  _cust_in_month = kpi_daily.copy() if not kpi_daily.empty else pd.DataFrame()
2398
  if not _cust_in_month.empty and "Date" in _cust_in_month.columns:
@@ -2412,8 +2450,8 @@ with tab_inv:
2412
  _value_per_cust = (_value_used_total / _cust_total) if _cust_total > 0 else None
2413
 
2414
  _qty_used_total = (
2415
- float(latest_rows["Qty_Used"].sum())
2416
- if "Qty_Used" in latest_rows.columns else 0.0
2417
  )
2418
  _qty_per_cust = (_qty_used_total / _cust_total) if _cust_total > 0 else None
2419
 
 
2386
  & (inv_filt["Date"].dt.month == _m_sel)
2387
  ]
2388
 
2389
+ # ── Read prior table selection (if any) BEFORE computing KPIs ────
2390
+ # `st.dataframe(on_select="rerun", key="inv_table")` (rendered
2391
+ # further down) stores its selection in st.session_state under
2392
+ # that key. By reading it here at the top of the rerun we can
2393
+ # use the picked item to filter both the KPI tiles AND the
2394
+ # downstream charts β€” keeping all three in sync.
2395
+ _ranked_preview = (
2396
+ latest_rows[latest_rows[sort_by] > 0]
2397
+ .sort_values(sort_by, ascending=False)
2398
+ .head(100)
2399
+ )
2400
+ _selected_item: "str | None" = None
2401
+ _prior_table_state = st.session_state.get("inv_table")
2402
+ if _prior_table_state is not None and "Item" in _ranked_preview.columns:
2403
+ try:
2404
+ # The state object exposes `.selection.rows` in recent
2405
+ # Streamlit; fall back to dict access for older builds.
2406
+ if hasattr(_prior_table_state, "selection"):
2407
+ _sel_rows = list(_prior_table_state.selection.rows)
2408
+ elif isinstance(_prior_table_state, dict):
2409
+ _sel_rows = list(_prior_table_state.get("selection", {}).get("rows", []))
2410
+ else:
2411
+ _sel_rows = []
2412
+ if _sel_rows:
2413
+ _i = _sel_rows[0]
2414
+ if 0 <= _i < len(_ranked_preview):
2415
+ _selected_item = str(_ranked_preview.iloc[_i]["Item"])
2416
+ except Exception:
2417
+ _selected_item = None
2418
+
2419
+ # KPI source rows: when a row is selected, narrow to just that
2420
+ # item; otherwise use the full month-filtered set.
2421
+ _kpi_rows = (
2422
+ latest_rows[latest_rows["Item"] == _selected_item]
2423
+ if (_selected_item is not None and "Item" in latest_rows.columns)
2424
+ else latest_rows
2425
+ )
2426
+
2427
  # ── KPI tiles β€” total Value_Used in the month + per-customer rate
2428
  # Customers for the same month come from kpi_daily, filtered by
2429
  # the same sidebar Restaurant / Branch filters so the ratio is
2430
  # consistent with whichever scope the user is viewing.
2431
  _value_used_total = (
2432
+ float(_kpi_rows["Value_Used"].sum())
2433
+ if "Value_Used" in _kpi_rows.columns else 0.0
2434
  )
2435
  _cust_in_month = kpi_daily.copy() if not kpi_daily.empty else pd.DataFrame()
2436
  if not _cust_in_month.empty and "Date" in _cust_in_month.columns:
 
2450
  _value_per_cust = (_value_used_total / _cust_total) if _cust_total > 0 else None
2451
 
2452
  _qty_used_total = (
2453
+ float(_kpi_rows["Qty_Used"].sum())
2454
+ if "Qty_Used" in _kpi_rows.columns else 0.0
2455
  )
2456
  _qty_per_cust = (_qty_used_total / _cust_total) if _cust_total > 0 else None
2457