"""End-to-end smoke of the Hyde override script for ONE property, against a real (ephemeral) Postgres. Seeds the landlord vocab (simulating post-classify, so no ChatGPT) + a minimal ``property`` row, then runs the script's real ``write`` + ``verify`` paths and asserts property_overrides + overlays land. """ from __future__ import annotations import argparse from typing import Any from sqlalchemy import Engine, text from sqlmodel import Session import scripts.hyde.build_property_overrides as b from domain.epc.property_overrides.built_form_type import BuiltFormType from domain.epc.property_overrides.construction_age_band import ConstructionAgeBand from domain.epc.property_overrides.glazing_type import GlazingType from domain.epc.property_overrides.main_fuel_type import MainFuelType from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType from domain.epc.property_overrides.property_type import PropertyType from domain.epc.property_overrides.roof_type import RoofType from domain.epc.property_overrides.wall_type import WallType from domain.epc.property_overrides.water_heating_type import WaterHeatingType from infrastructure.landlord_overrides.landlord_overrides_postgres_repository import ( LandlordOverridesRepository, ) from repositories.property.landlord_override_overlays import overlays_from from repositories.property.property_overrides_postgres_reader import ( PropertyOverridesPostgresReader, ) PORTFOLIO = 795 ORG_REF = "55180004001" EXCEL = "scripts/hyde/hyde_property_overrides.xlsx" # What ChatGPT WOULD resolve this property's 9 descriptions to (component -> # (raw Excel entry, enum member)). Seeded into the landlord ledger. SEED = { "property_type": ("House: MidTerrace", PropertyType.HOUSE), "built_form_type": ("House: MidTerrace", BuiltFormType.MID_TERRACE), "wall_type": ("TimberFrame: AsBuilt", WallType.TIMBER_FRAME_AS_BUILT_NO_INSULATION_ASSUMED), "roof_type": ("PitchedNormalLoftAccess: 300mm", RoofType.PITCHED_LOFT_300MM), "construction_age_band": ("L: 2012-2022", ConstructionAgeBand.L_2012_2022), "main_fuel": ("Gas: Mains Gas", MainFuelType.MAINS_GAS), "glazing": ("100% Double glazing 2002 or later", GlazingType.DOUBLE_POST_2002), "water_heating": ("From main heating system: Mains Gas", WaterHeatingType.FROM_MAIN_MAINS_GAS), "main_heating_system": ("Boiler: C rated Combi", MainHeatingSystemType.GAS_COMBI), } def test_one_property_end_to_end(db_engine: Engine, monkeypatch: Any) -> None: specs = b._specs_by_component() # pyright: ignore[reportPrivateUsage] # minimal FE-owned `property` table + the one row we'll match by org_ref with Session(db_engine) as s: s.execute(text( # pyright: ignore[reportDeprecated] "CREATE TABLE property (id bigint PRIMARY KEY, portfolio_id bigint, " "landlord_property_id text)")) s.execute(text("INSERT INTO property VALUES (1, :p, :ref)"), # pyright: ignore[reportDeprecated] {"p": PORTFOLIO, "ref": ORG_REF}) # seed the classifier ledger (keyed on normalised description) for comp, (raw, member) in SEED.items(): repo: LandlordOverridesRepository[Any] = LandlordOverridesRepository( s, specs[comp].row_type) repo.upsert_all(PORTFOLIO, {b._norm(raw): member}) # pyright: ignore[reportPrivateUsage] s.commit() # point the script at the ephemeral engine monkeypatch.setattr(b, "_db_session", lambda: Session(db_engine)) # --- run the real write() for this one property --- b.write(argparse.Namespace(excel=EXCEL, sheet="AddressProfilingResults", portfolio_id=PORTFOLIO, org_ref=ORG_REF, limit=None, apply=True)) with Session(db_engine) as s: rows = list(s.execute(text( # pyright: ignore[reportDeprecated] "SELECT override_component, building_part, override_value " "FROM property_overrides WHERE property_id = 1 ORDER BY override_component"))) got = {c: v for c, _, v in rows} # every seeded component produced a property_overrides row with the resolved value assert got["main_fuel"] == "mains gas" assert got["glazing"] == "Double glazing, 2002 or later" assert got["construction_age_band"] == "L" assert got["main_heating_system"] == "Gas boiler, combi" assert got["water_heating"] == "From main system, mains gas" assert len(rows) == 9 # all 9 components # --- the overrides reach the SAP overlay surface --- b.verify(argparse.Namespace(portfolio_id=PORTFOLIO, org_ref=ORG_REF)) # exercises verify() overlays = overlays_from( PropertyOverridesPostgresReader(lambda: Session(db_engine)).overrides_for(1)) assert len(overlays) == 9 assert any(o.heating is not None and o.heating.main_fuel_type == 26 for o in overlays) assert any(o.glazing is not None and o.glazing.glazing_type == 2 for o in overlays)