From f40abcedeb796b94f4be3f54404e4c3b19115a17 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 7 Jul 2026 11:36:13 +0000 Subject: [PATCH] =?UTF-8?q?Property-type=20override=20beats=20the=20lodged?= =?UTF-8?q?=20EPC=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .../app/modelling/test_property_filters.py | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/tests/backend/app/modelling/test_property_filters.py b/tests/backend/app/modelling/test_property_filters.py index 6b3e62685..3b2ec2f73 100644 --- a/tests/backend/app/modelling/test_property_filters.py +++ b/tests/backend/app/modelling/test_property_filters.py @@ -1,3 +1,5 @@ +from typing import Optional + from sqlalchemy import Engine from sqlmodel import Session @@ -6,6 +8,8 @@ from backend.app.modelling.property_filters import ( PropertyGroupFilters, resolve_filtered_property_ids, ) +from infrastructure.postgres.epc_property_table import EpcPropertyModel +from infrastructure.postgres.property_override_table import PropertyOverrideRow from infrastructure.postgres.property_table import PropertyRow @@ -28,6 +32,77 @@ def _seed_property( return row.id +def _seed_override( + session: Session, + *, + property_id: int, + component: str, + value: str, + building_part: int = 0, +) -> None: + session.add( + PropertyOverrideRow( + property_id=property_id, + portfolio_id=814, + building_part=building_part, + override_component=component, + override_value=value, + original_spreadsheet_description=value, + ) + ) + session.commit() + + +def _seed_epc( + session: Session, + *, + property_id: int, + source: str = "lodged", + property_type: Optional[str] = None, + built_form: Optional[str] = None, + dwelling_type: str = "Mid-terrace house", +) -> None: + session.add( + EpcPropertyModel( + property_id=property_id, + portfolio_id=814, + source=source, + dwelling_type=dwelling_type, + property_type=property_type, + built_form=built_form, + # Minimal NOT NULL ballast — irrelevant to filter resolution. + tenure="rental (social)", + transaction_type="assessment for green deal", + inspection_date="2024-01-01", + total_floor_area_m2=80.0, + solar_water_heating=False, + has_hot_water_cylinder=False, + has_fixed_air_conditioning=False, + door_count=1, + wet_rooms_count=1, + extensions_count=0, + heated_rooms_count=4, + open_chimneys_count=0, + habitable_rooms_count=4, + insulated_door_count=0, + cfl_fixed_lighting_bulbs_count=0, + led_fixed_lighting_bulbs_count=4, + incandescent_fixed_lighting_bulbs_count=0, + energy_gas_connection_available=True, + energy_meter_type="single", + energy_pv_battery_count=0, + energy_wind_turbines_count=0, + energy_gas_smart_meter_present=False, + energy_is_dwelling_export_capable=False, + energy_wind_turbines_terrain_type="", + energy_electricity_smart_meter_present=False, + energy_pv_diverter_present=False, + ventilation_present=False, + ) + ) + session.commit() + + def test_no_filters_resolves_the_whole_portfolio_minus_deletions( db_engine: Engine, ) -> None: @@ -49,6 +124,31 @@ def test_no_filters_resolves_the_whole_portfolio_minus_deletions( assert deleted not in [p.property_id for p in resolved] +def test_property_type_override_beats_the_lodged_epc(db_engine: Engine) -> None: + # arrange — both properties' lodged EPCs say House; one is overridden + with Session(db_engine) as session: + overridden = _seed_property(session, portfolio_id=814) + _seed_epc(session, property_id=overridden, property_type="House") + _seed_override( + session, + property_id=overridden, + component="property_type", + value="Bungalow", + ) + plain = _seed_property(session, portfolio_id=814) + _seed_epc(session, property_id=plain, property_type="House") + + # act + resolved = resolve_filtered_property_ids( + session, + portfolio_id=814, + filters=PropertyGroupFilters(property_types=["Bungalow"]), + ) + + # assert + assert [p.property_id for p in resolved] == [overridden] + + def test_postcode_filter_matches_exactly(db_engine: Engine) -> None: # arrange with Session(db_engine) as session: