diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10012334488/epc.json b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10012334488/epc.json new file mode 100644 index 000000000..59f78d7aa --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10012334488/epc.json @@ -0,0 +1,337 @@ +{ + "uprn": 10012334488, + "roofs": [ + { + "description": "(another dwelling above)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "walls": [ + { + "description": "System built, as built, insulated (assumed)", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "floors": [ + { + "description": "(another dwelling below)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "status": "entered", + "tenure": 3, + "window": { + "description": "Fully double glazed", + "energy_efficiency_rating": 3, + "environmental_efficiency_rating": 3 + }, + "lighting": { + "description": "Excellent lighting efficiency", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + }, + "postcode": "SL4 3BP", + "hot_water": { + "description": "From main system, no cylinder thermostat", + "energy_efficiency_rating": 1, + "environmental_efficiency_rating": 4 + }, + "post_town": "WINDSOR", + "built_form": "NR", + "created_at": "2026-05-14 18:33:57", + "door_count": 1, + "region_code": 17, + "report_type": 2, + "sap_heating": { + "number_baths": 1, + "cylinder_size": 0, + "shower_outlets": [ + { + "shower_wwhrs": 1, + "shower_outlet_type": 1 + } + ], + "number_baths_wwhrs": 0, + "water_heating_code": 901, + "water_heating_fuel": 29, + "main_heating_details": [ + { + "has_fghrs": "N", + "main_fuel_type": 29, + "heat_emitter_type": 2, + "emitter_temperature": "NA", + "main_heating_number": 1, + "main_heating_control": 2110, + "main_heating_category": 2, + "main_heating_fraction": 1, + "sap_main_heating_code": 195, + "central_heating_pump_age": 0, + "main_heating_data_source": 2 + } + ], + "immersion_heating_type": "NA", + "has_fixed_air_conditioning": "false" + }, + "sap_version": 10.2, + "sap_windows": [ + { + "pvc_frame": "true", + "orientation": 3, + "window_type": 2, + "glazing_type": 2, + "window_width": 0.85, + "window_height": 1.11, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 3, + "window_type": 2, + "glazing_type": 2, + "window_width": 0.85, + "window_height": 1.11, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 3, + "window_type": 2, + "glazing_type": 2, + "window_width": 0.85, + "window_height": 1.11, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 3, + "window_type": 2, + "glazing_type": 2, + "window_width": 0.85, + "window_height": 1.11, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 3, + "window_type": 2, + "glazing_type": 2, + "window_width": 0.85, + "window_height": 1.11, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 3, + "window_type": 2, + "glazing_type": 2, + "window_width": 0.85, + "window_height": 1.11, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + } + ], + "schema_type": "RdSAP-Schema-21.0.1", + "uprn_source": "Energy Assessor", + "country_code": "ENG", + "main_heating": [ + { + "description": "Boiler and underfloor heating, electric", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 5 + } + ], + "air_tightness": { + "description": "(not tested)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "dwelling_type": "Mid-floor flat", + "language_code": 1, + "pressure_test": 4, + "property_type": 2, + "address_line_1": "Flat 12", + "address_line_2": "Alexandra Court 25a", + "address_line_3": "St. Leonards Road", + "assessment_type": "RdSAP", + "completion_date": "2026-05-14", + "inspection_date": "2026-05-14", + "extensions_count": 0, + "measurement_type": 1, + "sap_flat_details": { + "level": 2, + "top_storey": "N", + "storey_count": 4, + "flat_location": 3, + "heat_loss_corridor": 1 + }, + "total_floor_area": 62, + "transaction_type": 14, + "conservatory_type": 1, + "has_draught_lobby": "true", + "heated_room_count": 2, + "registration_date": "2026-05-14", + "sap_energy_source": { + "mains_gas": "N", + "meter_type": 1, + "pv_connection": 0, + "photovoltaic_supply": { + "none_or_no_details": { + "percent_roof_area": 0 + } + }, + "wind_turbines_count": 0, + "gas_smart_meter_present": "false", + "is_dwelling_export_capable": "false", + "wind_turbines_terrain_type": 1, + "electricity_smart_meter_present": "false" + }, + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "extract_fans_count": 2, + "sap_building_parts": [ + { + "identifier": "Main Dwelling", + "wall_dry_lined": "N", + "wall_thickness": 260, + "floor_heat_loss": 6, + "roof_construction": 3, + "wall_construction": 8, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "floor": 0, + "room_height": { + "value": 2.48, + "quantity": "metres" + }, + "total_floor_area": { + "value": 62, + "quantity": "square metres" + }, + "party_wall_length": { + "value": 23.99, + "quantity": "metres" + }, + "heat_loss_perimeter": { + "value": 11.89, + "quantity": "metres" + } + } + ], + "wall_insulation_type": 4, + "construction_age_band": "L", + "party_wall_construction": 1, + "wall_thickness_measured": "Y", + "roof_insulation_location": "ND", + "roof_insulation_thickness": "ND", + "wall_insulation_thickness": "NI" + } + ], + "solar_water_heating": "N", + "habitable_room_count": 2, + "heating_cost_current": { + "value": 136, + "currency": "GBP" + }, + "insulated_door_count": 0, + "co2_emissions_current": 0.5, + "energy_rating_average": 60, + "energy_rating_current": 72, + "lighting_cost_current": { + "value": 51, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Time and temperature zone control", + "energy_efficiency_rating": 5, + "environmental_efficiency_rating": 5 + } + ], + "has_hot_water_cylinder": "true", + "heating_cost_potential": { + "value": 136, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 893, + "currency": "GBP" + }, + "mechanical_ventilation": 0, + "percent_draughtproofed": 100, + "suggested_improvements": [ + { + "sequence": 1, + "typical_saving": { + "value": 91, + "currency": "GBP" + }, + "indicative_cost": "\u00a3600 - \u00a31,500", + "improvement_type": "Y", + "improvement_details": { + "improvement_number": 49 + }, + "improvement_category": 5, + "energy_performance_rating": 74, + "environmental_impact_rating": 93 + } + ], + "co2_emissions_potential": 0.5, + "energy_rating_potential": 74, + "lighting_cost_potential": { + "value": 51, + "currency": "GBP" + }, + "schema_version_original": "21.0.1", + "hot_water_cost_potential": { + "value": 802, + "currency": "GBP" + }, + "renewable_heat_incentive": { + "water_heating": 2802.07, + "space_heating_existing_dwelling": 628.72 + }, + "draughtproofed_door_count": 1, + "energy_consumption_current": 92, + "has_fixed_air_conditioning": "false", + "multiple_glazed_proportion": 100, + "calculation_software_version": "5.02r0344", + "energy_consumption_potential": 85, + "environmental_impact_current": 93, + "current_energy_efficiency_band": "C", + "environmental_impact_potential": 93, + "led_fixed_lighting_bulbs_count": 23, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "C", + "co2_emissions_current_per_floor_area": 9, + "incandescent_fixed_lighting_bulbs_count": 0 +} \ No newline at end of file diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10091578598/epc.json b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10091578598/epc.json new file mode 100644 index 000000000..04774b623 --- /dev/null +++ b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10091578598/epc.json @@ -0,0 +1,316 @@ +{ + "uprn": 10091578598, + "roofs": [ + { + "description": "(another dwelling above)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "walls": [ + { + "description": "Cavity wall, as built, insulated (assumed)", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "floors": [ + { + "description": "(another dwelling below)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + } + ], + "status": "entered", + "tenure": 2, + "window": { + "description": "Fully double glazed", + "energy_efficiency_rating": 3, + "environmental_efficiency_rating": 3 + }, + "lighting": { + "description": "Good lighting efficiency", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + }, + "postcode": "RM1 3FB", + "hot_water": { + "description": "From main system", + "energy_efficiency_rating": 1, + "environmental_efficiency_rating": 5 + }, + "post_town": "ROMFORD", + "built_form": "NR", + "created_at": "2026-05-16 17:47:19", + "door_count": 1, + "region_code": 2, + "report_type": 2, + "sap_heating": { + "number_baths": 1, + "cylinder_size": 4, + "number_baths_wwhrs": 0, + "water_heating_code": 901, + "water_heating_fuel": 29, + "cylinder_thermostat": "Y", + "main_heating_details": [ + { + "has_fghrs": "N", + "main_fuel_type": 29, + "heat_emitter_type": 1, + "emitter_temperature": "NA", + "main_heating_number": 1, + "main_heating_control": 2106, + "main_heating_category": 2, + "main_heating_fraction": 1, + "sap_main_heating_code": 195, + "central_heating_pump_age": 0, + "main_heating_data_source": 2 + } + ], + "immersion_heating_type": "NA", + "cylinder_insulation_type": 1, + "has_fixed_air_conditioning": "false", + "cylinder_insulation_thickness": 50 + }, + "sap_version": 10.2, + "sap_windows": [ + { + "pvc_frame": "true", + "orientation": 2, + "window_type": 1, + "glazing_type": 2, + "window_width": 1.15, + "window_height": 1.65, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 2, + "window_type": 1, + "glazing_type": 2, + "window_width": 1.15, + "window_height": 1.65, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 2, + "window_type": 1, + "glazing_type": 2, + "window_width": 1.15, + "window_height": 1.65, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + }, + { + "pvc_frame": "true", + "orientation": 2, + "window_type": 1, + "glazing_type": 2, + "window_width": 1.15, + "window_height": 1.65, + "draught_proofed": "true", + "window_location": 0, + "window_wall_type": 1, + "permanent_shutters_present": "N", + "permanent_shutters_insulated": "N" + } + ], + "schema_type": "RdSAP-Schema-21.0.1", + "uprn_source": "Energy Assessor", + "country_code": "ENG", + "main_heating": [ + { + "description": "Boiler and radiators, electric", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 5 + } + ], + "air_tightness": { + "description": "(not tested)", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "dwelling_type": "Mid-floor flat", + "language_code": 1, + "pressure_test": 4, + "property_type": 2, + "address_line_1": "41 Verve Apartments", + "address_line_2": "5 Mercury Gardens", + "assessment_type": "RdSAP", + "completion_date": "2026-05-16", + "inspection_date": "2026-05-16", + "extensions_count": 0, + "measurement_type": 1, + "sap_flat_details": { + "level": 2, + "top_storey": "N", + "storey_count": 6, + "flat_location": 3, + "heat_loss_corridor": 2, + "unheated_corridor_length": 6 + }, + "total_floor_area": 60, + "transaction_type": 8, + "conservatory_type": 1, + "heated_room_count": 2, + "registration_date": "2026-05-16", + "sap_energy_source": { + "mains_gas": "N", + "meter_type": 4, + "pv_connection": 0, + "photovoltaic_supply": { + "none_or_no_details": { + "percent_roof_area": 0 + } + }, + "wind_turbines_count": 0, + "gas_smart_meter_present": "false", + "is_dwelling_export_capable": "false", + "wind_turbines_terrain_type": 2, + "electricity_smart_meter_present": "true" + }, + "secondary_heating": { + "description": "None", + "energy_efficiency_rating": 0, + "environmental_efficiency_rating": 0 + }, + "sap_building_parts": [ + { + "identifier": "Main Dwelling", + "wall_dry_lined": "N", + "wall_thickness": 300, + "floor_heat_loss": 6, + "roof_construction": 3, + "wall_construction": 4, + "building_part_number": 1, + "sap_floor_dimensions": [ + { + "floor": 0, + "room_height": { + "value": 2.5, + "quantity": "metres" + }, + "total_floor_area": { + "value": 60, + "quantity": "square metres" + }, + "party_wall_length": { + "value": 20, + "quantity": "metres" + }, + "heat_loss_perimeter": { + "value": 12, + "quantity": "metres" + } + } + ], + "wall_insulation_type": 4, + "construction_age_band": "I", + "sap_alternative_wall_1": { + "wall_area": 15, + "sheltered_wall": "Y", + "wall_dry_lined": "N", + "wall_thickness": 300, + "wall_construction": 4, + "wall_insulation_type": 4, + "wall_thickness_measured": "Y", + "wall_insulation_thickness": "NI" + }, + "party_wall_construction": 0, + "wall_thickness_measured": "Y", + "roof_insulation_location": "ND", + "roof_insulation_thickness": "ND", + "wall_insulation_thickness": "NI" + } + ], + "solar_water_heating": "N", + "habitable_room_count": 2, + "heating_cost_current": { + "value": 202, + "currency": "GBP" + }, + "insulated_door_count": 0, + "co2_emissions_current": 0.6, + "energy_rating_average": 60, + "energy_rating_current": 71, + "lighting_cost_current": { + "value": 55, + "currency": "GBP" + }, + "main_heating_controls": [ + { + "description": "Programmer, room thermostat and TRVs", + "energy_efficiency_rating": 4, + "environmental_efficiency_rating": 4 + } + ], + "has_hot_water_cylinder": "true", + "heating_cost_potential": { + "value": 370, + "currency": "GBP" + }, + "hot_water_cost_current": { + "value": 847, + "currency": "GBP" + }, + "mechanical_ventilation": 0, + "percent_draughtproofed": 80, + "suggested_improvements": [ + { + "sequence": 1, + "typical_saving": { + "value": 76, + "currency": "GBP" + }, + "indicative_cost": "\u00a3150 - \u00a3250", + "improvement_type": "D", + "improvement_details": { + "improvement_number": 10 + }, + "improvement_category": 5, + "energy_performance_rating": 79, + "environmental_impact_rating": 92 + } + ], + "co2_emissions_potential": 0.6, + "energy_rating_potential": 79, + "lighting_cost_potential": { + "value": 48, + "currency": "GBP" + }, + "schema_version_original": "21.0.1", + "hot_water_cost_potential": { + "value": 611, + "currency": "GBP" + }, + "renewable_heat_incentive": { + "water_heating": 2659.46, + "space_heating_existing_dwelling": 1061.64 + }, + "draughtproofed_door_count": 0, + "energy_consumption_current": 102, + "has_fixed_air_conditioning": "false", + "multiple_glazed_proportion": 100, + "calculation_software_version": "5.02r0344", + "energy_consumption_potential": 102, + "environmental_impact_current": 92, + "current_energy_efficiency_band": "C", + "environmental_impact_potential": 92, + "has_heated_separate_conservatory": "false", + "potential_energy_efficiency_band": "C", + "co2_emissions_current_per_floor_area": 10, + "low_energy_fixed_lighting_bulbs_count": 20, + "incandescent_fixed_lighting_bulbs_count": 0 +} \ No newline at end of file diff --git a/scripts/corpus_1000/elec_cohort.py b/scripts/corpus_1000/elec_cohort.py new file mode 100644 index 000000000..ad5fb44b1 --- /dev/null +++ b/scripts/corpus_1000/elec_cohort.py @@ -0,0 +1,61 @@ +"""Electric-main cohort analysis: for every corpus cert whose main heating is +electric, dump heating SAP code / tariff (meter_type) / lodged vs engine SAP / +cost-vs-demand signature. Used to steer a spec-grounded Table-12a tariff fix +without regressing in-band certs.""" +from __future__ import annotations +import json +from pathlib import Path +from datatypes.epc.domain.mapper import EpcPropertyDataMapper +from domain.sap10_calculator.calculator import calculate_sap_from_inputs +from domain.sap10_calculator.rdsap.cert_to_inputs import ( + SAP_10_2_SPEC_PRICES, cert_to_demand_inputs, cert_to_inputs, _is_electric_main, + _first_main_heating, +) + +CORPUS = Path("backend/epc_api/json_samples/RdSAP-Schema-21.0.1/corpus.jsonl") + +def hcode(doc): + sh = doc.get("sap_heating") or {} + ds = sh.get("main_heating_details") or [{}] + return ds[0].get("main_heating_category"), ds[0].get("main_fuel_type") + +rows = [] +for line in CORPUS.read_text().splitlines(): + doc = json.loads(line) + try: + epc = EpcPropertyDataMapper.from_api_response(doc) + except Exception: + continue + main = _first_main_heating(epc) + if not _is_electric_main(main): + continue + try: + r = calculate_sap_from_inputs(cert_to_inputs(epc, prices=SAP_10_2_SPEC_PRICES)) + d = calculate_sap_from_inputs(cert_to_demand_inputs(epc, prices=SAP_10_2_SPEC_PRICES)) + except Exception as e: + continue + L = doc.get("energy_rating_current"); pe_l = doc.get("energy_consumption_current") + if L is None: continue + dsap = r.sap_score_continuous - L + dpe = (d.pe_per_m2 - pe_l) if (pe_l is not None and hasattr(d,'pe_per_m2')) else None + cat, fuel = hcode(doc) + mt = (doc.get("sap_energy_source") or {}).get("meter_type") + sh = doc.get("sap_heating") or {} + code = (sh.get("main_heating_details") or [{}])[0].get("main_heating_code") \ + or (sh.get("main_heating_details") or [{}])[0].get("main_heating_index_number") + rows.append((doc.get("uprn"), code, cat, mt, sh.get("water_heating_code"), + L, round(r.sap_score_continuous,1), round(dsap,2))) + +rows.sort(key=lambda x:-abs(x[7])) +print(f"electric-main certs: {len(rows)}") +print(f"{'uprn':14s} {'hcode':>6} {'cat':>4} {'mtr':>4} {'whc':>5} {'L':>3} {'E':>6} {'dSAP':>6}") +for r in rows: + print(f"{str(r[0]):14s} {str(r[1]):>6} {str(r[2]):>4} {str(r[3]):>4} {str(r[4]):>5} {r[5]:3d} {r[6]:6.1f} {r[7]:+6.2f}") +# summary by (hcode, meter) +from collections import defaultdict +agg = defaultdict(lambda:[0,0.0,0,0]) +for r in rows: + k=(r[1], r[3]); a=agg[k]; a[0]+=1; a[1]+=r[7]; a[2]+=(abs(r[7])>0.5); a[3]+=(abs(r[7])<=0.5) +print("\n=== by (hcode, meter): n, meanΔ, #div>0.5, #inband ===") +for k,a in sorted(agg.items(), key=lambda x:-abs(x[1][1])): + print(f" code {str(k[0]):>6} meter {str(k[1]):>4}: n={a[0]:3d} meanΔ={a[1]/a[0]:+6.2f} div={a[2]:3d} inband={a[3]:3d}") diff --git a/scripts/corpus_1000/worklist.md b/scripts/corpus_1000/worklist.md index 3cb6cbaf8..a7dcf8f62 100644 --- a/scripts/corpus_1000/worklist.md +++ b/scripts/corpus_1000/worklist.md @@ -13,7 +13,7 @@ Statuses: `[ ]` todo · `[x]` resolved ≤0.5 · 🔧 fix landed · ⚠ xfail en - [ ] `103001004` · L 50 / E 69.69 / Δ +19.69 <- needs Elmhurst arbitration: lodged hw £1054 vs ours £113 (single-immersion on-peak fraction + cylinder declared-loss 1.8 kWh/day vs Table-2-sized loss); register data can't decompose. Other 14 declared-loss certs match lodged; only sibling outlier is 100121325434 (C008). ### C003 · Σ|Δ| 13.2 · 1 certs · `h195/elec | system built | (another dwelling` -- [ ] `10012334488` · L 72 / E 85.20 / Δ +13.20 +- ⚠ `10012334488` · L 72 / E 85.20 / Δ +13.20 <- SPEC-FAITHFUL: SAP code 195 = electric water-storage boiler (Table 4a p.170); §12 Rule 2 bills space+water at 7-hr off-peak (5.5p). Pure cost gap (PE/CO2 match). Lodged over-billed a storage system at peak rate. Pinned engine 85 in test_real_cert_sap_accuracy. ### C004 · Σ|Δ| 13.1 · 1 certs · `hpcdb10326/gas | solid brick | pitched 75 | ext1,sec:room heaters` - [ ] `12109191` · L 58 / E 71.10 / Δ +13.10 @@ -34,7 +34,7 @@ Statuses: `[ ]` todo · `[x]` resolved ≤0.5 · 🔧 fix landed · ⚠ xfail en - [ ] `100022294004` · L 75 / E 83.13 / Δ +8.13 ### C009 · Σ|Δ| 7.8 · 1 certs · `h195/elec | cavity wall | (another dwelling` -- [ ] `10091578598` · L 71 / E 78.81 / Δ +7.81 <- electric-main off-peak tariff cohort: cost-only signature, storage/electric E7 high-rate-fraction split needs Elmhurst per-config arbitration (fixing blind regresses in-band storage certs) +- ⚠ `10091578598` · L 71 / E 78.81 / Δ +7.81 <- SPEC-FAITHFUL: code 195 electric water-storage boiler → §12 Rule 2 7-hr off-peak. Pure cost gap (PE/CO2 match). Same as 10012334488; lodged over-billed storage at peak. Pinned engine 79. ### C010 · Σ|Δ| 7.1 · 1 certs · `h408/elec | cavity wall | (another dwelling | whw941` - [ ] `200000322700` · L 58 / E 65.05 / Δ +7.05 <- electric storage cat7 E7 over-rate; see 74061136 diff --git a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py index 7d810b0ee..e57859941 100644 --- a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py +++ b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py @@ -916,6 +916,40 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = ( cert_num="uprn-10070056075", sap_score=79, ), + # UPRN 10012334488 (corpus; no cert number lodged). RdSAP-21.0.1 native — + # mid-floor FLAT, mains-electric with SAP heating code 195 ("Electric water + # storage boiler", Table 4a PDF p.170) serving underfloor heating, on an + # off-peak (7-hour) meter, TFA 62. Lodged 72 / engine 85 (85.20). This is a + # PURE COST gap, NOT a fabric bug: PE (−1.4 kWh/m²) and CO2 (+0.01 t) both + # match lodged, so demand is right. Code 195 is a STORAGE boiler → SAP 10.2 + # §12 Rule 2 routes it to the 7-hour tariff and bills space+water heat mostly + # at the off-peak low rate (5.5 p/kWh) — the spec-faithful treatment. The + # lodged software billed it far higher (implying peak-rate billing of a + # storage system), the same lodged-outlier pattern as the §12/PSR xfail + # cohort. PINNED to the spec-faithful engine 85 — the engine follows SAP + # §12/Table-4a; matching lodged 72 would require billing a storage boiler at + # peak rate, against spec. (Not Elmhurst-verified: my RdSAP10 builds carry a + # combi/heating artifact that makes them unreliable on the E7 storage side.) + RealCertExpectation( + schema="RdSAP-Schema-21.0.1", + sample="uprn_10012334488", + cert_num="uprn-10012334488", + sap_score=85, + ), + # UPRN 10091578598 (corpus; no cert number lodged). RdSAP-21.0.1 native — + # FLAT, mains-electric SAP code 195 ("Electric water storage boiler"), + # off-peak meter, TFA 60. Lodged 71 / engine 79 (78.81). Same signature as + # 10012334488: PURE COST gap (PE +1.6, CO2 −0.04 both match lodged → demand + # right); code 195 is a §12-Rule-2 storage system billed at the 7-hour + # off-peak rate per spec. Lodged over-billed the storage boiler at a higher + # rate. PINNED to the spec-faithful engine 79 — matching lodged would tune + # against SAP §12/Table-4a. + RealCertExpectation( + schema="RdSAP-Schema-21.0.1", + sample="uprn_10091578598", + cert_num="uprn-10091578598", + sap_score=79, + ), )