mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
fix(ventilation): map API mechanical_ventilation_index_number for MEV fan electricity
Follow-up to the §2 MV-kind slice. Once MEV dwellings stopped under-stating their ventilation HEAT loss, a +0.9 SAP over-rate residual remained — the MEV FAN ELECTRICITY (§5 Table 4f line (230a), `SFPav × 1.22 × V`, PCDB Tables 322 decentralised-MEV + 329 in-use factors). `_mev_decentralised_kwh_per_yr_from_cert` already composes it, but reads `epc.mechanical_ventilation_index_number` + `epc.mechanical_vent_duct_type`, and the API builder (`from_rdsap_schema_21_0_1`) never set either — so `pcdf_id is None` short-circuited the fan energy to 0 on every API cert (the Summary/ Elmhurst path set them, so cert 000565 already billed it). Wire both schema fields through the 21.0.1 API construction (the corpus schema). Eval: the 9 MEV certs carrying a PCDB index closed +0.90 -> +0.13 signed (fan electricity now billed); headline within-0.5 55.01% -> 55.12%, mean|err| 1.233 -> 1.232, 909 computed / 0 raises. Only those 9 certs move (clean diff). The 11 index-less MEV certs still sit at +1.36 — they need the SAP Table 4h DEFAULT specific fan power (no PCDB record), a separate slice. New end-to-end test + fixture (cert 1300, Titon-class dMEV index 500777, Flexible duct): from_api_response preserves the index + duct type and (230a) resolves to a positive fan-energy contribution. Goldens + full calc/epc regression green; pyright net-zero. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
dfba20babf
commit
e7af6fda66
3 changed files with 38 additions and 0 deletions
|
|
@ -1559,6 +1559,18 @@ class EpcPropertyDataMapper:
|
|||
open_chimneys_count=schema.open_chimneys_count,
|
||||
insulated_door_count=schema.insulated_door_count,
|
||||
draughtproofed_door_count=schema.draughtproofed_door_count,
|
||||
# Mechanical ventilation PCDB plumbing — feeds the §5 Table 4f
|
||||
# line (230a) decentralised-MEV fan electricity
|
||||
# (`SFPav × 1.22 × V`, PCDB Tables 322/329). Without the index
|
||||
# the cascade's `_mev_decentralised_kwh_per_yr_from_cert`
|
||||
# short-circuits to 0, leaving the MEV fan running cost off the
|
||||
# bill (the +0.9 SAP over-rate residual on the MEV cohort once
|
||||
# the §2 ventilation heat-loss was fixed). Duct type selects the
|
||||
# Table 329 in-use factor (1=Flexible / 2=Rigid).
|
||||
mechanical_ventilation_index_number=(
|
||||
schema.mechanical_ventilation_index_number
|
||||
),
|
||||
mechanical_vent_duct_type=schema.mechanical_vent_duct_type,
|
||||
# Lighting
|
||||
led_fixed_lighting_bulbs_count=schema.led_fixed_lighting_bulbs_count,
|
||||
cfl_fixed_lighting_bulbs_count=schema.cfl_fixed_lighting_bulbs_count,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -983,6 +983,31 @@ def test_api_to_domain_mapper_preserves_main_heating_index_number(
|
|||
assert abs(inputs.main_heating_efficiency - expected_winter_eff) <= 1e-3
|
||||
|
||||
|
||||
def test_api_mapper_preserves_mechanical_ventilation_pcdb_index_for_mev_fan_energy() -> None:
|
||||
# Arrange — cert 1300 is a decentralised-MEV dwelling
|
||||
# (mechanical_ventilation=2) lodging a PCDB index (500777) + duct type
|
||||
# (1=Flexible). The API path previously DROPPED
|
||||
# `mechanical_ventilation_index_number`, so the §5 Table 4f line (230a)
|
||||
# MEV fan electricity (`SFPav × 1.22 × V`, PCDB Tables 322/329)
|
||||
# short-circuited to 0 in `_mev_decentralised_kwh_per_yr_from_cert` —
|
||||
# leaving the fan running cost off the bill (+0.9 SAP over-rate residual
|
||||
# on the MEV cohort once the §2 ventilation heat loss was fixed).
|
||||
from domain.sap10_calculator.rdsap.cert_to_inputs import (
|
||||
_mev_decentralised_kwh_per_yr_from_cert, # pyright: ignore[reportPrivateUsage]
|
||||
)
|
||||
|
||||
doc = _load_cert("1300-7634-0922-3203-3563")
|
||||
|
||||
# Act
|
||||
epc = EpcPropertyDataMapper.from_api_response(doc)
|
||||
|
||||
# Assert — the PCDB pointer + duct type survive the API mapping, and the
|
||||
# (230a) MEV fan electricity resolves to a positive contribution.
|
||||
assert epc.mechanical_ventilation_index_number == 500777
|
||||
assert epc.mechanical_vent_duct_type == 1
|
||||
assert _mev_decentralised_kwh_per_yr_from_cert(epc) > 0.0
|
||||
|
||||
|
||||
def test_0240_api_wall_type_4_windows_map_to_roof_windows() -> None:
|
||||
"""Cert 0240 lodges 6 windows with `window_wall_type=4` — the RdSAP
|
||||
API code for a roof window ("Roof of Room" rooflight / inclined
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue