diff --git a/datatypes/epc/domain/mapper.py b/datatypes/epc/domain/mapper.py index ec27d6fcb..e89062610 100644 --- a/datatypes/epc/domain/mapper.py +++ b/datatypes/epc/domain/mapper.py @@ -2966,8 +2966,9 @@ def _sap_17_1_meter_type(electricity_tariff: Optional[int]) -> str: The two code spaces *differ* (epc_codes.csv `energy_tariff` vs `_METER_INT_TO_TARIFF`): full-SAP 1=standard / 2=off-peak-7hr / 3=off-peak- - 10hr / 4=24-hour, whereas RdSAP meter 1=dual-7hr / 2=single / 3=unknown / - 4=24-hour. Passing the full-SAP code straight through (the prior bug) read a + 10hr / 4=24-hour / 5=off-peak-18hr, whereas RdSAP meter 1=dual-7hr / + 2=single / 3=unknown / 4=24-hour. Passing the full-SAP code straight + through (the prior bug) read a standard-tariff cert as Economy 7 (over-rated) and an Economy-7 cert as single (under-rated). Map onto the RdSAP word aliases so the resolved tariff is correct; absent/ND → "" (the unknown→standard sentinel).""" @@ -2985,6 +2986,7 @@ _SAP_TARIFF_TO_RDSAP_METER_TYPE: dict[int, str] = { 2: "dual", # off-peak 7 hour (Economy 7) 3: "dual", # off-peak 10 hour (§12 dispatch resolves 7/10hr) 4: "dual (24 hour)", # 24-hour tariff + 5: "off-peak 18 hour", # off-peak 18 hour (Table 12a EIGHTEEN_HOUR) } diff --git a/datatypes/epc/domain/tests/test_from_sap_schema.py b/datatypes/epc/domain/tests/test_from_sap_schema.py index 7a682c8d7..957cc4a44 100644 --- a/datatypes/epc/domain/tests/test_from_sap_schema.py +++ b/datatypes/epc/domain/tests/test_from_sap_schema.py @@ -181,6 +181,7 @@ class TestFullSapElectricityTariffTranslation: (2, "SEVEN_HOUR"), # off-peak 7-hour → Economy 7 (3, "SEVEN_HOUR"), # off-peak 10-hour → dual (§12 resolves 7/10hr) (4, "TWENTY_FOUR_HOUR"), # 24-hour tariff (e.g. property 709874 — unchanged) + (5, "EIGHTEEN_HOUR"), # off-peak 18-hour — was dropped to "" → STANDARD (None, "STANDARD"), # absent/ND → unknown → standard ], ) @@ -869,6 +870,27 @@ class TestFullSapSchema16xRouting: assert epc.door_count == 1 assert epc.dwelling_type == "Detached house" + def test_full_sap_16_x_electricity_tariff_is_translated_not_passed_through( + self, + ) -> None: + # A full-SAP 16.x cert lodges the SAP `energy_tariff` code space, not the + # RdSAP `meter_type` one. Routing it through the full-SAP mapper (via the + # assessment_type=SAP gate) must apply `_sap_17_1_meter_type`: tariff 1 = + # standard → STANDARD. Were it raw-passed to the RdSAP normaliser, code 1 + # = "dual" → SEVEN_HOUR (the prime-lead over-rating bug this guards). + from domain.sap10_calculator.tables.table_12a import ( + Tariff, + tariff_from_meter_type, + ) + + data = load("sap_16_0_full.json") # electricity_tariff = 1 (standard) + + epc = EpcPropertyDataMapper.from_api_response(data) + + assert tariff_from_meter_type(epc.sap_energy_source.meter_type) is ( + Tariff.STANDARD + ) + def test_reduced_16_x_cert_unaffected_by_full_sap_routing(self) -> None: # Arrange — a reduced 16.2 cert (assessment_type RdSAP) must stay on the # RdSAP path, keeping its top-level property_type.