working on rir insulation|

This commit is contained in:
Khalim Conn-Kowlessar 2026-01-26 13:25:15 +00:00
parent 0ad3f09902
commit e8b7a569ff
3 changed files with 100 additions and 25 deletions

6
.idea/copilot.data.migration.ask.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

6
.idea/copilot.data.migration.edit.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EditMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

View file

@ -170,7 +170,13 @@ class RoofRecommendations:
@staticmethod
def is_loft_insulation_appropriate(
non_invasive_recommendations, measures, is_pitched, is_at_rafters, rir_over_loft
measures: List,
is_pitched: bool,
is_at_rafters: bool,
rir_over_loft: bool,
is_assumed: bool,
has_loft_insulation_recommendation: bool,
has_sloping_ceiling_recommendation: bool
) -> bool:
"""
Determine if loft insulation is appropriate
@ -179,36 +185,59 @@ class RoofRecommendations:
:param is_pitched: Boolean - indicates whether or not the roof is pitched
:param is_at_rafters: Boolean - indicates whether or not the loft insulation is at rafters
:param rir_over_loft: Boolean - indicates whether or not there we should be doing RIR insulation
:param is_assumed: Boolean - indicates whether or not the roof insulation status is assumed
:param has_loft_insulation_recommendation: Boolean - indicates whether or not there
is a loft insulation non-invasive recommendation
:param has_sloping_ceiling_recommendation: Boolean - indicates whether or not there
is a sloping ceiling non-invasive recommendation
:return:
"""
has_li_in_measures = "loft_insulation" in measures
has_li_non_invasive_recommendation = any(
x["type"] == "loft_insulation" for x in non_invasive_recommendations
)
return has_li_non_invasive_recommendation or (
# Key business logic:
# If we have a pitched roof, no insulation, it's not assumed and we have a sloping ceiling recommendation,
# we do NOT recommend loft insulation
if is_pitched and not is_assumed and has_sloping_ceiling_recommendation:
return False
return has_loft_insulation_recommendation or (
is_pitched and has_li_in_measures and not is_at_rafters
) and not rir_over_loft
@staticmethod
def is_flat_roof_insulation_appropriate(
is_flat: bool, measures: List, non_invasive_recommendations: List
is_flat: bool, measures: List, has_flat_roof_recommendation: bool
) -> bool:
"""
Determine if flat roof insulation is appropriate
:param is_flat: Boolean - indicates whether or not the roof is flat
:param measures: List - list of measures
:param non_invasive_recommendations: List - list of non-invasive recommendations
:return:
:param has_flat_roof_recommendation: Boolean - indicates whether or not there is a flat roof non-invasive
recommendation
:return: Boolean
"""
flat_roof_in_measures = "flat_roof_insulation" in measures
flat_roof_non_invasive_rec = has_li_non_invasive_recommendation = any(
x["type"] == "flat_roof_insulation" for x in non_invasive_recommendations
)
return (is_flat and flat_roof_in_measures) or flat_roof_non_invasive_rec
return (is_flat and flat_roof_in_measures) or has_flat_roof_recommendation
@staticmethod
def is_room_roof_insulation_appropriate(
is_room_roof, measures, rir_over_loft, has_room_roof_recommendation
):
"""
Determine if room roof insulation is appropriate
:param is_room_roof: Boolean - indicates whether or not the roof is a room roof
:param measures: List - list of measures
:param rir_over_loft: Boolean - indicates whether or not there we should be doing RIR insulation
:param has_room_roof_recommendation: Boolean - indicates whether or not there is a room roof non-invasive
recommendation
:return:
"""
return is_room_roof and ("room_roof_insulation" in measures) or (
has_room_roof_recommendation or rir_over_loft
)
def _does_roof_need_recommendation(self, measures: List | None = None, u_value: float | None = None):
"""
@ -243,6 +272,28 @@ class RoofRecommendations:
):
return False
@staticmethod
def _is_primary_roof_sloped(
is_pitched: bool, is_loft: bool, is_assumed: bool
):
"""
Determine if the primary roof is sloped
:param is_pitched: bool - is the roof pitched
:param is_loft: bool - is the roof a loft
:param is_assumed: bool - is the roof insulation status assumed
:return:
"""
# Conditions for this to be true
# Case 1
# In the property roof description (primary roof)
# 1) Pitched Roof
# 2) Uninsulated
# 3) Not assumed
if is_pitched and not is_loft and not is_assumed:
return True
return False
def recommend(self, phase: int, measures: List | None = None, default_u_values: bool = False):
"""
Main method to recommend roof insulation measures
@ -290,14 +341,21 @@ class RoofRecommendations:
is_loft = self.property.roof["is_loft"]
is_assumed = self.property.roof["is_assumed"]
is_at_rafters = self.property.roof["is_at_rafters"]
is_flat = self.property.roof["is_flat"]
is_room_roof = self.property.roof["is_roof_room"]
has_sloping_ceiling_recommendation = any(
x["type"] == "sloping_ceiling_insulation" for x in non_invasive_recommendations
)
primary_roof_is_sloped = False # TODO
has_loft_insulation_recommendation = any(x["type"] == "loft_insulation" for x in non_invasive_recommendations)
has_flat_roof_recommendation = any(x["type"] == "flat_roof_insulation" for x in non_invasive_recommendations)
has_room_roof_recommendation = any(x["type"] == "room_roof_insulation" for x in non_invasive_recommendations)
primary_roof_is_sloped = self._is_primary_roof_sloped(
is_pitched=is_pitched, is_loft=is_loft, is_assumed=is_assumed
)
rir_over_loft = (
is_pitched and
self.property.roof["insulation_thickness"] == "none" and
is_pitched and self.property.roof["insulation_thickness"] == "none" and
"room_in_roof_insulation" in [x["type"] for x in non_invasive_recommendations]
)
@ -308,8 +366,19 @@ class RoofRecommendations:
)
needs_loft_insulation = self.is_loft_insulation_appropriate(
non_invasive_recommendations=non_invasive_recommendations, measures=measures,
is_pitched=is_pitched, is_at_rafters=is_at_rafters, rir_over_loft=rir_over_loft
measures=measures, is_pitched=is_pitched, is_at_rafters=is_at_rafters,
rir_over_loft=rir_over_loft, has_loft_insulation_recommendation=has_loft_insulation_recommendation,
is_assumed=is_assumed, has_sloping_ceiling_recommendation=has_sloping_ceiling_recommendation
)
needs_flat_roof_insulation = self.is_flat_roof_insulation_appropriate(
is_flat=is_flat, measures=measures, has_flat_roof_recommendation=has_flat_roof_recommendation
)
needs_rir_insulation = self.is_room_roof_insulation_appropriate(
is_room_roof=is_room_roof,
measures=measures,
rir_over_loft=rir_over_loft,
has_room_roof_recommendation=has_room_roof_recommendation
)
##################################################
@ -327,10 +396,7 @@ class RoofRecommendations:
)
return
if (
(self.property.roof["is_flat"] and "flat_roof_insulation" in measures) or
"flat_roof_insulation" in [x["type"] for x in non_invasive_recommendations]
):
if needs_flat_roof_insulation:
self.recommend_roof_insulation(
u_value=u_value,
insulation_thickness=0,
@ -343,10 +409,7 @@ class RoofRecommendations:
# There are cases where the property might have a room roof as the second roof, but we have a recommendation for
# it, so we allow this override
if self.property.roof["is_roof_room"] and ("room_roof_insulation" in measures) or (
"room_roof_insulation" in [x["type"] for x in non_invasive_recommendations] or
rir_over_loft
):
if needs_rir_insulation:
self.recommend_room_roof_insulation(u_value, phase, default_u_values)
return