mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Derive cylinder_size when has_hot_water_cylinder is false on SAP-15.0/16.x certs
Task 9d271e98-96e6-4be6-bb50-e9be6f954003 (portfolio 796) failed property
715358 with "SapHeating: missing required field 'cylinder_size'": cert
0685-2881-6867-9029-1761 lodges has_hot_water_cylinder="false" but omits
sap_heating.cylinder_size entirely. Mirrors the already-handled inverse
gap in _normalize_sap_schema_16_x, so default to code 1 ("no cylinder")
rather than fail loud.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
dc5c29c8c1
commit
5d5fa73372
3 changed files with 367 additions and 0 deletions
|
|
@ -4029,6 +4029,17 @@ def _normalize_sap_schema_16_x(data: Dict[str, Any]) -> Dict[str, Any]:
|
|||
"true" if cylinder_size != 1 else "false"
|
||||
)
|
||||
|
||||
# The inverse gap: some SAP-Schema-15.0 certs (e.g. cert
|
||||
# 0685-2881-6867-9029-1761, UPRN 100020699807) lodge
|
||||
# `has_hot_water_cylinder: "false"` but omit `sap_heating.cylinder_size`
|
||||
# entirely, rather than lodging it as code 1 ("no cylinder"). Same
|
||||
# RdSAP 10 §10.5 fact as above, just the other field missing this
|
||||
# time — derive the code-1 default so `RdSapSchema17_1` (which
|
||||
# requires `cylinder_size` as an independent field) doesn't fail
|
||||
# loud on a cert that has already told us there's no cylinder.
|
||||
if d.get("has_hot_water_cylinder") == "false" and "cylinder_size" not in heating:
|
||||
heating["cylinder_size"] = 1
|
||||
|
||||
for bp in _dicts(d.get("sap_building_parts")):
|
||||
for fd in _dicts(bp.get("sap_floor_dimensions")):
|
||||
fd.setdefault("party_wall_length", 0)
|
||||
|
|
|
|||
|
|
@ -122,3 +122,21 @@ class TestFromSapSchema15_0:
|
|||
epc = EpcPropertyDataMapper.from_api_response(data)
|
||||
|
||||
assert epc.has_hot_water_cylinder is True
|
||||
|
||||
def test_derives_cylinder_size_when_has_hot_water_cylinder_is_false(
|
||||
self,
|
||||
) -> None:
|
||||
# Task 9d271e98-96e6-4be6-bb50-e9be6f954003 (portfolio 796 / scenario
|
||||
# 1268) failed property_id 715358 (UPRN 100020699807) with
|
||||
# "SapHeating: missing required field 'cylinder_size'": cert
|
||||
# 0685-2881-6867-9029-1761 lodges `has_hot_water_cylinder: "false"`
|
||||
# but omits `sap_heating.cylinder_size` entirely, the inverse gap of
|
||||
# `test_derives_has_hot_water_cylinder_from_cylinder_size_when_absent`
|
||||
# above. Same RdSAP 10 §10.5 fact, so code 1 ("no cylinder") must be
|
||||
# derived rather than left to fail loud.
|
||||
epc = EpcPropertyDataMapper.from_api_response(
|
||||
load("sap_15_0_uprn_100020699807.json")
|
||||
)
|
||||
|
||||
assert epc.has_hot_water_cylinder is False
|
||||
assert epc.sap_heating.cylinder_size == 1
|
||||
|
|
|
|||
338
datatypes/epc/schema/tests/fixtures/sap_15_0_uprn_100020699807.json
vendored
Normal file
338
datatypes/epc/schema/tests/fixtures/sap_15_0_uprn_100020699807.json
vendored
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
{
|
||||
"uprn": 100020699807,
|
||||
"roofs": [
|
||||
{
|
||||
"description": "Pitched, 50 mm loft insulation",
|
||||
"energy_efficiency_rating": 2,
|
||||
"environmental_efficiency_rating": 2
|
||||
},
|
||||
{
|
||||
"description": "Pitched, insulated at rafters",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"walls": [
|
||||
{
|
||||
"description": "Solid brick, as built, no insulation (assumed)",
|
||||
"energy_efficiency_rating": 1,
|
||||
"environmental_efficiency_rating": 1
|
||||
},
|
||||
{
|
||||
"description": "Solid brick, as built, insulated (assumed)",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
},
|
||||
{
|
||||
"description": "Timber frame, as built, insulated (assumed)",
|
||||
"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",
|
||||
"windows": [
|
||||
{
|
||||
"description": "Fully double glazed",
|
||||
"energy_efficiency_rating": 3,
|
||||
"environmental_efficiency_rating": 3
|
||||
}
|
||||
],
|
||||
"lighting": {
|
||||
"description": "Low energy lighting in 38% of fixed outlets",
|
||||
"energy_efficiency_rating": 3,
|
||||
"environmental_efficiency_rating": 3
|
||||
},
|
||||
"postcode": "CR7 8HW",
|
||||
"hot_water": {
|
||||
"description": "From main system",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
},
|
||||
"post_town": "THORNTON HEATH",
|
||||
"built_form": 3,
|
||||
"created_at": "2011-07-05 13:20:20",
|
||||
"glazed_area": 1,
|
||||
"region_code": 17,
|
||||
"report_type": 2,
|
||||
"sap_heating": {
|
||||
"water_heating_code": 901,
|
||||
"water_heating_fuel": 26,
|
||||
"main_heating_details": [
|
||||
{
|
||||
"main_fuel_type": 26,
|
||||
"boiler_flue_type": 2,
|
||||
"fan_flue_present": "Y",
|
||||
"heat_emitter_type": 1,
|
||||
"boiler_index_number": 8829,
|
||||
"main_heating_number": 1,
|
||||
"main_heating_control": 2107,
|
||||
"main_heating_category": 2,
|
||||
"main_heating_fraction": 1.0,
|
||||
"main_heating_data_source": 1
|
||||
}
|
||||
],
|
||||
"has_fixed_air_conditioning": "false"
|
||||
},
|
||||
"sap_version": 9.9,
|
||||
"schema_type": "SAP-Schema-15.0",
|
||||
"uprn_source": "Energy Assessor",
|
||||
"country_code": "EAW",
|
||||
"main_heating": [
|
||||
{
|
||||
"description": "Boiler and radiators, mains gas",
|
||||
"energy_efficiency_rating": 4,
|
||||
"environmental_efficiency_rating": 4
|
||||
}
|
||||
],
|
||||
"dwelling_type": "End-terrace house",
|
||||
"language_code": 1,
|
||||
"property_type": 0,
|
||||
"address_line_1": "123, Northwood Road",
|
||||
"schema_version": "LIG-15.0",
|
||||
"assessment_type": "RdSAP",
|
||||
"completion_date": "2011-07-05",
|
||||
"inspection_date": "2011-06-29",
|
||||
"extensions_count": 3,
|
||||
"measurement_type": 1,
|
||||
"total_floor_area": 126,
|
||||
"transaction_type": 3,
|
||||
"conservatory_type": 1,
|
||||
"heated_room_count": 6,
|
||||
"registration_date": "2011-07-05",
|
||||
"restricted_access": 0,
|
||||
"sap_energy_source": {
|
||||
"main_gas": "Y",
|
||||
"meter_type": 1,
|
||||
"photovoltaic_supply": {
|
||||
"percent_roof_area": 0
|
||||
},
|
||||
"wind_turbines_count": 0,
|
||||
"wind_turbines_terrain_type": 2
|
||||
},
|
||||
"secondary_heating": {
|
||||
"description": "None",
|
||||
"energy_efficiency_rating": 0,
|
||||
"environmental_efficiency_rating": 0
|
||||
},
|
||||
"sap_building_parts": [
|
||||
{
|
||||
"identifier": "Main Dwelling",
|
||||
"floor_heat_loss": 7,
|
||||
"roof_construction": 7,
|
||||
"wall_construction": 3,
|
||||
"building_part_number": 1,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"floor": 0,
|
||||
"room_height": 2.71,
|
||||
"floor_insulation": 0,
|
||||
"total_floor_area": 34.64,
|
||||
"floor_construction": 2,
|
||||
"heat_loss_perimeter": 13.58
|
||||
},
|
||||
{
|
||||
"floor": 1,
|
||||
"room_height": 2.57,
|
||||
"total_floor_area": 26.11,
|
||||
"heat_loss_perimeter": 7.0
|
||||
}
|
||||
],
|
||||
"wall_insulation_type": 4,
|
||||
"construction_age_band": "B",
|
||||
"roof_insulation_location": "ND",
|
||||
"roof_insulation_thickness": "ND"
|
||||
},
|
||||
{
|
||||
"identifier": "Extension 1",
|
||||
"floor_heat_loss": 7,
|
||||
"roof_construction": 4,
|
||||
"wall_construction": 3,
|
||||
"building_part_number": 2,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"floor": 0,
|
||||
"room_height": 2.55,
|
||||
"floor_insulation": 0,
|
||||
"total_floor_area": 16.03,
|
||||
"floor_construction": 1,
|
||||
"heat_loss_perimeter": 8.32
|
||||
},
|
||||
{
|
||||
"floor": 1,
|
||||
"room_height": 2.53,
|
||||
"total_floor_area": 16.03,
|
||||
"heat_loss_perimeter": 8.32
|
||||
}
|
||||
],
|
||||
"wall_insulation_type": 4,
|
||||
"construction_age_band": "B",
|
||||
"roof_insulation_location": 2,
|
||||
"roof_insulation_thickness": "50mm"
|
||||
},
|
||||
{
|
||||
"identifier": "Extension 2",
|
||||
"floor_heat_loss": 8,
|
||||
"roof_construction": 4,
|
||||
"wall_construction": 3,
|
||||
"building_part_number": 3,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"floor": 0,
|
||||
"room_height": 2.57,
|
||||
"total_floor_area": 7.69,
|
||||
"heat_loss_perimeter": 6.26
|
||||
}
|
||||
],
|
||||
"wall_insulation_type": 4,
|
||||
"construction_age_band": "B",
|
||||
"roof_insulation_location": 1,
|
||||
"roof_insulation_thickness": "NI",
|
||||
"rafter_insulation_thickness": "150mm"
|
||||
},
|
||||
{
|
||||
"identifier": "Extension 3",
|
||||
"floor_heat_loss": 8,
|
||||
"roof_construction": 4,
|
||||
"wall_construction": 3,
|
||||
"building_part_number": 4,
|
||||
"sap_floor_dimensions": [
|
||||
{
|
||||
"floor": 0,
|
||||
"room_height": 1.89,
|
||||
"total_floor_area": 25.25,
|
||||
"heat_loss_perimeter": 20.26
|
||||
}
|
||||
],
|
||||
"wall_insulation_type": 4,
|
||||
"construction_age_band": "I",
|
||||
"roof_insulation_location": 1,
|
||||
"roof_insulation_thickness": "NI",
|
||||
"rafter_insulation_thickness": "150mm"
|
||||
},
|
||||
{
|
||||
"wall_area": 14.25,
|
||||
"wall_location": 3,
|
||||
"wall_construction": 5,
|
||||
"wall_insulation_type": 4
|
||||
}
|
||||
],
|
||||
"low_energy_lighting": 37,
|
||||
"solar_water_heating": "N",
|
||||
"bedf_revision_number": 310,
|
||||
"habitable_room_count": 6,
|
||||
"heating_cost_current": 1001,
|
||||
"co2_emissions_current": 6.3,
|
||||
"energy_rating_current": 57,
|
||||
"lighting_cost_current": 99,
|
||||
"main_heating_controls": [
|
||||
{
|
||||
"description": "Programmer, TRVs and bypass",
|
||||
"energy_efficiency_rating": 3,
|
||||
"environmental_efficiency_rating": 3
|
||||
}
|
||||
],
|
||||
"multiple_glazing_type": 3,
|
||||
"open_fireplaces_count": 0,
|
||||
"has_hot_water_cylinder": "false",
|
||||
"heating_cost_potential": 862,
|
||||
"hot_water_cost_current": 100,
|
||||
"mechanical_ventilation": 0,
|
||||
"suggested_improvements": [
|
||||
{
|
||||
"sequence": 1,
|
||||
"typical_saving": 32,
|
||||
"indicative_cost": "\u00a325",
|
||||
"improvement_type": "E",
|
||||
"improvement_details": {
|
||||
"improvement_number": 35
|
||||
},
|
||||
"improvement_category": 1,
|
||||
"energy_performance_rating": 58,
|
||||
"environmental_impact_rating": 52
|
||||
},
|
||||
{
|
||||
"sequence": 2,
|
||||
"typical_saving": 59,
|
||||
"indicative_cost": "\u00a3350 - \u00a3450",
|
||||
"improvement_type": "G",
|
||||
"improvement_details": {
|
||||
"improvement_number": 14
|
||||
},
|
||||
"improvement_category": 1,
|
||||
"energy_performance_rating": 60,
|
||||
"environmental_impact_rating": 54
|
||||
},
|
||||
{
|
||||
"sequence": 3,
|
||||
"typical_saving": 97,
|
||||
"indicative_cost": "\u00a31,500 - \u00a33,500",
|
||||
"improvement_type": "I",
|
||||
"improvement_details": {
|
||||
"improvement_number": 20
|
||||
},
|
||||
"improvement_category": 2,
|
||||
"energy_performance_rating": 63,
|
||||
"environmental_impact_rating": 59
|
||||
},
|
||||
{
|
||||
"sequence": 4,
|
||||
"typical_saving": 219,
|
||||
"indicative_cost": "\u00a35,500 - \u00a314,500",
|
||||
"improvement_type": "Q",
|
||||
"improvement_details": {
|
||||
"improvement_number": 7
|
||||
},
|
||||
"improvement_category": 3,
|
||||
"energy_performance_rating": 71,
|
||||
"environmental_impact_rating": 69
|
||||
},
|
||||
{
|
||||
"sequence": 5,
|
||||
"typical_saving": 214,
|
||||
"indicative_cost": "\u00a311,000 - \u00a320,000",
|
||||
"improvement_type": "U",
|
||||
"improvement_details": {
|
||||
"improvement_number": 34
|
||||
},
|
||||
"improvement_category": 3,
|
||||
"energy_performance_rating": 79,
|
||||
"environmental_impact_rating": 76
|
||||
}
|
||||
],
|
||||
"co2_emissions_potential": 5.2,
|
||||
"energy_rating_potential": 63,
|
||||
"lighting_cost_potential": 61,
|
||||
"hot_water_cost_potential": 89,
|
||||
"renewable_heat_incentive": {
|
||||
"water_heating": 2302,
|
||||
"space_heating_existing_dwelling": 18083,
|
||||
"space_heating_with_loft_insulation": 17854,
|
||||
"space_heating_with_loft_and_cavity_insulation": 17854
|
||||
},
|
||||
"seller_commission_report": "Y",
|
||||
"energy_consumption_current": 259,
|
||||
"has_fixed_air_conditioning": "false",
|
||||
"multiple_glazed_proportion": 100,
|
||||
"calculation_software_version": "8.0.0",
|
||||
"energy_consumption_potential": 216,
|
||||
"environmental_impact_current": 51,
|
||||
"fixed_lighting_outlets_count": 16,
|
||||
"current_energy_efficiency_band": "D",
|
||||
"environmental_impact_potential": 59,
|
||||
"has_heated_separate_conservatory": "false",
|
||||
"potential_energy_efficiency_band": "D",
|
||||
"co2_emissions_current_per_floor_area": 50,
|
||||
"low_energy_fixed_lighting_outlets_count": 6
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue