feat: add locale formatting config and update notebook outputs
Add configurable locale/display formatting environment variables (`PALLADIUM_CURRENCY_SYMBOL`, `PALLADIUM_THOUSANDS_SEP`, `PALLADIUM_DECIMAL_SEP`) to support regional number formatting in the Streamlit app. Update `.env.example` with documentation for these new variables. Also refresh `00_setup.ipynb` with current execution outputs reflecting a live Athena connection with report templates, a selected client (Global Guardian Insurance, ID=2), and resolved NameError in assumption override cells.
This commit is contained in:
@@ -5,9 +5,11 @@ from __future__ import annotations
|
||||
import pandas as pd
|
||||
import streamlit as st
|
||||
|
||||
from app.locale import currency_fmt, fmt_currency, fmt_pct, pct_fmt, _STANDARD_LOCALE
|
||||
|
||||
|
||||
def _years_for_table(fields: list[dict], analysis_years: int) -> list[int]:
|
||||
"""Years 1..N — taken from analysis_period_years on the report."""
|
||||
"""Years 1..N -- taken from analysis_period_years on the report."""
|
||||
return list(range(1, max(int(analysis_years or 3), 1) + 1))
|
||||
|
||||
|
||||
@@ -26,6 +28,11 @@ def value_editor(
|
||||
columns, an ``initial`` column for costs, a risk_adjustment column, and
|
||||
a notes column. Returns the edited DataFrame; the caller is responsible
|
||||
for converting it back to value-row dicts and PUTting to Athena.
|
||||
|
||||
Currency columns use the locale configured via PALLADIUM_CURRENCY_SYMBOL /
|
||||
PALLADIUM_THOUSANDS_SEP / PALLADIUM_DECIMAL_SEP in .env.
|
||||
The risk_adj column is stored as a 0-1 fraction and displayed as a
|
||||
percentage (e.g. 0.20 -> "20.00%").
|
||||
"""
|
||||
fields = [
|
||||
f
|
||||
@@ -44,43 +51,76 @@ def value_editor(
|
||||
for f in fields:
|
||||
v = by_key.get(f["field_key"], {}) or {}
|
||||
yv = v.get("year_values") or {}
|
||||
risk_raw = float(v.get("risk_adjustment") or 0.0)
|
||||
row = {
|
||||
"field_key": f["field_key"],
|
||||
"label": f.get("label", f["field_key"]),
|
||||
"category": f.get("category", "") or "",
|
||||
}
|
||||
if table == "costs":
|
||||
row["Initial"] = float(v.get("initial") or 0.0)
|
||||
if _STANDARD_LOCALE:
|
||||
row["Initial"] = float(v.get("initial") or 0.0)
|
||||
else:
|
||||
row["Initial"] = fmt_currency(float(v.get("initial") or 0.0))
|
||||
for y in years:
|
||||
row[f"Year {y}"] = float(yv.get(str(y)) or 0.0)
|
||||
row["risk_adj"] = float(v.get("risk_adjustment") or 0.0)
|
||||
raw = float(yv.get(str(y)) or 0.0)
|
||||
if _STANDARD_LOCALE:
|
||||
row[f"Year {y}"] = raw
|
||||
else:
|
||||
row[f"Year {y}"] = fmt_currency(raw)
|
||||
# Risk adj: store as fraction for standard locales (NumberColumn handles
|
||||
# display), or pre-format as "20.00%" string for non-standard locales.
|
||||
if _STANDARD_LOCALE:
|
||||
row["risk_adj"] = risk_raw
|
||||
else:
|
||||
row["risk_adj"] = fmt_pct(risk_raw)
|
||||
row["notes"] = v.get("notes", "") or ""
|
||||
rows.append(row)
|
||||
|
||||
df = pd.DataFrame(rows)
|
||||
|
||||
_cur_fmt = currency_fmt()
|
||||
_pct_fmt_str = pct_fmt()
|
||||
|
||||
column_config: dict = {
|
||||
"field_key": st.column_config.TextColumn("Key", disabled=True, width="small"),
|
||||
"label": st.column_config.TextColumn("Field", disabled=True),
|
||||
"category": st.column_config.TextColumn("Category", disabled=True, width="small"),
|
||||
"risk_adj": st.column_config.NumberColumn(
|
||||
"Risk Adj.", min_value=0.0, max_value=1.0, step=0.05, format="%.2f"
|
||||
),
|
||||
"notes": st.column_config.TextColumn("Notes", width="medium"),
|
||||
}
|
||||
if table == "costs":
|
||||
column_config["Initial"] = st.column_config.NumberColumn(
|
||||
"Initial", format="$%.0f"
|
||||
|
||||
if _STANDARD_LOCALE:
|
||||
column_config["risk_adj"] = st.column_config.NumberColumn(
|
||||
"Risk Adj.",
|
||||
min_value=0.0,
|
||||
max_value=1.0,
|
||||
step=0.05,
|
||||
format=_pct_fmt_str,
|
||||
help="Enter as a decimal fraction (e.g. 0.20 = 20%)",
|
||||
)
|
||||
for y in years:
|
||||
column_config[f"Year {y}"] = st.column_config.NumberColumn(
|
||||
f"Year {y}", format="$%.0f"
|
||||
if table == "costs":
|
||||
column_config["Initial"] = st.column_config.NumberColumn(
|
||||
"Initial", format=_cur_fmt
|
||||
)
|
||||
for y in years:
|
||||
column_config[f"Year {y}"] = st.column_config.NumberColumn(
|
||||
f"Year {y}", format=_cur_fmt
|
||||
)
|
||||
else:
|
||||
# Non-standard locale: display as pre-formatted strings (read-only display;
|
||||
# user edits the raw number and we re-format on save).
|
||||
column_config["risk_adj"] = st.column_config.TextColumn(
|
||||
"Risk Adj.", help="Displayed as percentage; stored as 0-1 fraction"
|
||||
)
|
||||
if table == "costs":
|
||||
column_config["Initial"] = st.column_config.TextColumn("Initial")
|
||||
for y in years:
|
||||
column_config[f"Year {y}"] = st.column_config.TextColumn(f"Year {y}")
|
||||
|
||||
edited = st.data_editor(
|
||||
df,
|
||||
column_config=column_config,
|
||||
use_container_width=True,
|
||||
width="stretch",
|
||||
num_rows="fixed",
|
||||
hide_index=True,
|
||||
key=key,
|
||||
|
||||
Reference in New Issue
Block a user