Model/tests/domain/property/test_property_physical_state_changed.py
Khalim Conn-Kowlessar 4d5504fa10 feat: thread physical-state-change signal into rebaselining 🟩
Add Property.physical_state_changed (true on Site Notes / Landlord Overrides
/ Prediction — trigger (b)/(c)) and pass it from the
PropertyBaselineOrchestrator into the Rebaseliner. So an overridden or
predicted SAP>=10.2 property now stores calc(effective) as its Effective
baseline instead of echoing the lodged headline — closing the "81 in the DB"
divergence between the displayed baseline and the modelled plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:15:11 +00:00

53 lines
2 KiB
Python

"""`Property.physical_state_changed` — the Rebaselining trigger (b)/(c) signal.
True when the Effective EPC was assembled from something other than a pristine
lodged cert: Landlord Overrides folded on, Site Notes superseding the cert, or an
EPC-Prediction synthesis. The PropertyBaselineOrchestrator threads it into the
Rebaseliner so an overridden / predicted SAP >= 10.2 picture rebaselines off the
calculator instead of echoing the (now-stale) accredited lodged figure.
"""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
from datatypes.epc.domain.epc_property_data import EpcPropertyData
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
from domain.epc.property_overlays.wall_type_overlay import wall_overlay_for
from domain.property.property import Property, PropertyIdentity
_JSON_SAMPLES = Path(__file__).resolve().parents[3] / "backend/epc_api/json_samples"
def _epc() -> EpcPropertyData:
raw: dict[str, Any] = json.loads(
(_JSON_SAMPLES / "RdSAP-Schema-21.0.0" / "epc.json").read_text()
)
return EpcPropertyDataMapper.from_api_response(raw)
def _identity() -> PropertyIdentity:
return PropertyIdentity(
portfolio_id=1, postcode="A0 0AA", address="1 Some Street", uprn=12345
)
def test_pristine_lodged_cert_with_no_overrides_is_unchanged() -> None:
prop = Property(identity=_identity(), epc=_epc())
assert prop.physical_state_changed is False
def test_lodged_cert_with_landlord_overrides_is_changed() -> None:
overlay = wall_overlay_for("Solid brick, with internal insulation", 0)
assert overlay is not None
prop = Property(identity=_identity(), epc=_epc(), landlord_overrides=[overlay])
assert prop.physical_state_changed is True
def test_predicted_property_is_changed() -> None:
# A neighbour-synthesised picture is assembled, not a real lodged cert, so it
# rebaselines off the calculator (trigger (c)).
prop = Property(identity=_identity(), epc=None, predicted_epc=_epc())
assert prop.physical_state_changed is True