From 338477ac97e711fff8600ea5b66434c4a20a60c6 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Sun, 30 Nov 2025 21:17:05 +0000 Subject: [PATCH] merge to main so kahlim has latest --- .../src/dashboard/components/pivot_charts.py | 12 ++- backend/src/dashboard/main.py | 92 +++++++++++++------ 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/backend/src/dashboard/components/pivot_charts.py b/backend/src/dashboard/components/pivot_charts.py index 67c09f6..6e5fd80 100644 --- a/backend/src/dashboard/components/pivot_charts.py +++ b/backend/src/dashboard/components/pivot_charts.py @@ -92,10 +92,14 @@ def build_pivot_tables(df, selected_week): for pt, vals in rows.items(): row = {"Product Type": pt} for wk in week_list_sorted: + # Visible numeric columns row[f"{wk}_Planned Jobs"] = vals.get(f"{wk}_planned_jobs", 0) row[f"{wk}_Actual Jobs"] = vals.get(f"{wk}_actual_jobs", 0) - jobs_records.append(row) + # 🔥 Hidden ID fields for modal + row[f"{wk}_planned_ids"] = vals.get(f"{wk}_planned_ids", "") + row[f"{wk}_actual_ids"] = vals.get(f"{wk}_actual_ids", "") + jobs_records.append(row) # ----- ADD TOTAL ROW ----- total_row = {"Product Type": "TOTAL"} for wk in week_list_sorted: @@ -113,10 +117,14 @@ def build_pivot_tables(df, selected_week): for pt, vals in rows.items(): row = {"Product Type": pt} for wk in week_list_sorted: + # Visible totals row[f"{wk} Planned £"] = vals.get(f"{wk}_planned_total", 0) row[f"{wk} Actual £"] = vals.get(f"{wk}_actual_total", 0) - revenue_records.append(row) + # 🔥 Hidden ID fields + row[f"{wk}_planned_ids"] = vals.get(f"{wk}_planned_ids", "") + row[f"{wk}_actual_ids"] = vals.get(f"{wk}_actual_ids", "") + revenue_records.append(row) # ----- ADD TOTAL ROW ----- total_rev = {"Product Type": "TOTAL"} for wk in week_list_sorted: diff --git a/backend/src/dashboard/main.py b/backend/src/dashboard/main.py index b88bc1e..760ebbb 100644 --- a/backend/src/dashboard/main.py +++ b/backend/src/dashboard/main.py @@ -2,11 +2,14 @@ from dash import Dash, html, dcc, dash_table, Input, Output, State import dash_bootstrap_components as dbc import pandas as pd from datetime import datetime, timedelta +from dash import ctx + from backend.src.dashboard.services.file_manager import FileManager from backend.src.dashboard.services.json_reader import jsonReader from backend.src.dashboard.components.pivot_charts import build_pivot_tables_and_charts, week_start_monday + SAFE_DELIM = "\\\\" @@ -23,10 +26,18 @@ def current_week_start(): # Product Types # ----------------------------------------------------- PRODUCT_TYPES = [ - "Empty Cavity - ECO4", "Solar PV - ECO4", "Extract & Fill - ECO4", + ### ECO THINGS + "Empty Cavity - ECO4", + "Solar PV - ECO4", "Extract & Fill - ECO4", "Solar PV + Heating Upgrade - ECO4", "Solar PV + HHRSH - ECO4", "ECO4 empty cavity survey", "ECO4 Retrofit Coordination", "ECO4 Solar with client contribution", "EPC", + ### WARM HOMES THINGS + "Design Archetype Complex", "Coordination Stage 1", "Full Lodgement Phase 2", + "Retrofit Assessment","Post EPC NO SHOW", "ATT NO SHOW", "RA NO SHOW", "Post ATT", "Post EPC", "Post EPR", "Lodgement Phase 1", + "Coordination Stage 2", "Design Repetitive Complex", "Design Repetitive Simple", "Air Tightness Test", "Design Archetype Simple", + # Other + "Boroscope Survey", ] @@ -213,8 +224,8 @@ def update_outputs(selected_week, n_clicks): # ----------------------------------------------------- def id_to_link(deal_id): url = f"https://app.hubspot.com/contacts/145275138/record/0-3/{deal_id}" - return html.Li(html.A(deal_id, href=url, target="_blank")) - + match = df.loc[df["hubspot_id"].astype(str) == str(deal_id)] + return html.Li(html.A(match.iloc[0].get("deal_name"), href=url, target="_blank")) @app.callback( Output("hubspot-modal", "is_open"), @@ -228,40 +239,67 @@ def id_to_link(deal_id): State("jobs-table", "data"), State("revenue-table", "data"), - State("hubspot-modal", "is_open") + State("hubspot-modal", "is_open"), ) def open_modal(jobs_cell, revenue_cell, close_click, jobs_data, revenue_data, is_open): - if close_click: + triggered = ctx.triggered_id + + # ------------------------- + # CLOSE THE MODAL + # ------------------------- + if triggered == "close-modal": return False, "", None, None + # modal closes & cells reset correctly - # ----- Jobs Table Click ----- - if jobs_cell: + # ------------------------- + # INTERNAL helper + # ------------------------- + def build_modal(row, col_id): + + if "_" not in col_id: + return html.P("No HubSpot IDs for this column.") + + week, side = col_id.split("_", 1) + + side_lower = side.lower() + + id_key = f"{week}_planned_ids" if "planned" in side_lower else f"{week}_actual_ids" + + raw_ids = row.get(id_key, "") + + if not raw_ids: + return html.P("No IDs recorded for this cell.") + + ids = raw_ids.split(SAFE_DELIM) + + return html.Ul([id_to_link(d) for d in ids]) + + # ------------------------- + # JOBS TABLE CLICK + # ------------------------- + if triggered == "jobs-table": row = jobs_data[jobs_cell["row"]] - col = jobs_cell["column_id"] + col_id = jobs_cell["column_id"] + return True, build_modal(row, col_id), None, None - wk = col.replace(" Planned Jobs", "").replace(" Actual Jobs", "") - id_key = f"{wk}_planned_ids" if "Planned" in col else f"{wk}_actual_ids" - - ids = row.get(id_key, "") - links = [id_to_link(i) for i in ids.split(SAFE_DELIM)] if ids else [] - return True, html.Ul(links), None, None - - # ----- Revenue Table Click ----- - if revenue_cell: + # ------------------------- + # REVENUE TABLE CLICK + # ------------------------- + if triggered == "revenue-table": row = revenue_data[revenue_cell["row"]] - col = revenue_cell["column_id"] - - wk = col.replace(" Planned £", "").replace(" Actual £", "") - id_key = f"{wk}_planned_ids" if "Planned" in col else f"{wk}_actual_ids" - - ids = row.get(id_key, "") - links = [id_to_link(i) for i in ids.split(SAFE_DELIM)] if ids else [] - return True, html.Ul(links), None, None - - return False, "", None, None + col_id = revenue_cell["column_id"] + return True, build_modal(row, col_id), None, None + # ------------------------- + # Default + # ------------------------- + return is_open, "", None, None # ----------------------------------------------------- if __name__ == "__main__": app.run(debug=True) + # TODO: + # 1) They just need a way to check numbers via hubspot deals + # 2) a few feedback changes from management as they need it + # 3) Investigate why this week numbers are wrong ( i think its something to do with attempts) ( might be that the data wasn't saved till now?)