diff --git a/backend/src/dashboard/main.py b/backend/src/dashboard/main.py index 50b53a8..cf89b57 100644 --- a/backend/src/dashboard/main.py +++ b/backend/src/dashboard/main.py @@ -8,6 +8,9 @@ import os BUCKET = "retrofit-data-dev" PREFIX = "hubspot_insight/" +# ------------------------- +# S3 Helpers +# ------------------------- def get_latest_s3_file(bucket: str, prefix: str = "") -> str: s3 = boto3.client("s3") response = s3.list_objects_v2(Bucket=bucket, Prefix=prefix) @@ -46,63 +49,69 @@ def download_and_read_latest(bucket: str, prefix: str = "", download_dir="downlo # ------------------------- -# Load S3 JSON +# Build DataFrame from S3 # ------------------------- -latest_key, file_path, data = download_and_read_latest(BUCKET, PREFIX) +def load_dataframe(): + latest_key, file_path, data = download_and_read_latest(BUCKET, PREFIX) -# ------------------------- -# Build expanded table -# ------------------------- -records = [] + records = [] + for entry in data: + p = entry["deal_properties"] + line_items = entry.get("line_items", []) -for entry in data: - p = entry["deal_properties"] - line_items = entry.get("line_items", []) - - if not line_items: - records.append({ - "Expected Commencement Date": p.get("expected_commencement_date"), - "Deal ID": p.get("deal_id"), - "Line Item Name": "Missing Line Item", - "Line Item Amount": 0 - }) - else: - for li in line_items: + if not line_items: records.append({ "Expected Commencement Date": p.get("expected_commencement_date"), "Deal ID": p.get("deal_id"), - "Line Item Name": li.get("name"), - "Line Item Amount": li.get("amount", 0) + "Line Item Name": "Missing Line Item", + "Line Item Amount": 0 }) + else: + for li in line_items: + records.append({ + "Expected Commencement Date": p.get("expected_commencement_date"), + "Deal ID": p.get("deal_id"), + "Line Item Name": li.get("name"), + "Line Item Amount": li.get("amount", 0) + }) -df = pd.DataFrame(records) + df = pd.DataFrame(records) + df["Line Item Amount"] = pd.to_numeric(df["Line Item Amount"], errors="coerce").fillna(0) + + return df -# Convert numeric fields -df["Line Item Amount"] = pd.to_numeric(df["Line Item Amount"], errors="coerce").fillna(0) # ------------------------- -# Unique date list +# Initial Load # ------------------------- -unique_dates = sorted(df["Expected Commencement Date"].dropna().unique()) -unique_dates = ["All Dates"] + list(unique_dates) +df = load_dataframe() + # ------------------------- # Dash App # ------------------------- app = Dash(__name__) -server = app.server # ← REQUIRED for Render/Gunicorn +server = app.server # required for Render app.layout = html.Div([ html.H1("Line Items by Expected Commencement Date", style={"textAlign": "center"}), dcc.Dropdown( id="date-filter", - options=[{"label": d, "value": d} for d in unique_dates], + options=[{"label": "All Dates", "value": "All Dates"}] + + [{"label": d, "value": d} for d in sorted(df["Expected Commencement Date"].dropna().unique())], value="All Dates", clearable=False, style={"width": "300px", "margin": "20px auto"} ), + html.Button( + "Refresh Data", + id="refresh-btn", + n_clicks=0, + style={"margin": "10px", "padding": "10px 20px"} + ), + dash_table.DataTable( id="lineitem-table", columns=[ @@ -118,15 +127,23 @@ app.layout = html.Div([ ) ]) + # ------------------------- -# Callback for filtering +# Callback (filter + refresh) # ------------------------- @app.callback( Output("lineitem-table", "data"), - Input("date-filter", "value") + Input("date-filter", "value"), + Input("refresh-btn", "n_clicks") ) -def update_table(selected_date): +def update_table(selected_date, n_clicks): + global df + # Refresh DF from AWS when button clicked + if n_clicks > 0: + df = load_dataframe() + + # Filter data if selected_date == "All Dates": dff = df.copy() else: @@ -141,14 +158,12 @@ def update_table(selected_date): .reset_index() ) - # Final rename to match DataTable column IDs grouped = grouped.rename(columns={ "Total_Deals": "Total Deals", "Total_Amount": "Total Amount (£)" }) grouped = grouped.sort_values("Total Amount (£)", ascending=False) - return grouped.to_dict("records")