From 6c6be1a432f5e69d65d74c8275111f006087f823 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Fri, 3 Jul 2026 16:00:40 +0000 Subject: [PATCH] =?UTF-8?q?Electric=20underfloor=20codes=20resolve=20their?= =?UTF-8?q?=20SAP=2010.2=20Table=2012a=20Grid=201=20rows=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 421 slab -> Other storage heaters (0.00); 422/423 integrated -> 0.20; 424/425 screed/timber -> 0.90/0.50 — per the Grid 1 row labels that name the codes (PDF p.184). Closes the None all-low-rate fallback that over-credited 7-hour-metered underfloor dwellings. Co-Authored-By: Claude Opus 4.8 --- .../sap10_calculator/rdsap/cert_to_inputs.py | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/domain/sap10_calculator/rdsap/cert_to_inputs.py b/domain/sap10_calculator/rdsap/cert_to_inputs.py index 5d87f80cd..7ebf4d40e 100644 --- a/domain/sap10_calculator/rdsap/cert_to_inputs.py +++ b/domain/sap10_calculator/rdsap/cert_to_inputs.py @@ -2603,6 +2603,23 @@ _ELECTRIC_STORAGE_BOILER_CODES: Final[frozenset[int]] = frozenset( {193, 194, 195, 196} ) _ELECTRIC_CPSU_CODES: Final[frozenset[int]] = frozenset({192}) +# Electric underfloor (Table 4a 421-425) — SAP 10.2 Table 12a Grid 1 (PDF +# p.184) names the codes in its row labels: +# 422/423 "Integrated (storage+direct-acting) systems (applies to storage +# heaters 408 and underfloor heating 422 and 423)" → 7-hour 0.20 +# 424/425 "Underfloor heating (in screed above insulation, in timber floor +# or immediately below floor covering)" → 7-hour 0.90 / 10-hour 0.50 +# 421 "in concrete slab (off-peak only)" is named in NEITHER underfloor +# row — the slab is the storage medium, so it takes the "Other +# storage heaters" row (0.00 at 7-hour or 24-hour), consistent with +# §12 Rule 2 listing 421 among the off-peak-implying storage codes. +# Before these branches every underfloor code fell to the None all-low-rate +# fallback, over-crediting a 7-hour screed dwelling's space heat at 5.50p/kWh +# instead of the blended ~14.3p (ADR-0050 deferred follow-up; 22 live +# 7-hour-metered underfloor dwellings on portfolio 796). +_SLAB_UNDERFLOOR_CODES: Final[frozenset[int]] = frozenset({421}) +_INTEGRATED_UNDERFLOOR_CODES: Final[frozenset[int]] = frozenset({422, 423}) +_SCREED_OR_TIMBER_UNDERFLOOR_CODES: Final[frozenset[int]] = frozenset({424, 425}) def _table_12a_system_for_main( @@ -2622,7 +2639,9 @@ def _table_12a_system_for_main( - ASHP / GSHP (codes 211-224, 521-524, PCDB index) — wired - Storage heaters (cat 7): 408 → INTEGRATED_STORAGE_DIRECT (0.20), all others → OTHER_STORAGE_HEATERS (0.00) — wired - - Underfloor heating (421-422) — TODO + - Underfloor heating: 421 slab → OTHER_STORAGE_HEATERS (0.00), + 422/423 integrated → INTEGRATED_STORAGE_DIRECT (0.20), + 424/425 screed/timber → UNDERFLOOR_HEATING (0.90/0.50) — wired - Direct-acting electric boiler (191) → 0.90/0.50; electric storage boilers (193/194/195/196) → 0.00 — wired - Electric CPSU (192) — Appendix F high-rate cascade still TODO @@ -2634,6 +2653,19 @@ def _table_12a_system_for_main( main.main_heating_index_number is not None and heat_pump_record(main.main_heating_index_number) is not None ) + # Electric UNDERFLOOR heating — routed by the Table 4a code per the Grid 1 + # row labels (see `_SLAB_UNDERFLOOR_CODES` et al. above), checked BEFORE + # the storage branch so a stale category 7 cannot drag a screed system + # (0.90 at 7-hour) down to the all-night storage row — the code is more + # authoritative than the coarser category, mirroring the storage-over- + # room-heater precedent below. Gated on `_is_electric_main` belt-and-braces. + if _is_electric_main(main) and code is not None: + if code in _SCREED_OR_TIMBER_UNDERFLOOR_CODES: + return Table12aSystem.UNDERFLOOR_HEATING + if code in _INTEGRATED_UNDERFLOOR_CODES: + return Table12aSystem.INTEGRATED_STORAGE_DIRECT + if code in _SLAB_UNDERFLOOR_CODES: + return Table12aSystem.OTHER_STORAGE_HEATERS # Electric STORAGE heaters — SAP 10.2 Table 12a Grid 1 (PDF p.191). # Detected by RdSAP main_heating_category 7 OR, authoritatively, by a Table # 4a electric-storage-heater SAP code (401-409). Keyed on the CODE as well as