From be0fb08e6552e8ae60549987b7788b9c04c32694 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Wed, 29 Jul 2026 16:13:39 +0000 Subject: [PATCH] =?UTF-8?q?test(calculator):=20RED=20=E2=80=94=20overlay?= =?UTF-8?q?=20(winter,summer)=20slot=20wins=20over=20Table=204b=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .../rdsap/test_cert_to_inputs.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py b/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py index d20230c18..adf75734d 100644 --- a/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py +++ b/tests/domain/sap10_calculator/rdsap/test_cert_to_inputs.py @@ -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