Remodel dataclasses map from LBWF objects 🟥

This commit is contained in:
Daniel Roth 2026-01-22 15:00:58 +00:00
parent 3289dc226d
commit 03fb727994
4 changed files with 274 additions and 31 deletions

View file

@ -0,0 +1,20 @@
from enum import Enum
class AspectType(str, Enum):
MATERIAL = "material"
CONDITION = "condition"
TYPE = "type"
CONFIGURATION = "configuration"
PRESENCE = "presence"
RISK = "risk"
SEVERITY = "severity"
LOCATION = "location"
FINISH = "finish"
INSULATION = "insulation"
POINTING = "pointing"
SPALLING = "spalling"
LINTELS = "lintels"
CLADDING = "cladding"
CATEGORY = "category"
QUANTITY = "quantity"

View file

@ -1,16 +1,27 @@
from dataclasses import dataclass
from typing import Optional
from datetime import date
from typing import Optional
from xml.dom.minidom import Element
from backend.condition.domain.lbwf_element import LbwfElement
from backend.condition.domain.aspect_type import AspectType
from backend.condition.domain.element import Element
@dataclass
class AssetCondition:
uprn: int
element: LbwfElement # TODO: should HHSRS elements be handled differently?
condition_description: str # TODO: this probably needs to be some sort of enum so it's searchable/filterable on the frontend. Could be hard to map from string though
quantity: int
renewal_year: Optional[int] = None
source: Optional[str] = None
element: Element
aspect_type: AspectType
value: Optional[str] = None
quantity: Optional[int] = None
install_date: Optional[date] = None
renewal_year: Optional[int] = None
element_instance: Optional[int] = None
element_location: Optional[str] = None
source_system: Optional[str] = None
comments: Optional[str] = None

View file

@ -0,0 +1,152 @@
from enum import Enum
class Element(str, Enum):
# ======================
# PROPERTY / GENERAL
# ======================
PROPERTY_TYPE = "property_type"
PROPERTY_CONSTRUCTION_TYPE = "property_construction_type"
PROPERTY_CLASSIFICATION = "property_classification"
PROPERTY_AGE_BAND = "property_age_band"
STOREY_COUNT = "storey_count"
FLOOR_LEVEL_FRONT_DOOR = "floor_level_front_door"
ACCESSIBLE_HOUSING_REGISTER = "accessible_housing_register"
ASBESTOS = "asbestos"
# ======================
# EXTERNAL ROOF
# ======================
ROOF_COVERING = "roof_covering"
ROOF_STRUCTURE = "roof_structure"
ROOF_CHIMNEY = "roof_chimney"
ROOF_FASCIA = "roof_fascia"
ROOF_SOFFIT = "roof_soffit"
RAINWATER_GOODS = "rainwater_goods"
ROOF_PORCH_CANOPY = "roof_porch_canopy"
LOFT_INSULATION = "loft_insulation"
# ======================
# EXTERNAL WALLS
# ======================
EXTERNAL_WALL = "external_wall"
# ======================
# EXTERNAL WINDOWS
# ======================
WINDOWS = "windows"
COMMUNAL_WINDOWS = "communal_windows"
SECONDARY_GLAZING = "secondary_glazing"
# ======================
# EXTERNAL DOORS
# ======================
FRONT_DOOR = "front_door"
REAR_DOOR = "rear_door"
STORE_DOOR = "store_door"
GARAGE_DOOR = "garage_door"
COMMUNAL_ENTRANCE_DOOR = "communal_entrance_door"
# ======================
# EXTERNAL AREAS
# ======================
PATHS_AND_HARDSTANDINGS = "paths_and_hardstandings"
PARKING_AREAS = "parking_areas"
BOUNDARY_WALLS = "boundary_walls"
FENCING = "fencing"
GATES = "gates"
RETAINING_WALLS = "retaining_walls"
PRIVATE_BALCONY = "private_balcony"
BALCONY_BALUSTRADE = "balcony_balustrade"
OUTBUILDINGS = "outbuildings"
GARAGE_STRUCTURE = "garage_structure"
# ======================
# INTERNAL KITCHEN
# ======================
KITCHEN = "kitchen"
KITCHEN_SPACE_LAYOUT = "kitchen_space_layout"
TENANT_INSTALLED_KITCHEN = "tenant_installed_kitchen"
# ======================
# INTERNAL BATHROOM
# ======================
BATHROOM = "bathroom"
# ======================
# INTERNAL HEATING / WATER
# ======================
HEATING_BOILER = "heating_boiler"
HEATING_DISTRIBUTION = "heating_distribution"
HEATING_EXTENT = "heating_extent"
SECONDARY_HEATING = "secondary_heating"
HOT_WATER_SYSTEM = "hot_water_system"
COLD_WATER_STORAGE = "cold_water_storage"
PROGRAMMABLE_HEATING = "programmable_heating"
# ======================
# INTERNAL ELECTRICS / FIRE
# ======================
ELECTRICAL_WIRING = "electrical_wiring"
CONSUMER_UNIT = "consumer_unit"
SMOKE_DETECTION = "smoke_detection"
HEAT_DETECTION = "heat_detection"
CARBON_MONOXIDE_DETECTION = "carbon_monoxide_detection"
FIRE_DOOR_RATING = "fire_door_rating"
# ======================
# COMMUNAL SYSTEMS
# ======================
COMMUNAL_HEATING = "communal_heating"
COMMUNAL_BOILER = "communal_boiler"
COMMUNAL_ELECTRICS = "communal_electrics"
COMMUNAL_FIRE_ALARM = "communal_fire_alarm"
COMMUNAL_EMERGENCY_LIGHTING = "communal_emergency_lighting"
COMMUNAL_LIFT = "communal_lift"
COMMUNAL_DOOR_ENTRY = "communal_door_entry"
COMMUNAL_CCTV = "communal_cctv"
COMMUNAL_BIN_STORE = "communal_bin_store"
COMMUNAL_REFUSE_CHUTE = "communal_refuse_chute"
# ==========================================================
# HHSRS ALL 29 HAZARDS
# ==========================================================
# --- Physiological requirements (4)
HHSRS_DAMP_AND_MOULD = "hhsrs_damp_and_mould"
HHSRS_EXCESS_COLD = "hhsrs_excess_cold"
HHSRS_EXCESS_HEAT = "hhsrs_excess_heat"
HHSRS_ASBESTOS_AND_MMF = "hhsrs_asbestos_and_mmf"
# --- Psychological requirements (4)
HHSRS_CROWDING_AND_SPACE = "hhsrs_crowding_and_space"
HHSRS_ENTRY_BY_INTRUDERS = "hhsrs_entry_by_intruders"
HHSRS_LIGHTING = "hhsrs_lighting"
HHSRS_NOISE = "hhsrs_noise"
# --- Protection against infection (6)
HHSRS_DOMESTIC_HYGIENE_PESTS_REFUSE = "hhsrs_domestic_hygiene_pests_refuse"
HHSRS_FOOD_SAFETY = "hhsrs_food_safety"
HHSRS_PERSONAL_HYGIENE_SANITATION = "hhsrs_personal_hygiene_sanitation"
HHSRS_WATER_SUPPLY = "hhsrs_water_supply"
HHSRS_FALLS_ASSOCIATED_WITH_BATHS = "hhsrs_falls_associated_with_baths"
HHSRS_SURFACES_MOULD = "hhsrs_surfaces_mould"
# --- Protection against accidents (10)
HHSRS_FALLS_ON_LEVEL_SURFACES = "hhsrs_falls_on_level_surfaces"
HHSRS_FALLS_ON_STAIRS = "hhsrs_falls_on_stairs"
HHSRS_FALLS_BETWEEN_LEVELS = "hhsrs_falls_between_levels"
HHSRS_ELECTRICAL_HAZARDS = "hhsrs_electrical_hazards"
HHSRS_FIRE = "hhsrs_fire"
HHSRS_FLAMES_HOT_SURFACES = "hhsrs_flames_hot_surfaces"
HHSRS_COLLISION_AND_ENTRAPMENT = "hhsrs_collision_and_entrapment"
HHSRS_EXPLOSION = "hhsrs_explosion"
HHSRS_STRUCTURAL_COLLAPSE = "hhsrs_structural_collapse"
HHSRS_UNSAFE_GAS = "hhsrs_unsafe_gas"
# --- Protection against pollution (4)
HHSRS_CARBON_MONOXIDE = "hhsrs_carbon_monoxide"
HHSRS_LEAD = "hhsrs_lead"
HHSRS_RADIATION = "hhsrs_radiation"
HHSRS_UNCOMBUSTED_FUEL_GAS = "hhsrs_uncombusted_fuel_gas"

View file

@ -1,7 +1,10 @@
from typing import List
from xml.dom.minidom import Element
import pytest
from datetime import date
from backend.condition.domain.aspect_type import AspectType
from backend.condition.domain.element import Element
from backend.condition.domain.mapping.lbwf_mapper import LbwfMapper
from backend.condition.parsing.records.lbwf.lbwf_house import LbwfHouse
from backend.condition.parsing.records.lbwf.lbwf_asset_condition import (
@ -85,6 +88,27 @@ def test_lbwf_mapper_maps_house():
remaining_life=None,
element_comments="Source of Data = ACT",
),
LbwfAssetCondition(
prop_ref=100,
domna=100,
address="123 Fake Street, London, A10 1AB",
ownership="LBWF_OWNED",
prop_status="OCCP",
prop_type="HOU",
prop_sub_type="TERRACED",
element_group="ASSETS",
element_code="HHSRSASB",
element_code_description="Asbestos (and MMF)",
attribute_code="TYPRISK",
attribute_code_description="Category 4 - Typical Risk",
element_date_value=None,
element_numerical_value=None,
element_text_value=None,
quantity=None,
install_date=None,
remaining_life=None,
element_comments="Source of Data = ACT",
),
LbwfAssetCondition(
prop_ref=100,
domna=100,
@ -158,9 +182,9 @@ def test_lbwf_mapper_maps_house():
prop_sub_type="TERRACED",
element_group="ASSETS",
element_code="EXTWALLFN1",
element_code_description="Wall Finish 1 in External Area",
attribute_code="RENDERPBBL",
attribute_code_description="Render or Pebbledash Wall Finish 1 in External Area",
element_code_description="Wall Finish 2 in External Area",
attribute_code="SMTHRENDER",
attribute_code_description="Smooth Render Wall Finish 1 in External Area",
element_date_value=None,
element_numerical_value=None,
element_text_value=None,
@ -178,66 +202,102 @@ def test_lbwf_mapper_maps_house():
expected_assets: List[AssetCondition] = [
AssetCondition(
uprn=1,
element=LbwfElement.AHR_CAT,
condition_description="General Needs",
element=Element.ACCESSIBLE_HOUSING_REGISTER,
aspect_type=AspectType.CATEGORY,
element_instance=None,
value="General Needs",
quantity=1,
renewal_year=None,
source=None,
install_date=None,
comments=None,
),
AssetCondition(
uprn=1,
element=LbwfElement.FLVL,
condition_description="Ground Floor",
element=Element.FLOOR_LEVEL_FRONT_DOOR,
aspect_type=AspectType.LOCATION,
element_instance=None,
value="Ground Floor",
quantity=1,
renewal_year=None,
source=None,
install_date=None,
comments=None,
),
AssetCondition(
uprn=1,
element=LbwfElement.ASBESTOS,
condition_description="Yes",
element=Element.ASBESTOS,
aspect_type=AspectType.PRESENCE,
element_instance=None,
value="Yes",
quantity=None,
renewal_year=None,
source="Source of Data = ACT",
install_date=None,
comments="Source of Data = ACT",
),
AssetCondition(
uprn=1,
element=LbwfElement.INTBTHRLOC,
condition_description="Bathroom on Entrance Level in Property",
element=Element.HHSRS_ASBESTOS_AND_MMF,
aspect_type=AspectType.RISK,
element_instance=None,
value="Category 4 - Typical Risk",
quantity=None,
renewal_year=None,
install_date=None,
comments="Source of Data = ACT",
),
AssetCondition(
uprn=1,
element=Element.BATHROOM,
aspect_type=AspectType.LOCATION,
element_instance=None,
value="Bathroom on Entrance Level in Property",
quantity=1,
renewal_year=None,
source="Source of Data = Codeman",
install_date=None,
comments="Source of Data = Codeman",
),
AssetCondition(
uprn=1,
element=LbwfElement.INTCHEXTNT,
condition_description="No Central Heating in Property",
element=Element.HEATING_EXTENT,
aspect_type=AspectType.CONFIGURATION,
element_instance=None,
value="No Central Heating in Property",
quantity=1,
renewal_year=None,
source="Source of Data = Codeman",
install_date=None,
comments="Source of Data = Codeman",
),
AssetCondition(
uprn=1,
element=LbwfElement.HHSRSFIRE,
condition_description="Category 4 - Typical Risk",
element=Element.HHSRS_FIRE,
aspect_type=AspectType.RISK,
element_instance=None,
value="Category 4 - Typical Risk",
quantity=1,
renewal_year=None,
source="Source of Data = Morgan Sindall",
install_date=None,
comments="Source of Data = Morgan Sindall",
),
AssetCondition(
uprn=1,
element=LbwfElement.EXTWALLFN1,
condition_description="Render or Pebbledash Wall Finish 1 in External Area",
element=Element.EXTERNAL_WALL,
aspect_type=AspectType.FINISH,
element_instance=1,
value="Render or Pebbledash",
quantity=1,
renewal_year=2052,
source="Source of Data = Codeman",
install_date=date(2009, 4, 1),
comments="Source of Data = Codeman",
),
AssetCondition(
uprn=1,
element=Element.EXTERNAL_WALL,
aspect_type=AspectType.FINISH,
element_instance=2,
value="Smooth Render Wall Finish 1 in External Area",
quantity=1,
renewal_year=2052,
install_date=date(2009, 4, 1),
comments="Source of Data = Codeman",
),
]