diff --git a/backend/app/plan/schemas.py b/backend/app/plan/schemas.py index c08cdefc..6f0f6327 100644 --- a/backend/app/plan/schemas.py +++ b/backend/app/plan/schemas.py @@ -58,7 +58,7 @@ NON_INVASIVE_SPECIFIC_MEASURES = [ # such as "external_wall_insulation", "internal_wall_insulation", "cavity_wall_insulation" MEASURE_MAP = { "wall_insulation": [ - "internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation", "cavity_extract_and_refill" + "internal_wall_insulation", "external_wall_insulation", "cavity_wall_insulation", ], "roof_insulation": ["loft_insulation", "flat_roof_insulation", "room_roof_insulation"], "floor_insulation": ["suspended_floor_insulation", "solid_floor_insulation"], diff --git a/recommendations/tests/test_wall_recommendations.py b/recommendations/tests/test_wall_recommendations.py index 580ebb91..a4093e58 100644 --- a/recommendations/tests/test_wall_recommendations.py +++ b/recommendations/tests/test_wall_recommendations.py @@ -10,8 +10,10 @@ from recommendations.tests.test_data.materials import materials from etl.epc.Record import EPCRecord +# import inspect +# file_path = inspect.getfile(lambda: None) # with open( -# os.path.abspath(os.path.dirname(__file__)) + "/recommendations/tests/test_data/input_properties.pkl", "rb" +# os.path.abspath(os.path.dirname(file_path)) + "/recommendations/tests/test_data/input_properties.pkl", "rb" # ) as f: # input_properties = pickle.load(f) @@ -86,17 +88,21 @@ class TestWallRecommendations: input_properties[1].walls["is_sandstone_or_limestone"] = False input_properties[1].age_band = "A" input_properties[1].restricted_measures = False + input_properties[1].already_installed = [] + input_properties[1].walls["is_park_home"] = False + input_properties[1].construction_age_band = "England and Wales: 1930-1949" + input_properties[1].non_invasive_recommendations = [] recommender = WallRecommendations( property_instance=input_properties[1], materials=materials ) assert recommender.property.walls["original_description"] == "Solid brick, as built, no insulation (assumed)" - assert not recommender.ewi_valid + assert not recommender.ewi_valid() assert recommender.property.in_conservation_area == "not_in_conservation_area" assert recommender.property.data["property-type"] == "Flat" - recommender.recommend() + recommender.recommend(phase=0) # This should result in some recommendations, all of which should be internal insulation assert recommender.recommendations @@ -131,7 +137,7 @@ class TestWallRecommendations: ) assert recommender.property.walls["original_description"] == "Solid brick, as built, insulated (assumed)" - assert not recommender.ewi_valid + assert not recommender.ewi_valid() assert recommender.property.in_conservation_area == "not_in_conservation_area" assert recommender.property.data["property-type"] == "Flat" assert recommender.estimated_u_value is None @@ -204,6 +210,11 @@ class TestWallRecommendationsBase: property_mock.restricted_measures = False property_mock.insulation_wall_area = 100 property_mock.data = {"county": "Derbyshire"} + property_mock.walls = { + "is_cob": False, + "is_sandstone_or_limestone": False, + "is_cavity_wall": False + } return property_mock @pytest.fixture @@ -216,24 +227,24 @@ class TestWallRecommendationsBase: def test_ewi_valid_in_conservation_area(self, wall_recommendations_instance): wall_recommendations_instance.property.in_conservation_area = "in_conversation_area" wall_recommendations_instance.property.restricted_measures = True - assert wall_recommendations_instance.ewi_valid is False + assert wall_recommendations_instance.ewi_valid() is False def test_ewi_valid_is_flat(self, wall_recommendations_instance): wall_recommendations_instance.property.data = {"property-type": "flat"} - assert wall_recommendations_instance.ewi_valid is False + assert wall_recommendations_instance.ewi_valid() is False def test_ewi_valid_not_in_conservation_area_and_not_flat(self, wall_recommendations_instance): wall_recommendations_instance.property.in_conservation_area = "not_in_conversation_area" wall_recommendations_instance.property.restricted_measures = False wall_recommendations_instance.property.data = {"property-type": "house"} - assert wall_recommendations_instance.ewi_valid is True + assert wall_recommendations_instance.ewi_valid() is True class TestCavityWallRecommensations: def test_fill_empty_cavity(self): epc_record = EPCRecord() - epc_record.prepared_epc = {"county": "Derbyshire"} + epc_record.prepared_epc = {"county": "Derbyshire", "walls-energy-eff": "Very Poor"} input_property = Property(id=1, postcode="F4k3", address="123 fake street", epc_record=epc_record) input_property.walls = { 'original_description': 'Cavity wall, as built, no insulation (assumed)', @@ -248,6 +259,7 @@ class TestCavityWallRecommensations: } input_property.age_band = "C" input_property.insulation_wall_area = 50 + input_property.construction_age_band = "England and Wales: 1930-1949" recommender = WallRecommendations( property_instance=input_property, @@ -261,14 +273,11 @@ class TestCavityWallRecommensations: assert recommender.recommendations assert recommender.estimated_u_value == 1.5 assert np.isclose(recommender.recommendations[0]["new_u_value"], 0.35) - assert np.isclose(recommender.recommendations[0]["total"], 1668.6600000000003) - - assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.35) - assert np.isclose(recommender.recommendations[1]["total"], 2004.6600000000003) + assert np.isclose(recommender.recommendations[0]["total"], 710.5) def test_fill_partial_filled_cavity(self): epc_record = EPCRecord() - epc_record.prepared_epc = {"county": "County Durham"} + epc_record.prepared_epc = {"county": "County Durham", "walls-energy-eff": "Poor"} input_property = Property(id=1, postcode="F4k3", address="123 fake street", epc_record=epc_record) input_property.walls = { 'original_description': 'Cavity wall, as built, partial insulation (assumed)', @@ -283,6 +292,7 @@ class TestCavityWallRecommensations: } input_property.age_band = "C" input_property.insulation_wall_area = 50 + input_property.construction_age_band = "England and Wales: 1930-1949" recommender = WallRecommendations( property_instance=input_property, @@ -296,14 +306,13 @@ class TestCavityWallRecommensations: assert recommender.recommendations assert recommender.estimated_u_value == 1.3 assert np.isclose(recommender.recommendations[0]["new_u_value"], 0.41) - assert np.isclose(recommender.recommendations[0]["total"], 1663.9350000000002) - - assert np.isclose(recommender.recommendations[1]["new_u_value"], 0.41) - assert np.isclose(recommender.recommendations[1]["total"], 1999.9350000000002) + assert np.isclose(recommender.recommendations[0]["total"], 710.5) def test_system_built_wall(self): epc_record = EPCRecord() - epc_record.prepared_epc = {"property-type": "House", "county": "Derbyshire", "built-form": "Detached"} + epc_record.prepared_epc = { + "property-type": "House", "county": "Derbyshire", "built-form": "Detached", "walls-energy-eff": "Very Poor" + } input_property2 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record) input_property2.walls = { 'original_description': 'System built, as built, no insulation (assumed)', @@ -319,6 +328,7 @@ class TestCavityWallRecommensations: input_property2.age_band = "F" input_property2.insulation_wall_area = 120 input_property2.restricted_measures = False + input_property2.construction_age_band = "England and Wales: 1976-1982" assert input_property2.walls["is_system_built"] @@ -332,26 +342,24 @@ class TestCavityWallRecommensations: recommender2.recommend() assert recommender2.recommendations - assert len(recommender2.recommendations) == 9 + assert len(recommender2.recommendations) == 2 assert recommender2.estimated_u_value == 1 - assert np.isclose(recommender2.recommendations[0]["new_u_value"], 0.19) - assert np.isclose(recommender2.recommendations[0]["total"], 16429.960320000002) + assert np.isclose(recommender2.recommendations[0]["new_u_value"], 0.21) + assert np.isclose(recommender2.recommendations[0]["total"], 35802.0) assert recommender2.recommendations[0]["parts"][0]["type"] == "external_wall_insulation" - assert recommender2.recommendations[0]["parts"][0]["depth"] == 100 + assert recommender2.recommendations[0]["parts"][0]["depth"] == 150 - assert np.isclose(recommender2.recommendations[8]["new_u_value"], 0.23) - assert np.isclose(recommender2.recommendations[8]["total"], 11292.768) - assert recommender2.recommendations[8]["parts"][0]["type"] == "internal_wall_insulation" - assert recommender2.recommendations[8]["parts"][0]["depth"] == 72.5 - - assert np.isclose(recommender2.recommendations[6]["new_u_value"], 0.29) - assert np.isclose(recommender2.recommendations[6]["total"], 10988.208) - assert recommender2.recommendations[6]["parts"][0]["type"] == "internal_wall_insulation" - assert recommender2.recommendations[6]["parts"][0]["depth"] == 52.5 + assert np.isclose(recommender2.recommendations[1]["new_u_value"], 0.26) + assert np.isclose(recommender2.recommendations[1]["total"], 29376) + assert recommender2.recommendations[1]["parts"][0]["type"] == "internal_wall_insulation" + assert recommender2.recommendations[1]["parts"][0]["depth"] == 95 def test_timber_frame_wall(self): epc_record = EPCRecord() - epc_record.prepared_epc = {"property-type": "House", "county": "Derbyshire", "built-form": "Semi-Detached"} + epc_record.prepared_epc = { + "property-type": "House", "county": "Derbyshire", "built-form": "Semi-Detached", + "walls-energy-eff": "Very Poor" + } input_property3 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record) input_property3.walls = { 'original_description': 'Timber frame, as built, no insulation (assumed)', @@ -367,6 +375,7 @@ class TestCavityWallRecommensations: input_property3.age_band = "B" input_property3.insulation_wall_area = 99 input_property3.restricted_measures = False + input_property3.construction_age_band = "England and Wales: 1950-1966" assert input_property3.walls["is_timber_frame"] @@ -380,21 +389,24 @@ class TestCavityWallRecommensations: recommender3.recommend() assert recommender3.recommendations - assert len(recommender3.recommendations) == 6 + assert len(recommender3.recommendations) == 2 assert recommender3.estimated_u_value == 1.9 - assert np.isclose(recommender3.recommendations[0]["new_u_value"], 0.2) - assert np.isclose(recommender3.recommendations[0]["total"], 13554.717263999999) + assert np.isclose(recommender3.recommendations[0]["new_u_value"], 0.23) + assert np.isclose(recommender3.recommendations[0]["total"], 29536.65) assert recommender3.recommendations[0]["parts"][0]["type"] == "external_wall_insulation" - assert recommender3.recommendations[0]["parts"][0]["depth"] == 100.0 + assert recommender3.recommendations[0]["parts"][0]["depth"] == 150.0 - assert np.isclose(recommender3.recommendations[1]["new_u_value"], 0.23) - assert np.isclose(recommender3.recommendations[1]["total"], 35206.19308800001) - assert recommender3.recommendations[1]["parts"][0]["type"] == "external_wall_insulation" - assert recommender3.recommendations[1]["parts"][0]["depth"] == 150.0 + assert np.isclose(recommender3.recommendations[1]["new_u_value"], 0.29) + assert np.isclose(recommender3.recommendations[1]["total"], 24235.2) + assert recommender3.recommendations[1]["parts"][0]["type"] == "internal_wall_insulation" + assert recommender3.recommendations[1]["parts"][0]["depth"] == 95.0 def test_granite_or_whinstone_wall(self): epc_record = EPCRecord() - epc_record.prepared_epc = {"property-type": "Bungalow", "county": "Derbyshire", "built-form": "Detached"} + epc_record.prepared_epc = { + "property-type": "Bungalow", "county": "Derbyshire", "built-form": "Detached", + "walls-energy-eff": "Very Poor" + } input_property4 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record) input_property4.walls = { 'original_description': 'Granite or whinstone, as built, no insulation (assumed)', @@ -410,6 +422,7 @@ class TestCavityWallRecommensations: input_property4.age_band = "A" input_property4.insulation_wall_area = 223 input_property4.restricted_measures = False + input_property4.construction_age_band = "England and Wales: before 1900" assert input_property4.walls["is_granite_or_whinstone"] @@ -423,21 +436,24 @@ class TestCavityWallRecommensations: recommender4.recommend() assert recommender4.recommendations - assert len(recommender4.recommendations) == 6 + assert len(recommender4.recommendations) == 2 assert recommender4.estimated_u_value == 2.3 - assert np.isclose(recommender4.recommendations[0]["new_u_value"], 0.21) - assert np.isclose(recommender4.recommendations[0]["total"], 29547.42864) + assert np.isclose(recommender4.recommendations[0]["new_u_value"], 0.23) + assert np.isclose(recommender4.recommendations[0]["total"], 66532.05) assert recommender4.recommendations[0]["parts"][0]["type"] == "external_wall_insulation" - assert recommender4.recommendations[0]["parts"][0]["depth"] == 100 + assert recommender4.recommendations[0]["parts"][0]["depth"] == 150 - assert np.isclose(recommender4.recommendations[1]["new_u_value"], 0.23) - assert np.isclose(recommender4.recommendations[1]["total"], 76744.68288000001) - assert recommender4.recommendations[1]["parts"][0]["type"] == "external_wall_insulation" - assert recommender4.recommendations[1]["parts"][0]["depth"] == 150 + assert np.isclose(recommender4.recommendations[1]["new_u_value"], 0.3) + assert np.isclose(recommender4.recommendations[1]["total"], 54590.4) + assert recommender4.recommendations[1]["parts"][0]["type"] == "internal_wall_insulation" + assert recommender4.recommendations[1]["parts"][0]["depth"] == 95 def test_cob_wall(self): epc_record = EPCRecord() - epc_record.prepared_epc = {"property-type": "Bungalow", "county": "Derbyshire", "built-form": "Detached"} + epc_record.prepared_epc = { + "property-type": "Bungalow", "county": "Derbyshire", "built-form": "Detached", + "walls-energy-eff": "Very Poor" + } input_property5 = Property(id=1, postcode="F4k3 2", address="223 fake street", epc_record=epc_record) input_property5.walls = { 'original_description': 'Cob, as built', @@ -453,6 +469,7 @@ class TestCavityWallRecommensations: input_property5.age_band = "E" input_property5.insulation_wall_area = 77 input_property5.restricted_measures = False + input_property5.construction_age_band = "England and Wales: 1967-1975" assert input_property5.walls["is_cob"] @@ -465,22 +482,15 @@ class TestCavityWallRecommensations: recommender5.recommend() - assert recommender5.recommendations - assert len(recommender5.recommendations) == 5 - assert recommender5.estimated_u_value == 0.8 - assert np.isclose(recommender5.recommendations[0]["new_u_value"], 0.29) - assert np.isclose(recommender5.recommendations[0]["total"], 8963.834880000002) - assert recommender5.recommendations[0]["parts"][0]["type"] == "external_wall_insulation" - assert recommender5.recommendations[0]["parts"][0]["depth"] == 50 - - assert np.isclose(recommender5.recommendations[3]["new_u_value"], 0.26) - assert np.isclose(recommender5.recommendations[3]["total"], 20771.11344) - assert recommender5.recommendations[3]["parts"][0]["type"] == "internal_wall_insulation" - assert recommender5.recommendations[3]["parts"][0]["depth"] == 100 + # No insulation recommendations for cob walls + assert not recommender5.recommendations def test_sandstone_or_limestone_wall(self): epc_record = EPCRecord() - epc_record.prepared_epc = {"property-type": "House", "county": "Derbyshire", "built-form": "Mid-Terrace"} + epc_record.prepared_epc = { + "property-type": "House", "county": "Derbyshire", "built-form": "Mid-Terrace", + "walls-energy-eff": "Very Poor" + } input_property6 = Property(id=1, postcode="F4k3 6", address="623 fake street", epc_record=epc_record) input_property6.walls = { 'original_description': 'Sandstone or limestone, as built, no insulation (assumed)', @@ -496,6 +506,7 @@ class TestCavityWallRecommensations: input_property6.age_band = "F" input_property6.insulation_wall_area = 350 input_property6.restricted_measures = False + input_property6.construction_age_band = "England and Wales: 1976-1982" assert input_property6.walls["is_sandstone_or_limestone"] @@ -508,20 +519,11 @@ class TestCavityWallRecommensations: recommender6.recommend() + # For sandstone walls, we only recommend internal wall insulation assert recommender6.recommendations - assert len(recommender6.recommendations) == 9 + assert len(recommender6.recommendations) == 1 assert recommender6.estimated_u_value == 1 - assert np.isclose(recommender6.recommendations[0]["new_u_value"], 0.19) - assert np.isclose(recommender6.recommendations[0]["total"], 46374.888000000006) - assert recommender6.recommendations[0]["parts"][0]["type"] == "external_wall_insulation" - assert recommender6.recommendations[0]["parts"][0]["depth"] == 100 - - assert np.isclose(recommender6.recommendations[2]["new_u_value"], 0.21) - assert np.isclose(recommender6.recommendations[2]["total"], 120451.29600000002) - assert recommender6.recommendations[2]["parts"][0]["type"] == "external_wall_insulation" - assert recommender6.recommendations[2]["parts"][0]["depth"] == 150 - - assert np.isclose(recommender6.recommendations[4]["new_u_value"], 0.28) - assert np.isclose(recommender6.recommendations[4]["total"], 94414.15199999999) - assert recommender6.recommendations[4]["parts"][0]["type"] == "internal_wall_insulation" - assert recommender6.recommendations[4]["parts"][0]["depth"] == 100 + assert np.isclose(recommender6.recommendations[0]["new_u_value"], 0.26) + assert np.isclose(recommender6.recommendations[0]["total"], 85680.0) + assert recommender6.recommendations[0]["parts"][0]["type"] == "internal_wall_insulation" + assert recommender6.recommendations[0]["parts"][0]["depth"] == 95