From 0988fb7d6da8dbb30130b165d7702e9e96f8d005 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Sat, 9 Aug 2025 18:53:39 +0100 Subject: [PATCH] handling uncommon heating systems --- backend/Funding.py | 23 ++++++-- backend/tests/test_funding.py | 104 ++++++++++++++++++---------------- 2 files changed, 72 insertions(+), 55 deletions(-) diff --git a/backend/Funding.py b/backend/Funding.py index 9c4022b1..0aa86545 100644 --- a/backend/Funding.py +++ b/backend/Funding.py @@ -402,8 +402,11 @@ class Funding: ): return 'DHS non-CHP' - if mainheating["has_electric_storage_heaters"] and mainheat_energy_eff == "Very Poor": + if mainheating["has_electric_storage_heaters"] and ( + (mainheat_energy_eff == "Very Poor") or pd.isnull(mainheat_energy_eff) + ): return 'Electric Storage Heaters Responsiveness <=0.2' + if mainheating["has_electric_storage_heaters"] and mainheat_energy_eff in [ "Poor", "Average", "Good", "Very Good", ]: @@ -421,7 +424,7 @@ class Funding: if mainheating["has_room_heaters"] and ( main_fuel["fuel_type"] in [ "dual fuel appliance mineral and wood", "manufactured smokeless fuel", "dual fuel mineral wood", "oil", - 'smokeless coal' + 'smokeless coal', 'wood logs' ] or mainheating["has_coal"] ): return 'Solid Fossil Room Heaters' @@ -437,11 +440,12 @@ class Funding: return 'Electric Room Heaters' if mainheating["has_warm_air"] and main_fuel["fuel_type"] == "mains gas": - # Treat warm air gas system as a condensing gas boiler if mainheat_energy_eff in ["Good", "Very Good"]: - return "Condensing Gas Boiler" - else: - return "Non Condensing Gas Boiler" + return 'Condensing Gas Boiler' + elif mainheat_energy_eff in ["Average", "Poor"]: + return 'Non Condensing Gas Boiler' + elif mainheat_energy_eff == "Very Poor": + return 'Gas Back Boiler to Radiators' if mainheating["has_electricaire"]: # Based on current understanding, electricaire is an electric warm air storage heater, using @@ -455,6 +459,13 @@ class Funding: if mainheating["has_electric_underfloor_heating"] or mainheating["has_electric_ceiling_heating"]: return "Electric Room Heaters" + # Treat warm air lpg as a direct acting lpg oiler + if mainheating["has_warm_air"] and main_fuel["fuel_type"] == "lpg": + if mainheat_energy_eff in ["Good", "Very Good"]: + return 'Condensing LPG Boiler' + else: # Average, Poor, Very Poor + return 'Non Condensing LPG Boiler' + raise ValueError("Invalid pre heating system") def calculate_partial_project_abs( diff --git a/backend/tests/test_funding.py b/backend/tests/test_funding.py index 21a160bf..1608ca39 100644 --- a/backend/tests/test_funding.py +++ b/backend/tests/test_funding.py @@ -1015,57 +1015,63 @@ mock_project_scores_matrix = mock_project_scores_matrix() mock_whlg_postcodes = mock_whlg_postcodes() mock_partial_scores_matrix = mock_partial_scores_matrix() +errors = [] for _, x in tqdm(epc_df.iterrows(), total=len(epc_df)): - # inputs - mainheat_energy_eff = x["MAINHEAT_ENERGY_EFF"] - heating_cleaner = MainHeatAttributes(description=x["MAINHEAT_DESCRIPTION"]) - fuel_cleaner = MainFuelAttributes(description="" if pd.isnull(x["MAIN_FUEL"]) else x["MAIN_FUEL"]) + try: + # inputs + mainheat_energy_eff = x["MAINHEAT_ENERGY_EFF"] + heating_cleaner = MainHeatAttributes(description=x["MAINHEAT_DESCRIPTION"]) + fuel_cleaner = MainFuelAttributes(description="" if pd.isnull(x["MAIN_FUEL"]) else x["MAIN_FUEL"]) - h = heating_cleaner.process() - f = fuel_cleaner.process() + h = heating_cleaner.process() + f = fuel_cleaner.process() - funding = Funding( - project_scores_matrix=mock_project_scores_matrix, - partial_project_scores_matrix=mock_partial_scores_matrix, - whlg_eligible_postcodes=mock_whlg_postcodes, - social_cavity_abs_rate=13.5, - social_solid_abs_rate=17, - private_cavity_abs_rate=13.5, - private_solid_abs_rate=17, - tenure="Social" - ) + funding = Funding( + project_scores_matrix=mock_project_scores_matrix, + partial_project_scores_matrix=mock_partial_scores_matrix, + whlg_eligible_postcodes=mock_whlg_postcodes, + social_cavity_abs_rate=13.5, + social_solid_abs_rate=17, + private_cavity_abs_rate=13.5, + private_solid_abs_rate=17, + tenure="Social" + ) - self = funding - measures = measures - starting_sap = 33 - ending_sap = 69 - floor_area = 71 - mainheat_description = x["MAINHEAT_DESCRIPTION"] - heating_control_description = x["MAINHEATCONT_DESCRIPTION"] - is_cavity = True - current_wall_uvalue = 2 - is_partial = False - existing_li_thickness = 0 - has_wall_insulation_recommendation = True - has_roof_insulation_recommendation = True - mainheating = h - main_fuel = f - mainheat_energy_eff = mainheat_energy_eff + self = funding + measures = measures + starting_sap = 33 + ending_sap = 69 + floor_area = 71 + mainheat_description = x["MAINHEAT_DESCRIPTION"] + heating_control_description = x["MAINHEATCONT_DESCRIPTION"] + is_cavity = True + current_wall_uvalue = 2 + is_partial = False + existing_li_thickness = 0 + has_wall_insulation_recommendation = True + has_roof_insulation_recommendation = True + mainheating = h + main_fuel = f + mainheat_energy_eff = mainheat_energy_eff - funding.check_funding( - measures=measures, - starting_sap=33, - ending_sap=69, - floor_area=71, - mainheat_description=x["MAINHEAT_DESCRIPTION"], - heating_control_description=x["MAINHEATCONT_DESCRIPTION"], - is_cavity=True, - current_wall_uvalue=2, - is_partial=False, - existing_li_thickness=0, - has_wall_insulation_recommendation=True, - has_roof_insulation_recommendation=True, - mainheating=h, - main_fuel=f, - mainheat_energy_eff=mainheat_energy_eff, - ) + funding.check_funding( + measures=measures, + starting_sap=33, + ending_sap=69, + floor_area=71, + mainheat_description=x["MAINHEAT_DESCRIPTION"], + heating_control_description=x["MAINHEATCONT_DESCRIPTION"], + is_cavity=True, + current_wall_uvalue=2, + is_partial=False, + existing_li_thickness=0, + has_wall_insulation_recommendation=True, + has_roof_insulation_recommendation=True, + mainheating=h, + main_fuel=f, + mainheat_energy_eff=mainheat_energy_eff, + ) + except Exception as e: + errors.append(x["LMK_KEY"]) + +errored_epcs = epc_df[epc_df["LMK_KEY"].isin(errors)]