diff --git a/packages/domain/src/domain/sap/rdsap/cert_to_inputs.py b/packages/domain/src/domain/sap/rdsap/cert_to_inputs.py index b08b718c..b2fa1e63 100644 --- a/packages/domain/src/domain/sap/rdsap/cert_to_inputs.py +++ b/packages/domain/src/domain/sap/rdsap/cert_to_inputs.py @@ -365,27 +365,39 @@ def _fuel_cost_gbp_per_kwh( return prices.unit_price_p_per_kwh(_main_fuel_code(main)) * _PENCE_TO_GBP +# RdSAP energy_tariff enum (per datatypes/epc/domain/epc_codes.csv): +# 1 = dual (off-peak / Economy-7) +# 2 = Single (standard tariff) +# 3 = Unknown (treated as Single — verified against +# Elmhurst assessor software with one +# real property; SAP assessor behavior is +# to default Unknown tariffs to Single) +# 4 = dual (24 hour) (off-peak / 24h heating) +# 5 = off-peak 18 hour (off-peak) +# +# Different from the SAP-Schema enum which is 1=standard, 2=off-peak. +# Our corpus is RdSAP so we use RdSAP codes. +_RDSAP_OFF_PEAK_METER_CODES: Final[frozenset[int]] = frozenset({1, 4, 5}) + + def _is_off_peak_meter(meter_type: object) -> bool: - """The cert's `sap_energy_source.meter_type` reports the electricity - tariff. SAP10 enum (verified empirically on the 250k corpus — - distribution: 75% type 2, 14% type 1, 11% type 3): - 1 = Off-peak (Economy-7 / dual) - 2 = Single (Standard) - 3 = Off-peak (24h heating) - The transform.py docstring describes 1=Standard / 2=Off-peak but the - corpus distribution rules that out (75% on off-peak would not match - UK demographics). Per user guidance we trust whatever meter_type the - cert lodges, but the mapping is to-be-confirmed against the SAP10 - schema definition.""" + """True when the cert's `sap_energy_source.meter_type` lodges an + off-peak / dual-rate tariff per the RdSAP enum (codes 1, 4, 5). + Unknown (3) defaults to standard since that's the cert software's + behaviour. Trusts whatever meter_type the cert lodges regardless of + whether the heating system makes that tariff "natural" — per user + guidance the cert's lodged meter_type is the source of truth.""" if meter_type is None: return False if isinstance(meter_type, int): - return meter_type != 2 + return meter_type in _RDSAP_OFF_PEAK_METER_CODES if isinstance(meter_type, str): stripped = meter_type.strip().lower() - if stripped in {"single", "standard", "2"}: - return False - return stripped not in {"", "unknown", "not specified"} + if stripped in {"dual", "off-peak", "1", "4", "5"}: + return True + if stripped in {"dual (24 hour)", "off-peak 18 hour"}: + return True + return False return False