mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Merge pull request #562 from Hestia-Homes/eco-eligiblity-bug
fixed missing task and subtask for single remote assessments
This commit is contained in:
commit
02acac8603
9 changed files with 62 additions and 39 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
from etl.epc.settings import DATA_ANOMALY_MATCHES as data_anon_matches
|
from etl.epc.settings import DATA_ANOMALY_MATCHES as data_anon_matches
|
||||||
from etl.epc.settings import DATA_ANOMALY_MATCHES as data_anon_matches
|
|
||||||
|
|
||||||
|
|
||||||
class Definitions:
|
class Definitions:
|
||||||
|
|
|
||||||
|
|
@ -592,13 +592,21 @@ class Property:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not cleaned:
|
# if not cleaned:
|
||||||
raise ValueError("Cleaner does not contain cleaned data")
|
# raise ValueError("Cleaner does not contain cleaned data")
|
||||||
|
|
||||||
if not self.data:
|
if not self.data:
|
||||||
raise ValueError("Property does not contain data")
|
raise ValueError("Property does not contain data")
|
||||||
|
|
||||||
for description, attribute in cleaned.items():
|
components = [
|
||||||
|
'floor-description', 'hotwater-description', 'main-fuel', 'mainheat-description',
|
||||||
|
'mainheatcont-description', 'roof-description', 'walls-description', 'windows-description',
|
||||||
|
'lighting-description'
|
||||||
|
]
|
||||||
|
|
||||||
|
for description in components:
|
||||||
|
|
||||||
|
cleaner_cls = all_cleaner_map[description]
|
||||||
|
|
||||||
if self.data[description] in self.DATA_ANOMALY_MATCHES:
|
if self.data[description] in self.DATA_ANOMALY_MATCHES:
|
||||||
template = cleaned[description][0]
|
template = cleaned[description][0]
|
||||||
|
|
@ -616,35 +624,22 @@ class Property:
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
attributes = [
|
if description == "lighting-description":
|
||||||
x
|
cleaner_cls = cleaner_cls(self.data[description], averages=None)
|
||||||
for x in cleaned[description]
|
else:
|
||||||
if x["original_description"] == self.data[description]
|
cleaner_cls = cleaner_cls(self.data[description])
|
||||||
]
|
|
||||||
|
|
||||||
if len(attributes) > 1:
|
processed = {
|
||||||
raise ValueError(
|
"original_description": self.data[description],
|
||||||
"Either No attributes or multiple found for %s" % description
|
"clean_description": cleaner_cls.description.replace(
|
||||||
|
"(assumed)", ""
|
||||||
)
|
)
|
||||||
|
.rstrip()
|
||||||
|
.capitalize(),
|
||||||
|
**cleaner_cls.process(),
|
||||||
|
}
|
||||||
|
|
||||||
if len(attributes) == 0:
|
attributes = [processed]
|
||||||
# We attempt to perform the clean on the fly
|
|
||||||
cleaner_cls = all_cleaner_map[description]
|
|
||||||
if description == "lighting-description":
|
|
||||||
cleaner_cls = cleaner_cls(self.data[description], averages=None)
|
|
||||||
else:
|
|
||||||
cleaner_cls = cleaner_cls(self.data[description])
|
|
||||||
processed = {
|
|
||||||
"original_description": self.data[description],
|
|
||||||
"clean_description": cleaner_cls.description.replace(
|
|
||||||
"(assumed)", ""
|
|
||||||
)
|
|
||||||
.rstrip()
|
|
||||||
.capitalize(),
|
|
||||||
**cleaner_cls.process(),
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes = [processed]
|
|
||||||
|
|
||||||
setattr(self, self.ATTRIBUTE_MAP[description], attributes[0])
|
setattr(self, self.ATTRIBUTE_MAP[description], attributes[0])
|
||||||
|
|
||||||
|
|
@ -1160,6 +1155,7 @@ class Property:
|
||||||
'has_community_scheme': 'Varied (Community Scheme)',
|
'has_community_scheme': 'Varied (Community Scheme)',
|
||||||
"has_dual_fuel_mineral_and_wood": 'Wood Logs',
|
"has_dual_fuel_mineral_and_wood": 'Wood Logs',
|
||||||
"has_electricaire": 'Electricity',
|
"has_electricaire": 'Electricity',
|
||||||
|
"has_wood_chips": 'Wood Logs'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Hot water
|
# Hot water
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,14 @@ async def trigger_plan_entrypoint(body: PlanTriggerRequest):
|
||||||
else:
|
else:
|
||||||
# Fallback: Just send a single message
|
# Fallback: Just send a single message
|
||||||
try:
|
try:
|
||||||
|
task_id, subtask_id = TasksInterface.create_task(
|
||||||
|
task_source="backend/plan/router.py:trigger_plan_entrypoint",
|
||||||
|
service="plan_engine",
|
||||||
|
inputs=data,
|
||||||
|
task_only=False
|
||||||
|
)
|
||||||
|
data["task_id"] = task_id
|
||||||
|
data["subtask_id"] = subtask_id
|
||||||
message_body = json.dumps(data)
|
message_body = json.dumps(data)
|
||||||
response = sqs_client.send_message(
|
response = sqs_client.send_message(
|
||||||
QueueUrl=settings.ENGINE_SQS_URL,
|
QueueUrl=settings.ENGINE_SQS_URL,
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ def parse_eco_packages(config: dict[str, Any], prepared_epc) -> tuple[list[str],
|
||||||
return measures, mapped["target_sap"], mapped["plan_type"], already_installed
|
return measures, mapped["target_sap"], mapped["plan_type"], already_installed
|
||||||
|
|
||||||
|
|
||||||
def build_cloudwatch_log_url(start_ms: int, end_ms: int) -> str:
|
def build_cloudwatch_log_url(start_ms: int) -> str:
|
||||||
"""
|
"""
|
||||||
Build a CloudWatch Logs URL for the current Lambda invocation,
|
Build a CloudWatch Logs URL for the current Lambda invocation,
|
||||||
including timestamp window from start_ms to end_ms (epoch ms).
|
including timestamp window from start_ms to end_ms (epoch ms).
|
||||||
|
|
@ -235,7 +235,6 @@ def build_cloudwatch_log_url(start_ms: int, end_ms: int) -> str:
|
||||||
f"#logsV2:log-groups/log-group/{encoded_group}"
|
f"#logsV2:log-groups/log-group/{encoded_group}"
|
||||||
f"/log-events/{encoded_stream}"
|
f"/log-events/{encoded_stream}"
|
||||||
f"$3Fstart={start_ms}"
|
f"$3Fstart={start_ms}"
|
||||||
f"$26end={end_ms}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1290,8 +1290,7 @@ async def model_engine(body: PlanTriggerRequest):
|
||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
end_ms = int(time.time() * 1000)
|
cloud_logs_url = build_cloudwatch_log_url(start_ms)
|
||||||
cloud_logs_url = build_cloudwatch_log_url(start_ms, end_ms)
|
|
||||||
# Mark the subtask as successful
|
# Mark the subtask as successful
|
||||||
SubTaskInterface().update_subtask_status(
|
SubTaskInterface().update_subtask_status(
|
||||||
subtask_id=UUID(body.subtask_id), status="complete", cloud_logs_url=cloud_logs_url
|
subtask_id=UUID(body.subtask_id), status="complete", cloud_logs_url=cloud_logs_url
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,8 @@ DATA_ANOMALY_MATCHES = {
|
||||||
"UNKNOWN",
|
"UNKNOWN",
|
||||||
#
|
#
|
||||||
"Unknown",
|
"Unknown",
|
||||||
|
# Observed error case
|
||||||
|
"(error), (error)",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add the post_sap10 date to indicate if the epc is post sap10
|
# Add the post_sap10 date to indicate if the epc is post sap10
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ class FloorAttributes(Definitions):
|
||||||
or (description in self.DATA_ANOMALY_MATCHES)
|
or (description in self.DATA_ANOMALY_MATCHES)
|
||||||
or (description in self.OBSERVED_ERRORS)
|
or (description in self.OBSERVED_ERRORS)
|
||||||
or (self.description == "sap05:floor")
|
or (self.description == "sap05:floor")
|
||||||
|
or not self.description
|
||||||
)
|
)
|
||||||
|
|
||||||
# Try and perform a translation, incase it's in welsh
|
# Try and perform a translation, incase it's in welsh
|
||||||
|
|
@ -63,8 +64,8 @@ class FloorAttributes(Definitions):
|
||||||
if not self.nodata and not any(
|
if not self.nodata and not any(
|
||||||
rt in self.description
|
rt in self.description
|
||||||
for rt in self.FLOOR_TYPES
|
for rt in self.FLOOR_TYPES
|
||||||
+ self.DWELLING_BELOW
|
+ self.DWELLING_BELOW
|
||||||
+ ["average thermal transmittance"]
|
+ ["average thermal transmittance"]
|
||||||
):
|
):
|
||||||
raise ValueError("Invalid description")
|
raise ValueError("Invalid description")
|
||||||
|
|
||||||
|
|
@ -97,7 +98,11 @@ class FloorAttributes(Definitions):
|
||||||
def process(self) -> Dict[str, Union[str, bool, int, None]]:
|
def process(self) -> Dict[str, Union[str, bool, int, None]]:
|
||||||
|
|
||||||
if self.nodata:
|
if self.nodata:
|
||||||
return {"no_data": True}
|
return {
|
||||||
|
'thermal_transmittance': None, 'thermal_transmittance_unit': None, 'is_assumed': True,
|
||||||
|
'is_to_unheated_space': False, 'is_to_external_air': False, 'is_suspended': True, 'is_solid': False,
|
||||||
|
'another_property_below': False, 'insulation_thickness': 'none', 'no_data': True
|
||||||
|
}
|
||||||
|
|
||||||
result: Dict[str, Union[float, str, bool, None]] = {}
|
result: Dict[str, Union[float, str, bool, None]] = {}
|
||||||
description = self.description
|
description = self.description
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class MainHeatAttributes(Definitions):
|
||||||
]
|
]
|
||||||
FUEL_TYPES = ["electric", "mains gas", "wood logs", "coal", "oil", "wood pellets", "anthracite",
|
FUEL_TYPES = ["electric", "mains gas", "wood logs", "coal", "oil", "wood pellets", "anthracite",
|
||||||
"dual fuel mineral and wood", "smokeless fuel", "lpg", "b30k", "mineral and wood",
|
"dual fuel mineral and wood", "smokeless fuel", "lpg", "b30k", "mineral and wood",
|
||||||
"dual fuel appliance"]
|
"dual fuel appliance", "wood chips"]
|
||||||
DISTRIBUTION_SYSTEMS = ["radiators", "fan coil units", "pipes in screed above insulation",
|
DISTRIBUTION_SYSTEMS = ["radiators", "fan coil units", "pipes in screed above insulation",
|
||||||
"pipes in insulated timber floor", "pipes in concrete slab"]
|
"pipes in insulated timber floor", "pipes in concrete slab"]
|
||||||
OTHERS = ["assumed", "electricaire", "assumed for most rooms"]
|
OTHERS = ["assumed", "electricaire", "assumed for most rooms"]
|
||||||
|
|
|
||||||
|
|
@ -1752,6 +1752,21 @@ mainheat_cases = [
|
||||||
'has_dual_fuel_mineral_and_wood': False, 'has_smokeless_fuel': False, 'has_lpg': False, 'has_b30k': False,
|
'has_dual_fuel_mineral_and_wood': False, 'has_smokeless_fuel': False, 'has_lpg': False, 'has_b30k': False,
|
||||||
'has_mineral_and_wood': False, 'has_dual_fuel_appliance': False, 'has_assumed': False,
|
'has_mineral_and_wood': False, 'has_dual_fuel_appliance': False, 'has_assumed': False,
|
||||||
'has_electricaire': False, 'has_assumed_for_most_rooms': False, 'has_underfloor_heating': False
|
'has_electricaire': False, 'has_assumed_for_most_rooms': False, 'has_underfloor_heating': False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'original_description': 'Boiler and radiators, wood chips',
|
||||||
|
'has_radiators': True, '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': True,
|
||||||
|
'has_air_source_heat_pump': False, 'has_room_heaters': False, 'has_electric_storage_heaters': False,
|
||||||
|
'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_heat_pump': False,
|
||||||
|
'has_micro-cogeneration': False, 'has_solar_assisted_heat_pump': False, 'has_exhaust_source_heat_pump': False,
|
||||||
|
'has_community_heat_pump': False, 'has_hot-water-only': False, 'has_electric': False, '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_b30k': False,
|
||||||
|
'has_mineral_and_wood': False, 'has_dual_fuel_appliance': False, 'has_wood_chips': True, 'has_assumed': False,
|
||||||
|
'has_electricaire': False, 'has_assumed_for_most_rooms': False, 'has_underfloor_heating': False
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue