From 65fb4fabadfc4916a1f740a9cd5798abe7b76b11 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Mon, 13 Jul 2026 23:16:27 +0000 Subject: [PATCH] =?UTF-8?q?Extract=20per-Property=20row=20construction=20b?= =?UTF-8?q?ehind=20a=20shape=20helper=20=F0=9F=9F=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/scenario_export/scenario_sheet.py | 117 +++++++++++------------ 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/domain/scenario_export/scenario_sheet.py b/domain/scenario_export/scenario_sheet.py index 5365f7bca..018b89e11 100644 --- a/domain/scenario_export/scenario_sheet.py +++ b/domain/scenario_export/scenario_sheet.py @@ -180,66 +180,65 @@ class ExportSheet: rows: tuple[dict[str, Any], ...] +_COLUMNS: tuple[str, ...] = ( + _ID_COLUMNS + _ALL_MEASURE_COLUMNS + _SAVINGS_COLUMNS + _TOTAL_COLUMNS + _PLAN_COLUMNS +) + + +def _shape_row(prop: PropertyScenarioData) -> dict[str, Any]: + """One Property's wide row: identity + Effective-EPC descriptive fields, the + measures pivoted onto their cost columns, the savings rolled up, and the + Plan's post-works figures (ADR-0065).""" + row: dict[str, Any] = { + "property_id": prop.property_id, + "landlord_property_id": _blank(prop.landlord_property_id), + "uprn": _blank(prop.uprn), + "address": _blank(prop.address), + "postcode": _blank(prop.postcode), + "property_type": _blank(prop.property_type), + "walls": _blank(prop.walls), + "roof": _blank(prop.roof), + "floor": _blank(prop.floor), + "windows": _blank(prop.windows), + "heating": _blank(prop.heating), + "hot_water": _blank(prop.hot_water), + "lighting": _blank(prop.lighting), + "total_floor_area": _blank(prop.total_floor_area), + "number_of_rooms": _blank(prop.number_of_rooms), + "lodgement_date": _blank(prop.lodgement_date), + "is_expired": _blank(prop.is_expired), + "current_epc_rating": _blank(prop.current_epc_rating), + "current_sap_points": _blank(prop.current_sap_points), + } + # Every measure column is present, blank unless this Property has it, so all + # scenario sheets share one contract (ADR-0065). + for column in _ALL_MEASURE_COLUMNS: + row[column] = "" + for measure in prop.measures: + column = _measure_column(measure) + if column in _ALL_MEASURE_COLUMNS: + row[column] = measure.estimated_cost + # Roll the selected measures' attributed impact up to the Property. + row["sap_points"] = _sum([m.sap_points for m in prop.measures]) + row["co2_equivalent_savings"] = _sum([m.co2_equivalent_savings for m in prop.measures]) + row["kwh_savings"] = _sum([m.kwh_savings for m in prop.measures]) + row["energy_cost_savings"] = _sum([m.energy_cost_savings for m in prop.measures]) + row["total_retrofit_cost"] = _sum([m.estimated_cost for m in prop.measures]) + # The default Plan's post-works figures, passed through as persisted. + row["post_sap_points"] = _blank(prop.post_sap_points) + row["post_epc_rating"] = _blank(prop.post_epc_rating) + row["cost_of_works"] = _blank(prop.cost_of_works) + row["contingency_cost"] = _blank(prop.contingency_cost) + row["co2_savings"] = _blank(prop.co2_savings) + row["energy_bill_savings"] = _blank(prop.energy_bill_savings) + row["energy_consumption_savings"] = _blank(prop.energy_consumption_savings) + row["valuation_increase"] = _blank(prop.valuation_increase) + return row + + def shape_scenario_sheet( properties: Sequence[PropertyScenarioData], ) -> ExportSheet: """Shape one Scenario's Properties into a wide export sheet (ADR-0065).""" - columns: tuple[str, ...] = ( - _ID_COLUMNS - + _ALL_MEASURE_COLUMNS - + _SAVINGS_COLUMNS - + _TOTAL_COLUMNS - + _PLAN_COLUMNS - ) - rows: list[dict[str, Any]] = [] - for prop in properties: - row: dict[str, Any] = { - "property_id": prop.property_id, - "landlord_property_id": _blank(prop.landlord_property_id), - "uprn": _blank(prop.uprn), - "address": _blank(prop.address), - "postcode": _blank(prop.postcode), - "property_type": _blank(prop.property_type), - "walls": _blank(prop.walls), - "roof": _blank(prop.roof), - "floor": _blank(prop.floor), - "windows": _blank(prop.windows), - "heating": _blank(prop.heating), - "hot_water": _blank(prop.hot_water), - "lighting": _blank(prop.lighting), - "total_floor_area": _blank(prop.total_floor_area), - "number_of_rooms": _blank(prop.number_of_rooms), - "lodgement_date": _blank(prop.lodgement_date), - "is_expired": _blank(prop.is_expired), - "current_epc_rating": _blank(prop.current_epc_rating), - "current_sap_points": _blank(prop.current_sap_points), - } - # Every measure column is present, blank unless this Property has it, so - # all scenario sheets share one contract (ADR-0065). - for column in _ALL_MEASURE_COLUMNS: - row[column] = "" - for measure in prop.measures: - column = _measure_column(measure) - if column in _ALL_MEASURE_COLUMNS: - row[column] = measure.estimated_cost - # Roll the selected measures' attributed impact up to the Property. - row["sap_points"] = _sum([m.sap_points for m in prop.measures]) - row["co2_equivalent_savings"] = _sum( - [m.co2_equivalent_savings for m in prop.measures] - ) - row["kwh_savings"] = _sum([m.kwh_savings for m in prop.measures]) - row["energy_cost_savings"] = _sum( - [m.energy_cost_savings for m in prop.measures] - ) - row["total_retrofit_cost"] = _sum([m.estimated_cost for m in prop.measures]) - # The default Plan's post-works figures, passed through as persisted. - row["post_sap_points"] = _blank(prop.post_sap_points) - row["post_epc_rating"] = _blank(prop.post_epc_rating) - row["cost_of_works"] = _blank(prop.cost_of_works) - row["contingency_cost"] = _blank(prop.contingency_cost) - row["co2_savings"] = _blank(prop.co2_savings) - row["energy_bill_savings"] = _blank(prop.energy_bill_savings) - row["energy_consumption_savings"] = _blank(prop.energy_consumption_savings) - row["valuation_increase"] = _blank(prop.valuation_increase) - rows.append(row) - return ExportSheet(columns=columns, rows=tuple(rows)) + rows = tuple(_shape_row(prop) for prop in properties) + return ExportSheet(columns=_COLUMNS, rows=rows)