implmenting innovation uplift

This commit is contained in:
Khalim Conn-Kowlessar 2025-08-08 18:41:02 +01:00
parent e2e2e8c71c
commit a55d2902ce
7 changed files with 391 additions and 8 deletions

View file

@ -949,9 +949,19 @@ class AssetList:
if self.phase: if self.phase:
# We filter on just the properties that have had an inspection # We filter on just the properties that have had an inspection
self.standardised_asset_list = self.standardised_asset_list[ if self.new_format_non_insturives_present_v2:
~self.standardised_asset_list['Surveyors Name'].isin(["YET TO BE SURVEYED"]) self.standardised_asset_list = self.standardised_asset_list[
] ~self.standardised_asset_list['NAME OF SURVEYOR'].isin(
["YET TO BE SURVEYED", "", None]
)
]
self.standardised_asset_list = self.standardised_asset_list[
~pd.isnull(self.standardised_asset_list["NAME OF SURVEYOR"])
]
else:
self.standardised_asset_list = self.standardised_asset_list[
~self.standardised_asset_list['Surveyors Name'].isin(["YET TO BE SURVEYED"])
]
if not self.variable_mappings and not override_empty_mappings: if not self.variable_mappings and not override_empty_mappings:
raise ValueError("Please run init_standardise first") raise ValueError("Please run init_standardise first")

View file

@ -58,6 +58,39 @@ def app():
EPC recommendations EPC recommendations
Property UPRN Property UPRN
""" """
# Freebridge
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Freebridge"
data_filename = "Domna - FCH property data May 25 copy.xlsx"
sheet_name = "EPC Data"
postcode_column = 'Post Code'
address1_column = "Address 1"
address1_method = None
fulladdress_column = None
address_cols_to_concat = ["Address 1", "Address 4"]
missing_postcodes_method = None
landlord_year_built = "Build Date"
landlord_os_uprn = None
landlord_property_type = "Property Type"
landlord_built_form = None
landlord_wall_construction = "Walls Description"
landlord_heating_system = "Heating Type"
landlord_existing_pv = None
landlord_property_id = "Place Ref"
landlord_roof_construction = "Roof Description"
landlord_sap = "Current SAP"
outcomes_filename = []
outcomes_sheetname = []
outcomes_postcode = []
outcomes_houseno = []
outcomes_address = []
outcomes_id = []
master_filepaths = []
master_to_asset_list_filepath = None
asset_list_header = 0
landlord_block_reference = None
master_id_colnames = []
phase = True # Inspections not complete, produce a partial view
ecosurv_landlords = None
data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Broadlands" data_folder = "/Users/khalimconn-kowlessar/Documents/hestia/Customers/Broadlands"
data_filename = "Broadlands Asset List.xlsx" data_filename = "Broadlands Asset List.xlsx"

View file

@ -431,6 +431,47 @@ HEATING_MAPPINGS = {
'Mains Electric': 'electric fuel', 'Mains Electric': 'electric fuel',
'Unvented cylinder': 'other', 'Unvented cylinder': 'other',
'MVHR & Heat Recovery': 'other', 'MVHR & Heat Recovery': 'other',
'Solar': 'other' 'Solar': 'other',
'Electric storage heaters, Electric storage heaters': 'electric storage heaters',
'Room heaters, electric': 'room heaters',
'Room heaters, mains gas, Room heaters, electric': 'room heaters',
'Air source heat pump, underfloor, electric': 'air source heat pump',
'Air source heat pump, radiators, electric': 'air source heat pump',
'Air source heat pump, Systems with radiators, electric': 'air source heat pump',
'Electric storage heaters': 'electric storage heaters',
'Air source heat pump, Underfloor heating and radiators, pipes in screed above insulation, electric': 'air source '
'heat pump',
'Room heaters, coal': 'room heaters',
'Room heaters, electric, Electric storage heaters': 'electric storage heaters',
'Air source heat pump, fan coil units, electric': 'air source heat pump',
'Boiler and radiators, mains gas': 'gas boiler, radiators',
'Boiler and radiators, mains gas, Electric storage heaters': 'condensing boiler, radiators',
'Room heaters, mains gas': 'room heaters',
'Air source heat pump, radiators, electric, Air source heat pump, fan coil units, electric': 'air source heat pump',
'Air source heat pump, warm air, electric': 'air source heat pump',
'Electric ceiling heating, electric': 'electric ceiling',
'Electric storage heaters, Room heaters, electric': 'electric storage heaters',
'Room heaters, dual fuel (mineral and wood)': 'room heaters',
'Water source heat pump, radiators, electric': 'other',
'Warm air, electric': 'warm air heating',
'Boiler and radiators, wood logs': 'solid fuel',
'Boiler and radiators, dual fuel (mineral and wood)': 'solid fuel',
'Boiler & underfloor, mains gas': 'gas boiler, radiators',
'Boiler and underfloor heating, mains gas': 'gas boiler, radiators',
'Community scheme': 'communal heating',
'Warm air, Electricaire': 'warm air heating',
'Boiler and radiators, smokeless fuel': 'solid fuel',
'Warm air, mains gas': 'warm air heating',
'Warm air , electric': 'warm air heating',
'Boiler and radiators, LPG': 'boiler - other fuel',
'Boiler & underfloor, oil': 'oil boiler',
'Boiler and radiators, bottled LPG': 'boiler - other fuel',
'Boiler and underfloor heating, oil': 'oil boiler',
'SAP05:Main-Heating': 'unknown',
'Boiler and radiators, coal': 'solid fuel',
'Boiler and radiators, oil': 'oil boiler',
'Boiler and radiators, electric': 'electric boiler',
'No system present: electric heaters assumed': 'electric radiators',
'Boiler and radiators, anthracite': 'solid fuel'
} }

View file

@ -10,8 +10,12 @@ STANDARD_ROOF_CONSTRUCTIONS = {
"another dwelling above", "another dwelling above",
"flat unknown insulation", "flat unknown insulation",
"flat insulated", "flat insulated",
"flat uninsulated",
"unknown insulated", "unknown insulated",
"unknown", "unknown",
"room roof insulated",
"room roof uninsulated",
"average thermal transmittance",
} }
ROOF_CONSTRUCTION_MAPPINGS = { ROOF_CONSTRUCTION_MAPPINGS = {
@ -173,6 +177,73 @@ ROOF_CONSTRUCTION_MAPPINGS = {
'PitchedNormalNoLoftAccess: Unknown': 'pitched no access to loft', 'PitchedNormalNoLoftAccess: Unknown': 'pitched no access to loft',
'PitchedNormalLoftAccess: Unknown': 'pitched unknown insulation', 'PitchedNormalLoftAccess: Unknown': 'pitched unknown insulation',
'AnotherDwellingAbove: Unknown': 'another dwelling above' 'AnotherDwellingAbove: Unknown': 'another dwelling above',
'Flat, insulated': 'flat insulated',
'Pitched, insulated (assumed)': 'pitched insulated',
'Flat, insulated (assumed)': 'flat insulated',
'(another dwelling above)': 'another dwelling above',
'Pitched, insulated at rafters': 'pitched insulated',
'(other premises above)': 'another dwelling above',
'Average thermal transmittance 0.15 W/m-¦K': 'average thermal transmittance',
'Pitched, 25 mm loft insulation': 'pitched less than 100mm insulation',
'Roof room(s), insulated (assumed)': 'room roof insulated',
'Pitched, limited insulation (assumed)': 'pitched less than 100mm insulation',
'Pitched, 270 mm loft insulation': 'pitched insulated',
'Pitched, 250 mm loft insulation': 'pitched insulated',
'Pitched, 200mm loft insulation': 'pitched insulated',
'Flat, no insulation': 'flat uninsulated',
'Pitched, 75 mm loft insulation': 'pitched less than 100mm insulation',
'Average thermal transmittance 0.09 W/m-¦K': 'average thermal transmittance',
'SAP05:Roof': 'unknown',
'Pitched, 400 mm loft insulation': 'pitched insulated',
'Pitched, 150mm loft insulation': 'pitched insulated',
'Average thermal transmittance 0.11 W/m-¦K': 'unknown',
'Pitched, 100 mm loft insulation': 'pitched less than 100mm insulation',
'Pitched, 300 mm loft insulation': 'pitched insulated',
'Pitched, 75mm loft insulation': 'pitched less than 100mm insulation',
'Pitched, 300+mm loft insulation': 'pitched insulated',
'Pitched, 300+ mm loft insulation': 'pitched insulated',
'Average thermal transmittance 0.11 W/m?K': 'average thermal transmittance',
'Average thermal transmittance 0.10 W/m?K': 'average thermal transmittance',
'Pitched, 250mm loft insulation': 'pitched insulated',
'Pitched, 300+ mm loft insulation': 'pitched insulated',
'Average thermal transmittance 0.1 W/m-¦K': 'average thermal transmittance',
'Pitched, *** INVALID INPUT Code : 57 *** loft insulation': 'unknown',
'Pitched, 100mm loft insulation': 'pitched less than 100mm insulation',
'Pitched, loft insulation': 'pitched less than 100mm insulation',
'Average thermal transmittance 0.20 W/m?K': 'average thermal transmittance',
'Average thermal transmittance 0.1 W/m?K': 'average thermal transmittance',
'Average thermal transmittance 0.16 W/m-¦K': 'average thermal transmittance',
'Average thermal transmittance 0.14 W/m?K': 'average thermal transmittance',
'Pitched, 50 mm loft insulation': 'pitched less than 100mm insulation',
'Flat, limited insulation': 'flat uninsulated',
'Average thermal transmittance 0.12 W/m?K': 'average thermal transmittance',
'Roof room(s), ceiling insulated': 'room roof insulated',
'Average thermal transmittance 0.18 W/m?K': 'average thermal transmittance',
'Average thermal transmittance 0.10 W/m-¦K': 'average thermal transmittance',
'Pitched, 400+ mm loft insulation': 'pitched insulated',
'Average thermal transmittance 0.14 W/m²K': 'average thermal transmittance',
'Pitched, no insulation (assumed)': 'pitched less than 100mm insulation',
'Average thermal transmittance 0.16 W/m?K': 'average thermal transmittance',
'Average thermal transmittance 0.21 W/m?K': 'average thermal transmittance',
'Flat, no insulation (assumed)': 'flat uninsulated',
'Pitched, no insulation': 'pitched less than 100mm insulation',
'Average thermal transmittance 0.12 W/m-¦K': 'average thermal transmittance',
'Pitched, 12 mm loft insulation': 'pitched less than 100mm insulation',
'Average thermal transmittance 0.07 W/m-¦K': 'average thermal transmittance',
'Roof room(s), no insulation (assumed)': 'room roof uninsulated',
'Pitched, no insulation(assumed)': 'pitched less than 100mm insulation',
'Average thermal transmittance 0.13 W/m-¦K': 'average thermal transmittance',
'Average thermal transmittance 0.08 W/m-¦K': 'average thermal transmittance',
'Average thermal transmittance 0.14 W/m-¦K': 'average thermal transmittance',
'Pitched, 350 mm loft insulation': 'pitched insulated',
'Average thermal transmittance 0 W/m-¦K': 'average thermal transmittance',
'Pitched, 200 mm loft insulation': 'pitched insulated',
'Pitched, 150 mm loft insulation': 'pitched insulated',
'Flat, limited insulation (assumed)': 'flat uninsulated',
} }

View file

@ -334,4 +334,13 @@ WALL_CONSTRUCTION_MAPPINGS = {
'Cavity: FilledCavity, TimberFrame: AsBuilt': 'filled cavity', 'Cavity: FilledCavity, TimberFrame: AsBuilt': 'filled cavity',
'Cavity: FilledCavity, SolidBrick: AsBuilt, SolidBrick: Internal': 'filled cavity', 'Cavity: FilledCavity, SolidBrick: AsBuilt, SolidBrick: Internal': 'filled cavity',
'Cavity: Internal, SolidBrick: AsBuilt': 'filled cavity', 'Cavity: Internal, SolidBrick: AsBuilt': 'filled cavity',
'Timber frame, filled cavity': 'filled cavity',
'Cob, as built': 'cob',
'Cavity wall, filled cavity and internal insulation': 'filled cavity',
'SAP05:Walls': 'other',
'Solid brick, as built, partial insulation (assumed)': 'insulated solid brick',
'Sandstone, as built, no insulation (assumed)': 'uninsulated sandstone or limestone',
'System built, as built, partial insulation (assumed)': 'system built unknown insulation',
'Timber frame, with external insulation': 'insulated timber frame'
} }

View file

@ -96,8 +96,9 @@ class Funding:
""" """
measure_types = [m["type"] for m in measures] measure_types = [m["type"] for m in measures]
innovation_flags = [m.get("is_innovation", False) for m in measures] innovation_flags = [m.get("is_innovation", False) for m in measures]
uplifts = [m["uplift"] for m in measures]
innovation_measures = [m["type"] for m in measures if m.get("is_innovation", False)] innovation_measures = [m["type"] for m in measures if m.get("is_innovation", False)]
return measure_types, innovation_flags, innovation_measures return measure_types, uplifts, innovation_flags, innovation_measures
@staticmethod @staticmethod
def _meets_upgrade_target(starting_sap: int, ending_sap: int) -> bool: def _meets_upgrade_target(starting_sap: int, ending_sap: int) -> bool:
@ -325,9 +326,104 @@ class Funding:
return starting_str, ending_uvalue return starting_str, ending_uvalue
@staticmethod
def _map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff):
# We check most likely primary heating system. Because mixed systems are hard to break up, we
# check the larger, more prominent heating systems first and then the smaller ones. We aim
# to cover the case where properties have heating systems like
# "boiler radiators, mains gas, electric storage heaters" so mixed systems
if mainheating["has_air_source_heat_pump"]:
return 'Air to Water ASHP'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "biomass"):
return 'Biomass Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "lpg"):
return 'Bottled LPG Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
mainheat_energy_eff in ["Good", "Very Good"]
):
# Assume higher efficiency condensing boiler
return 'Condensing Gas Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
mainheat_energy_eff in ["Average", "Poor"]
):
return 'Non Condensing Gas Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
mainheat_energy_eff in ["Very Poor"]
) and mainheating["has_radiators"]:
return 'Gas Back Boiler to Radiators'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "mains gas") and (
mainheat_energy_eff in ["Very Poor"]
) and not mainheating["has_radiators"]:
# Doesnt have radiators
return 'Gas Fire with Back Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "oil") and (
mainheat_energy_eff in ["Good", "Very Good"]
):
return 'Condensing Oil Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "oil") and (
mainheat_energy_eff in ["Average", "Very Poor", "Poor"]
):
return 'Non Condensing Oil Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "lpg") and (
mainheat_energy_eff in ["Good", "Very Good"]
):
return 'Condensing LPG Boiler'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "lpg") and (
mainheat_energy_eff in ["Average", "Very Poor", "Poor"]
):
return 'Non Condensing LPG Boiler'
if mainheating["has_boiler"] and (
main_fuel["fuel_type"] in ["dual fuel appliance mineral and wood", "manufactured smokeless fuel"]
) and (mainheat_energy_eff in ["Average", "Very Poor", "Poor"]):
return 'Solid Fossil Boiler'
if mainheating["has_ground_source_heat_pump"]:
return 'GSHP'
if mainheating["has_boiler"] and (main_fuel["fuel_type"] == "electric"):
return 'Electric Boiler'
if mainheating["has_community_scheme"] and mainheat_energy_eff in ["Good", "Very Good"]:
return 'DHS CHP'
if mainheating["has_community_scheme"] and mainheat_energy_eff in ["Average", "Very Poor", "Poor"]:
return 'DHS non-CHP'
if mainheating["has_electric_storage_heaters"] and mainheat_energy_eff == "Very Poor":
return 'Electric Storage Heaters Responsiveness <=0.2'
if mainheating["has_electric_storage_heaters"] and mainheat_energy_eff in [
"Poor", "Average", "Good", "Very Good",
]:
return 'Electric Storage Heaters Responsiveness >0.2'
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "lpg":
return 'Bottled LPG Room Heaters'
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "electricity":
return 'Electric Room Heaters'
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] == "mains gas":
return 'Gas Room Heaters'
if mainheating["has_room_heaters"] and main_fuel["fuel_tye"] in [
"dual fuel appliance mineral and wood", "manufactured smokeless fuel"
]:
return 'Solid Fossil Room Heaters'
raise ValueError("Invalid pre heating system")
def calculate_partial_project_abs( def calculate_partial_project_abs(
self, self,
measure_type: str, measure_type: str,
mainheating: dict,
main_fuel: dict,
mainheat_energy_eff: str,
current_wall_uvalue: float = None, current_wall_uvalue: float = None,
is_partial: bool = False, is_partial: bool = False,
existing_li_thickness: float = None, existing_li_thickness: float = None,
@ -411,6 +507,23 @@ class Funding:
raise ValueError("Invalid SFI category") raise ValueError("Invalid SFI category")
return pps.squeeze()["Cost Savings"] return pps.squeeze()["Cost Savings"]
if measure_type == "solar_pv":
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
solar_pps_df = df[
(df["Measure_Type"] == "Solar_PV") & (df["Pre_Main_Heating_Source"] == pre_heating_system)
]
return solar_pps_df.squeeze()["Cost Savings"]
if measure_type == "air_source_heat_pump":
pre_heating_system = self._map_to_pre_main_heating(mainheating, main_fuel, mainheat_energy_eff)
pps = df[
(df["Pre_Main_Heating_Source"] == pre_heating_system) &
(df["Post_Main_Heating_Source"] == "Air to Water ASHP")
]
if pps.shape[0] != 1:
raise ValueError("something went wrong, more than one pps for ashp")
return pps.squeeze()["Cost Savings"]
raise ValueError(f"Invalid measure type for partial project ABS calculation: {measure_type}") raise ValueError(f"Invalid measure type for partial project ABS calculation: {measure_type}")
# ----------------------- # -----------------------
@ -588,6 +701,9 @@ class Funding:
current_wall_uvalue: float, current_wall_uvalue: float,
is_partial: False, is_partial: False,
existing_li_thickness: float, existing_li_thickness: float,
mainheating: dict,
main_fuel: dict,
mainheat_energy_eff: str,
council_tax_band: str = None, council_tax_band: str = None,
has_wall_insulation_recommendation: bool = False, has_wall_insulation_recommendation: bool = False,
has_roof_insulation_recommendation: bool = False, has_roof_insulation_recommendation: bool = False,
@ -602,7 +718,7 @@ class Funding:
""" """
# Normalize measures # Normalize measures
measure_types, innovation_flags, innovation_measures = self._split_measures(measures) measure_types, uplifts, innovation_flags, innovation_measures = self._split_measures(measures)
# If we have a heating measure, we check if we meet the pre conditions # If we have a heating measure, we check if we meet the pre conditions
has_ftch = "first_time_central_heating" in measure_types has_ftch = "first_time_central_heating" in measure_types
@ -666,6 +782,22 @@ class Funding:
if self.eco4_eligible: if self.eco4_eligible:
# Calculate the full project ABS for ECO4 # Calculate the full project ABS for ECO4
self.full_project_abs = self.calculate_full_project_abs() self.full_project_abs = self.calculate_full_project_abs()
# We calculate uplift innovation, where required
project_uplifts = []
for i, measure in enumerate(measure_types):
pps = self.calculate_partial_project_abs(
measure_type=measure,
mainheating=mainheating,
main_fuel=main_fuel,
mainheat_energy_eff=mainheat_energy_eff,
current_wall_uvalue=current_wall_uvalue,
is_partial=is_partial,
existing_li_thickness=existing_li_thickness,
)
project_uplifts.append(pps * uplifts[i])
total_uplift = sum(project_uplifts)
self.full_project_abs += total_uplift
self.eco4_funding = self.full_project_abs * ( self.eco4_funding = self.full_project_abs * (
self.social_cavity_abs_rate if is_cavity else self.social_solid_abs_rate self.social_cavity_abs_rate if is_cavity else self.social_solid_abs_rate
) )
@ -673,7 +805,13 @@ class Funding:
if self.gbis_eligible: if self.gbis_eligible:
# Calculate the partial project score - this is dependent on the measure # Calculate the partial project score - this is dependent on the measure
self.partial_project_abs = self.calculate_partial_project_abs( self.partial_project_abs = self.calculate_partial_project_abs(
measure_types[0], current_wall_uvalue, is_partial, existing_li_thickness, measure_type=measure_types[0],
mainheating=mainheating,
main_fuel=main_fuel,
mainheat_energy_eff=mainheat_energy_eff,
current_wall_uvalue=current_wall_uvalue,
is_partial=is_partial,
existing_li_thickness=existing_li_thickness,
) )

View file

@ -907,3 +907,84 @@ def test_custom_eco4_scenarios(
assert caveat in funding.eco4_eligibility_caveats, f"Missing caveat in: {scenario['description']}" assert caveat in funding.eco4_eligibility_caveats, f"Missing caveat in: {scenario['description']}"
for caveat in funding.eco4_eligibility_caveats: for caveat in funding.eco4_eligibility_caveats:
assert caveat in scenario.get("expected_caveats", []), f"Unexpected caveat in: {scenario['description']}" assert caveat in scenario.get("expected_caveats", []), f"Unexpected caveat in: {scenario['description']}"
### -------------------------
### Innovation uplift scenarios
### -------------------------
def test_uplift(
mock_project_scores_matrix,
mock_partial_scores_matrix,
mock_whlg_postcodes
):
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"
)
# # TODO: Add a scenario with multiple measures, where some are innovation, some are not and we have
# TODO: Make sure private works too
measures = [
{"type": "solar_pv", "is_innovation": True, "uplift": 0.45},
{"type": "internal_wall_insulation", "is_innovation": False, "uplift": 0},
{"type": "loft_insulation", "is_innovation": False, "uplift": 0},
{"type": "air_source_heat_pump", "is_innovation": False, "uplift": 0},
{"type": "cavity_wall_insulation", "is_innovation": False, "uplift": 0.25},
]
mainheating = {
'original_description': 'Electric storage heaters', 'has_radiators': False,
'has_fan_coil_units': False,
'has_pipes_in_screed_above_insulation': False,
'has_pipes_in_insulated_timber_floor': False,
'has_pipes_in_concrete_slab': False, 'has_boiler': False,
'has_air_source_heat_pump': False,
'has_room_heaters': False, 'has_electric_storage_heaters': True, 'has_warm_air': False,
'has_electric_underfloor_heating': False, 'has_electric_ceiling_heating': False,
'has_community_scheme': False,
'has_ground_source_heat_pump': False, 'has_no_system_present': False,
'has_portable_electric_heaters': False,
'has_water_source_heat_pump': False, 'has_electric': True, 'has_mains_gas': False,
'has_wood_logs': False,
'has_coal': False, 'has_oil': False, 'has_wood_pellets': False, 'has_anthracite':
False,
'has_dual_fuel_mineral_and_wood': False, 'has_smokeless_fuel': False, 'has_lpg': False,
'has_assumed': False,
'has_electricaire': False, 'has_assumed_for_most_rooms': False,
'has_underfloor_heating': False,
"has_electric_heat_pumps": False,
"has_micro-cogeneration": False
}
main_fuel = {
'original_description': 'Electricity: electricity, unspecified tariff', 'fuel_type':
'electricity',
'tariff_type': 'unspecified tariff', 'is_community': False,
'no_individual_heating_or_community_network': False,
'complex_fuel_type': None
}
mainheat_energy_eff = "Good"
funding.check_funding(
measures=measures,
starting_sap=33,
ending_sap=69,
floor_area=71,
mainheat_description="Electic storage heaters",
heating_control_description="Manual charge control",
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=mainheating,
main_fuel=main_fuel,
mainheat_energy_eff=mainheat_energy_eff,
)