mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Charge the C6 half heat-network standing charge on a water-only dwelling's fuel cost worksheet 🟥
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cc84a091e6
commit
bd3a7ac317
2 changed files with 70 additions and 0 deletions
41
c6_cohort.py
Normal file
41
c6_cohort.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
"""Which 21.0.1-corpus certs are in #1606's C6 half-charge cohort?
|
||||
Cohort = WHC in {950,951,952} AND space main is NOT a heat network.
|
||||
"""
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datatypes.epc.domain.mapper import EpcPropertyDataMapper
|
||||
from datatypes.epc.domain.field_mappings import is_heat_network_main
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
||||
_first_main_heating, _heat_network_standing_charge_gbp,
|
||||
_WATER_HEAT_NETWORK_ONLY_CODES,
|
||||
)
|
||||
|
||||
path = Path("backend/epc_api/json_samples/RdSAP-Schema-21.0.1/corpus.jsonl")
|
||||
certs = [json.loads(l) for l in path.read_text().splitlines() if l.strip()]
|
||||
|
||||
hits = []
|
||||
for c in certs:
|
||||
epc = EpcPropertyDataMapper.from_api_response(c)
|
||||
whc = epc.sap_heating.water_heating_code if epc.sap_heating else None
|
||||
if whc not in _WATER_HEAT_NETWORK_ONLY_CODES:
|
||||
continue
|
||||
m1 = _first_main_heating(epc)
|
||||
net = is_heat_network_main(m1)
|
||||
hits.append({
|
||||
"rrn": c.get("rrn") or c.get("lmk_key"),
|
||||
"uprn": c.get("uprn"),
|
||||
"addr": (c.get("address1") or "")[:34],
|
||||
"whc": whc,
|
||||
"main_code": m1.sap_main_heating_code if m1 else None,
|
||||
"main_is_network": net,
|
||||
"net_standing": _heat_network_standing_charge_gbp(epc, m1),
|
||||
"in_C6_half_cohort": not net,
|
||||
})
|
||||
|
||||
print(f"WHC 950/951/952 certs in 21.0.1 corpus: {len(hits)}\n")
|
||||
for h in hits:
|
||||
flag = " <== C6 HALF COHORT" if h["in_C6_half_cohort"] else ""
|
||||
print(f" rrn={h['rrn']} uprn={h['uprn']}")
|
||||
print(f" addr={h['addr']!r} whc={h['whc']} main={h['main_code']} "
|
||||
f"network_main={h['main_is_network']} net_standing={h['net_standing']}{flag}")
|
||||
print(f"\nIn C6 half cohort: {sum(h['in_C6_half_cohort'] for h in hits)}")
|
||||
|
|
@ -68,6 +68,7 @@ from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
|||
_mev_default_data_iuf, # pyright: ignore[reportPrivateUsage]
|
||||
_TABLE_4G_DEFAULT_MEV_SFP_W_PER_L_PER_S, # pyright: ignore[reportPrivateUsage]
|
||||
dimensions_from_cert,
|
||||
fuel_cost_section_from_cert,
|
||||
_table_12_factor_fuel_code, # pyright: ignore[reportPrivateUsage]
|
||||
_table_12a_system_for_main, # pyright: ignore[reportPrivateUsage]
|
||||
_is_electric_main, # pyright: ignore[reportPrivateUsage]
|
||||
|
|
@ -9160,6 +9161,34 @@ def test_water_only_heat_network_half_charge_adds_to_the_dwellings_fuel_standing
|
|||
assert abs(total - 84.0) <= 1e-9
|
||||
|
||||
|
||||
def test_water_only_heat_network_half_charge_reaches_the_fuel_cost_worksheet() -> None:
|
||||
# Arrange — the §C6 half charge must reach worksheet (251), not just the
|
||||
# helper. A gas-boiler main (SAP 102, not a network) with WHC 950 keeps the
|
||||
# dwelling on the STANDARD tariff, so `_fuel_cost` returns the real
|
||||
# (240)..(255) result rather than the off-peak zero sentinel.
|
||||
#
|
||||
# Table 12 note (a): "The standing charge for gas fuels is added to space
|
||||
# and water heating costs where the gas fuel is used for space heating" →
|
||||
# Table 32 code 1 = £120. Plus the C6 half (£60) = £180.
|
||||
from dataclasses import replace
|
||||
|
||||
base = _typical_semi_detached_epc()
|
||||
epc = replace(
|
||||
base,
|
||||
sap_heating=make_sap_heating(
|
||||
main_heating_details=[_gas_boiler_detail(sap_main_heating_code=102)],
|
||||
water_heating_code=950, # DHW-only heat network (boilers)
|
||||
),
|
||||
)
|
||||
|
||||
# Act
|
||||
fc = fuel_cost_section_from_cert(epc)
|
||||
|
||||
# Assert
|
||||
assert fc is not None
|
||||
assert abs(fc.additional_standing_charges_gbp - 180.0) <= 1e-9
|
||||
|
||||
|
||||
def test_mev_default_data_iuf_is_table_329_system_type_10_value() -> None:
|
||||
# Arrange / Act — SAP 10.2 Table 4g note 3 (PDF p.176) directs the
|
||||
# default SFP to "the appropriate in-use factor for default data from
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue