Translate full-SAP electricity tariff into the RdSAP meter type 🟩

Full-SAP energy_tariff (1=standard/2=7hr/3=10hr/4=24hr) and RdSAP meter_type
(1=dual/2=single/3=unknown/4=24hr) are different code spaces; the mapper passed
the code through untranslated, reading standard-tariff full-SAP certs as Economy 7
(over-rated) and Economy-7 certs as single (under-rated). Map onto the RdSAP word
aliases so the resolved Table 12a tariff is correct; absent/ND -> unknown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-29 18:54:51 +00:00
parent a764b5fa9c
commit 6ec0989283
2 changed files with 41 additions and 2 deletions

View file

@ -866,7 +866,9 @@ class EpcPropertyDataMapper:
# explicit flag); tariff → meter_type; wind turbines pass through.
sap_energy_source=SapEnergySource(
mains_gas=_sap_dwelling_on_mains_gas(schema),
meter_type=str(schema.sap_energy_source.electricity_tariff or ""),
meter_type=_sap_17_1_meter_type(
schema.sap_energy_source.electricity_tariff
),
pv_battery_count=0,
wind_turbines_count=schema.sap_energy_source.wind_turbines_count or 0,
gas_smart_meter_present=False,
@ -2943,7 +2945,21 @@ def _sap_17_1_meter_type(electricity_tariff: Optional[int]) -> str:
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 unknownstandard sentinel)."""
raise NotImplementedError(electricity_tariff)
if electricity_tariff is None:
return ""
return _SAP_TARIFF_TO_RDSAP_METER_TYPE.get(electricity_tariff, "")
# full-SAP `energy_tariff` code → RdSAP `meter_type` word alias (consumed by
# `tariff_from_meter_type` / `_METER_STR_TO_INT`). 10-hour (3) has no dedicated
# RdSAP meter code — it maps to "dual", and the §12 dispatch resolves 7-/10-hour
# from the heating system.
_SAP_TARIFF_TO_RDSAP_METER_TYPE: dict[int, str] = {
1: "single", # standard tariff
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
}
def _sap_17_1_heating(schema: SapSchema17_1) -> SapHeating:

View file

@ -156,6 +156,29 @@ class TestFullSapElectricityTariffTranslation:
assert tariff_from_meter_type(meter_type) is Tariff.SEVEN_HOUR
@pytest.mark.parametrize(
("energy_tariff", "expected"),
[
(1, "STANDARD"), # standard tariff → single-rate (was over-rated as E7)
(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)
(None, "STANDARD"), # absent/ND → unknown → standard
],
)
def test_energy_tariff_resolves_to_the_correct_calculator_tariff(
self, energy_tariff: Any, expected: str
) -> None:
from domain.sap10_calculator.tables.table_12a import (
tariff_from_meter_type,
)
from datatypes.epc.domain.mapper import _sap_17_1_meter_type
resolved = tariff_from_meter_type(_sap_17_1_meter_type(energy_tariff))
assert resolved.name == expected
class TestFromSapSchema17_1DisplayElements:
"""Display EnergyElements the WIP mapper dropped, leaving the FE