Model/backend/documents_parser
Khalim Conn-Kowlessar ff80fb4b5c Slice S0380.176: Table 4b combi sub-row dispatch for (61)m
SAP 10.2 §4 line 7702 (PDF p.137) defines (61)m as "Combi loss for
each month from Table 3a, 3b or 3c (enter '0' if not a combi
boiler)". Table 4b sub-rows 128 / 129 / 130 are explicit combi sub-
rows per the spec row names:
    128: Combi oil boiler, pre-1998
    129: Combi oil boiler, 1998 or later
    130: Condensing combi oil boiler

Pre-slice `_table_3a_combi_loss_default_applies` gated only on
`main_heating_category ∈ {1, 2, 3, 6}`. The Elmhurst mapper leaves
`main_heating_category=None` on Table 4b liquid-fuel boilers (FAME,
HVO, B30K) — the cascade fell through to (61)m=0 despite the lodged
SAP code being a combi sub-row, under-counting (62)m by 600 kWh/yr
for FAME combi certs.

Extended the helper with a `_TABLE_4B_COMBI_OR_CPSU_CODES` fall-
through (set already exists for the symmetric `_primary_loss_
applies` Table 4b non-combi branch — see S0380.146). The set carries
the canonical combi + CPSU sub-row codes (103/104/107/108/112/113/
118/120-123/128-130). For cylinder-lodged certs the existing
`if epc.has_hot_water_cylinder: combi_loss_override = zero_monthly`
guard in `_water_heating_worksheet_and_gains` still pre-empts the
combi-loss fall-through correctly — non-combi codes with cylinders
remain (61)m=0.

Closures (heating-systems corpus 001431):
  oil 3 (code 128, FAME, no cylinder) ALL EXACT (±0.0000):
    ΔSAP_c +2.5863 → -0.0000
    Δcost  -£61.89 → -£0.00
    ΔCO2   -14.58  → +0.00
    ΔPE    -967.10 → +0.00
  oil 4 (code 129, FAME, no cylinder) ALL EXACT (±0.0000):
    ΔSAP_c +2.5603 → +0.0000
    Δcost  -£56.66 → +£0.00
    ΔCO2   -13.35  → +0.00
    ΔPE    -884.90 → +0.00

Oil 6 (code 126, NOT a combi, with cylinder) unchanged — the fix
is gated on the combi sub-row set. Cohort moves from 9 pinned
residuals to 7.

933 pass + 0 fail (+1 new mapper test). Pyright net-zero on cert_
to_inputs.py + tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 15:40:26 +00:00
..
handler address JTK review comments 2026-04-20 15:11:17 +00:00
tests Slice S0380.176: Table 4b combi sub-row dispatch for (61)m 2026-06-04 15:40:26 +00:00
__init__.py Map to RdSapSiteNotes from site notes JSON 🟥 2026-04-16 13:54:03 +00:00
db_writer.py include updating epc_property_data to pashub to ara workflow 2026-04-29 09:55:14 +00:00
elmhurst_extractor.py Slice S0380.170: Community heating mapper unblock (Table 12 dispatch) 2026-06-04 15:40:25 +00:00
extractor.py Handle wall thickness "Unmeasurable" 🟩 2026-04-30 16:41:16 +00:00
local_runner.py update local runner to work for elmhurst 2026-04-24 14:01:36 +00:00
parser.py load ecmk site notes to db 2026-04-29 11:20:47 +00:00
pdf.py update local runner to work for elmhurst 2026-04-24 14:01:36 +00:00