From 44726469d4e37bb051681879ee752b3d5b027ad9 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Fri, 26 Jun 2026 10:44:05 +0000 Subject: [PATCH] =?UTF-8?q?Carry=20donor's=20display=20heating=20+=20contr?= =?UTF-8?q?ol=20into=20predicted=20EPC=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _apply_heating_donor now also deepcopies the donor's main_heating and main_heating_controls EnergyElements alongside its calc sap_heating cluster, so the building-passport heating rows are coherent with the donated system and a control row the size-template lacked (but the donor lodges) is populated. Fixes 'Heating Control: Unknown' on predicted properties (e.g. 721167). Display-only: component-accuracy gate + corpus harness unchanged (26/6 green). Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc_prediction/epc_prediction.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/domain/epc_prediction/epc_prediction.py b/domain/epc_prediction/epc_prediction.py index 4261df6d..072fcfc6 100644 --- a/domain/epc_prediction/epc_prediction.py +++ b/domain/epc_prediction/epc_prediction.py @@ -93,7 +93,15 @@ class EpcPrediction: electricity tariff (`sap_energy_source.meter_type`) and hot-water flags live on loose top-level fields. Carry the donor's whole set, not a subset — otherwise a donated storage system lands on the template's single-rate - meter and the SAP score collapses (off-peak heat billed at the peak rate).""" + meter and the SAP score collapses (off-peak heat billed at the peak rate). + + The system also has a DISPLAY face — the building-passport "Main Heating" + and "Heating Control" rows (`main_heating` / `main_heating_controls` + EnergyElements). These describe the same system as the calc cluster, so + they travel with the donor too; left on the structural template they are + incoherent with the donated calc heating, and `main_heating_controls` + shows "Unknown" whenever the size-template lodged no control row but the + donor does (predicted property 721167, ADR-0029 follow-up).""" donor = _heating_donor(comparables.members) if donor is None: return @@ -101,6 +109,10 @@ class EpcPrediction: predicted.has_hot_water_cylinder = donor.epc.has_hot_water_cylinder predicted.solar_water_heating = donor.epc.solar_water_heating predicted.sap_energy_source.meter_type = donor.epc.sap_energy_source.meter_type + predicted.main_heating = copy.deepcopy(donor.epc.main_heating) + predicted.main_heating_controls = copy.deepcopy( + donor.epc.main_heating_controls + ) @staticmethod def _apply_glazing_mode(