diff --git a/packages/domain/src/domain/sap/rdsap/tests/test_golden_fixtures.py b/packages/domain/src/domain/sap/rdsap/tests/test_golden_fixtures.py index 616e7d70..a61187cf 100644 --- a/packages/domain/src/domain/sap/rdsap/tests/test_golden_fixtures.py +++ b/packages/domain/src/domain/sap/rdsap/tests/test_golden_fixtures.py @@ -162,3 +162,52 @@ def test_golden_cert_stays_within_tolerance(expectation: _GoldenExpectation) -> f"±{_PE_TOLERANCE_KWH_PER_M2} (expected ≈{expectation.expected_pe_resid_kwh_per_m2:+.2f}). " f"Notes: {expectation.notes}" ) + + +# Cert 0390 lodges Firebird Boilers S 150-200 oil boiler at PCDB index_number +# 9005 (Table 105 winter eff 86.4%). End-to-end mapper → cert_to_inputs chain +# must surface that PCDB winter efficiency on `inputs.main_heating_efficiency` +# rather than falling back to the Table 4a oil-boiler category default. +_PCDB_CHAIN_EXPECTATIONS: tuple[tuple[str, int, float], ...] = ( + ("0390-2954-3640-2196-4175", 9005, 0.864), # Firebird oil PCDB-listed + ("7536-3827-0600-0600-0276", 17679, None), # Vaillant gas PCDB-listed + ("0300-2747-7640-2526-2135", 17992, None), # gas PCDB-listed + ("8135-1728-8500-0511-3296", 17702, None), # gas PCDB-listed +) + + +@pytest.mark.parametrize( + "cert_number, expected_pcdb_id, expected_winter_eff", + _PCDB_CHAIN_EXPECTATIONS, + ids=lambda v: v if isinstance(v, str) else "", +) +def test_api_to_domain_mapper_preserves_main_heating_index_number( + cert_number: str, expected_pcdb_id: int, expected_winter_eff: float | None +) -> None: + """The full API JSON → EpcPropertyData → CalculatorInputs chain must + preserve `main_heating_index_number` end-to-end so the PCDB precedence + cascade (Appendix D2.1) fires correctly. Pins: + + 1. EpcPropertyDataMapper.from_api_response surfaces the PCDB pointer + on `sap_heating.main_heating_details[0].main_heating_index_number`. + 2. cert_to_inputs resolves Table 105 record by that ID and applies the + winter efficiency to `inputs.main_heating_efficiency`. + + Schema versions ≥17_1 carry the field on their dataclass; schema 17_0 + hardcodes None in the mapper (the field didn't exist in that schema's + EPC API contract). The 4 corpus golden certs are all post-17_1. + """ + # Arrange + doc = _load_cert(cert_number) + + # Act + epc = EpcPropertyDataMapper.from_api_response(doc) + inputs = cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES) + + # Assert + main = epc.sap_heating.main_heating_details[0] + assert main.main_heating_index_number == expected_pcdb_id + if expected_winter_eff is not None: + assert inputs.main_heating_efficiency == pytest.approx( + expected_winter_eff, abs=1e-3 + )