test(calculator): RED — overlay (winter,summer) slot wins over Table 4b code

The override-supplied seasonal efficiency must take precedence in both the §206
winter path (main_heating_efficiency) and the Appendix D Eq D1 summer water path,
the same precedence slot the PCDB winter_efficiency_pct occupies (ADR-0068).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-29 16:13:39 +00:00
parent 4244b16d17
commit be0fb08e65

View file

@ -2885,6 +2885,65 @@ def test_living_area_rounds_half_up_at_2_dp_decimal_boundary_per_rdsap_15() -> N
assert abs(fla_off_boundary - (14.06 / 46.87)) <= 1e-12
def _epc_with_override_boiler(
base: object, seasonal_efficiency_override_pct: Optional[tuple[float, float]]
):
"""A copy of the typical semi-detached cert whose primary gas boiler (Table 4b
code 102) carries a Landlord-Override `(winter, summer)` efficiency slot the
fifth Heating Companion (ADR-0068)."""
import dataclasses
typical = _typical_semi_detached_epc()
detail = dataclasses.replace(
_gas_boiler_detail(sap_main_heating_code=102),
seasonal_efficiency_override_pct=seasonal_efficiency_override_pct,
)
return make_minimal_sap10_epc(
total_floor_area_m2=_TYPICAL_TFA_M2,
habitable_rooms_count=4,
region_code="1",
sap_building_parts=typical.sap_building_parts,
sap_windows=typical.sap_windows,
sap_heating=make_sap_heating(main_heating_details=[detail]),
)
def test_seasonal_efficiency_override_wins_over_the_table_4b_code_default() -> None:
# A gas boiler override forces the SEDBUK-band efficiency ahead of the Table
# 4b code default: a G-rated boiler on code 102 (84%) is modelled at 66%, not
# the condensing 84% — the fix at the heart of #1704 / ADR-0068. "Override
# wins": the band-derived efficiency replaces the code's, symmetric up or down.
epc = _epc_with_override_boiler(None, (66.0, 56.0)) # G band (winter, summer)
inputs = cert_to_inputs(epc)
assert inputs.main_heating_efficiency == 0.66
def test_no_override_keeps_the_table_4b_code_efficiency() -> None:
# Absent the slot, the code default stands (today's behaviour) — the override
# is the only thing that moves it.
epc = _epc_with_override_boiler(None, None)
inputs = cert_to_inputs(epc)
assert inputs.main_heating_efficiency == 0.84
def test_seasonal_efficiency_override_feeds_the_eq_d1_water_summer_efficiency() -> None:
# The slot is a `(winter, summer)` pair; the summer leg drives SAP Appendix D
# §D2.1 Eq D1 water-heating efficiency (WHC 901, from main). A lower-band
# boiler burns less efficiently in summer, so it needs MORE hot-water fuel —
# a direction check that the override reaches the Eq D1 branch, not just §206.
default_code = _epc_with_override_boiler(None, None) # code 102 → summer 74%
g_band = _epc_with_override_boiler(None, (66.0, 56.0)) # summer 56%
hw_default = cert_to_inputs(default_code).hot_water_kwh_per_yr
hw_g_band = cert_to_inputs(g_band).hot_water_kwh_per_yr
assert hw_g_band > hw_default
def test_main_heating_efficiency_reads_sap_main_heating_code() -> None:
# Arrange — Direction check: a gas combi (Table 4b code 102, 84% eff)
# vs a non-condensing gas boiler (code 105, 70% eff) must show through