Model/backend/documents_parser/tests
Khalim Conn-Kowlessar e3abe9b2b5 Slice S0380.103: MEV fans cost split via Table 12a Grid 2 FANS_FOR_MECH_VENT rate (SAP 10.2 Table 12a)
SAP 10.2 Table 12a Grid 2 (PDF p.191) splits off-peak electricity
costs into two categories:

  Other electricity uses                       Tariff    Fraction at
                                                          high rate
  Fans for mechanical ventilation systems      7-hour    0.71
                                              10-hour    0.58
  All other uses, and locally generated        7-hour    0.90
  electricity                                 10-hour    0.80

Cert 000565 (Dual meter, 10-hour off-peak, MEV decentralised) lodges
127.5159 kWh of MEV-fan electricity (line 230a) that bills at the
`FANS_FOR_MECH_VENT` blend (0.58 × 14.68 + 0.42 × 7.50 = 11.6644
p/kWh), distinct from the 125 kWh of other pumps_fans (45 kWh gas-
boiler flue fan + 80 kWh solar HW pump) which bills at the
`ALL_OTHER_USES` blend (0.80 × 14.68 + 0.20 × 7.50 = 13.2440 p/kWh).

Pre-slice the cascade applied `ALL_OTHER_USES` to ALL 252.5159 kWh,
over-counting MEV cost by 127.5159 × (0.13244 - 0.11664) = +£2.01/yr.

Worksheet pin verification (line (249)):
  "Pumps, fans and electric keep-hot ... 172.5159  13.2440  20.8338"
  127.5159 × 0.11664 + 45 × 0.13244 = £14.8753 + £5.9598 = £20.8351
  ≈ ws £20.8338 ✓
  Pump for solar water heating 80.0 × 0.13244 = £10.5952 ✓

Implementation (3-layer):
1. `calculator.py:CalculatorInputs` — new optional
   `pumps_fans_fuel_cost_gbp_per_kwh: Optional[float] = None`.
2. `calculator.py` legacy cost path — `pumps_fans_cost` resolves
   via the new field with fallback to `other_fuel_cost_gbp_per_kwh`.
3. `cert_to_inputs.py:_pumps_fans_fuel_cost_gbp_per_kwh` — computes
   the kWh-weighted blended rate when off-peak + MEV is lodged.
   Reuses `_mev_decentralised_kwh_per_yr_from_cert` (S0380.102) to
   recover the MEV portion.

Cohort safety: STANDARD-tariff certs (the entire cohort except cert
000565) get None back → existing `other_fuel_cost_gbp_per_kwh`
fallback unchanged. Certs without MEV (zero MEV kWh) also get None
→ no behavioural change.

Movement at HEAD (cert 000565):
- pumps_fans_kwh_per_yr ✓ EXACT (unchanged)
- total_fuel_cost_gbp: 4680.6514 → 4678.6372  (Δ +£0.39 → -£1.62)
- ecf: 5.3873 → 5.3850 (Δ +0.0007 → -0.0016)
- sap_score_continuous: 28.5043 → 28.5269 (Δ -0.0044 → +0.0182)

Continuous-SAP residual drifted from -0.0044 to +0.0182 in absolute
value: closing the MEV cost over-count exposes a pre-existing
space-heating cascade under-count (main_heating_fuel_kwh is -16 kWh
under ws). Per user direction [[feedback-spec-floor-skepticism]]:
shipping spec-correct intermediate-value fixes even when they
transiently drift continuous SAP. The remaining residual is now
SH-cascade driven; a separate slice.

Test count: 597 pass + 7 expected 000565 fails unchanged.

Pyright net-zero per touched file.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 16:07:55 +00:00
..
fixtures Slice S0380.52: cert 000565 Elmhurst-only mapper-driven cascade pin + glazing-label coverage 2026-05-28 22:03:52 +00:00
__init__.py Map to RdSapSiteNotes from site notes JSON 🟥 2026-04-16 13:54:03 +00:00
test_elmhurst_end_to_end.py Slice S0380.17: map Elmhurst §11 glazing-type labels to SAP10 codes 2026-05-27 23:05:52 +00:00
test_elmhurst_extractor.py extract window frame details from elmhurst site notes 🟥 2026-04-27 15:50:25 +00:00
test_end_to_end.py P6.1 follow-on: unbox BuildingPartIdentifier at backend boundaries 2026-05-20 09:58:23 +00:00
test_extractor.py Handle wall thickness "Unmeasurable" 🟩 2026-04-30 16:41:16 +00:00
test_pdf.py rename example site notes to PasHub_ and add Elmhurst example 2026-04-24 13:01:51 +00:00
test_summary_pdf_mapper_chain.py Slice S0380.103: MEV fans cost split via Table 12a Grid 2 FANS_FOR_MECH_VENT rate (SAP 10.2 Table 12a) 2026-05-30 16:07:55 +00:00