diff --git a/.idea/Model.iml b/.idea/Model.iml
index b0f9c00d..4413bb06 100644
--- a/.idea/Model.iml
+++ b/.idea/Model.iml
@@ -7,7 +7,7 @@
-
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1122b380..6f308057 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/backend/Property.py b/backend/Property.py
index 79bd1659..4c8bd5bc 100644
--- a/backend/Property.py
+++ b/backend/Property.py
@@ -10,7 +10,7 @@ from utils.logger import setup_logger
from utils.s3 import read_dataframe_from_s3_parquet
from epc_api.client import EpcClient
from BaseUtility import Definitions
-from recommendations.rdsap_tables import england_wales_age_band_lookup
+from recommendations.rdsap_tables import england_wales_age_band_lookup, FLOOR_LEVEL_MAP
from recommendations.recommendation_utils import (
estimate_perimeter, get_wall_type, estimate_external_wall_area, esimtate_pitched_roof_area
)
@@ -84,6 +84,7 @@ class Property(Definitions):
self.pitched_roof_area = None
self.insulation_floor_area = None
self.number_lighting_outlets = None
+ self.floor_level = None
self.current_adjusted_energy = None
self.expected_adjusted_energy = None
@@ -324,6 +325,7 @@ class Property(Definitions):
self.set_wall_type()
self.set_floor_type()
+ self.set_floor_level()
def set_age_band(self):
"""
@@ -642,6 +644,27 @@ class Property(Definitions):
floor_area=self.insulation_floor_area, floor_height=self.floor_height
)
+ def set_floor_level(self):
+ self.floor_level = (
+ FLOOR_LEVEL_MAP[self.data["floor-level"]] if
+ self.data["floor-level"] not in self.DATA_ANOMALY_MATCHES else None
+ )
+
+ # We perform some extra checks, if the property is not on the ground floor, as we have found cases
+ # where a property is marked as being on the first floor
+ if self.floor_level > 0:
+
+ # We check if there is another property below
+ if not self.floor["another_property_below"]:
+ self.floor_level = 0
+ return
+
+ if self.floor_level == 0:
+ # Check if another property below
+ if self.floor["another_property_below"]:
+ self.floor_level = 1
+ return
+
def set_wall_type(self):
"""
This method sets the wall type of the property, using a simple approach based on the wall description
diff --git a/backend/tests/test_property.py b/backend/tests/test_property.py
index 39a7e86e..9188f545 100644
--- a/backend/tests/test_property.py
+++ b/backend/tests/test_property.py
@@ -375,3 +375,51 @@ class TestProperty:
assert not prop2.is_listed
assert not prop2.is_heritage
assert not prop2.restricted_measures
+
+ def test_set_floor_level(self, mock_epc_client):
+ # In this case, we have a flat which looks looks it's on the first floor, but it's actually on the ground
+ # floor, so we should set floor_level to 0
+ prop = Property(1, "AB12CD", "Test Address", mock_epc_client)
+ prop.data = {'floor-level': '01', 'property-type': 'Flat'}
+ prop.floor = {
+ 'original_description': 'Solid, no insulation (assumed)', 'clean_description': 'Solid, no insulation',
+ 'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_assumed': True,
+ 'is_to_unheated_space': False, 'is_to_external_air': False, 'is_suspended': False, 'is_solid': True,
+ 'another_property_below': False, 'insulation_thickness': 'none', 'floor_thermal_transmittance': None,
+ 'floor_insulation_thickness': 'none'
+ }
+
+ prop.set_floor_level()
+
+ assert prop.floor_level == 0
+
+ # This property is labelled as being on the ground floor but actually has another property below
+ # so we set floor level to 1
+ prop2 = Property(1, "AB12CD", "Test Address", mock_epc_client)
+ prop2.data = {'floor-level': 'Ground', 'property-type': 'Flat'}
+ prop2.floor = {
+ 'original_description': '(Another dwelling below)', 'clean_description': 'Solid, no insulation',
+ 'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_assumed': False,
+ 'is_to_unheated_space': False, 'is_to_external_air': False, 'is_suspended': False, 'is_solid': False,
+ 'another_property_below': True, 'insulation_thickness': 'none', 'floor_thermal_transmittance': None,
+ 'floor_insulation_thickness': 'none'
+ }
+
+ prop2.set_floor_level()
+
+ assert prop2.floor_level == 1
+
+ # this property is correctly labelled as being on the 2nd floor
+ prop3 = Property(1, "AB12CD", "Test Address", mock_epc_client)
+ prop3.data = {'floor-level': '02', 'property-type': 'Flat'}
+ prop3.floor = {
+ 'original_description': '(Another dwelling below)', 'clean_description': 'Solid, no insulation',
+ 'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_assumed': False,
+ 'is_to_unheated_space': False, 'is_to_external_air': False, 'is_suspended': False, 'is_solid': False,
+ 'another_property_below': True, 'insulation_thickness': 'none', 'floor_thermal_transmittance': None,
+ 'floor_insulation_thickness': 'none'
+ }
+
+ prop3.set_floor_level()
+
+ assert prop3.floor_level == 2
diff --git a/recommendations/FloorRecommendations.py b/recommendations/FloorRecommendations.py
index 48245554..a246c8cb 100644
--- a/recommendations/FloorRecommendations.py
+++ b/recommendations/FloorRecommendations.py
@@ -10,7 +10,6 @@ from recommendations.recommendation_utils import (
r_value_per_mm_to_u_value, calculate_u_value_uplift, is_diminishing_returns, update_lowest_selected_u_value,
get_recommended_part, get_floor_u_value
)
-from recommendations.rdsap_tables import FLOOR_LEVEL_MAP
from recommendations.Costs import Costs
@@ -73,10 +72,6 @@ class FloorRecommendations(Definitions):
def recommend(self):
u_value = self.property.floor["thermal_transmittance"]
- floor_level = (
- FLOOR_LEVEL_MAP[self.property.data["floor-level"]] if
- self.property.data["floor-level"] not in self.DATA_ANOMALY_MATCHES else None
- )
property_type = self.property.data["property-type"]
floor_area = self.property.insulation_floor_area
@@ -90,7 +85,9 @@ class FloorRecommendations(Definitions):
return
# If the property is a flat that isn't at ground level, it's likely impractical to recommend a floor upgrade
- if (floor_level != 0) and (property_type == "Flat"):
+ if (self.property.floor_level != 0) and (property_type == "Flat") and (
+ self.property.floor["another_property_below"]
+ ):
return
if u_value: