slice S-B16: RdSAP energy_tariff enum verified (1=dual, 2=Single, 3=Unknown)

Confirmed against the official RdSAP enum in
datatypes/epc/domain/epc_codes.csv:
  1 = dual                  (off-peak / Economy-7)
  2 = Single                (standard tariff)
  3 = Unknown               (verified against Elmhurst assessor software:
                             treated as Single)
  4 = dual (24 hour)        (off-peak)
  5 = off-peak 18 hour      (off-peak)

Different from the SAP-Schema enum (1=standard / 2=off-peak) — the
transform.py docstring referenced the SAP enum, not RdSAP. Our corpus
is RdSAP so we use the RdSAP codes.

This locks in the meter_type-based tariff selection from S-B15 with
the authoritative enum, replacing the earlier heating-code heuristic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-05-18 16:33:28 +00:00
parent 4c50c1b0fb
commit dae2a6f3fe

View file

@ -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