mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Slice 39: PV credit input boundary uses RdSAP10 Table 32 + DE22 PV fixture
`_pv_export_credit_gbp_per_kwh` previously read from `prices.unit_price` (SAP10.2 Table 12 code 60 = 5.59 p/kWh) while the actual rating cascade inside _fuel_cost reads from `table_32_unit_price_p_per_kwh` (RdSAP10 Table 32 code 60 = 13.19 p/kWh, same as standard electricity). The exposed CalculatorInputs.pv_export_credit_gbp_per_kwh therefore misled about what the cascade applied. The calculator's fallback path at calculator.py:442 fires for synthetic inputs without `fuel_cost` and would compute the wrong PV credit by reading the misleading input. Per ADR-0010 §10 the rating cascade uses Table 32 prices. Unified both code paths on Table 32 so the input boundary reports the same 13.19 p/kWh the cascade applies. Cert-path math unchanged (cert path always sets fuel_cost). Synthetic/fallback path now consistent with cert path. Also adds cert 2130-1033-4050-5007-8395 (DE22, end-terrace + 1 ext, gas combi PCDB 17505, 2× 2.04 kWp PV) as 9th golden fixture. First PV-bearing cert in the cohort. Pinned residual is SAP +8 / PE −61 / CO2 +0.19 — spec-version drift not a code bug (cert was scored by SAP10.2 software using Table 12 PV export 5.59 p/kWh = £194 credit → SAP 82; calc targets RdSAP10 Table 32 = 13.19 p/kWh = £457 credit → SAP 90). Both internally consistent against their own price table. The PE residual is amplified because PV gen also offsets PE via inputs.other_primary_factor, which scales with gen kWh independently of the export-credit price. 930/930 Elmhurst cascade green. 14/14 golden cohort + 1 new cert_to_inputs unit test green. Pyright net-zero (49 errors before and after). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
6a6811e548
commit
1d7c13b995
4 changed files with 501 additions and 6 deletions
|
|
@ -698,11 +698,15 @@ def _pv_generation_kwh_per_yr(epc: EpcPropertyData) -> float:
|
||||||
return total_kwp * _PV_ANNUAL_YIELD_KWH_PER_KWP
|
return total_kwp * _PV_ANNUAL_YIELD_KWH_PER_KWP
|
||||||
|
|
||||||
|
|
||||||
def _pv_export_credit_gbp_per_kwh(prices: PriceTable) -> float:
|
def _pv_export_credit_gbp_per_kwh() -> float:
|
||||||
"""PV cost credit per kWh generated. SAP 10.2 Table 12 code 60 (PV
|
"""PV cost credit per kWh generated. Per ADR-0010 §10 the rating
|
||||||
export to grid) — 5.59 p/kWh on the spec table, 13.19 p/kWh under
|
cascade uses RdSAP10 Table 32 prices; code 60 (PV export to grid)
|
||||||
cert calibration (legacy unit prices)."""
|
= 13.19 p/kWh (same as standard electricity — PV gen displaces
|
||||||
return prices.unit_price_p_per_kwh(_PV_EXPORT_TARIFF_CODE) * _PENCE_TO_GBP
|
grid imports at the standard rate). The legacy SAP 10.2 Table 12
|
||||||
|
value (5.59 p/kWh) is no longer the target and is intentionally
|
||||||
|
not read here, so the CalculatorInputs boundary reports the same
|
||||||
|
rate _fuel_cost applies internally."""
|
||||||
|
return table_32_unit_price_p_per_kwh(_PV_EXPORT_TARIFF_CODE) * _PENCE_TO_GBP
|
||||||
|
|
||||||
|
|
||||||
def _other_fuel_cost_gbp_per_kwh(
|
def _other_fuel_cost_gbp_per_kwh(
|
||||||
|
|
@ -2178,7 +2182,7 @@ def cert_to_inputs(
|
||||||
_STANDARD_ELECTRICITY_FUEL_CODE,
|
_STANDARD_ELECTRICITY_FUEL_CODE,
|
||||||
),
|
),
|
||||||
pv_generation_kwh_per_yr=_pv_generation_kwh_per_yr(epc),
|
pv_generation_kwh_per_yr=_pv_generation_kwh_per_yr(epc),
|
||||||
pv_export_credit_gbp_per_kwh=_pv_export_credit_gbp_per_kwh(prices),
|
pv_export_credit_gbp_per_kwh=_pv_export_credit_gbp_per_kwh(),
|
||||||
secondary_heating_fraction=secondary_fraction_value,
|
secondary_heating_fraction=secondary_fraction_value,
|
||||||
secondary_heating_efficiency=secondary_efficiency_value,
|
secondary_heating_efficiency=secondary_efficiency_value,
|
||||||
energy_requirements=energy_requirements_result,
|
energy_requirements=energy_requirements_result,
|
||||||
|
|
|
||||||
453
packages/domain/src/domain/sap/rdsap/tests/fixtures/golden/2130-1033-4050-5007-8395.json
vendored
Normal file
453
packages/domain/src/domain/sap/rdsap/tests/fixtures/golden/2130-1033-4050-5007-8395.json
vendored
Normal file
|
|
@ -0,0 +1,453 @@
|
||||||
|
{
|
||||||
|
"uprn": 100030334057,
|
||||||
|
"roofs": [
|
||||||
|
{
|
||||||
|
"description": "Pitched, 300 mm loft insulation",
|
||||||
|
"energy_efficiency_rating": 5,
|
||||||
|
"environmental_efficiency_rating": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Pitched, 100 mm loft insulation",
|
||||||
|
"energy_efficiency_rating": 3,
|
||||||
|
"environmental_efficiency_rating": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"walls": [
|
||||||
|
{
|
||||||
|
"description": "Solid brick, as built, no insulation (assumed)",
|
||||||
|
"energy_efficiency_rating": 1,
|
||||||
|
"environmental_efficiency_rating": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Solid brick, with internal insulation",
|
||||||
|
"energy_efficiency_rating": 4,
|
||||||
|
"environmental_efficiency_rating": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"floors": [
|
||||||
|
{
|
||||||
|
"description": "Suspended, no insulation (assumed)",
|
||||||
|
"energy_efficiency_rating": 0,
|
||||||
|
"environmental_efficiency_rating": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Solid, no insulation (assumed)",
|
||||||
|
"energy_efficiency_rating": 0,
|
||||||
|
"environmental_efficiency_rating": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"status": "entered",
|
||||||
|
"tenure": 3,
|
||||||
|
"window": {
|
||||||
|
"description": "Fully double glazed",
|
||||||
|
"energy_efficiency_rating": 2,
|
||||||
|
"environmental_efficiency_rating": 2
|
||||||
|
},
|
||||||
|
"addendum": {
|
||||||
|
"addendum_numbers": [
|
||||||
|
8
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lighting": {
|
||||||
|
"description": "Excellent lighting efficiency",
|
||||||
|
"energy_efficiency_rating": 5,
|
||||||
|
"environmental_efficiency_rating": 5
|
||||||
|
},
|
||||||
|
"postcode": "DE22 3RW",
|
||||||
|
"hot_water": {
|
||||||
|
"description": "From main system",
|
||||||
|
"energy_efficiency_rating": 4,
|
||||||
|
"environmental_efficiency_rating": 4
|
||||||
|
},
|
||||||
|
"post_town": "DERBY",
|
||||||
|
"psv_count": 0,
|
||||||
|
"built_form": 3,
|
||||||
|
"created_at": "2025-07-24 16:36:27",
|
||||||
|
"door_count": 2,
|
||||||
|
"region_code": 6,
|
||||||
|
"report_type": 2,
|
||||||
|
"sap_heating": {
|
||||||
|
"number_baths": 1,
|
||||||
|
"cylinder_size": 1,
|
||||||
|
"shower_outlets": [
|
||||||
|
{
|
||||||
|
"shower_outlet": {
|
||||||
|
"shower_wwhrs": 1,
|
||||||
|
"shower_outlet_type": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"number_baths_wwhrs": 0,
|
||||||
|
"water_heating_code": 901,
|
||||||
|
"water_heating_fuel": 26,
|
||||||
|
"cylinder_thermostat": "N",
|
||||||
|
"main_heating_details": [
|
||||||
|
{
|
||||||
|
"has_fghrs": "N",
|
||||||
|
"main_fuel_type": 26,
|
||||||
|
"boiler_flue_type": 2,
|
||||||
|
"fan_flue_present": "Y",
|
||||||
|
"heat_emitter_type": 1,
|
||||||
|
"emitter_temperature": 1,
|
||||||
|
"main_heating_number": 1,
|
||||||
|
"main_heating_control": 2106,
|
||||||
|
"main_heating_category": 2,
|
||||||
|
"main_heating_fraction": 1,
|
||||||
|
"central_heating_pump_age": 0,
|
||||||
|
"main_heating_data_source": 1,
|
||||||
|
"main_heating_index_number": 17505
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"immersion_heating_type": "NA",
|
||||||
|
"has_fixed_air_conditioning": "false"
|
||||||
|
},
|
||||||
|
"sap_version": 10.2,
|
||||||
|
"sap_windows": [
|
||||||
|
{
|
||||||
|
"pvc_frame": "true",
|
||||||
|
"glazing_gap": "16+",
|
||||||
|
"orientation": 8,
|
||||||
|
"window_type": 1,
|
||||||
|
"glazing_type": 3,
|
||||||
|
"window_width": {
|
||||||
|
"value": 0.95,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"window_height": {
|
||||||
|
"value": 1.75,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"draught_proofed": "true",
|
||||||
|
"window_location": 0,
|
||||||
|
"window_wall_type": 1,
|
||||||
|
"permanent_shutters_present": "N",
|
||||||
|
"permanent_shutters_insulated": "N"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pvc_frame": "true",
|
||||||
|
"glazing_gap": "16+",
|
||||||
|
"orientation": 8,
|
||||||
|
"window_type": 1,
|
||||||
|
"glazing_type": 3,
|
||||||
|
"window_width": {
|
||||||
|
"value": 0.95,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"window_height": {
|
||||||
|
"value": 1.7,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"draught_proofed": "true",
|
||||||
|
"window_location": 0,
|
||||||
|
"window_wall_type": 1,
|
||||||
|
"permanent_shutters_present": "N",
|
||||||
|
"permanent_shutters_insulated": "N"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pvc_frame": "true",
|
||||||
|
"glazing_gap": "16+",
|
||||||
|
"orientation": 4,
|
||||||
|
"window_type": 1,
|
||||||
|
"glazing_type": 3,
|
||||||
|
"window_width": {
|
||||||
|
"value": 1,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"window_height": {
|
||||||
|
"value": 1.7,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"draught_proofed": "true",
|
||||||
|
"window_location": 0,
|
||||||
|
"window_wall_type": 1,
|
||||||
|
"permanent_shutters_present": "N",
|
||||||
|
"permanent_shutters_insulated": "N"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pvc_frame": "true",
|
||||||
|
"glazing_gap": "16+",
|
||||||
|
"orientation": 4,
|
||||||
|
"window_type": 1,
|
||||||
|
"glazing_type": 3,
|
||||||
|
"window_width": {
|
||||||
|
"value": 0.95,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"window_height": {
|
||||||
|
"value": 1.7,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"draught_proofed": "true",
|
||||||
|
"window_location": 0,
|
||||||
|
"window_wall_type": 1,
|
||||||
|
"permanent_shutters_present": "N",
|
||||||
|
"permanent_shutters_insulated": "N"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pvc_frame": "true",
|
||||||
|
"glazing_gap": "16+",
|
||||||
|
"orientation": 6,
|
||||||
|
"window_type": 1,
|
||||||
|
"glazing_type": 3,
|
||||||
|
"window_width": {
|
||||||
|
"value": 0.7,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"window_height": {
|
||||||
|
"value": 0.9,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"draught_proofed": "true",
|
||||||
|
"window_location": 0,
|
||||||
|
"window_wall_type": 1,
|
||||||
|
"permanent_shutters_present": "N",
|
||||||
|
"permanent_shutters_insulated": "N"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pvc_frame": "true",
|
||||||
|
"glazing_gap": "16+",
|
||||||
|
"orientation": 6,
|
||||||
|
"window_type": 1,
|
||||||
|
"glazing_type": 3,
|
||||||
|
"window_width": {
|
||||||
|
"value": 0.65,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"window_height": {
|
||||||
|
"value": 0.5,
|
||||||
|
"quantity": "m"
|
||||||
|
},
|
||||||
|
"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, mains gas",
|
||||||
|
"energy_efficiency_rating": 4,
|
||||||
|
"environmental_efficiency_rating": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"air_tightness": {
|
||||||
|
"description": "(not tested)",
|
||||||
|
"energy_efficiency_rating": 0,
|
||||||
|
"environmental_efficiency_rating": 0
|
||||||
|
},
|
||||||
|
"dwelling_type": "End-terrace house",
|
||||||
|
"language_code": 1,
|
||||||
|
"pressure_test": 4,
|
||||||
|
"property_type": 0,
|
||||||
|
"address_line_1": "5 Lynton Street",
|
||||||
|
"assessment_type": "RdSAP",
|
||||||
|
"completion_date": "2025-07-24",
|
||||||
|
"inspection_date": "2025-07-18",
|
||||||
|
"extensions_count": 1,
|
||||||
|
"measurement_type": 1,
|
||||||
|
"open_flues_count": 0,
|
||||||
|
"total_floor_area": 64,
|
||||||
|
"transaction_type": 1,
|
||||||
|
"conservatory_type": 1,
|
||||||
|
"heated_room_count": 4,
|
||||||
|
"other_flues_count": 0,
|
||||||
|
"registration_date": "2025-07-24",
|
||||||
|
"sap_energy_source": {
|
||||||
|
"mains_gas": "Y",
|
||||||
|
"meter_type": 2,
|
||||||
|
"pv_connection": 2,
|
||||||
|
"photovoltaic_supply": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"pitch": 2,
|
||||||
|
"peak_power": 2.04,
|
||||||
|
"orientation": 4,
|
||||||
|
"overshading": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"pitch": 2,
|
||||||
|
"peak_power": 2.04,
|
||||||
|
"orientation": 8,
|
||||||
|
"overshading": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"wind_turbines_count": 0,
|
||||||
|
"gas_smart_meter_present": "false",
|
||||||
|
"is_dwelling_export_capable": "true",
|
||||||
|
"wind_turbines_terrain_type": 2,
|
||||||
|
"electricity_smart_meter_present": "true"
|
||||||
|
},
|
||||||
|
"secondary_heating": {
|
||||||
|
"description": "None",
|
||||||
|
"energy_efficiency_rating": 0,
|
||||||
|
"environmental_efficiency_rating": 0
|
||||||
|
},
|
||||||
|
"closed_flues_count": 0,
|
||||||
|
"extract_fans_count": 1,
|
||||||
|
"lzc_energy_sources": [
|
||||||
|
11
|
||||||
|
],
|
||||||
|
"sap_building_parts": [
|
||||||
|
{
|
||||||
|
"identifier": "Main Dwelling",
|
||||||
|
"wall_dry_lined": "N",
|
||||||
|
"wall_thickness": 230,
|
||||||
|
"floor_heat_loss": 7,
|
||||||
|
"roof_construction": 4,
|
||||||
|
"wall_construction": 3,
|
||||||
|
"building_part_number": 1,
|
||||||
|
"sap_floor_dimensions": [
|
||||||
|
{
|
||||||
|
"floor": 0,
|
||||||
|
"room_height": 2.64,
|
||||||
|
"floor_insulation": 1,
|
||||||
|
"total_floor_area": 28.2,
|
||||||
|
"party_wall_length": 8.27,
|
||||||
|
"floor_construction": 2,
|
||||||
|
"heat_loss_perimeter": 13.38
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"floor": 1,
|
||||||
|
"room_height": 2.58,
|
||||||
|
"total_floor_area": 28.2,
|
||||||
|
"party_wall_length": 8.27,
|
||||||
|
"heat_loss_perimeter": 15.09
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"wall_insulation_type": 4,
|
||||||
|
"construction_age_band": "B",
|
||||||
|
"party_wall_construction": 1,
|
||||||
|
"wall_thickness_measured": "Y",
|
||||||
|
"roof_insulation_location": 2,
|
||||||
|
"roof_insulation_thickness": "300mm",
|
||||||
|
"wall_insulation_thickness_measured": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identifier": "Extension 1",
|
||||||
|
"wall_dry_lined": "N",
|
||||||
|
"floor_heat_loss": 7,
|
||||||
|
"roof_construction": 5,
|
||||||
|
"wall_construction": 3,
|
||||||
|
"building_part_number": 2,
|
||||||
|
"sap_floor_dimensions": [
|
||||||
|
{
|
||||||
|
"floor": 0,
|
||||||
|
"room_height": 2.5,
|
||||||
|
"floor_insulation": 1,
|
||||||
|
"total_floor_area": 7.21,
|
||||||
|
"party_wall_length": 0,
|
||||||
|
"floor_construction": 1,
|
||||||
|
"heat_loss_perimeter": 9.88
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"wall_insulation_type": 3,
|
||||||
|
"construction_age_band": "B",
|
||||||
|
"party_wall_construction": "NA",
|
||||||
|
"wall_thickness_measured": "N",
|
||||||
|
"roof_insulation_location": 2,
|
||||||
|
"roof_insulation_thickness": "100mm",
|
||||||
|
"wall_insulation_thickness": "measured",
|
||||||
|
"wall_insulation_thickness_measured": 100,
|
||||||
|
"wall_insulation_thermal_conductivity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"boilers_flues_count": 0,
|
||||||
|
"open_chimneys_count": 0,
|
||||||
|
"solar_water_heating": "N",
|
||||||
|
"habitable_room_count": 4,
|
||||||
|
"heating_cost_current": {
|
||||||
|
"value": 939,
|
||||||
|
"currency": "GBP"
|
||||||
|
},
|
||||||
|
"insulated_door_count": 0,
|
||||||
|
"co2_emissions_current": 2.7,
|
||||||
|
"energy_rating_average": 60,
|
||||||
|
"energy_rating_current": 82,
|
||||||
|
"lighting_cost_current": {
|
||||||
|
"value": 45,
|
||||||
|
"currency": "GBP"
|
||||||
|
},
|
||||||
|
"main_heating_controls": [
|
||||||
|
{
|
||||||
|
"description": "Programmer, room thermostat and TRVs",
|
||||||
|
"energy_efficiency_rating": 4,
|
||||||
|
"environmental_efficiency_rating": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"blocked_chimneys_count": 0,
|
||||||
|
"has_hot_water_cylinder": "false",
|
||||||
|
"heating_cost_potential": {
|
||||||
|
"value": 591,
|
||||||
|
"currency": "GBP"
|
||||||
|
},
|
||||||
|
"hot_water_cost_current": {
|
||||||
|
"value": 161,
|
||||||
|
"currency": "GBP"
|
||||||
|
},
|
||||||
|
"mechanical_ventilation": 0,
|
||||||
|
"percent_draughtproofed": 100,
|
||||||
|
"schema_version_current": "LIG-21.0",
|
||||||
|
"suggested_improvements": [
|
||||||
|
{
|
||||||
|
"sequence": 1,
|
||||||
|
"typical_saving": 290,
|
||||||
|
"indicative_cost": "\u00a37,500 - \u00a311,000",
|
||||||
|
"improvement_type": "Q",
|
||||||
|
"improvement_details": {
|
||||||
|
"improvement_number": 7
|
||||||
|
},
|
||||||
|
"improvement_category": 5,
|
||||||
|
"energy_performance_rating": 91,
|
||||||
|
"environmental_impact_rating": 76
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sequence": 2,
|
||||||
|
"typical_saving": 58,
|
||||||
|
"indicative_cost": "\u00a35,000 - \u00a310,000",
|
||||||
|
"improvement_type": "W1",
|
||||||
|
"improvement_details": {
|
||||||
|
"improvement_number": 57
|
||||||
|
},
|
||||||
|
"improvement_category": 5,
|
||||||
|
"energy_performance_rating": 92,
|
||||||
|
"environmental_impact_rating": 79
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"co2_emissions_potential": 1.6,
|
||||||
|
"energy_rating_potential": 92,
|
||||||
|
"lighting_cost_potential": {
|
||||||
|
"value": 45,
|
||||||
|
"currency": "GBP"
|
||||||
|
},
|
||||||
|
"schema_version_original": "LIG-21.0",
|
||||||
|
"hot_water_cost_potential": {
|
||||||
|
"value": 161,
|
||||||
|
"currency": "GBP"
|
||||||
|
},
|
||||||
|
"renewable_heat_incentive": {
|
||||||
|
"water_heating": 2166.19,
|
||||||
|
"space_heating_existing_dwelling": 10128.81
|
||||||
|
},
|
||||||
|
"draughtproofed_door_count": 2,
|
||||||
|
"energy_consumption_current": 232,
|
||||||
|
"has_fixed_air_conditioning": "false",
|
||||||
|
"multiple_glazed_proportion": 100,
|
||||||
|
"calculation_software_version": "10.2.2.0",
|
||||||
|
"energy_consumption_potential": 138,
|
||||||
|
"environmental_impact_current": 65,
|
||||||
|
"cfl_fixed_lighting_bulbs_count": 0,
|
||||||
|
"current_energy_efficiency_band": "B",
|
||||||
|
"environmental_impact_potential": 79,
|
||||||
|
"led_fixed_lighting_bulbs_count": 9,
|
||||||
|
"has_heated_separate_conservatory": "false",
|
||||||
|
"potential_energy_efficiency_band": "A",
|
||||||
|
"co2_emissions_current_per_floor_area": 43,
|
||||||
|
"incandescent_fixed_lighting_bulbs_count": 0
|
||||||
|
}
|
||||||
|
|
@ -394,6 +394,23 @@ def test_calculator_always_uses_uk_average_weather_for_rating() -> None:
|
||||||
assert inputs_default.region == 0
|
assert inputs_default.region == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_pv_export_credit_input_reports_rdsap10_table_32_rate() -> None:
|
||||||
|
# Arrange — per ADR-0010 the rating cascade uses RdSAP10 Table 32
|
||||||
|
# prices (code 60 = 13.19 p/kWh for PV export). The CalculatorInputs
|
||||||
|
# boundary must report the same rate _fuel_cost applies internally
|
||||||
|
# so synthetic consumers (and the calculator's fallback path) don't
|
||||||
|
# see a different number from what the cascade produces. Previously
|
||||||
|
# this read from SAP10.2 Table 12 (5.59 p/kWh), leaving the input
|
||||||
|
# boundary out of step with the cascade.
|
||||||
|
epc = _typical_semi_detached_epc()
|
||||||
|
|
||||||
|
# Act
|
||||||
|
inputs = cert_to_inputs(epc)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert abs(inputs.pv_export_credit_gbp_per_kwh - 0.1319) <= 1e-6
|
||||||
|
|
||||||
|
|
||||||
def test_open_chimneys_raise_infiltration_ach() -> None:
|
def test_open_chimneys_raise_infiltration_ach() -> None:
|
||||||
# Arrange — Direction check: chimneys add Table 2.1 volume to the
|
# Arrange — Direction check: chimneys add Table 2.1 volume to the
|
||||||
# infiltration calc, so an otherwise identical dwelling with 2 open
|
# infiltration calc, so an otherwise identical dwelling with 2 open
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,26 @@ _EXPECTATIONS: tuple[_GoldenExpectation, ...] = (
|
||||||
expected_co2_resid_tonnes_per_yr=-0.2234,
|
expected_co2_resid_tonnes_per_yr=-0.2234,
|
||||||
notes="Semi-detached, TFA 102, age C, gas PCDB-listed.",
|
notes="Semi-detached, TFA 102, age C, gas PCDB-listed.",
|
||||||
),
|
),
|
||||||
|
_GoldenExpectation(
|
||||||
|
cert_number="2130-1033-4050-5007-8395",
|
||||||
|
actual_sap=82,
|
||||||
|
expected_sap_resid=+8,
|
||||||
|
expected_pe_resid_kwh_per_m2=-61.2533,
|
||||||
|
expected_co2_resid_tonnes_per_yr=+0.1856,
|
||||||
|
notes=(
|
||||||
|
"End-terrace + 1 extension, TFA 64, gas combi PCDB index 17505, "
|
||||||
|
"postcode DE22 (PCDB Table 172 match), PV: 2× 2.04 kWp arrays "
|
||||||
|
"(SE + NE). Cert scored under SAP10.2 software (Table 12 PV "
|
||||||
|
"export = 5.59 p/kWh, £194 PV credit → SAP 82). Our calc "
|
||||||
|
"targets RdSAP10 (Table 32 PV export = 13.19 p/kWh, £457 PV "
|
||||||
|
"credit → SAP 90) per ADR-0010. The +8 SAP / −61 PE residual "
|
||||||
|
"is spec-version drift, not a code bug — both calcs are "
|
||||||
|
"internally consistent against their own price table. The PE "
|
||||||
|
"residual is amplified because PV generation also offsets PE "
|
||||||
|
"via inputs.other_primary_factor; that offset scales with the "
|
||||||
|
"PV gen kWh, not the export-credit price."
|
||||||
|
),
|
||||||
|
),
|
||||||
_GoldenExpectation(
|
_GoldenExpectation(
|
||||||
cert_number="0390-2254-6420-2126-5561",
|
cert_number="0390-2254-6420-2126-5561",
|
||||||
actual_sap=65,
|
actual_sap=65,
|
||||||
|
|
@ -221,6 +241,7 @@ _PCDB_CHAIN_EXPECTATIONS: tuple[tuple[str, int, float], ...] = (
|
||||||
("0300-2747-7640-2526-2135", 17992, None), # gas PCDB-listed
|
("0300-2747-7640-2526-2135", 17992, None), # gas PCDB-listed
|
||||||
("8135-1728-8500-0511-3296", 17702, None), # gas PCDB-listed
|
("8135-1728-8500-0511-3296", 17702, None), # gas PCDB-listed
|
||||||
("0390-2254-6420-2126-5561", 18119, None), # LN12 gas combi PCDB-listed
|
("0390-2254-6420-2126-5561", 18119, None), # LN12 gas combi PCDB-listed
|
||||||
|
("2130-1033-4050-5007-8395", 17505, None), # DE22 gas combi PCDB-listed + PV
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue