mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
test: 7 calculator-read EPC fields must round-trip 🟥
community heating fuel + CHP fraction, alt-wall is_sheltered, wall insulation thermal conductivity, pv_diverter_present, measured cylinder volume, AP50 air permeability — all calculator-read, all silently dropped on save. FE columns now live; assert deep-equal round-trip and drop their coverage-guard allow-list entries so the guard enforces reconstruction. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
bb4f8577fe
commit
5c4a8d9094
2 changed files with 48 additions and 11 deletions
|
|
@ -62,17 +62,6 @@ _UNPERSISTED_ALLOWLIST: dict[str, str] = {
|
|||
"SapRoomInRoof.gable_2_height_m": "FE child table pending — room-in-roof detail",
|
||||
"SapRoomInRoof.gable_2_length_m": "FE child table pending — room-in-roof detail",
|
||||
"SapRoomInRoofSurface": "FE child table pending — room-in-roof surface detail",
|
||||
# --- Nested gaps surfaced by the recursive guard (pre-existing; this guard
|
||||
# only just became able to see them). The calculator READS these, so they are
|
||||
# scoring-relevant silent-drop gaps awaiting FE columns — tracked follow-up,
|
||||
# docs/migrations/epc-property-round-trip-fidelity.md §"recursive-guard gaps".
|
||||
"MainHeatingDetail.community_heating_boiler_fuel_type": "calc-read; no FE column — tracked follow-up",
|
||||
"MainHeatingDetail.community_heating_chp_fraction": "calc-read; no FE column — tracked follow-up",
|
||||
"SapAlternativeWall.is_sheltered": "calc-read; no FE column — tracked follow-up",
|
||||
"SapBuildingPart.wall_insulation_thermal_conductivity": "calc-read; no FE column — tracked follow-up",
|
||||
"SapEnergySource.pv_diverter_present": "calc-read; no FE column — tracked follow-up",
|
||||
"SapHeating.cylinder_volume_measured_l": "calc-read; no FE column — tracked follow-up",
|
||||
"SapVentilation.air_permeability_ap50_m3_h_m2": "calc-read; no FE column — tracked follow-up",
|
||||
# --- Nested gaps the calculator does NOT read (dormant); no FE column.
|
||||
"SapAlternativeWall.is_basement": "dormant — not read by the calculator; no FE column",
|
||||
"SapBuildingPart.floor_u_value": "dormant — not read by the calculator (column exists, unread)",
|
||||
|
|
|
|||
|
|
@ -124,6 +124,54 @@ def test_photovoltaic_arrays_round_trip(db_engine: Engine) -> None:
|
|||
assert reloaded == original
|
||||
|
||||
|
||||
def test_calculator_read_fields_round_trip(db_engine: Engine) -> None:
|
||||
# Seven fields the SAP calculator reads (cert_to_inputs / heat_transmission)
|
||||
# that had no DB column, so they were silently dropped on save (persist !=
|
||||
# score). FE columns now exist; inject all seven onto a clean fixture and
|
||||
# prove they survive the round-trip deep-equal.
|
||||
from dataclasses import replace
|
||||
|
||||
# Arrange
|
||||
original = _load_epc("RdSAP-Schema-21.0.1")
|
||||
bp0 = original.sap_building_parts[0]
|
||||
assert bp0.sap_alternative_wall_1 is not None, "fixture must carry an alt wall"
|
||||
bp0 = replace(
|
||||
bp0,
|
||||
sap_alternative_wall_1=replace(bp0.sap_alternative_wall_1, is_sheltered=True),
|
||||
wall_insulation_thermal_conductivity=35, # Union[int,str] → JSONB int
|
||||
)
|
||||
heating = original.sap_heating
|
||||
mh0 = replace(
|
||||
heating.main_heating_details[0],
|
||||
community_heating_boiler_fuel_type=35,
|
||||
community_heating_chp_fraction=0.35,
|
||||
)
|
||||
heating = replace(
|
||||
heating,
|
||||
main_heating_details=[mh0, *heating.main_heating_details[1:]],
|
||||
cylinder_volume_measured_l=180,
|
||||
)
|
||||
original = replace(
|
||||
original,
|
||||
sap_building_parts=[bp0, *original.sap_building_parts[1:]],
|
||||
sap_heating=heating,
|
||||
sap_energy_source=replace(original.sap_energy_source, pv_diverter_present=True),
|
||||
sap_ventilation=replace(
|
||||
original.sap_ventilation, air_permeability_ap50_m3_h_m2=7.5
|
||||
),
|
||||
)
|
||||
|
||||
# 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 — all seven calculator-read fields survive, 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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue