mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Map full-SAP code-based heating systems via sap_main_heating_code 🟩
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
345154c6b7
commit
140ad39898
4 changed files with 315 additions and 6 deletions
|
|
@ -2593,9 +2593,18 @@ def _sap_17_1_heating(schema: SapSchema17_1) -> SapHeating:
|
|||
main_heating_details=[
|
||||
MainHeatingDetail(
|
||||
has_fghrs=False,
|
||||
main_fuel_type=d.main_fuel_type,
|
||||
heat_emitter_type=d.heat_emitter_type,
|
||||
emitter_temperature=d.emitter_temperature,
|
||||
# D6b: code-based systems (category 6/10) lodge no explicit
|
||||
# fuel/emitter — the calculator drives them off
|
||||
# sap_main_heating_code instead. Default the absent fields so
|
||||
# the cert still maps (0 = unspecified; emitter_temperature "NA").
|
||||
main_fuel_type=d.main_fuel_type if d.main_fuel_type is not None else 0,
|
||||
heat_emitter_type=(
|
||||
d.heat_emitter_type if d.heat_emitter_type is not None else 0
|
||||
),
|
||||
emitter_temperature=(
|
||||
d.emitter_temperature if d.emitter_temperature is not None else "NA"
|
||||
),
|
||||
sap_main_heating_code=d.main_heating_code,
|
||||
main_heating_control=d.main_heating_control,
|
||||
fan_flue_present=d.is_flue_fan_present == "true",
|
||||
boiler_flue_type=d.main_heating_flue_type,
|
||||
|
|
|
|||
|
|
@ -254,6 +254,23 @@ class TestFromSapSchema17_1EnergySource:
|
|||
assert sample.sap_energy_source.wind_turbines_count == 0
|
||||
|
||||
|
||||
class TestFromSapSchema17_1CodeBasedHeating:
|
||||
"""Slice D6b: ~27% of full-SAP certs use a code-based heating encoding
|
||||
(main_heating_category 6/10 — community heating, heat pumps) lodging
|
||||
main_heating_code instead of explicit heat_emitter_type/main_fuel_type.
|
||||
A known variant — map main_heating_code → sap_main_heating_code rather than
|
||||
fail loud, so the cert maps for completeness (score is a later concern)."""
|
||||
|
||||
def test_code_based_heating_cert_maps(self) -> None:
|
||||
# Previously raised "missing required field 'heat_emitter_type'".
|
||||
result = EpcPropertyDataMapper.from_api_response(load("sap_17_1_codeheat.json"))
|
||||
assert isinstance(result, EpcPropertyData)
|
||||
|
||||
def test_main_heating_code_carried(self) -> None:
|
||||
result = EpcPropertyDataMapper.from_api_response(load("sap_17_1_codeheat.json"))
|
||||
assert result.sap_heating.main_heating_details[0].sap_main_heating_code == 691
|
||||
|
||||
|
||||
class TestFromSapSchema17_1Ventilation:
|
||||
"""Slice D5-vent: full-SAP sap_ventilation → measured air permeability (AP4),
|
||||
ventilation_type → MechanicalVentilationKind, sheltered sides, wet rooms and
|
||||
|
|
|
|||
|
|
@ -126,10 +126,13 @@ class SapMainHeatingDetail:
|
|||
`is_flue_fan_present` vs `fan_flue_present`, `main_heating_flue_type` vs
|
||||
`boiler_flue_type`); the mapper translates them."""
|
||||
|
||||
main_fuel_type: int
|
||||
heat_emitter_type: int
|
||||
emitter_temperature: Union[int, str]
|
||||
main_heating_control: int
|
||||
# code-based heating (category 6/10 — community heating, heat pumps) lodges
|
||||
# main_heating_code instead of explicit fuel/emitter; both then absent.
|
||||
main_fuel_type: Optional[int] = None
|
||||
heat_emitter_type: Optional[int] = None
|
||||
emitter_temperature: Optional[Union[int, str]] = None
|
||||
main_heating_code: Optional[int] = None
|
||||
main_heating_number: Optional[int] = None
|
||||
main_heating_category: Optional[int] = None
|
||||
main_heating_fraction: Optional[Union[int, float]] = None
|
||||
|
|
|
|||
280
datatypes/epc/schema/tests/fixtures/sap_17_1_codeheat.json
vendored
Normal file
280
datatypes/epc/schema/tests/fixtures/sap_17_1_codeheat.json
vendored
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
{
|
||||
"uprn": 100071290385,
|
||||
"roofs": [
|
||||
{
|
||||
"description": "Average thermal transmittance 0.16 W/m\u00b2K",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"walls": [
|
||||
{
|
||||
"description": "Average thermal transmittance 0.63 W/m\u00b2K",
|
||||
"energy_efficiency_rating": 3,
|
||||
"environmental_efficiency_rating": 3
|
||||
}
|
||||
],
|
||||
"floors": [
|
||||
{
|
||||
"description": "(other premises below)",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
}
|
||||
],
|
||||
"status": "entered",
|
||||
"tenure": 1,
|
||||
"windows": {
|
||||
"description": "High performance glazing",
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
},
|
||||
"lighting": {
|
||||
"description": "Low energy lighting in all fixed outlets",
|
||||
"energy_efficiency_rating": 5,
|
||||
"environmental_efficiency_rating": 5
|
||||
},
|
||||
"postcode": "B7 5SP",
|
||||
"data_type": 4,
|
||||
"hot_water": {
|
||||
"description": "Electric immersion, standard tariff",
|
||||
"energy_efficiency_rating": 1,
|
||||
"environmental_efficiency_rating": 2
|
||||
},
|
||||
"post_town": "BIRMINGHAM",
|
||||
"built_form": 2,
|
||||
"created_at": "2019-05-28 09:11:44",
|
||||
"living_area": 9.5,
|
||||
"orientation": 4,
|
||||
"region_code": 6,
|
||||
"report_type": 3,
|
||||
"sap_heating": {
|
||||
"water_fuel_type": 39,
|
||||
"water_heating_code": 903,
|
||||
"hot_water_store_size": 90,
|
||||
"main_heating_details": [
|
||||
{
|
||||
"main_fuel_type": 39,
|
||||
"main_heating_code": 691,
|
||||
"emitter_temperature": "NA",
|
||||
"main_heating_number": 1,
|
||||
"main_heating_control": 2603,
|
||||
"main_heating_category": 10,
|
||||
"main_heating_fraction": 1,
|
||||
"main_heating_data_source": 3
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "true",
|
||||
"immersion_heating_type": 1,
|
||||
"has_cylinder_thermostat": "true",
|
||||
"hot_water_store_heat_loss": 1.37,
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"secondary_heating_category": 1,
|
||||
"is_cylinder_in_heated_space": "true",
|
||||
"hot_water_store_heat_loss_source": 2
|
||||
},
|
||||
"sap_version": 9.92,
|
||||
"schema_type": "SAP-Schema-17.1",
|
||||
"uprn_source": "Energy Assessor",
|
||||
"country_code": "ENG",
|
||||
"main_heating": [
|
||||
{
|
||||
"description": "Room heaters, electric",
|
||||
"energy_efficiency_rating": 1,
|
||||
"environmental_efficiency_rating": 2
|
||||
}
|
||||
],
|
||||
"air_tightness": {
|
||||
"description": "(not tested)",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
},
|
||||
"dwelling_type": "Top-floor flat",
|
||||
"language_code": 1,
|
||||
"property_type": 2,
|
||||
"address_line_1": "208, Nechells Park Road",
|
||||
"assessment_date": "2019-05-24",
|
||||
"assessment_type": "SAP",
|
||||
"completion_date": "2019-05-28",
|
||||
"inspection_date": "2019-05-28",
|
||||
"sap_ventilation": {
|
||||
"psv_count": 0,
|
||||
"pressure_test": 3,
|
||||
"air_permeability": 15,
|
||||
"open_flues_count": 0,
|
||||
"ventilation_type": 1,
|
||||
"extract_fans_count": 1,
|
||||
"open_fireplaces_count": 0,
|
||||
"sheltered_sides_count": 2,
|
||||
"flueless_gas_fires_count": 0
|
||||
},
|
||||
"design_water_use": 1,
|
||||
"sap_data_version": 9.92,
|
||||
"sap_flat_details": {
|
||||
"level": 3
|
||||
},
|
||||
"total_floor_area": 13,
|
||||
"transaction_type": 6,
|
||||
"conservatory_type": 1,
|
||||
"registration_date": "2019-05-28",
|
||||
"sap_energy_source": {
|
||||
"electricity_tariff": 1,
|
||||
"wind_turbines_count": 0,
|
||||
"wind_turbine_terrain_type": 2,
|
||||
"fixed_lighting_outlets_count": 15,
|
||||
"low_energy_fixed_lighting_outlets_count": 15,
|
||||
"low_energy_fixed_lighting_outlets_percentage": 100
|
||||
},
|
||||
"sap_opening_types": [
|
||||
{
|
||||
"name": "Glazing",
|
||||
"type": 4,
|
||||
"u_value": 1.4,
|
||||
"data_source": 2,
|
||||
"frame_factor": 0.7,
|
||||
"glazing_type": 7,
|
||||
"solar_transmittance": 0.63
|
||||
},
|
||||
{
|
||||
"name": "Solid Door",
|
||||
"type": 1,
|
||||
"u_value": 1.8,
|
||||
"data_source": 2,
|
||||
"glazing_type": 1
|
||||
}
|
||||
],
|
||||
"secondary_heating": {
|
||||
"description": "None",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
},
|
||||
"sap_building_parts": [
|
||||
{
|
||||
"sap_roofs": [
|
||||
{
|
||||
"name": "Roof 1",
|
||||
"u_value": 0.16,
|
||||
"roof_type": 2,
|
||||
"description": "Insulated Ceiling",
|
||||
"total_roof_area": 12.62
|
||||
}
|
||||
],
|
||||
"sap_walls": [
|
||||
{
|
||||
"name": "External Wall 1",
|
||||
"u_value": 0.34,
|
||||
"wall_type": 2,
|
||||
"description": "Upgraded Ext Walls",
|
||||
"total_wall_area": 20.54,
|
||||
"is_curtain_walling": "false"
|
||||
},
|
||||
{
|
||||
"name": "External Wall 2",
|
||||
"u_value": 1,
|
||||
"wall_type": 2,
|
||||
"description": "Wall to Lobby",
|
||||
"total_wall_area": 16.38,
|
||||
"is_curtain_walling": "false"
|
||||
},
|
||||
{
|
||||
"name": "Party Wall 0",
|
||||
"u_value": 0,
|
||||
"wall_type": 4,
|
||||
"total_wall_area": 9.88
|
||||
}
|
||||
],
|
||||
"identifier": "Main Dwelling",
|
||||
"overshading": 2,
|
||||
"sap_openings": [
|
||||
{
|
||||
"name": "W1",
|
||||
"type": "Glazing",
|
||||
"width": 1200,
|
||||
"height": 2000,
|
||||
"location": "External Wall 1",
|
||||
"orientation": 8
|
||||
},
|
||||
{
|
||||
"name": "D1",
|
||||
"type": "Solid Door",
|
||||
"width": 900,
|
||||
"height": 2100,
|
||||
"location": "External Wall 2",
|
||||
"orientation": 0
|
||||
}
|
||||
],
|
||||
"construction_year": 2019,
|
||||
"sap_thermal_bridges": {
|
||||
"thermal_bridge_code": 1
|
||||
},
|
||||
"building_part_number": 1,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"storey": 1,
|
||||
"u_value": 0,
|
||||
"floor_type": 4,
|
||||
"storey_height": 2.6,
|
||||
"heat_loss_area": 0,
|
||||
"total_floor_area": 12.62
|
||||
}
|
||||
],
|
||||
"thermal_mass_parameter": 250
|
||||
}
|
||||
],
|
||||
"heating_cost_current": {
|
||||
"value": 278,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"co2_emissions_current": 1.5,
|
||||
"energy_rating_average": 60,
|
||||
"energy_rating_current": 59,
|
||||
"lighting_cost_current": {
|
||||
"value": 16,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"main_heating_controls": [
|
||||
{
|
||||
"description": "Programmer and appliance thermostats",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"has_hot_water_cylinder": "true",
|
||||
"heating_cost_potential": {
|
||||
"value": 278,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"hot_water_cost_current": {
|
||||
"value": 206,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"co2_emissions_potential": 1.5,
|
||||
"energy_rating_potential": 59,
|
||||
"lighting_cost_potential": {
|
||||
"value": 16,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"schema_version_original": "LIG-17.0",
|
||||
"hot_water_cost_potential": {
|
||||
"value": 206,
|
||||
"currency": "GBP"
|
||||
},
|
||||
"is_in_smoke_control_area": "unknown",
|
||||
"renewable_heat_incentive": {
|
||||
"rhi_new_dwelling": {
|
||||
"space_heating": 1637,
|
||||
"water_heating": 1212
|
||||
}
|
||||
},
|
||||
"seller_commission_report": "Y",
|
||||
"energy_consumption_current": 716,
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"multiple_glazed_percentage": 100,
|
||||
"calculation_software_version": "4.09r14",
|
||||
"energy_consumption_potential": 716,
|
||||
"environmental_impact_current": 63,
|
||||
"current_energy_efficiency_band": "D",
|
||||
"environmental_impact_potential": 63,
|
||||
"has_heated_separate_conservatory": "false",
|
||||
"potential_energy_efficiency_band": "D",
|
||||
"co2_emissions_current_per_floor_area": 121
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue