mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
Slice S0380.2: surface main_heating_category=4 for PCDB heat-pump indices
Extends `_elmhurst_main_heating_category` in `datatypes/epc/domain/mapper.py` so a PCDB index that resolves to a Table 362 record (heat pumps only) yields category 4 — the SAP 10.2 Table 4a code that gates the Appendix N3.6/N3.7 heat-pump cascade (`cert_to_inputs.py` lines 1896, 2005, 2057, 2104 all branch on `main_heating_category == 4`). Authoritative signal: PCDB Table 362 is heat-pumps-only, so membership IS the heat-pump answer. `heat_pump_record(pcdb_id)` (introduced for the API path's cohort closure) returns the typed record or None; a non-None return is sufficient. No fuel-type belt-and-braces is needed — Table 362 membership is unambiguous, unlike the gas-boiler branch which uses fuel type to disambiguate PCDB Table 105 records. Forcing function (Slice S0380.1): cert 0380 Summary cascade SAP moves from 33.7920 (Δ -54.7184) to 81.7528 (Δ -6.7576) — closes ~88% of the gap. Remaining -6.76 SAP is the next workstream: cylinder / HW cascade, PV array surfacing, secondary-heating routing (per HANDOVER_CERT_0380_SUMMARY_PATH.md debug order steps 3–4). Added focused unit test `test_summary_0380_main_heating_category_is_heat_pump` that pins the contract at the mapper boundary (idx 104568 → category 4), so future debuggers can localise regressions before walking the full chain. Architectural note: introduces the first `datatypes/epc/domain/mapper.py → domain/sap10_calculator/tables/pcdb` import. PCDB is BRE reference data shared by both layers; treating it as importable shared reference is the lighter alternative to either (a) duplicating an HP-PCDB-IDs frozenset in the mapper or (b) hoisting PCDB into a new shared package. Pyright baseline preserved: datatypes/epc/domain/mapper.py: 32 errors (no new errors introduced) backend/documents_parser/tests/test_summary_pdf_mapper_chain.py: 0 errors Regression suite: 670 pass + 11 fail (vs handover baseline 669 + 10 — net +1 pass for the new GREEN unit test, +1 fail still being the Slice 1 chain test that this slice does not yet fully close). Spec refs: - SAP 10.2 Table 4a (main heating category codes — code 4 = heat pump) - SAP 10.2 Appendix N3.6/N3.7 (heat-pump space-heating efficiency with PSR interpolation, routed via the category-4 gate) - BRE PCDB Table 362 (heat-pump records — pcdb_id 104568 = Mitsubishi Ecodan PUZ-WM50VHA, the cert 0380 main heating appliance) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
2828bf988d
commit
19e23d0c31
2 changed files with 40 additions and 10 deletions
|
|
@ -492,6 +492,28 @@ def test_summary_0330_full_chain_sap_matches_worksheet_pdf_exactly() -> None:
|
|||
assert abs(result.sap_score_continuous - worksheet_unrounded_sap) < 1e-4
|
||||
|
||||
|
||||
def test_summary_0380_main_heating_category_is_heat_pump() -> None:
|
||||
# Arrange — cert 0380's Summary lodges main heating as a PCDB-
|
||||
# indexed Mitsubishi PUZ-WM50VHA (idx 104568), which lives in
|
||||
# PCDB Table 362 (heat pumps only). The Elmhurst mapper must
|
||||
# surface `main_heating_category=4` so the cascade routes the
|
||||
# cert through the Appendix N3.6/N3.7 heat-pump path instead of
|
||||
# falling through to the default boiler-ish branches that key off
|
||||
# `main_heating_category in {1, 2}`. Spec ref: SAP 10.2 Table 4a
|
||||
# (main heating category code 4 = heat pump).
|
||||
pages = _summary_pdf_to_textract_style_pages(_SUMMARY_000899_PDF)
|
||||
site_notes = ElmhurstSiteNotesExtractor(pages).extract()
|
||||
|
||||
# Act
|
||||
epc = EpcPropertyDataMapper.from_elmhurst_site_notes(site_notes)
|
||||
|
||||
# Assert
|
||||
assert epc.sap_heating.main_heating_details, "no main heating details surfaced"
|
||||
main = epc.sap_heating.main_heating_details[0]
|
||||
assert main.main_heating_index_number == 104568
|
||||
assert main.main_heating_category == 4
|
||||
|
||||
|
||||
def test_summary_0380_full_chain_sap_matches_worksheet_pdf_exactly() -> None:
|
||||
# Arrange — cert 0380-2471-3250-2596-8761 (Summary_000899.pdf /
|
||||
# dr87-0001-000899.pdf) is the first heat-pump cert under per-cert
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ from datatypes.epc.schema.rdsap_schema_21_0_1 import (
|
|||
RdSapSchema21_0_1,
|
||||
EnergyElement as EnergyElement_21_0_1,
|
||||
)
|
||||
from domain.sap10_calculator.tables.pcdb import heat_pump_record
|
||||
from datatypes.epc.surveys.elmhurst_site_notes import (
|
||||
AlternativeWall as ElmhurstAlternativeWall,
|
||||
BuildingPartDimensions as ElmhurstBuildingPartDimensions,
|
||||
|
|
@ -3332,14 +3333,16 @@ def _elmhurst_sap_control_code(sap_control: str) -> Optional[int]:
|
|||
return int(m.group(1)) if m else None
|
||||
|
||||
|
||||
# SAP10.2 Table 4a main-heating-category codes. Currently only the
|
||||
# gas-fired-boiler branch is exercised by the Elmhurst cohort — the
|
||||
# cascade reads `main_heating_category` to key the §4f pumps+fans table
|
||||
# (160 kWh/yr for cat 2 = 115 central heating pump + 45 flue fan) and to
|
||||
# detect heat-network mains (cat 6). Other categories (heat pumps,
|
||||
# warm-air, electric storage, oil/biomass) are deferred until a fixture
|
||||
# exercises them.
|
||||
# SAP10.2 Table 4a main-heating-category codes. The cascade reads
|
||||
# `main_heating_category` to key the §4f pumps+fans table (160 kWh/yr
|
||||
# for cat 2 = 115 central heating pump + 45 flue fan), to detect
|
||||
# heat-network mains (cat 6), and to gate the Appendix N3.6/N3.7
|
||||
# heat-pump path (cat 4 — `cert_to_inputs.py` line 1896/2005/2057/
|
||||
# 2104 all branch on `main_heating_category == 4`). Other categories
|
||||
# (warm-air, electric storage, oil/biomass) are deferred until a
|
||||
# fixture exercises them.
|
||||
_ELMHURST_HEATING_CATEGORY_GAS_BOILER: Final[int] = 2
|
||||
_ELMHURST_HEATING_CATEGORY_HEAT_PUMP: Final[int] = 4
|
||||
_ELMHURST_GAS_BOILER_FUEL_TYPES: frozenset[str] = frozenset({
|
||||
"Mains gas",
|
||||
"LPG bottled",
|
||||
|
|
@ -3352,9 +3355,14 @@ def _elmhurst_main_heating_category(
|
|||
mh: ElmhurstMainHeating, pcdb_index: Optional[int]
|
||||
) -> Optional[int]:
|
||||
"""Derive the SAP10.2 Table 4a main-heating-category from Elmhurst-
|
||||
lodged data. A PCDB-referenced boiler on mains/LPG gas is category 2
|
||||
(gas-fired boilers); other system types fall through to None so the
|
||||
cascade applies its default pumps_fans 130 kWh/yr until extended."""
|
||||
lodged data. A PCDB index that resolves to a Table 362 record is a
|
||||
heat pump (category 4) — Table 362 lists heat pumps only, so
|
||||
membership is the authoritative signal. A PCDB-referenced boiler on
|
||||
mains/LPG gas is category 2 (gas-fired boilers). Other system types
|
||||
fall through to None so the cascade applies its default pumps_fans
|
||||
130 kWh/yr until extended."""
|
||||
if pcdb_index is not None and heat_pump_record(pcdb_index) is not None:
|
||||
return _ELMHURST_HEATING_CATEGORY_HEAT_PUMP
|
||||
if pcdb_index is not None and mh.fuel_type in _ELMHURST_GAS_BOILER_FUEL_TYPES:
|
||||
return _ELMHURST_HEATING_CATEGORY_GAS_BOILER
|
||||
return None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue