test: solar PV arrays must round-trip through persistence 🟥

sap_energy_source.photovoltaic_arrays has no table, so every array is
dropped on save — worth ~12 SAP points on an electrically-heated dwelling
(persist != score). Inject two ordered arrays onto a PV-free fixture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-26 16:43:26 +00:00
parent e5d94adc36
commit 1041c8ed0e

View file

@ -86,6 +86,44 @@ def test_non_separated_conservatory_round_trips(db_engine: Engine) -> None:
assert reloaded == original
def test_photovoltaic_arrays_round_trip(db_engine: Engine) -> None:
# SAP 10.2 Appendix M — a dwelling's solar PV arrays generate electricity that
# offsets demand, worth a large slice of the SAP score (≈12 points on an
# electrically-heated dwelling). `sap_energy_source.photovoltaic_arrays` had
# no table, so every array was dropped on save (persist != score). We inject
# two arrays (distinct, so ORDER is observable) onto a clean PV-free fixture
# so the ONLY thing that can break deep-equality is the array list itself.
from dataclasses import replace
from datatypes.epc.domain.epc_property_data import PhotovoltaicArray
# Arrange — a green fixture with no PV, plus two ordered arrays.
original = _load_epc("RdSAP-Schema-21.0.1")
assert original.sap_energy_source.photovoltaic_arrays is None, (
"fixture must start PV-free so the array list is the only variable"
)
arrays = [
PhotovoltaicArray(peak_power=3.24, pitch=3, overshading=1, orientation=3),
PhotovoltaicArray(peak_power=1.5, pitch=2, overshading=2, orientation=None),
]
original = replace(
original,
sap_energy_source=replace(
original.sap_energy_source, photovoltaic_arrays=arrays
),
)
# Act
with Session(db_engine) as session:
epc_property_id = EpcPostgresRepository(session).save(original)
session.commit()
with Session(db_engine) as session:
reloaded = EpcPostgresRepository(session).get(epc_property_id)
# Assert — both arrays survive in order, deep-equal.
assert reloaded == original
def test_floor_dimension_heat_loss_flags_round_trip(db_engine: Engine) -> None:
# SAP 10.2 §3.3 — `is_exposed_floor` and `is_above_partially_heated_space`
# are heat-loss flags on a `SapFloorDimension`: the calculator routes a floor