mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Map lbwf data to new structure 🟩
This commit is contained in:
parent
d6112f3dc8
commit
803484defd
6 changed files with 161 additions and 43 deletions
|
|
@ -175,7 +175,8 @@ LBWF_ELEMENT_MAP: dict[str, ElementMapping] = {
|
|||
"EXTWALLFN2": ElementMapping(
|
||||
element=ElementType.EXTERNAL_WALL,
|
||||
aspect_type=AspectType.FINISH,
|
||||
element_instance=2,
|
||||
element_instance=1,
|
||||
aspect_instance=2,
|
||||
),
|
||||
"EXTWALLINS": ElementMapping(
|
||||
element=ElementType.EXTERNAL_WALL,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
from typing import Any, List, Optional
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from datetime import date
|
||||
|
||||
from backend.condition.domain.aspect_condition import AspectCondition
|
||||
from backend.condition.domain.element import Element
|
||||
from backend.condition.domain.element_type import ElementType
|
||||
from backend.condition.domain.mapping.element_mapping import ElementMapping
|
||||
from backend.condition.domain.mapping.lbwf.lbwf_element_map import LBWF_ELEMENT_MAP
|
||||
from backend.condition.domain.mapping.mapper import Mapper
|
||||
|
|
@ -19,51 +22,85 @@ class LbwfMapper(Mapper):
|
|||
def map_asset_conditions_for_property(
|
||||
self, client_property_data: Any, survey_year: Optional[int] = None
|
||||
) -> PropertyConditionSurvey:
|
||||
raise NotImplementedError
|
||||
|
||||
assert isinstance(
|
||||
client_property_data, LbwfHouse
|
||||
) # TODO: think of a better way to do this
|
||||
|
||||
mapped_assets: List[Element] = []
|
||||
elements_by_key: dict[tuple[ElementType, int], Element] = {}
|
||||
|
||||
uprn: int = client_property_data.uprn
|
||||
for raw_asset in client_property_data.assets:
|
||||
# Ignore metadata rows
|
||||
if raw_asset.element_code not in ["EICINSFREQ", "DECNTHMINC"]:
|
||||
try:
|
||||
element_mapping: ElementMapping = LbwfMapper._map_element(
|
||||
raw_asset.element_code
|
||||
)
|
||||
except:
|
||||
logger.warning(
|
||||
f"Unrecognised LBWF Asset Element Code: {raw_asset.element_code}. Skipping record"
|
||||
)
|
||||
continue
|
||||
element_mapping = LbwfMapper._safe_map_element(raw_asset)
|
||||
|
||||
mapped_assets.append(
|
||||
Element(
|
||||
uprn=uprn,
|
||||
element_type=element_mapping.element,
|
||||
aspect_type=element_mapping.aspect_type,
|
||||
value=raw_asset.attribute_code_description,
|
||||
quantity=raw_asset.quantity,
|
||||
install_date=raw_asset.install_date,
|
||||
renewal_year=LbwfMapper._calculate_renewal_year(
|
||||
raw_asset, survey_year
|
||||
),
|
||||
element_instance=element_mapping.element_instance,
|
||||
source_system=None, # Once we know the system name we'll set it here
|
||||
comments=raw_asset.element_comments,
|
||||
)
|
||||
aspect_condition = LbwfMapper._build_aspect_condition(
|
||||
raw_asset, element_mapping, survey_year
|
||||
)
|
||||
|
||||
element_key = (
|
||||
element_mapping.element,
|
||||
element_mapping.element_instance or 1,
|
||||
)
|
||||
|
||||
LbwfMapper._attach_aspect_condition_to_element(
|
||||
elements_by_key, element_key, aspect_condition
|
||||
)
|
||||
|
||||
return PropertyConditionSurvey(
|
||||
uprn=client_property_data.uprn,
|
||||
elements=list(elements_by_key.values()),
|
||||
date=date(2000, 1, 1), # Temp - not sure how to get this
|
||||
source="LBWF", # TODO: Make this the system, not the client
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _safe_map_element(raw_asset: LbwfAssetCondition) -> Optional[ElementMapping]:
|
||||
try:
|
||||
return LbwfMapper._map_element(raw_asset.element_code)
|
||||
except KeyError:
|
||||
logger.warning(
|
||||
logger.warning(
|
||||
f"Unrecognised LBWF Asset Element: "
|
||||
f"{raw_asset.element_code} ({raw_asset.element_code_description})). "
|
||||
"Skipping record"
|
||||
)
|
||||
|
||||
return mapped_assets
|
||||
)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _map_element(lbwf_element_code: str) -> ElementMapping:
|
||||
return LBWF_ELEMENT_MAP[lbwf_element_code]
|
||||
|
||||
@staticmethod
|
||||
def _build_aspect_condition(
|
||||
raw_asset, element_mapping: ElementMapping, survey_year: int
|
||||
) -> AspectCondition:
|
||||
return AspectCondition(
|
||||
aspect_type=element_mapping.aspect_type,
|
||||
aspect_instance=element_mapping.aspect_instance or 1,
|
||||
value=raw_asset.attribute_code_description,
|
||||
quantity=raw_asset.quantity,
|
||||
install_date=raw_asset.install_date,
|
||||
renewal_year=LbwfMapper._calculate_renewal_year(raw_asset, survey_year),
|
||||
comments=raw_asset.element_comments,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _attach_aspect_condition_to_element(
|
||||
elements_by_key: Dict[Tuple[ElementType, int], Element],
|
||||
element_key: Tuple[ElementType, int],
|
||||
aspect_condition: AspectCondition,
|
||||
) -> None:
|
||||
element = elements_by_key.get(element_key)
|
||||
|
||||
if element is None:
|
||||
element = Element(
|
||||
element_type=element_key[0],
|
||||
element_instance=element_key[1],
|
||||
aspect_conditions=[],
|
||||
)
|
||||
elements_by_key[element_key] = element
|
||||
|
||||
element.aspect_conditions.append(aspect_condition)
|
||||
|
||||
@staticmethod
|
||||
def _calculate_renewal_year(
|
||||
lbwf_asset: LbwfAssetCondition, survey_year: Optional[int]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ from backend.condition.domain.mapping.peabody.peabody_element_map import (
|
|||
)
|
||||
from backend.condition.domain.mapping.mapper import Mapper
|
||||
from backend.condition.domain.property_condition_survey import PropertyConditionSurvey
|
||||
from backend.condition.parsing.records.peabody.peabody_asset_condition import (
|
||||
PeabodyAssetCondition,
|
||||
)
|
||||
from backend.condition.parsing.records.peabody.peabody_property import PeabodyProperty
|
||||
from utils.logger import setup_logger
|
||||
|
||||
|
|
@ -52,7 +55,7 @@ class PeabodyMapper(Mapper):
|
|||
)
|
||||
|
||||
@staticmethod
|
||||
def _safe_map_element(raw_asset) -> Optional[ElementMapping]:
|
||||
def _safe_map_element(raw_asset: PeabodyAssetCondition) -> Optional[ElementMapping]:
|
||||
try:
|
||||
return PeabodyMapper._map_element(
|
||||
raw_asset.element_code,
|
||||
|
|
@ -98,7 +101,7 @@ class PeabodyMapper(Mapper):
|
|||
aspect_instance=element_mapping.aspect_instance or 1,
|
||||
value=raw_asset.material_or_answer,
|
||||
quantity=raw_asset.renewal_quantity,
|
||||
install_date=None,
|
||||
install_date=None, # Not available in peabody data
|
||||
renewal_year=raw_asset.renewal_year,
|
||||
comments=None,
|
||||
)
|
||||
|
|
|
|||
74
backend/condition/tests/custom_asserts.py
Normal file
74
backend/condition/tests/custom_asserts.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
from backend.condition.domain.property_condition_survey import PropertyConditionSurvey
|
||||
|
||||
|
||||
class CustomAsserts:
|
||||
def assert_property_condition_surveys_equal(
|
||||
actual: PropertyConditionSurvey,
|
||||
expected: PropertyConditionSurvey,
|
||||
) -> bool:
|
||||
assert actual.uprn == expected.uprn, "UPRN differs"
|
||||
assert actual.source == expected.source, "Source differs"
|
||||
assert actual.date == expected.date, "Date differs"
|
||||
|
||||
assert len(actual.elements) == len(expected.elements), (
|
||||
f"Expected {len(expected.elements)} elements, "
|
||||
f"got {len(actual.elements)}"
|
||||
)
|
||||
|
||||
for i, (actual_element, expected_element) in enumerate(
|
||||
zip(actual.elements, expected.elements)
|
||||
):
|
||||
assert actual_element.element_type == expected_element.element_type, (
|
||||
f"Element[{i}] type differs: "
|
||||
f"{actual_element.element_type} != {expected_element.element_type}"
|
||||
)
|
||||
assert (
|
||||
actual_element.element_instance == expected_element.element_instance
|
||||
), (
|
||||
f"Element[{i}] instance differs: "
|
||||
f"{actual_element.element_instance} != {expected_element.element_instance}"
|
||||
)
|
||||
|
||||
assert len(actual_element.aspect_conditions) == len(
|
||||
expected_element.aspect_conditions
|
||||
), f"Element[{i}] aspect count differs"
|
||||
|
||||
for j, (actual_aspect, expected_aspect) in enumerate(
|
||||
zip(
|
||||
actual_element.aspect_conditions,
|
||||
expected_element.aspect_conditions,
|
||||
)
|
||||
):
|
||||
prefix = f"Element[{i}].Aspect[{j}]"
|
||||
|
||||
assert actual_aspect.aspect_type == expected_aspect.aspect_type, (
|
||||
f"{prefix}.aspect_type differs: "
|
||||
f"{actual_aspect.aspect_type} != {expected_aspect.aspect_type}"
|
||||
)
|
||||
assert (
|
||||
actual_aspect.aspect_instance == expected_aspect.aspect_instance
|
||||
), (
|
||||
f"{prefix}.aspect_instance differs: "
|
||||
f"{actual_aspect.aspect_instance} != {expected_aspect.aspect_instance}"
|
||||
)
|
||||
assert actual_aspect.value == expected_aspect.value, (
|
||||
f"{prefix}.value differs: "
|
||||
f"{actual_aspect.value} != {expected_aspect.value}"
|
||||
)
|
||||
assert actual_aspect.quantity == expected_aspect.quantity, (
|
||||
f"{prefix}.quantity differs: "
|
||||
f"{actual_aspect.quantity} != {expected_aspect.quantity}"
|
||||
)
|
||||
assert actual_aspect.install_date == expected_aspect.install_date, (
|
||||
f"{prefix}.install_date differs: "
|
||||
f"{actual_aspect.install_date} != {expected_aspect.install_date}"
|
||||
)
|
||||
assert actual_aspect.renewal_year == expected_aspect.renewal_year, (
|
||||
f"{prefix}.renewal_year differs: "
|
||||
f"{actual_aspect.renewal_year} != {expected_aspect.renewal_year}"
|
||||
)
|
||||
assert actual_aspect.comments == expected_aspect.comments, (
|
||||
f"{prefix}.comments differs: "
|
||||
f"{actual_aspect.comments} != {expected_aspect.comments}"
|
||||
)
|
||||
return True
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
from typing import List
|
||||
from xml.dom.minidom import Element
|
||||
import pytest
|
||||
from datetime import date
|
||||
|
||||
from backend.condition.domain.aspect_condition import AspectCondition
|
||||
|
|
@ -13,6 +10,7 @@ from backend.condition.parsing.records.lbwf.lbwf_asset_condition import (
|
|||
LbwfAssetCondition,
|
||||
)
|
||||
from backend.condition.domain.element import Element
|
||||
from backend.condition.tests.custom_asserts import CustomAsserts
|
||||
|
||||
|
||||
def test_lbwf_mapper_maps_house():
|
||||
|
|
@ -265,7 +263,7 @@ def test_lbwf_mapper_maps_house():
|
|||
quantity=None,
|
||||
install_date=None,
|
||||
renewal_year=None,
|
||||
comments=None,
|
||||
comments="Source of Data = ACT",
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -359,8 +357,10 @@ def test_lbwf_mapper_maps_house():
|
|||
|
||||
# act
|
||||
actual_condition_survey: PropertyConditionSurvey = (
|
||||
mapper.map_asset_conditions_for_property(lbwf_house)
|
||||
mapper.map_asset_conditions_for_property(lbwf_house, survey_year)
|
||||
)
|
||||
|
||||
# assert
|
||||
assert actual_condition_survey == expected_condition_survey
|
||||
assert CustomAsserts.assert_property_condition_surveys_equal(
|
||||
actual_condition_survey, expected_condition_survey
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from backend.condition.parsing.records.peabody.peabody_asset_condition import (
|
|||
)
|
||||
from backend.condition.parsing.records.peabody.peabody_property import PeabodyProperty
|
||||
from backend.condition.domain.element import Element
|
||||
from backend.condition.tests.custom_asserts import CustomAsserts
|
||||
|
||||
|
||||
def test_peabody_mapper_maps_property():
|
||||
|
|
@ -214,4 +215,6 @@ def test_wall_primary_and_secondary_wall_finish_map_correctly():
|
|||
)
|
||||
|
||||
# assert
|
||||
assert actual_condition_survey == expected_condition_survey
|
||||
assert CustomAsserts.assert_property_condition_surveys_equal(
|
||||
actual_condition_survey, expected_condition_survey
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue