From a955a09e9cb9f274d0cd16078d3735f381e82324 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Wed, 17 Jun 2026 10:26:11 +0000 Subject: [PATCH 01/74] Pin uprn_10093116330 (full-SAP gas-combi 2-storey semi): engine 82 vs Elmhurst 78 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 7th sibling full-SAP cert; documented full-SAP→RdSAP +4 residual. Build clean. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../expand-sap-accuracy-corpus/worklist.md | 2 +- .../uprn_10093116330/elmhurst_summary.pdf | Bin 0 -> 63536 bytes .../uprn_10093116330/elmhurst_worksheet.pdf | Bin 0 -> 43031 bytes .../test_real_cert_sap_accuracy.py | 10 ++++++++++ 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116330/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116330/elmhurst_worksheet.pdf diff --git a/.claude/skills/expand-sap-accuracy-corpus/worklist.md b/.claude/skills/expand-sap-accuracy-corpus/worklist.md index c062be22..2890163c 100644 --- a/.claude/skills/expand-sap-accuracy-corpus/worklist.md +++ b/.claude/skills/expand-sap-accuracy-corpus/worklist.md @@ -86,7 +86,7 @@ Skip the 🚩 MVHR / 🚩 heat-pump-fuel and ⛔ sparse certs. - [⚠] 10091636116 — SAP-17.0 · eng 80 / lodged 88 · 🚩 MVHR idx 500249 not credited (flagged) - [ ] 10093049853 — SAP-17.0 · eng 82 / lodged 87 - [ ] 10093390790 — SAP-17.1 · eng 79 / lodged 82 -- [ ] 10093116330 — SAP-17.1 · eng 82 / lodged 83 +- [x] 10093116330 — SAP-17.1 (2017 gas-combi 2-storey semi HOUSE, TFA 73) · eng 82 / elm 78 (lodged 83) · PINNED engine 82. +4 = documented full-SAP→RdSAP residual. Build clean. No mapper change. - [ ] 10093116326 — SAP-17.1 · eng 82 / lodged 82 - [ ] 10090317693 — SAP-17.0 · eng 81 / lodged 88 - [ ] 10090034872 — SAP-17.0 · eng 83 / lodged 85 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116330/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116330/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c830b3f9df45321b08a43c49143548641097f63c GIT binary patch literal 63536 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 literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116330/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093116330/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b1bbad345f894318f2d4bba29446a8b5e286ea81 GIT binary patch literal 43031 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 dY8WCS7_M$6E^dGICT Date: Fri, 19 Jun 2026 09:51:49 +0000 Subject: [PATCH 02/74] more examples --- .../expand-sap-accuracy-corpus/SKILL.md | 53 +- .../expand-sap-accuracy-corpus/worklist.md | 19 +- .../uprn_100021943298/elmhurst_inputs.md | 98 ++++ .../uprn_100021943298/elmhurst_summary.pdf | Bin 0 -> 63418 bytes .../uprn_100021943298/elmhurst_worksheet.pdf | Bin 0 -> 43041 bytes .../uprn_100021943298/epc.json | 232 +++++++++ .../uprn_100020933699/elmhurst_summary.pdf | Bin 0 -> 80690 bytes .../uprn_100020933699/elmhurst_worksheet.pdf | Bin 0 -> 43088 bytes .../uprn_44012843/elmhurst_summary.pdf | Bin 0 -> 62686 bytes .../uprn_44012843/elmhurst_worksheet.pdf | Bin 0 -> 43994 bytes .../uprn_10023444320/elmhurst_summary.pdf | Bin 0 -> 62601 bytes .../uprn_10023444320/elmhurst_worksheet.pdf | Bin 0 -> 23393 bytes .../uprn_10023444324/elmhurst_summary.pdf | Bin 0 -> 62607 bytes .../uprn_10023444324/elmhurst_worksheet.pdf | Bin 0 -> 23365 bytes .../uprn_10096028301/elmhurst_inputs.md | 96 ++++ .../uprn_10096028301/elmhurst_summary.pdf | Bin 0 -> 62575 bytes .../uprn_10096028301/elmhurst_worksheet.pdf | Bin 0 -> 23200 bytes .../uprn_10096028301/epc.json | 456 ++++++++++++++++++ datatypes/epc/domain/mapper.py | 111 ++++- domain/elmhurst/README.md | 28 ++ scripts/hyde/elmhurst_dom/conservatories.json | 6 - scripts/hyde/elmhurst_dom/dimensions.json | 54 ++- scripts/hyde/elmhurst_dom/floors.json | 6 - .../hyde/elmhurst_dom/newtechnologies.json | 6 - scripts/hyde/elmhurst_dom/openings.json | 172 +------ .../elmhurst_dom/propertydescription.json | 71 ++- .../hyde/elmhurst_dom/propertydetails.json | 6 - scripts/hyde/elmhurst_dom/roofs.json | 12 +- scripts/hyde/elmhurst_dom/spaceheating.json | 36 +- .../elmhurst_dom/ventilationandcooling.json | 42 +- scripts/hyde/elmhurst_dom/walls.json | 48 +- scripts/hyde/elmhurst_dom/waterheating.json | 155 +----- scripts/hyde/elmhurst_download.py | 8 +- scripts/hyde/elmhurst_lib.py | 110 +++++ .../test_real_cert_sap_accuracy.py | 93 ++++ 35 files changed, 1467 insertions(+), 451 deletions(-) create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.1/uprn_100021943298/elmhurst_inputs.md create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.1/uprn_100021943298/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.1/uprn_100021943298/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.1/uprn_100021943298/epc.json create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100020933699/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100020933699/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.3/uprn_44012843/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.3/uprn_44012843/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444320/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444320/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444324/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.0/uprn_10023444324/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-19.1.0/uprn_10096028301/elmhurst_inputs.md create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-19.1.0/uprn_10096028301/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-19.1.0/uprn_10096028301/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-19.1.0/uprn_10096028301/epc.json create mode 100644 domain/elmhurst/README.md diff --git a/.claude/skills/expand-sap-accuracy-corpus/SKILL.md b/.claude/skills/expand-sap-accuracy-corpus/SKILL.md index 9c2d4062..437c305e 100644 --- a/.claude/skills/expand-sap-accuracy-corpus/SKILL.md +++ b/.claude/skills/expand-sap-accuracy-corpus/SKILL.md @@ -105,13 +105,52 @@ Pattern: `with E.session() as (ctx,page): E.goto(...); E.set_text/set_select(... default. Pin the engine's observed value; document the Elmhurst delta (don't tune). - **FGHRS** (full-SAP `has_fghrs`/`fghrs_index_number`) is dropped by the mapper and not yet modelled — omit it on BOTH sides so the comparison stays clean. +- **Validation errors live on the Recommendations page as LINKS** (red ✗ anchors), + not coloured spans — parse `[id*=ContentPlaceHolder1] a` text, not CSS colour. + Until Recommendations shows ZERO errors the **Energy Report Summary nav silently + redirects to the Address page** and the worksheet/Results PDFs won't generate + (Results renders empty). Two errors that bit the 16.1/19.1.0 builds: *"Walls + (Main): Insulation Thickness must be entered"* (set the insulation-thickness + dropdown — "Unknown" is fine for a reduced cert) and *"Incorrect Controls (NNNN + ctrl-group-X) for Heating System (idx ctrl-group-Y)"* (the heating control's + system-type must match the boiler's — see the controls dialog below). +- **All Elmhurst modal dialogs sit above a `modalBackground` that defeats element + clicks** (Playwright sees it "intercepting pointer events", even with force). + The cracked pattern is now in `elmhurst_lib.py`: open via JS click, set cascade + ` values by JS (set .value + dispatch 'change') — this drives +# the AutoPostBack cascade without a real click, +# * commit by a raw `page.mouse.click(x, y)` at the OK/Select control's centre +# (coordinate clicks land on the topmost element = the dialog, not the +# background). +# Typing into the boiler search box needs force-click-then-keyboard (the box is +# overlapped); result cells are clicked by coordinate (the model column is +# display:none at >=1024px, so match the row by its Ref-No cell and click the +# first VISIBLE cell). Direct-writing the PCDF reference number is COSMETIC — it +# does NOT re-resolve the boiler type/efficiency; only the search dialog does. +MH1 = ( + "ContentBody_ContentPlaceHolder1_TabContainer_TabPanelMainHeating1_" + "WebUserControlMainHeating1_" +) +HEATING_DIALOG = "ContentBody_OutsideUpdatePanel_SelectHeatingDialog_" + + +def dialog_commit(page: Page, label: str = "OK") -> bool: + """Coordinate-click a dialog's commit control (a styled , e.g. 'OK' or + 'Select') — bypasses the modalBackground that defeats element clicks.""" + pt = page.evaluate( + """(lbl)=>{const e=[...document.querySelectorAll('[id*=SelectHeatingDialog] span,[id*=SelectHeatingDialog] a,[id*=SelectHeatingDialog] input,[id*=SelectBoilerDialog] span')] + .find(x=>new RegExp('^'+lbl+'$','i').test((x.value||x.innerText||'').trim()) && x.offsetParent); + if(!e)return null;const c=e.getBoundingClientRect();return {x:c.x+c.width/2,y:c.y+c.height/2};}""", + label, + ) + if not pt: + return False + page.mouse.click(pt["x"], pt["y"]) + page.wait_for_timeout(SETTLE_MS * 3) + return True + + +def set_heating_dialog(page: Page, open_button_suffix: str, *level_regexes: str) -> None: + """Open a SelectHeatingDialog cascade (water-heating method or main-heating + controls) via the button at FP+`open_button_suffix`, set DropDownList1..N to + the options matching each regex (JS, fires the cascade), then coordinate-OK. + e.g. water (combi): set_heating_dialog(page, MH..ButtonWaterHeatingCode, + 'From Space Heating', 'From the primary heating system'); + control 2106: set_heating_dialog(page, ..ButtonMainHeatingControls, + '^Boilers', '^Standard', 'CBE Programmer, room thermostat and TRVs').""" + page.evaluate("(id)=>{const e=document.getElementById(id); if(e)e.click();}", f"{FP}{open_button_suffix}") + page.wait_for_timeout(SETTLE_MS * 3) + for i, rx in enumerate(level_regexes, start=1): + page.evaluate( + """(a)=>{const s=document.getElementById(a[0]);if(!s)return; + const o=[...s.options].find(o=>new RegExp(a[1],'i').test(o.text)); + if(o){s.value=o.value;s.dispatchEvent(new Event('change',{bubbles:true}));}}""", + [f"{HEATING_DIALOG}DropDownList{i}", rx], + ) + page.wait_for_timeout(SETTLE_MS * 4) # AutoPostBack re-renders the next level + dialog_commit(page, "OK") + + +def select_boiler(page: Page, query: str, ref: str) -> str: + """Set the main-heating boiler to PCDB `ref` via the search dialog. `query` + is a full-text search (brand/model) that surfaces `ref` on page 1. TWO-STEP + commit: click the result ROW (highlights it) then the top 'Select' span.""" + page.evaluate("(id)=>{const e=document.getElementById(id); if(e)e.click();}", f"{MH1}ButtonBoilerReference") + page.wait_for_selector("[id*='SelectBoilerDialog_TextBoxFullSearch']", state="visible", timeout=10_000) + page.locator("[id*='SelectBoilerDialog_TextBoxFullSearch']").click(force=True) + page.keyboard.type(query) + page.locator("[id*='SelectBoilerDialog_HyperLinkActionBoilerSearch']").click(force=True) + page.wait_for_timeout(SETTLE_MS * 4) + pt = page.evaluate( + """(ref)=>{const t=document.querySelector("[id*=SelectBoilerDialog] [id*=GridView]");if(!t)return null; + for(const r of t.querySelectorAll('tr')){const tds=[...r.querySelectorAll('td')]; + if(tds.length>2 && tds[2].innerText.replace(/\\s+/g,' ').trim()===ref){ + const v=tds.find(td=>td.offsetParent&&td.getClientRects().length); + if(v){const c=v.getBoundingClientRect();return {x:c.x+c.width/2,y:c.y+c.height/2};}}}return null;}""", + ref, + ) + if not pt: + return "row-not-found" + page.mouse.click(pt["x"], pt["y"]) # highlight the row + page.wait_for_timeout(SETTLE_MS) + page.locator("[id*=SelectBoilerDialog] span", has_text="Select").filter( + visible=True + ).first.click(force=True, timeout=8_000) + page.wait_for_timeout(SETTLE_MS * 3) + return "ok" + + +def clear_hot_water_cylinder(page: Page, panel: str = "TabContainer_TabPanelWaterHeating_") -> None: + """Uncheck the HW cylinder (combi). The checkbox won't uncheck via + .uncheck()/commit (a regular-boiler default re-asserts it); JS-set + checked=false + fire click + change drives the AutoPostBack.""" + cid = f"{FP}{panel}CheckBoxHotWaterCylinder" + if not page.locator(f"#{cid}").is_checked(): + return + try: + with page.expect_navigation(wait_until="load", timeout=8_000): + page.evaluate( + """(id)=>{const c=document.getElementById(id);if(c){c.checked=false; + c.dispatchEvent(new Event('click',{bubbles:true})); + c.dispatchEvent(new Event('change',{bubbles:true}));}}""", + cid, + ) + except PlaywrightTimeoutError: + page.wait_for_timeout(2_000) 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 715fb053..aa657543 100644 --- a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py +++ b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py @@ -256,6 +256,99 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = ( cert_num="0215-2818-7357-9703-2145", sap_score=61, ), + # UPRN 100021943298 → cert 0498-6963-7270-0822-1980. SAP-Schema-16.1 — a + # reduced-field (RdSAP-shaped) ground-floor FLAT, band B (1900-1929), solid + # brick with internal insulation, mains-gas COMBI (PCDB 10328 Vaillant Ecotec + # Pro 28), double glazed, TFA 78 m². New-schema coverage: mapped via the + # dedicated `from_sap_schema_16_1` → `_normalize_sap_schema_16_x` → + # `from_rdsap_schema_17_1`. Lodged 72 (old 2012 assessment); engine 76. + # Built in Elmhurst RdSAP10 on the mapped inputs (evidence saved: + # elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst worksheet SAP 75 — + # engine within ~1 (continuous 75.70 vs 75), the tightest agreement in the + # cohort because this is reduced-field (both sides use RdSAP age-band/ + # description U-values, not measured). Boiler set to the cert's exact PCDB + # 10328 via the search dialog; control 2106 (CBE programmer + room stat + + # TRVs); water from primary (combi, no cylinder). The ~0.7 residual is minor + # RdSAP defaults (wall thickness 280 vs 300 mm, internal-insulation thickness + # Unknown vs lodged 50 mm). PINNED to the observed 76 — mapping untuned. + RealCertExpectation( + schema="SAP-Schema-16.1", + sample="uprn_100021943298", + cert_num="0498-6963-7270-0822-1980", + sap_score=76, + ), + # UPRN 10096028301 → cert 0390-3321-6060-2405-7985. SAP-Schema-19.1.0 — a + # FULL-SAP ground-floor FLAT (band M 2023+, mains-gas COMBI Ideal Logic Combi + # PCDB 17929, decentralised MEV, measured AP50 3.5, TFA 73 m²). New-schema + # coverage: mapped via the dedicated `from_sap_schema_19_1_0` (parses with the + # 17.1 dataclass, delegates to from_sap_schema_17_1). Lodged 85; engine 82. + # Built in Elmhurst RdSAP10 on the mapped inputs (evidence saved: + # elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst worksheet SAP 82 — + # engine EXACTLY matches (82.11 vs 82), and engine-on-Elmhurst's-own-parsed- + # inputs is 82.16 ≈ 82, so the calculator is confirmed faithful on identical + # inputs. Boiler set to the cert's exact PCDB 17929 via the search dialog; + # control 2106 (CBE); water from primary (combi); MEV on; AP50 Blower Door 3.5. + # The −3 vs lodged 85 is the documented full-SAP→RdSAP gap: the engine uses the + # cert's MEASURED U (wall 0.24 / floor 0.13, WORSE than RdSAP band-M defaults) + # + MEV priced as extract loss not heat recovery. PINNED to the observed 82 — + # mapping untuned; engine == Elmhurst. + RealCertExpectation( + schema="SAP-Schema-19.1.0", + sample="uprn_10096028301", + cert_num="0390-3321-6060-2405-7985", + sap_score=82, + ), + # UPRN 44012843 → cert 0775-2898-6628-9594-8005. SAP-Schema-16.3 — a + # reduced-field (RdSAP-shaped) ground-floor FLAT, band K (2007-2011), cavity + # insulated, mains-gas REGULAR boiler (PCDB 9895 Ideal icos HE15) + cylinder, + # double glazed, TFA 55 m². New-schema coverage via the dedicated + # `from_sap_schema_16_3` → `_normalize_sap_schema_16_x` → from_rdsap_schema_17_1. + # Lodged 81; engine 79. Built in Elmhurst RdSAP10 on the mapped inputs + # (evidence saved: elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst + # worksheet SAP 78 — engine within ~1 (continuous 78.82 vs 78), and engine-on- + # Elmhurst's-own-parsed-inputs is 78.48 ≈ 78 → calculator confirmed faithful. + # Boiler set to the cert's exact PCDB 9895 via the search dialog; control 2106 + # (CBE); regular boiler + cylinder (Large, foam, 50 mm), water from primary. + # The −2 vs lodged 81 is reduced-field RdSAP defaults. PINNED to the observed + # 79 — mapping untuned. + RealCertExpectation( + schema="SAP-Schema-16.3", + sample="uprn_44012843", + cert_num="0775-2898-6628-9594-8005", + sap_score=79, + ), + # UPRN 10023444324 → cert 8501-5064-6739-1407-0163. SAP-Schema-17.0 — a + # FULL-SAP ground-floor FLAT (band M, mains-gas COMBI Ideal Logic+ combi 35 + # PCDB 16211, decentralised MEV, measured AP50 3.2, lodged party wall 6.43 m, + # TFA 50 m²). Full-SAP shape ≡ 17.1, dispatched via from_sap_schema_17_1. + # Lodged 82; engine 80. Built in Elmhurst RdSAP10 on the mapped inputs + # (evidence saved: elmhurst_summary.pdf / elmhurst_worksheet.pdf): Elmhurst + # worksheet SAP 80 — engine EXACTLY matches (80.13 vs 80); engine-on-Elmhurst's- + # own-parsed-inputs 81.03 ≈ 80 → calculator faithful. Boiler set to the cert's + # exact PCDB 16211 via the search dialog; control 2106 (CBE); water from primary + # (combi); MEV on; AP50 Blower Door 3.2; party wall 6.43 m entered. The −2 vs + # lodged 82 is the documented full-SAP→RdSAP gap (measured U 0.2/0.1 + MEV + # extract loss). PINNED to the observed 80 — mapping untuned; engine == Elmhurst. + RealCertExpectation( + schema="SAP-Schema-17.0", + sample="uprn_10023444324", + cert_num="8501-5064-6739-1407-0163", + sap_score=80, + ), + # UPRN 10023444320 → cert 0868-6045-7331-4376-0914. SAP-Schema-17.0 — FULL-SAP + # MID-FLOOR FLAT (sibling of 10023444324, same block / combi PCDB 16211 / MEV), + # band M, no party wall, floor + roof both to other dwellings, TFA 50.68 m². + # Lodged 81; engine 81. Built in Elmhurst RdSAP10 (evidence saved): Elmhurst + # worksheet 82 — engine within ~1 (81.38 vs 82); engine-on-Elmhurst-inputs 82.46 + # ≈ 82 → calculator faithful. Boiler PCDB 16211 via search; control 2106 (CBE); + # water from primary (combi); MEV on; AP50 Blower Door 3.09; mid-floor (floor = + # another dwelling below). PINNED to the observed 81 — mapping untuned. + RealCertExpectation( + schema="SAP-Schema-17.0", + sample="uprn_10023444320", + cert_num="0868-6045-7331-4376-0914", + sap_score=81, + ), ) From 37b0a384257a1d408353d2d6130831c229ac6e04 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 10:59:51 +0000 Subject: [PATCH 03/74] add more test cases --- .../expand-sap-accuracy-corpus/worklist.md | 2 +- .../uprn_10090844932/elmhurst_summary.pdf | Bin 0 -> 63489 bytes .../uprn_10090844932/elmhurst_worksheet.pdf | Bin 0 -> 44321 bytes scripts/hyde/elmhurst_download.py | 2 +- .../test_real_cert_sap_accuracy.py | 15 +++++++++++++++ 5 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_10090844932/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_10090844932/elmhurst_worksheet.pdf diff --git a/.claude/skills/expand-sap-accuracy-corpus/worklist.md b/.claude/skills/expand-sap-accuracy-corpus/worklist.md index 0c331804..e4db5aa5 100644 --- a/.claude/skills/expand-sap-accuracy-corpus/worklist.md +++ b/.claude/skills/expand-sap-accuracy-corpus/worklist.md @@ -58,7 +58,7 @@ Skip the 🚩 MVHR / 🚩 heat-pump-fuel and ⛔ sparse certs. - [x] 🔧 10023444324 — SAP-17.0 (full-SAP g/f FLAT, band M, combi PCDB 16211, MEV, AP50 3.2, party wall 6.43) · eng 80 / elm 80 (lodged 82) · PINNED engine 80. Built in Elmhurst (boiler 16211 via search, control CBE/2106, water from primary, MEV on, AP50 Blower Door 3.2, party wall 6.43). Engine EXACTLY matches Elmhurst worksheet (80.13 vs 80); engine-on-Elmhurst-inputs 81.03 ≈ 80 → calculator faithful. −2 vs lodged = full-SAP→RdSAP residual (measured U + MEV). No mapper change beyond coverage. - [⚠] 10092970673 — SAP-17.0 · eng 77 / lodged 86 · 🚩 MVHR idx 500418 not credited (flagged) - [⚠] 10094601287 — SAP-18.0.0 · eng 80 / lodged 84 · 🚩 MVHR idx 500230 not credited (flagged) -- [ ] 10090844932 — RdSAP-20.0.0 · eng 78 / lodged 78 +- [x] 10090844932 — RdSAP-20.0.0 (end-terrace HOUSE 2-storey, band L, combi PCDB 10327, party wall 4.93, 250mm loft) · eng 78 / elm 77 (lodged 78) · PINNED engine 78. Built in Elmhurst (House, boiler 10327 via search, control CBE/2106, water from primary, party wall 4.93 filled). Within ~1 (78.13 vs 77); engine-on-Elmhurst-inputs 77.24 ≈ 77 → faithful. - [⛔] 10090844948 — SAP-16.3 · NOT MAPPABLE (ValueError: RdSapSchema17_1: missing required field ) - [ ] 100090182288 — SAP-16.2 · eng 71 / lodged 71 - [⚠] 10093114053 — SAP-17.0 · eng 93 / lodged 79 · 🚩 heat-pump fuel-39 (flagged) diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_10090844932/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_10090844932/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e6335fd0fea43d1f74a843783a29432ddfa6b2bc GIT binary patch literal 63489 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 literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_10090844932/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-20.0.0/uprn_10090844932/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0effc7b72e51ac47cb31c5dbcf9c73e867b90655 GIT binary patch literal 44321 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 literal 0 HcmV?d00001 diff --git a/scripts/hyde/elmhurst_download.py b/scripts/hyde/elmhurst_download.py index 418d9dbe..3ef55011 100644 --- a/scripts/hyde/elmhurst_download.py +++ b/scripts/hyde/elmhurst_download.py @@ -28,7 +28,7 @@ SESSION_DIR = HERE / ".elmhurst-session" SAMPLE_DIR = ( HERE.parent.parent / "backend/epc_api/json_samples/real_life_examples" - / "SAP-Schema-17.0/uprn_10023444320" + / "RdSAP-Schema-20.0.0/uprn_10090844932" ) ASSESSMENT_GUID = "B44A0DB4-4C08-4241-B818-86F060172105" 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 aa657543..7deb4449 100644 --- a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py +++ b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py @@ -349,6 +349,21 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = ( cert_num="0868-6045-7331-4376-0914", sap_score=81, ), + # UPRN 10090844932 → cert 0646-3008-6208-0619-6204. RdSAP-Schema-20.0.0 — + # END-TERRACE HOUSE, 2-storey, band L (2012-2022), cavity insulated, pitched + # roof 250 mm loft insulation, mains-gas COMBI (PCDB 10327 Vaillant Ecotec Plus + # 831), double glazed, lodged party wall 4.93 m, TFA 74.7 m². Native RdSAP + # (from_rdsap_schema_20_0_0). Lodged 78; engine 78. Built in Elmhurst RdSAP10 + # (evidence saved): Elmhurst worksheet 77 — engine within ~1 (78.13 vs 77); + # engine-on-Elmhurst-inputs 77.24 ≈ 77 → calculator faithful. Boiler PCDB 10327 + # via search; control 2106 (CBE); water from primary (combi); party wall 4.93 m + # (filled cavity). PINNED to the observed 78 — mapping untuned. + RealCertExpectation( + schema="RdSAP-Schema-20.0.0", + sample="uprn_10090844932", + cert_num="0646-3008-6208-0619-6204", + sap_score=78, + ), ) From 360e069386e0205499e63d0bdfc4c858ec183fa0 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 11:07:30 +0000 Subject: [PATCH 04/74] hubspot etl 20 in parrell --- deployment/terraform/lambda/hubspot_deal_etl/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/terraform/lambda/hubspot_deal_etl/variables.tf b/deployment/terraform/lambda/hubspot_deal_etl/variables.tf index 84f0e567..189822f0 100644 --- a/deployment/terraform/lambda/hubspot_deal_etl/variables.tf +++ b/deployment/terraform/lambda/hubspot_deal_etl/variables.tf @@ -19,7 +19,7 @@ variable "image_digest" { variable "maximum_concurrency" { type = number - default = 2 + default = 20 description = "Maximum number of concurrent Lambda invocations from SQS (2-1000). null = no limit." } From 240d7b102513e8d9430d760b0add12d24184a20e Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:07:32 +0000 Subject: [PATCH 05/74] =?UTF-8?q?Resolve=20a=20landlord=20mains-gas=20over?= =?UTF-8?q?ride=20to=20the=20primary=20fuel=20code=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property_overlays/main_fuel_overlay.py | 22 +++++++++++++++++++ tests/domain/epc/test_main_fuel_overlay.py | 19 ++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 domain/epc/property_overlays/main_fuel_overlay.py create mode 100644 tests/domain/epc/test_main_fuel_overlay.py diff --git a/domain/epc/property_overlays/main_fuel_overlay.py b/domain/epc/property_overlays/main_fuel_overlay.py new file mode 100644 index 00000000..4d721865 --- /dev/null +++ b/domain/epc/property_overlays/main_fuel_overlay.py @@ -0,0 +1,22 @@ +"""Map a Landlord-Override main-fuel value to a heating Simulation Overlay. + +A main-fuel value is one canonical gov-EPC `main_fuel` description ("mains gas", +"electricity", …). The calculator reads the dwelling's primary fuel from +`main_heating_details[0].main_fuel_type` as the RdSAP **int code**, so the +overlay decomposes the value into that code and emits a whole-dwelling +`HeatingOverlay` (fuel is not a per-building-part attribute, so `building_part` +is ignored). Codes follow the modern RdSAP-20/21 `(not community)` family the +gov-EPC API baseline uses. Unresolvable values produce no overlay. +""" + +from __future__ import annotations + +from typing import Optional + +from domain.modelling.simulation import EpcSimulation + + +def fuel_overlay_for( + main_fuel_value: str, building_part: int +) -> Optional[EpcSimulation]: + raise NotImplementedError diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py new file mode 100644 index 00000000..96072c1d --- /dev/null +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -0,0 +1,19 @@ +"""The Landlord-Override main-fuel → heating Simulation Overlay mapping. + +A main-fuel value resolves to the RdSAP `main_fuel_type` int code the calculator +reads from the dwelling's primary heating system; the overlay is whole-dwelling. +""" + +from __future__ import annotations + +from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for + + +def test_mains_gas_overlays_the_primary_fuel() -> None: + # Act + simulation = fuel_overlay_for("mains gas", 0) + + # Assert — mains gas (not community) is RdSAP main_fuel code 26. + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.main_fuel_type == 26 From 0e85da15079e9f3d9f99c8e35a9d3eb64593ed5b Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:15:54 +0000 Subject: [PATCH 06/74] =?UTF-8?q?Resolve=20a=20landlord=20mains-gas=20over?= =?UTF-8?q?ride=20to=20the=20primary=20fuel=20code=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property_overlays/main_fuel_overlay.py | 12 +- scripts/fill_domna_addresses.py | 353 ++++++++++++++++++ scripts/finalise_to_property_table.py | 331 ++++++++++++++++ scripts/hyde_epc_schema_versions.py | 159 ++++++++ scripts/lisasrequest/compare_to_ara.py | 169 +++++++++ .../lisasrequest/durkan_805_schema_check.py | 142 +++++++ scripts/lisasrequest/fill_domna_address.py | 200 ++++++++++ .../finalise_to_property_table.py | 111 ++++++ .../resolve_uprns_for_finaliser.py | 212 +++++++++++ scripts/lisasrequest/review_flags.py | 135 +++++++ scripts/resolve_uprns_for_finaliser.py | 328 ++++++++++++++++ 11 files changed, 2150 insertions(+), 2 deletions(-) create mode 100644 scripts/fill_domna_addresses.py create mode 100644 scripts/finalise_to_property_table.py create mode 100644 scripts/hyde_epc_schema_versions.py create mode 100644 scripts/lisasrequest/compare_to_ara.py create mode 100644 scripts/lisasrequest/durkan_805_schema_check.py create mode 100644 scripts/lisasrequest/fill_domna_address.py create mode 100644 scripts/lisasrequest/finalise_to_property_table.py create mode 100644 scripts/lisasrequest/resolve_uprns_for_finaliser.py create mode 100644 scripts/lisasrequest/review_flags.py create mode 100644 scripts/resolve_uprns_for_finaliser.py diff --git a/domain/epc/property_overlays/main_fuel_overlay.py b/domain/epc/property_overlays/main_fuel_overlay.py index 4d721865..9118c0c9 100644 --- a/domain/epc/property_overlays/main_fuel_overlay.py +++ b/domain/epc/property_overlays/main_fuel_overlay.py @@ -13,10 +13,18 @@ from __future__ import annotations from typing import Optional -from domain.modelling.simulation import EpcSimulation +from domain.modelling.simulation import EpcSimulation, HeatingOverlay + +# RdSAP-20/21 `main_fuel` `(not community)` codes (epc_codes.csv `main_fuel`). +_FUEL_CODES: dict[str, int] = { + "mains gas": 26, +} def fuel_overlay_for( main_fuel_value: str, building_part: int ) -> Optional[EpcSimulation]: - raise NotImplementedError + code = _FUEL_CODES.get(main_fuel_value) + if code is None: + return None + return EpcSimulation(heating=HeatingOverlay(main_fuel_type=code)) diff --git a/scripts/fill_domna_addresses.py b/scripts/fill_domna_addresses.py new file mode 100644 index 00000000..e4a7e18b --- /dev/null +++ b/scripts/fill_domna_addresses.py @@ -0,0 +1,353 @@ +"""Fill the DOMNA columns in the AddressProfilingResults spreadsheet. + +Input: scripts/manipulation(2).xlsx, sheet "AddressProfilingResults", columns + Organisation Reference | UPRN | DOMNA FOUND UPRN | DOMNA FOUND ADDRESS | Address | Postcode + +Per-row rule ("if there's a UPRN in the UPRN column we're done"): + + * UPRN present AND Address present -> nothing to do (already sorted). + * UPRN present AND Address missing -> reverse-lookup the address from the UPRN + via the EPC API -> DOMNA FOUND ADDRESS. + * UPRN missing AND Address present -> resolve a UPRN from address + postcode + (EPC API, then Ordnance Survey) -> writes + DOMNA FOUND UPRN + DOMNA FOUND ADDRESS. + * not resolvable -> marked "NOT FOUND" and listed in the + unresolved report. + +Relaxed matching (this batch only — production AddressMatch is untouched): the +landlord writes flats as "3 GLADYS COURT" while EPC stores "Flat 3 Gladys +Court", which the production matcher hard-rejects. So per address we try several +query variants — the full string, just the first comma-segment, and a +"Flat ..." form — and keep the best-scoring, unambiguous match. The unit +number must still match exactly (AddressMatch zeroes mismatched numbers), so a +wrong-unit match stays unlikely. Each fill carries its score + source so you can +spot-check (DOMNA SCORE / DOMNA SOURCE). + +Rows that already have a DOMNA FOUND UPRN are skipped (idempotent / resumable). + + python -m scripts.fill_domna_addresses + python -m scripts.fill_domna_addresses --limit 200 # smoke test first N + +Keys come from backend/.env (OPEN_EPC_API_TOKEN, ORDNANCE_SURVEY_API_KEY). Run +from the worktree root (import trap). +""" + +from __future__ import annotations + +import argparse +import os +import re +import sys +from pathlib import Path +from typing import Optional + +import pandas as pd + +_REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from backend.address2UPRN.main import get_epc_data_with_postcode # noqa: E402 +from backend.address2UPRN.scoring import all_uprns_match, rank_address_similarity # noqa: E402 +from backend.ordnanceSurvey.helpers import ( # noqa: E402 + lookup_os_places, + os_places_results_to_dataframe, +) +from backend.utils.addressMatch import AddressMatch # noqa: E402 +from datatypes.epc.search import EpcSearchResult # noqa: E402 +from infrastructure.epc_client.epc_client_service import EpcClientService # noqa: E402 +from scripts.resolve_uprns_for_finaliser import clean_postcode, load_keys # noqa: E402 + +SHEET = "AddressProfilingResults" +UPRN_COL = "UPRN" +ADDRESS_COL = "Address" +POSTCODE_COL = "Postcode" +REF_COL = "Organisation Reference" +FOUND_UPRN_COL = "DOMNA FOUND UPRN" +FOUND_ADDRESS_COL = "DOMNA FOUND ADDRESS" +SCORE_COL = "DOMNA SCORE" +SOURCE_COL = "DOMNA SOURCE" +NOT_FOUND = "NOT FOUND" + +# EPC matches are tight (short addresses) so we hold the production 0.7 bar; OS +# addresses carry more trailing tokens, so a slightly lower bar is appropriate. +EPC_THRESHOLD = 0.7 +OS_THRESHOLD = 0.6 + +_DEFAULT_IN = _REPO_ROOT / "scripts" / "manipulation(2).xlsx" +_DEFAULT_OUT = _REPO_ROOT / "scripts" / "manipulation_filled.xlsx" +_DEFAULT_UNRESOLVED = _REPO_ROOT / "scripts" / "manipulation_unresolved.csv" + +# A resolved hit: (uprn, matched_address, score, source). +Hit = tuple[str, str, float, str] + + +def cell_str(value: object) -> str: + """Coerce a spreadsheet cell to a trimmed string ("" for NaN/None).""" + if value is None: + return "" + text = str(value).strip() + return "" if text.lower() == "nan" else text + + +def parse_uprn_cell(value: object) -> Optional[int]: + """Read a UPRN cell that pandas loaded as float64 back into an int.""" + text = cell_str(value) + if not text: + return None + try: + return int(float(text)) + except ValueError: + return None + + +def address_variants(address: str) -> list[str]: + """Query forms to try for one input address, best-discriminating first. + + Landlord flats read "3 GLADYS COURT, 260 REIGATE ROAD" but EPC stores + "Flat 3 Gladys Court"; the full string scores low (extra tokens) and the + bare "3 ..." trips the flat guard. So we also try the first comma-segment + and a "Flat " form. + """ + address = address.strip() + first = address.split(",")[0].strip() + variants = [address, first] + if re.match(r"^\d", first): # starts with a unit/house number + variants.append("Flat " + first) + variants.append("Flat " + address) + seen: set[str] = set() + out: list[str] = [] + for v in variants: + key = v.lower() + if v and key not in seen: + seen.add(key) + out.append(v) + return out + + +def resolve_epc_relaxed( + address: str, + postcode_clean: str, + epc_cache: dict[str, pd.DataFrame], + threshold: float = EPC_THRESHOLD, +) -> Optional[Hit]: + """Best unambiguous EPC match across the address variants (cached per postcode).""" + epc_df = epc_cache.get(postcode_clean) + if epc_df is None: + epc_df = get_epc_data_with_postcode(postcode=postcode_clean) + epc_cache[postcode_clean] = epc_df + if epc_df.empty: + return None + + best: Optional[Hit] = None + for variant in address_variants(address): + scored = rank_address_similarity(epc_df, user_address=variant) + if scored.empty: + continue + score = float(scored.iloc[0]["lexiscore"]) + if best is not None and score <= best[2]: + continue + top_rank = scored[scored["lexirank"] == 1] + # rank-1 rows must agree on one UPRN, else it's ambiguous — skip. + if not all_uprns_match(top_rank, top_rank.iloc[0]["uprn"]): + continue + uprn = str(top_rank.iloc[0]["uprn"]) + if uprn in ("", "nan"): + continue + best = (uprn, str(scored.iloc[0]["address"]), score, "epc") + + return best if best is not None and best[2] >= threshold else None + + +def resolve_os_relaxed( + address: str, + postcode_clean: str, + os_api_key: str, + os_cache: dict[str, pd.DataFrame], + threshold: float = OS_THRESHOLD, +) -> Optional[Hit]: + """Best OS Places match across the address variants (cached per postcode).""" + places_df = os_cache.get(postcode_clean) + if places_df is None: + response = lookup_os_places(postcode_clean, os_api_key) + if response.get("status") == 200 and "data" in response: + places_df = os_places_results_to_dataframe(response["data"]) + else: + places_df = pd.DataFrame() + os_cache[postcode_clean] = places_df + if places_df.empty or "ADDRESS" not in places_df.columns: + return None + + records: list[dict[str, object]] = places_df.to_dict(orient="records") + best: Optional[Hit] = None + for variant in address_variants(address): + for rec in records: + candidate = str(rec.get("ADDRESS", "")) + score = AddressMatch.score(variant, candidate) + if best is None or score > best[2]: + best = (str(rec.get("UPRN", "")), candidate, score, "ordnance_survey") + return best if best is not None and best[2] >= threshold else None + + +def _address_from_search(result: EpcSearchResult) -> str: + parts = [ + result.address_line_1, + result.address_line_2, + result.address_line_3, + result.address_line_4, + result.post_town, + ] + return ", ".join(p.strip() for p in parts if p and p.strip()) + + +def reverse_address_from_uprn( + uprn: int, + postcode_clean: str, + service: EpcClientService, + search_cache: dict[str, list[EpcSearchResult]], +) -> Optional[str]: + """Find the EPC address for a known UPRN by searching its postcode (cached).""" + results = search_cache.get(postcode_clean) + if results is None: + results = service.search_by_postcode(postcode_clean) + search_cache[postcode_clean] = results + for result in results: + if result.uprn is not None and int(result.uprn) == uprn: + return _address_from_search(result) + return None + + +def fill(df: pd.DataFrame, *, os_api_key: Optional[str]) -> list[dict[str, str]]: + """Fill the DOMNA columns in place. Returns the unresolved rows.""" + for col in (FOUND_UPRN_COL, FOUND_ADDRESS_COL, SCORE_COL, SOURCE_COL): + if col not in df.columns: + df[col] = "" + df[FOUND_UPRN_COL] = df[FOUND_UPRN_COL].astype("object") + df[FOUND_ADDRESS_COL] = df[FOUND_ADDRESS_COL].astype("object") + + token = os.environ.get("OPEN_EPC_API_TOKEN") + service = EpcClientService(auth_token=token) if token else None + epc_cache: dict[str, pd.DataFrame] = {} + os_cache: dict[str, pd.DataFrame] = {} + search_cache: dict[str, list[EpcSearchResult]] = {} + + unresolved: list[dict[str, str]] = [] + resolved_uprn = resolved_addr = skipped = 0 + total = len(df) + + for n, idx in enumerate(df.index, start=1): + ref = cell_str(df.at[idx, REF_COL]) + given_uprn = parse_uprn_cell(df.at[idx, UPRN_COL]) + address = cell_str(df.at[idx, ADDRESS_COL]) + postcode_raw = cell_str(df.at[idx, POSTCODE_COL]) + postcode_clean = clean_postcode(postcode_raw) + + # Already sorted (UPRN + address) or already filled by a prior run. + if given_uprn is not None and address: + skipped += 1 + continue + if cell_str(df.at[idx, FOUND_UPRN_COL]) and cell_str(df.at[idx, FOUND_UPRN_COL]) != NOT_FOUND: + skipped += 1 + continue + + def mark_not_found(reason: str) -> None: + df.at[idx, FOUND_UPRN_COL] = NOT_FOUND if given_uprn is None else "" + df.at[idx, FOUND_ADDRESS_COL] = NOT_FOUND + df.at[idx, SOURCE_COL] = "not_found" + unresolved.append( + { + "Organisation Reference": ref, + "reason": reason, + "Address": address, + "Postcode": postcode_raw, + } + ) + + # Case B — UPRN present, address missing: reverse-lookup the address. + if given_uprn is not None and not address: + found: Optional[str] = None + if service is not None and postcode_clean: + try: + found = reverse_address_from_uprn( + given_uprn, postcode_clean, service, search_cache + ) + except Exception as exc: + print(f" reverse failed {ref} {given_uprn}: {exc}") + if found: + df.at[idx, FOUND_ADDRESS_COL] = found + df.at[idx, SOURCE_COL] = "epc_reverse" + resolved_addr += 1 + else: + mark_not_found("no address for UPRN") + continue + + # Case A — no UPRN, has address: resolve a UPRN. + if given_uprn is None and address: + if not postcode_clean: + mark_not_found("no postcode") + continue + hit: Optional[Hit] = None + if token: + try: + hit = resolve_epc_relaxed(address, postcode_clean, epc_cache) + except Exception as exc: + print(f" EPC failed {ref} {postcode_clean}: {exc}") + if hit is None and os_api_key: + try: + hit = resolve_os_relaxed(address, postcode_clean, os_api_key, os_cache) + except Exception as exc: + print(f" OS failed {ref} {postcode_clean}: {exc}") + if hit is not None: + uprn, matched, score, source = hit + df.at[idx, FOUND_UPRN_COL] = uprn + df.at[idx, FOUND_ADDRESS_COL] = matched + df.at[idx, SCORE_COL] = round(score, 4) + df.at[idx, SOURCE_COL] = source + resolved_uprn += 1 + else: + mark_not_found("no UPRN match") + if n % 100 == 0: + print( + f"[{n}/{total}] resolved={resolved_uprn} not_found={len(unresolved)}" + ) + continue + + # Case C — neither a UPRN nor an address. + mark_not_found("no UPRN and no address") + + print( + f"\nResolved {resolved_uprn} UPRNs, {resolved_addr} addresses; " + f"{skipped} already sorted/done; {len(unresolved)} not found." + ) + return unresolved + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--in", dest="inp", type=Path, default=_DEFAULT_IN) + parser.add_argument("--out", type=Path, default=_DEFAULT_OUT) + parser.add_argument("--unresolved", type=Path, default=_DEFAULT_UNRESOLVED) + parser.add_argument("--limit", type=int, default=None, help="process first N rows") + return parser.parse_args() + + +def main() -> int: + args = _parse_args() + _epc_token, os_api_key = load_keys() + + df = pd.read_excel(args.inp, sheet_name=SHEET) + if args.limit is not None: + df = df.head(args.limit).copy() + print(f"Loaded {len(df)} rows from {args.inp} [{SHEET}]") + + unresolved = fill(df, os_api_key=os_api_key) + + df.to_excel(args.out, sheet_name=SHEET, index=False) + print(f"Wrote filled sheet -> {args.out}") + if unresolved: + pd.DataFrame(unresolved).to_csv(args.unresolved, index=False) + print(f"Wrote {len(unresolved)} unresolved rows -> {args.unresolved}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/finalise_to_property_table.py b/scripts/finalise_to_property_table.py new file mode 100644 index 00000000..751e8c59 --- /dev/null +++ b/scripts/finalise_to_property_table.py @@ -0,0 +1,331 @@ +"""Insert resolved manipulation_filled rows into the FE-owned ``property`` table. + +Reuses the bulk_upload_finaliser's own row->PropertyIdentityInsert mapping +(``BulkUploadFinaliserOrchestrator._row_to_insert``) and the same +``PropertyPostgresRepository.insert_all`` the Lambda uses, so a row inserted here +is identical to one the real finaliser would write. The status-writer / +property_overrides path is skipped — this only populates ``property`` (no +BulkUpload task needed). + +Insert is ON CONFLICT (portfolio_id, uprn) DO NOTHING, so re-running is safe. + + # one random resolved row into portfolio 796, then read it back + python -m scripts.finalise_to_property_table --portfolio 796 --one + + # a specific Organisation Reference + python -m scripts.finalise_to_property_table --portfolio 796 --ref 56100000101 + + # the whole sheet (resolved rows only by default; --include-unmatched to add + # null-UPRN rows too) + python -m scripts.finalise_to_property_table --portfolio 796 --all + +Postgres target comes from the root .env (POSTGRES_*). Run from the worktree root. +""" + +from __future__ import annotations + +import argparse +import os +import sys +from pathlib import Path +from typing import Optional + +import pandas as pd +from dotenv import load_dotenv +from sqlmodel import select + +_REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from infrastructure.postgres.config import PostgresConfig # noqa: E402 +from infrastructure.postgres.engine import commit_scope, make_engine, make_session # noqa: E402 +from infrastructure.postgres.property_table import PropertyRow # noqa: E402 +from orchestration.bulk_upload_finaliser_orchestrator import ( # noqa: E402 + BulkUploadFinaliserOrchestrator, +) +from repositories.property.property_postgres_repository import ( # noqa: E402 + PropertyPostgresRepository, +) +from repositories.property.property_repository import PropertyIdentityInsert # noqa: E402 +from scripts.fill_domna_addresses import ( # noqa: E402 + ADDRESS_COL, + FOUND_ADDRESS_COL, + FOUND_UPRN_COL, + POSTCODE_COL, + REF_COL, + SCORE_COL, + SHEET, + UPRN_COL, + NOT_FOUND, + cell_str, + parse_uprn_cell, +) + +_DEFAULT_IN = _REPO_ROOT / "scripts" / "manipulation_filled.xlsx" + + +def _final_uprn(row: pd.Series) -> Optional[int]: + """The authoritative UPRN: the given one, else the DOMNA-found one.""" + given = parse_uprn_cell(row.get(UPRN_COL)) + if given is not None: + return given + found = cell_str(row.get(FOUND_UPRN_COL)) + if found and found != NOT_FOUND: + return parse_uprn_cell(found) + return None + + +def to_combiner_row(row: pd.Series) -> dict[str, str]: + """Map one spreadsheet row to the combiner-output shape the finaliser reads.""" + given_uprn = parse_uprn_cell(row.get(UPRN_COL)) + address = cell_str(row.get(ADDRESS_COL)) + uprn = _final_uprn(row) + + domna_addr = cell_str(row.get(FOUND_ADDRESS_COL)) + if domna_addr == NOT_FOUND: + domna_addr = "" + # Matched address: the resolved one when we found it, else the given address + # (for rows that already had a UPRN + address). + matched = domna_addr or (address if given_uprn is not None else "") + score = cell_str(row.get(SCORE_COL)) + + return { + "Address 1": address, + "Address 2": "", + "Address 3": "", + "postcode": cell_str(row.get(POSTCODE_COL)), + "Internal Reference": cell_str(row.get(REF_COL)), + "address2uprn_uprn": "" if uprn is None else str(uprn), + "address2uprn_address": matched, + "address2uprn_lexiscore": score, + } + + +def load_rows( + path: Path, *, include_unmatched: bool +) -> tuple[pd.DataFrame, list[dict[str, str]]]: + """Load the sheet and the combiner rows. By default drop rows with no UPRN.""" + df = pd.read_excel(path, sheet_name=SHEET) + df = df.reset_index(drop=True) + if not include_unmatched: + keep = df.apply(lambda r: _final_uprn(r) is not None, axis=1) + df = df[keep].reset_index(drop=True) + rows = [to_combiner_row(r) for _, r in df.iterrows()] + return df, rows + + +def dedupe_by_uprn( + rows: list[dict[str, str]], +) -> tuple[list[dict[str, str]], list[dict[str, str]]]: + """Keep the first row per UPRN; return (kept, dropped collisions). + + The DB INSERT collapses duplicate (portfolio, uprn) via ON CONFLICT DO + NOTHING anyway, so this just makes the collision explicit (the dropped rows + are written out for review) rather than letting an arbitrary ref win silently. + """ + seen: set[str] = set() + kept: list[dict[str, str]] = [] + dropped: list[dict[str, str]] = [] + for row in rows: + uprn = row["address2uprn_uprn"] + if uprn in seen: + dropped.append(row) + else: + seen.add(uprn) + kept.append(row) + return kept, dropped + + +# Force-reload teardown order (bottom-up). property_overrides is ON DELETE +# CASCADE so it clears itself when the property goes; everything below is NO +# ACTION and must be deleted first, deepest child first. +# property -> epc_property -> {these children} +_EPC_CHILD_TABLES = ( + "epc_energy_element", + "epc_window", + "epc_main_heating_detail", + "epc_renewable_heat_incentive", + "epc_building_part", + "epc_flat_details", +) +# property -> {these direct dependents}, deleted after the epc children +_PROPERTY_DEPENDENTS = ("epc_property", "plan") +_INSERT_CHUNK = 4000 # 9 cols/row -> well under psycopg2's 65535-param limit + + +def _reset_portfolio(session: object, portfolio_id: int) -> int: + """Delete a portfolio's properties and their NO ACTION dependency tree. + + Returns the number of property rows deleted (property_overrides cascade). + """ + from sqlalchemy import text + + pids = "SELECT id FROM property WHERE portfolio_id = :pid" + epc_ids = f"SELECT id FROM epc_property WHERE property_id IN ({pids})" + for table in _EPC_CHILD_TABLES: + session.execute( # type: ignore[attr-defined] + text(f"DELETE FROM {table} WHERE epc_property_id IN ({epc_ids})"), + {"pid": portfolio_id}, + ) + for table in _PROPERTY_DEPENDENTS: + session.execute( # type: ignore[attr-defined] + text(f"DELETE FROM {table} WHERE property_id IN ({pids})"), + {"pid": portfolio_id}, + ) + result = session.execute( # type: ignore[attr-defined] + text("DELETE FROM property WHERE portfolio_id = :pid"), {"pid": portfolio_id} + ) + return result.rowcount + + +def clean_reload( + rows: list[dict[str, str]], portfolio_id: int, *, reset: bool +) -> tuple[int, int]: + """Optionally wipe the portfolio, then chunk-insert rows. One transaction. + + Returns (properties_deleted, properties_inserted). + """ + inserts: list[PropertyIdentityInsert] = [ + BulkUploadFinaliserOrchestrator._row_to_insert(r, portfolio_id) for r in rows + ] + engine = _engine() + session = make_session(engine) + deleted = 0 + inserted = 0 + try: + repo = PropertyPostgresRepository(session) + with commit_scope(session): + if reset: + deleted = _reset_portfolio(session, portfolio_id) + for start in range(0, len(inserts), _INSERT_CHUNK): + inserted += repo.insert_all(inserts[start : start + _INSERT_CHUNK]) + finally: + session.close() + return deleted, inserted + + +def _engine(): + load_dotenv(_REPO_ROOT / ".env") + return make_engine(PostgresConfig.from_env(os.environ)) + + +def insert_rows(rows: list[dict[str, str]], portfolio_id: int) -> int: + """Insert via the finaliser's mapper + repository. Returns rows inserted.""" + inserts: list[PropertyIdentityInsert] = [ + BulkUploadFinaliserOrchestrator._row_to_insert(r, portfolio_id) for r in rows + ] + engine = _engine() + session = make_session(engine) + try: + repo = PropertyPostgresRepository(session) + with commit_scope(session): + inserted = repo.insert_all(inserts) + finally: + session.close() + return inserted + + +def fetch_by_ref(portfolio_id: int, ref: str) -> list[PropertyRow]: + """Read back inserted rows for one Organisation Reference (for verification).""" + engine = _engine() + session = make_session(engine) + try: + stmt = select(PropertyRow).where( + PropertyRow.portfolio_id == portfolio_id, + PropertyRow.landlord_property_id == ref, + ) + return list(session.exec(stmt).all()) + finally: + session.close() + + +def _show(row: dict[str, str], insert: PropertyIdentityInsert) -> None: + print("\nSource (combiner) row:") + for k, v in row.items(): + print(f" {k}: {v!r}") + print("\nMapped PropertyIdentityInsert:") + for k, v in insert.__dict__.items(): + print(f" {k}: {v!r}") + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--in", dest="inp", type=Path, default=_DEFAULT_IN) + parser.add_argument("--portfolio", type=int, required=True) + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument("--one", action="store_true", help="one random resolved row") + group.add_argument("--ref", help="a specific Organisation Reference") + group.add_argument("--all", action="store_true", help="every row") + parser.add_argument( + "--include-unmatched", + action="store_true", + help="also insert rows with no UPRN (null-UPRN property rows)", + ) + parser.add_argument( + "--reset", + action="store_true", + help="(with --all) DELETE all properties in the portfolio first " + "(cascades property_overrides; clears plan/epc_property)", + ) + parser.add_argument( + "--collisions", + type=Path, + default=_REPO_ROOT / "scripts" / "manipulation_collisions.csv", + help="where to write rows dropped as duplicate-UPRN collisions", + ) + parser.add_argument("--seed", type=int, default=0, help="random seed for --one") + return parser.parse_args() + + +def main() -> int: + args = _parse_args() + df, rows = load_rows(args.inp, include_unmatched=args.include_unmatched) + print(f"Loaded {len(rows)} candidate rows from {args.inp}") + + if args.all: + kept, dropped = dedupe_by_uprn(rows) + if dropped: + pd.DataFrame(dropped).to_csv(args.collisions, index=False) + print( + f"{len(dropped)} duplicate-UPRN rows dropped -> {args.collisions} " + f"({len(kept)} unique to insert)" + ) + deleted, inserted = clean_reload(kept, args.portfolio, reset=args.reset) + if args.reset: + print(f"Deleted {deleted} existing properties in portfolio {args.portfolio}.") + print(f"Inserted {inserted} properties into portfolio {args.portfolio}.") + return 0 + + # Single-row paths: pick the row, show the mapping, insert, read back. + if args.ref: + match = [r for r in rows if r["Internal Reference"] == args.ref] + if not match: + print(f"No resolved row with Organisation Reference {args.ref!r}.") + return 1 + row = match[0] + else: # --one: deterministic "random" pick via seed + idx = (args.seed * 7919) % len(rows) + row = rows[idx] + + ref = row["Internal Reference"] + insert = BulkUploadFinaliserOrchestrator._row_to_insert(row, args.portfolio) + _show(row, insert) + + inserted = insert_rows([row], args.portfolio) + print( + f"\ninsert_all -> {inserted} new row(s) " + f"(0 means it already existed; ON CONFLICT DO NOTHING)." + ) + + print(f"\nproperty rows for portfolio {args.portfolio}, ref {ref!r}:") + for pr in fetch_by_ref(args.portfolio, ref): + print( + f" id={pr.id} uprn={pr.uprn} address={pr.address!r} " + f"postcode={pr.postcode!r} status={pr.creation_status} " + f"lexiscore={pr.lexiscore}" + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/hyde_epc_schema_versions.py b/scripts/hyde_epc_schema_versions.py new file mode 100644 index 00000000..7bb882ac --- /dev/null +++ b/scripts/hyde_epc_schema_versions.py @@ -0,0 +1,159 @@ +"""Tally the EPC schema versions across the hyde list (manipulation_filled UPRNs). + +For every resolved UPRN we look up its EPC certificate's ``schemaType`` (e.g. +``RdSAP-Schema-21.0.1``, ``RdSAP-Schema-17.1``, ``SAP-Schema-16.2``). The +gov EPC ``/api/domestic/search`` endpoint returns ``schemaType`` per row, so one +search-per-postcode covers every UPRN in that postcode — far cheaper than a +certificate fetch per UPRN. The latest cert (max registrationDate) wins per UPRN. + +Outputs: a per-schema-version tally with one example UPRN each, plus a CSV +mapping every UPRN -> schema version. + + python -m scripts.hyde_epc_schema_versions + python -m scripts.hyde_epc_schema_versions --workers 8 --out scripts/hyde_schema_versions.csv + +Reads OPEN_EPC_API_TOKEN from backend/.env. Run from the worktree root. +""" + +from __future__ import annotations + +import argparse +import os +import sys +import time +from collections import Counter, defaultdict +from concurrent.futures import ThreadPoolExecutor +from pathlib import Path +from typing import Any, Optional + +import httpx +from dotenv import load_dotenv + +_REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from scripts.fill_domna_addresses import clean_postcode # noqa: E402 +from scripts.finalise_to_property_table import load_rows # noqa: E402 + +_BASE = "https://api.get-energy-performance-data.communities.gov.uk" +_SEARCH = f"{_BASE}/api/domestic/search" +NOT_IN_EPC = "NOT_IN_EPC" + +_DEFAULT_IN = _REPO_ROOT / "scripts" / "manipulation_filled.xlsx" +_DEFAULT_OUT = _REPO_ROOT / "scripts" / "hyde_schema_versions.csv" + + +def search_postcode( + client: httpx.Client, postcode: str, headers: dict[str, str] +) -> list[dict[str, Any]]: + """Return the search rows for a postcode, retrying on rate-limit (429).""" + for attempt in range(5): + resp = client.get(_SEARCH, params={"postcode": postcode}, headers=headers, timeout=30) + if resp.status_code == 429: + retry_after = float(resp.headers.get("Retry-After", "2")) + time.sleep(min(retry_after, 10) * (attempt + 1)) + continue + # 400 = malformed postcode (data-entry typo), 404 = no certs — skip both. + if resp.status_code in (400, 404): + return [] + resp.raise_for_status() + return resp.json().get("data", []) + return [] + + +def build_uprn_schema_map( + postcodes: list[str], token: str, workers: int +) -> dict[int, tuple[str, str]]: + """Map UPRN -> (schemaType, registrationDate) for the latest cert per UPRN. + + One search per postcode (concurrent); later we look our UPRNs up in here. + """ + headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"} + by_uprn: dict[int, tuple[str, str]] = {} + done = 0 + total = len(postcodes) + + def fetch(pc: str) -> list[dict[str, Any]]: + with httpx.Client() as client: + return search_postcode(client, pc, headers) + + with ThreadPoolExecutor(max_workers=workers) as pool: + for rows in pool.map(fetch, postcodes): + for row in rows: + uprn = row.get("uprn") + schema = row.get("schemaType") + reg = row.get("registrationDate") or "" + if uprn is None or not schema: + continue + prev = by_uprn.get(int(uprn)) + # Keep the latest-registered cert's schema for this UPRN. + if prev is None or reg > prev[1]: + by_uprn[int(uprn)] = (str(schema), str(reg)) + done += 1 + if done % 250 == 0: + print(f" searched {done}/{total} postcodes, {len(by_uprn)} uprns seen") + return by_uprn + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--in", dest="inp", type=Path, default=_DEFAULT_IN) + parser.add_argument("--out", type=Path, default=_DEFAULT_OUT) + parser.add_argument("--workers", type=int, default=8) + return parser.parse_args() + + +def main() -> int: + args = _parse_args() + load_dotenv(_REPO_ROOT / "backend" / ".env") + token = os.environ.get("OPEN_EPC_API_TOKEN") + if not token: + print("OPEN_EPC_API_TOKEN not set (backend/.env)") + return 2 + + _, rows = load_rows(args.inp, include_unmatched=False) + pairs: list[tuple[int, str, str]] = [] # (uprn, postcode_clean, address) + for r in rows: + uprn = r["address2uprn_uprn"] + if uprn: + pairs.append((int(uprn), clean_postcode(r["postcode"]), r["address2uprn_address"])) + postcodes = sorted({pc for _, pc, _ in pairs if pc}) + print(f"{len(pairs)} UPRNs across {len(postcodes)} unique postcodes") + + by_uprn = build_uprn_schema_map(postcodes, token, args.workers) + print(f"EPC search returned schema for {len(by_uprn)} distinct UPRNs") + + # Resolve each hyde UPRN to its schema version. + tally: Counter[str] = Counter() + example: dict[str, tuple[int, str]] = {} + out_lines: list[tuple[int, str, str, str]] = [] # uprn, schema, postcode, address + seen: set[int] = set() + for uprn, pc, address in pairs: + if uprn in seen: + continue + seen.add(uprn) + schema = by_uprn.get(uprn, (NOT_IN_EPC, ""))[0] + tally[schema] += 1 + example.setdefault(schema, (uprn, address)) + out_lines.append((uprn, schema, pc, address)) + + # Write the full per-UPRN mapping. + import csv + + with args.out.open("w", newline="", encoding="utf-8") as fh: + w = csv.writer(fh) + w.writerow(["uprn", "schema_version", "postcode", "matched_address"]) + w.writerows(out_lines) + + print(f"\nSchema versions across {len(seen)} distinct UPRNs:\n") + print(f" {'schema version':<26} {'count':>7} example UPRN") + print(f" {'-'*26} {'-'*7} {'-'*12}") + for schema, count in tally.most_common(): + ex_uprn, ex_addr = example[schema] + print(f" {schema:<26} {count:>7} {ex_uprn} ({ex_addr})") + print(f"\nFull mapping -> {args.out}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/lisasrequest/compare_to_ara.py b/scripts/lisasrequest/compare_to_ara.py new file mode 100644 index 00000000..c30b5f29 --- /dev/null +++ b/scripts/lisasrequest/compare_to_ara.py @@ -0,0 +1,169 @@ +"""Compare our step-1 UPRN resolution against the old "Ara output" data. + +The Ara data lives in scripts/lisasrequest/Durkan data.xlsx, sheet "Ara output", +and carries UPRNs from our previous dataset. It is NOT treated as ground truth — +this just lines it up against what we found / didn't find so a human can eyeball +the differences. (We read the xlsx, not the CSV export: the CSV mangled half the +UPRNs to Excel scientific notation, e.g. ``1.00023E+11``; the xlsx keeps them +intact, so every comparison below is exact.) + +Join key is (postcode, leading number, first street word), since the UPRN is the +thing under comparison and Ara's address strings differ from the landlord input. + +Each of our rows lands in one comparison bucket: + match both found a UPRN and they are equal. + differ both found a UPRN and they differ. + we_only we resolved a UPRN, Ara had none for this address. + ara_only we did NOT resolve, but Ara had a UPRN <- recovery candidates. + both_missing neither resolved a UPRN. + no_ara_record the Ara sheet had no row matching this address at all. + + python -m scripts.lisasrequest.compare_to_ara +""" + +from __future__ import annotations + +import argparse +import csv +import re +import sys +from collections import Counter, OrderedDict +from pathlib import Path +from typing import Optional + +import pandas as pd + +_REPO_ROOT = Path(__file__).resolve().parents[2] + +ADDRESS_COL = "address" +POSTCODE_COL = "postcode" +OUR_UPRN_COL = "domna_address_uprn" +OUR_SOURCE_COL = "domna_source" + +ARA_UPRN_COL = "EPC_B.uprn" +ARA_ADDRESS_COL = "EPC_B.address" +ARA_POSTCODE_COL = "EPC_B.postcode" +ARA_SHEET = "Ara output" + +_OUR_IN = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_domna_filled.csv" +_ARA_IN = _REPO_ROOT / "scripts" / "lisasrequest" / "Durkan data.xlsx" +_DEFAULT_OUT = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_vs_ara.csv" + +Key = tuple[str, str, str] + + +def norm_key(address: str, postcode: str) -> Key: + """(postcode-no-space, leading number, first street word) — the join key.""" + pc = postcode.upper().replace(" ", "") + upper = address.upper() + nums = re.findall(r"\d+[A-Z]?", upper) + words = [w for w in re.findall(r"[A-Z]+", upper) if w != "FLAT"] + return (pc, nums[0] if nums else "", words[0] if words else "") + + +def load_ara(path: Path) -> tuple[dict[Key, dict[str, str]], int]: + """Index the Ara-output xlsx sheet by join key (first row wins). + + Returns (index, duplicates). Read as strings so UPRNs keep their full value. + """ + df = pd.read_excel(path, sheet_name=ARA_SHEET, dtype=str) + rows: list[dict[str, str]] = df.fillna("").to_dict(orient="records") + index: dict[Key, dict[str, str]] = OrderedDict() + dupes = 0 + for row in rows: + address = str(row.get(ARA_ADDRESS_COL) or "").strip() + postcode = str(row.get(ARA_POSTCODE_COL) or row.get(POSTCODE_COL) or "").strip() + if not address: + continue + key = norm_key(address, postcode) + if key in index: + dupes += 1 + continue + index[key] = row + return index, dupes + + +def classify( + our_uprn: str, our_found: bool, ara: Optional[dict[str, str]] +) -> tuple[str, str, str]: + """Return (comparison, ara_uprn, ara_address) for one of our rows.""" + if ara is None: + return ("no_ara_record", "", "") + ara_uprn = (ara.get(ARA_UPRN_COL) or "").strip() + ara_address = (ara.get(ARA_ADDRESS_COL) or "").strip() + ara_found = bool(ara_uprn) + + if our_found and ara_found: + comparison = "match" if our_uprn == ara_uprn else "differ" + elif our_found and not ara_found: + comparison = "we_only" + elif not our_found and ara_found: + comparison = "ara_only" + else: + comparison = "both_missing" + return (comparison, ara_uprn, ara_address) + + +def compare( + our_rows: list[dict[str, str]], ara_index: dict[Key, dict[str, str]] +) -> list[dict[str, str]]: + out: list[dict[str, str]] = [] + for row in our_rows: + address = (row.get(ADDRESS_COL) or "").strip() + postcode = (row.get(POSTCODE_COL) or "").strip() + our_uprn = (row.get(OUR_UPRN_COL) or "").strip() + our_source = (row.get(OUR_SOURCE_COL) or "").strip() + our_found = bool(our_uprn) and our_source != "not_found" + + ara = ara_index.get(norm_key(address, postcode)) + comparison, ara_uprn, ara_address = classify(our_uprn, our_found, ara) + out.append( + { + "address": address, + "postcode": postcode, + "our_uprn": our_uprn, + "our_source": our_source, + "ara_uprn": ara_uprn, + "ara_address": ara_address, + "comparison": comparison, + } + ) + return out + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--ours", type=Path, default=_OUR_IN) + parser.add_argument("--ara", type=Path, default=_ARA_IN) + parser.add_argument("--out", type=Path, default=_DEFAULT_OUT) + args = parser.parse_args() + + with args.ours.open(newline="", encoding="utf-8-sig") as fh: + our_rows = [dict(r) for r in csv.DictReader(fh)] + ara_index, dupes = load_ara(args.ara) + print(f"Loaded {len(our_rows)} of our rows; {len(ara_index)} Ara keys " + f"({dupes} duplicate Ara rows ignored).") + + result = compare(our_rows, ara_index) + fieldnames = list(result[0].keys()) + with args.out.open("w", newline="", encoding="utf-8") as fh: + writer = csv.DictWriter(fh, fieldnames=fieldnames) + writer.writeheader() + writer.writerows(result) + + counts = Counter(r["comparison"] for r in result) + print(f"\nComparison of {len(result)} rows -> {args.out}") + for name in ( + "match", + "differ", + "we_only", + "ara_only", + "both_missing", + "no_ara_record", + ): + print(f" {name}: {counts.get(name, 0)}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/lisasrequest/durkan_805_schema_check.py b/scripts/lisasrequest/durkan_805_schema_check.py new file mode 100644 index 00000000..776a7813 --- /dev/null +++ b/scripts/lisasrequest/durkan_805_schema_check.py @@ -0,0 +1,142 @@ +"""EPC SAP-schema check for portfolio 805, and whether each is mapper-supported. + +For every UPRN currently in the ``property`` table for portfolio 805, look up its +latest EPC certificate's ``schemaType`` (one /api/domestic/search per postcode, +reusing scripts.hyde_epc_schema_versions) and check it against the schemas the +EpcPropertyData mapper actually handles +(``EpcPropertyDataMapper.from_api_response``, datatypes/epc/domain/mapper.py). + +Prints a per-schema tally with a supported? flag and an example UPRN, and writes +the full per-UPRN mapping to durkan_805_schema_check.csv. + + python -m scripts.lisasrequest.durkan_805_schema_check + python -m scripts.lisasrequest.durkan_805_schema_check --portfolio 805 --workers 8 + +Reads OPEN_EPC_API_TOKEN from backend/.env and POSTGRES_* from the root .env. +Run from the worktree root. +""" + +from __future__ import annotations + +import argparse +import csv +import os +import sys +from collections import Counter +from pathlib import Path + +from dotenv import load_dotenv +from sqlmodel import select + +_REPO_ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from infrastructure.postgres.config import PostgresConfig # noqa: E402 +from infrastructure.postgres.engine import make_engine, make_session # noqa: E402 +from infrastructure.postgres.property_table import PropertyRow # noqa: E402 +from scripts.fill_domna_addresses import clean_postcode # noqa: E402 +from scripts.hyde_epc_schema_versions import ( # noqa: E402 + NOT_IN_EPC, + build_uprn_schema_map, +) + +# Schemas EpcPropertyDataMapper.from_api_response dispatches on (everything else +# raises "Unsupported EPC schema"). Keep in sync with mapper.py:2539-2603. +SUPPORTED_SCHEMAS = frozenset( + { + "RdSAP-Schema-17.0", + "RdSAP-Schema-17.1", + "RdSAP-Schema-18.0", + "RdSAP-Schema-19.0", + "RdSAP-Schema-20.0.0", + "RdSAP-Schema-21.0.0", + "RdSAP-Schema-21.0.1", + "SAP-Schema-16.0", + "SAP-Schema-16.2", + "SAP-Schema-16.3", + "SAP-Schema-17.0", + "SAP-Schema-17.1", + "SAP-Schema-18.0.0", + } +) + +_DEFAULT_OUT = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_805_schema_check.csv" + + +def load_portfolio_uprns(portfolio_id: int) -> list[tuple[int, str]]: + """Return (uprn, postcode) for every property in the portfolio with a UPRN.""" + load_dotenv(_REPO_ROOT / ".env") + engine = make_engine(PostgresConfig.from_env(os.environ)) + session = make_session(engine) + try: + stmt = select(PropertyRow.uprn, PropertyRow.postcode).where( + PropertyRow.portfolio_id == portfolio_id + ) + out: list[tuple[int, str]] = [] + for uprn, postcode in session.exec(stmt).all(): + if uprn is not None: + out.append((int(uprn), str(postcode or ""))) + return out + finally: + session.close() + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--portfolio", type=int, default=805) + parser.add_argument("--out", type=Path, default=_DEFAULT_OUT) + parser.add_argument("--workers", type=int, default=8) + args = parser.parse_args() + + load_dotenv(_REPO_ROOT / "backend" / ".env") + token = os.environ.get("OPEN_EPC_API_TOKEN") + if not token: + print("OPEN_EPC_API_TOKEN not set (backend/.env)") + return 2 + + pairs = load_portfolio_uprns(args.portfolio) + postcodes = sorted({clean_postcode(pc) for _, pc in pairs if pc}) + print( + f"Portfolio {args.portfolio}: {len(pairs)} UPRNs across " + f"{len(postcodes)} unique postcodes" + ) + + by_uprn = build_uprn_schema_map(postcodes, token, args.workers) + print(f"EPC search returned a schema for {len(by_uprn)} distinct UPRNs") + + tally: Counter[str] = Counter() + example: dict[str, int] = {} + rows_out: list[tuple[int, str, str, str]] = [] # uprn, schema, supported, postcode + seen: set[int] = set() + for uprn, pc in pairs: + if uprn in seen: + continue + seen.add(uprn) + schema = by_uprn.get(uprn, (NOT_IN_EPC, ""))[0] + supported = "yes" if schema in SUPPORTED_SCHEMAS else "no" + tally[schema] += 1 + example.setdefault(schema, uprn) + rows_out.append((uprn, schema, supported, clean_postcode(pc))) + + with args.out.open("w", newline="", encoding="utf-8") as fh: + writer = csv.writer(fh) + writer.writerow(["uprn", "schema_version", "mapper_supported", "postcode"]) + writer.writerows(rows_out) + + supported_count = sum(c for s, c in tally.items() if s in SUPPORTED_SCHEMAS) + print(f"\nSchema versions across {len(seen)} distinct UPRNs in portfolio " + f"{args.portfolio}:\n") + print(f" {'schema version':<26} {'count':>5} {'supported?':<10} example UPRN") + print(f" {'-' * 26} {'-' * 5} {'-' * 10} {'-' * 12}") + for schema, count in tally.most_common(): + supported = "yes" if schema in SUPPORTED_SCHEMAS else "NO" + print(f" {schema:<26} {count:>5} {supported:<10} {example[schema]}") + print( + f"\nMapper-supported: {supported_count}/{len(seen)} UPRNs. " + f"Full mapping -> {args.out}" + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/lisasrequest/fill_domna_address.py b/scripts/lisasrequest/fill_domna_address.py new file mode 100644 index 00000000..98d70071 --- /dev/null +++ b/scripts/lisasrequest/fill_domna_address.py @@ -0,0 +1,200 @@ +"""Step 1 (Durkan portfolio): resolve a UPRN per CSV row via EPC then OS. + +Input: scripts/lisasrequest/260611_Sample_Seed_Portfolio_Durkan_split_addresses(Split Addresses).csv + columns include ``address`` and ``postcode``. + +Every row carries an address and none carry a UPRN, so there is a single case: + + * resolve a UPRN from ``address`` + ``postcode`` via the EPC API (relaxed + address variants, threshold 0.7), then Ordnance Survey Places as a fallback + (threshold 0.6). + * not resolvable -> domna_source = "not_found"; uprn/address/score left empty. + +Writes a NEW CSV = every original column, in order, plus four DOMNA columns: + + domna_address_found the canonical address EPC/OS returned (matched string) + domna_address_uprn the resolved UPRN ("" when unresolved) + domna_lexiscore the match score in [0, 1] ("" when unresolved) + domna_source epc / ordnance_survey / not_found + +This is the human-review file; step 2 (resolve_uprns_for_finaliser) reshapes it +into the finaliser columns without re-hitting the APIs. + + python -m scripts.lisasrequest.fill_domna_address + python -m scripts.lisasrequest.fill_domna_address --limit 20 # smoke test + +Resolution reuses the relaxed matchers from scripts.fill_domna_addresses. Keys +come from backend/.env (OPEN_EPC_API_TOKEN, ORDNANCE_SURVEY_API_KEY). Run from +the worktree root (import trap). +""" + +from __future__ import annotations + +import argparse +import csv +import sys +from pathlib import Path +from typing import Optional + +import pandas as pd + +_REPO_ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from scripts.fill_domna_addresses import ( # noqa: E402 + Hit, + resolve_epc_relaxed, + resolve_os_relaxed, +) +from scripts.resolve_uprns_for_finaliser import clean_postcode, load_keys # noqa: E402 + +ADDRESS_COL = "address" +POSTCODE_COL = "postcode" +FOUND_ADDRESS_COL = "domna_address_found" +FOUND_UPRN_COL = "domna_address_uprn" +LEXISCORE_COL = "domna_lexiscore" +SOURCE_COL = "domna_source" +NOT_FOUND = "not_found" +_RESULT_COLS = (FOUND_ADDRESS_COL, FOUND_UPRN_COL, LEXISCORE_COL, SOURCE_COL) + +_CSV_NAME = "260611_Sample_Seed_Portfolio_Durkan_split_addresses(Split Addresses).csv" +_DEFAULT_IN = _REPO_ROOT / "scripts" / "lisasrequest" / _CSV_NAME +_DEFAULT_OUT = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_domna_filled.csv" + + +def read_rows(path: Path) -> tuple[list[dict[str, str]], list[str]]: + """Read a CSV into (rows, fieldnames), preserving column order.""" + with path.open(newline="", encoding="utf-8-sig") as fh: + reader = csv.DictReader(fh) + fieldnames = list(reader.fieldnames or []) + rows = [dict(row) for row in reader] + return rows, fieldnames + + +def resolve_one( + address: str, + postcode_raw: str, + *, + epc_token: Optional[str], + os_api_key: Optional[str], + epc_cache: dict[str, pd.DataFrame], + os_cache: dict[str, pd.DataFrame], +) -> Optional[Hit]: + """Resolve one row's UPRN: EPC (relaxed) first, then OS Places fallback.""" + postcode_clean = clean_postcode(postcode_raw) + if not address or not postcode_clean: + return None + + hit: Optional[Hit] = None + if epc_token: + try: + hit = resolve_epc_relaxed(address, postcode_clean, epc_cache) + except Exception as exc: + print(f" EPC failed {address!r} / {postcode_clean}: {exc}") + if hit is None and os_api_key: + try: + hit = resolve_os_relaxed(address, postcode_clean, os_api_key, os_cache) + except Exception as exc: + print(f" OS failed {address!r} / {postcode_clean}: {exc}") + return hit + + +def fill( + rows: list[dict[str, str]], + *, + epc_token: Optional[str], + os_api_key: Optional[str], +) -> tuple[int, int, int]: + """Fill the DOMNA columns on each row in place. + + Returns (epc_hits, os_hits, not_found) counts. + """ + epc_cache: dict[str, pd.DataFrame] = {} + os_cache: dict[str, pd.DataFrame] = {} + epc_hits = os_hits = not_found = 0 + total = len(rows) + + for n, row in enumerate(rows, start=1): + address = str(row.get(ADDRESS_COL, "") or "").strip() + postcode_raw = str(row.get(POSTCODE_COL, "") or "").strip() + hit = resolve_one( + address, + postcode_raw, + epc_token=epc_token, + os_api_key=os_api_key, + epc_cache=epc_cache, + os_cache=os_cache, + ) + if hit is None: + row[FOUND_ADDRESS_COL] = "" + row[FOUND_UPRN_COL] = "" + row[LEXISCORE_COL] = "" + row[SOURCE_COL] = NOT_FOUND + not_found += 1 + else: + uprn, matched, score, source = hit + row[FOUND_ADDRESS_COL] = matched + row[FOUND_UPRN_COL] = uprn + row[LEXISCORE_COL] = str(round(score, 4)) + row[SOURCE_COL] = source + if source == "epc": + epc_hits += 1 + else: + os_hits += 1 + print( + f"[{n}/{total}] {address!r} -> " + f"{row[FOUND_UPRN_COL] or '(no match)'} ({row[SOURCE_COL]})" + ) + + return epc_hits, os_hits, not_found + + +def write_rows(rows: list[dict[str, str]], path: Path, fieldnames: list[str]) -> None: + """Write rows to CSV, preserving input columns and appending DOMNA columns.""" + out_fields = list(fieldnames) + for col in _RESULT_COLS: + if col not in out_fields: + out_fields.append(col) + with path.open("w", newline="", encoding="utf-8") as fh: + writer = csv.DictWriter(fh, fieldnames=out_fields, extrasaction="ignore") + writer.writeheader() + writer.writerows(rows) + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--in", dest="inp", type=Path, default=_DEFAULT_IN) + parser.add_argument("--out", type=Path, default=_DEFAULT_OUT) + parser.add_argument("--limit", type=int, default=None, help="process first N rows") + return parser.parse_args() + + +def main() -> int: + args = _parse_args() + epc_token, os_api_key = load_keys() + if not epc_token: + print("OPEN_EPC_API_TOKEN not set (backend/.env) — EPC resolution disabled") + if not os_api_key: + print("ORDNANCE_SURVEY_API_KEY not set (backend/.env) — OS fallback disabled") + + rows, fieldnames = read_rows(args.inp) + if args.limit is not None: + rows = rows[: args.limit] + print(f"Loaded {len(rows)} rows from {args.inp}") + + epc_hits, os_hits, not_found = fill( + rows, epc_token=epc_token, os_api_key=os_api_key + ) + + write_rows(rows, args.out, fieldnames) + resolved = epc_hits + os_hits + print( + f"\nResolved {resolved}/{len(rows)} " + f"(epc={epc_hits}, ordnance_survey={os_hits}); {not_found} not found." + ) + print(f"Wrote filled CSV -> {args.out}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/lisasrequest/finalise_to_property_table.py b/scripts/lisasrequest/finalise_to_property_table.py new file mode 100644 index 00000000..eee66a0f --- /dev/null +++ b/scripts/lisasrequest/finalise_to_property_table.py @@ -0,0 +1,111 @@ +"""Step 3 (Durkan portfolio): insert the reshaped rows into the ``property`` table. + +Reads durkan_finaliser_input.csv (step 2) and, per row, maps it with the real +finaliser mapper (``BulkUploadFinaliserOrchestrator._row_to_insert``) and inserts +via the same ``PropertyPostgresRepository.insert_all`` the Lambda uses — so a row +written here is identical to one the production finaliser would write. Insert is +ON CONFLICT (portfolio_id, uprn) DO NOTHING, so re-running is safe. + +DRY RUN BY DEFAULT — it dedupes, reports, and writes the collisions file but does +NOT touch the database. Add --commit to actually insert. + + # preview only (no DB writes): dedupe + mapping report + python -m scripts.lisasrequest.finalise_to_property_table --portfolio 805 + + # actually insert + python -m scripts.lisasrequest.finalise_to_property_table --portfolio 805 --commit + +Postgres target comes from the root .env (POSTGRES_*). Run from the worktree root. +""" + +from __future__ import annotations + +import argparse +import csv +import sys +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from scripts.finalise_to_property_table import ( # noqa: E402 + dedupe_by_uprn, + insert_rows, +) + +_DEFAULT_IN = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_finaliser_input.csv" +_DEFAULT_COLLISIONS = ( + _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_finaliser_collisions.csv" +) +UPRN_COL = "address2uprn_uprn" +MATCHED_ADDRESS_COL = "address2uprn_address" +POSTCODE_COL = "postcode" +LEXISCORE_COL = "address2uprn_lexiscore" + + +def read_rows(path: Path) -> list[dict[str, str]]: + with path.open(newline="", encoding="utf-8-sig") as fh: + return [dict(row) for row in csv.DictReader(fh)] + + +def _preview(rows: list[dict[str, str]]) -> None: + """Show the first few rows as they will be inserted (no DB, no mapper call). + + The finalise step applies the standard finaliser mapper + (BulkUploadFinaliserOrchestrator) on insert; the fields below are its inputs. + """ + print("\nSample rows to insert (uprn | matched address | postcode | lexiscore):") + for row in rows[:3]: + print( + f" {row.get(UPRN_COL)} | {row.get(MATCHED_ADDRESS_COL)!r} | " + f"{row.get(POSTCODE_COL)!r} | {row.get(LEXISCORE_COL)}" + ) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--in", dest="inp", type=Path, default=_DEFAULT_IN) + parser.add_argument("--portfolio", type=int, required=True) + parser.add_argument( + "--commit", + action="store_true", + help="actually insert into property (default is a dry-run preview)", + ) + parser.add_argument("--collisions", type=Path, default=_DEFAULT_COLLISIONS) + args = parser.parse_args() + + rows = read_rows(args.inp) + print(f"Loaded {len(rows)} finaliser rows from {args.inp}") + + kept, dropped = dedupe_by_uprn(rows) + if dropped: + with args.collisions.open("w", newline="", encoding="utf-8") as fh: + writer = csv.DictWriter(fh, fieldnames=list(dropped[0].keys())) + writer.writeheader() + writer.writerows(dropped) + print( + f"{len(dropped)} duplicate-UPRN rows dropped -> {args.collisions} " + f"({len(kept)} unique to insert)" + ) + else: + print(f"No duplicate-UPRN collisions; {len(kept)} unique rows to insert.") + + _preview(kept) + + if not args.commit: + print( + f"\nDRY RUN — nothing written. {len(kept)} rows would be inserted into " + f"portfolio {args.portfolio}. Re-run with --commit to write." + ) + return 0 + + inserted = insert_rows(kept, args.portfolio) + print( + f"\nInserted {inserted} new properties into portfolio {args.portfolio} " + f"({len(kept) - inserted} already existed; ON CONFLICT DO NOTHING)." + ) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/lisasrequest/resolve_uprns_for_finaliser.py b/scripts/lisasrequest/resolve_uprns_for_finaliser.py new file mode 100644 index 00000000..6107b837 --- /dev/null +++ b/scripts/lisasrequest/resolve_uprns_for_finaliser.py @@ -0,0 +1,212 @@ +"""Step 2 (Durkan portfolio): split step-1 matches, reshape the confident ones. + +Reads durkan_domna_filled.csv (step 1) and SPLITS it in two — no re-resolution, +just column work: + + * Rows we cannot confidently insert are held back to a client-clarification CSV + (durkan_client_clarification.csv) for Khalim to take to the client. Reasons: + not_found_no_match no UPRN was resolved. + no_flat_level_uprn a block of flats all collapsed onto one building + UPRN — OS/EPC carry no flat-level records, so we + can't tell the flats apart. + unit_number_mismatch the matched house number differs from the input + (e.g. "9 ..." matched "9A ..."), so the property is + ambiguous. + * Every remaining row is reshaped into the columns the finaliser reads + (bulk_upload_finaliser_orchestrator), written to durkan_finaliser_input.csv + ready for step 3: + Address 1/2/3 | postcode | Internal Reference | address2uprn_uprn + | address2uprn_address | address2uprn_lexiscore + Internal Reference is left blank (landlord_property_id null, by decision). + + python -m scripts.lisasrequest.resolve_uprns_for_finaliser + +This stage hits no APIs. The held rows are not lost — once the client confirms +them they can be appended to the finaliser input by hand. +""" + +from __future__ import annotations + +import argparse +import csv +import sys +from collections import Counter +from pathlib import Path +from typing import Optional + +_REPO_ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from scripts.lisasrequest.fill_domna_address import ( # noqa: E402 + ADDRESS_COL, + FOUND_ADDRESS_COL, + FOUND_UPRN_COL, + LEXISCORE_COL, + POSTCODE_COL, + SOURCE_COL, +) +from scripts.lisasrequest.review_flags import address_numbers, input_unit # noqa: E402 + +# Finaliser input columns — must match bulk_upload_finaliser_orchestrator +# (ADDRESS_COLS / POSTCODE_COL / INTERNAL_REF_COL / UPRN_COL / +# MATCHED_ADDRESS_COL / LEXISCORE_COL). Hard-coded to keep this a light, +# stdlib-only reshape; step 3 imports the real orchestrator and will fail loudly +# if these ever drift. +FIN_ADDRESS_1, FIN_ADDRESS_2, FIN_ADDRESS_3 = "Address 1", "Address 2", "Address 3" +FIN_POSTCODE = "postcode" +FIN_INTERNAL_REF = "Internal Reference" +FIN_UPRN = "address2uprn_uprn" +FIN_MATCHED_ADDRESS = "address2uprn_address" +FIN_LEXISCORE = "address2uprn_lexiscore" +_FINALISER_COLS = [ + FIN_ADDRESS_1, + FIN_ADDRESS_2, + FIN_ADDRESS_3, + FIN_POSTCODE, + FIN_INTERNAL_REF, + FIN_UPRN, + FIN_MATCHED_ADDRESS, + FIN_LEXISCORE, +] + +# Client-clarification report columns (kept human-readable for the client). +CONTEXT_COLS = ["address", "postcode", "No.", "Address Block"] +DOMNA_COLS = [FOUND_ADDRESS_COL, FOUND_UPRN_COL, LEXISCORE_COL, SOURCE_COL] +REASON_COL = "clarification_reason" +ACTION_COL = "action_needed" +_CLARIFY_COLS = CONTEXT_COLS + DOMNA_COLS + [REASON_COL, ACTION_COL] + +_REASON_ORDER = { + "not_found_no_match": 0, + "no_flat_level_uprn": 1, + "unit_number_mismatch": 2, +} +_REASON_ACTION = { + "not_found_no_match": "No UPRN found for this address — please confirm the " + "exact address or provide the UPRN.", + "no_flat_level_uprn": "Address registers hold only the building, not the " + "individual flats — please provide a UPRN per flat, or confirm a " + "building-level record is acceptable.", + "unit_number_mismatch": "Closest match has a different unit number (see " + "domna_address_found) — please confirm the correct property / UPRN.", +} + +_DEFAULT_IN = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_domna_filled.csv" +_DEFAULT_FINALISER = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_finaliser_input.csv" +_DEFAULT_CLARIFY = ( + _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_client_clarification.csv" +) + + +def read_rows(path: Path) -> list[dict[str, str]]: + with path.open(newline="", encoding="utf-8-sig") as fh: + return [dict(row) for row in csv.DictReader(fh)] + + +def clarification_reason( + row: dict[str, str], uprn_counts: Counter[str] +) -> Optional[str]: + """Why this row can't be inserted yet, or None if it's safe to finalise.""" + uprn = row.get(FOUND_UPRN_COL, "") + if row.get(SOURCE_COL) == "not_found" or not uprn: + return "not_found_no_match" + + unit = input_unit(row.get(ADDRESS_COL, "")) + unit_missing = bool(unit) and unit not in address_numbers( + row.get(FOUND_ADDRESS_COL, "") + ) + duplicate = uprn_counts[uprn] > 1 + if unit_missing: + return "no_flat_level_uprn" if duplicate else "unit_number_mismatch" + if duplicate: + # A shared UPRN with the right unit number still collides at finalise. + return "no_flat_level_uprn" + return None + + +def to_finaliser_row(row: dict[str, str]) -> dict[str, str]: + """Rename a confident step-1 row into the finaliser's input columns.""" + return { + FIN_ADDRESS_1: row.get(ADDRESS_COL, ""), + FIN_ADDRESS_2: "", + FIN_ADDRESS_3: "", + FIN_POSTCODE: row.get(POSTCODE_COL, ""), + FIN_INTERNAL_REF: "", # landlord_property_id null, by decision + FIN_UPRN: row.get(FOUND_UPRN_COL, ""), + FIN_MATCHED_ADDRESS: row.get(FOUND_ADDRESS_COL, ""), + FIN_LEXISCORE: row.get(LEXISCORE_COL, ""), + } + + +def to_clarify_row(row: dict[str, str], reason: str) -> dict[str, str]: + out = {col: row.get(col, "") for col in CONTEXT_COLS + DOMNA_COLS} + out[REASON_COL] = reason + out[ACTION_COL] = _REASON_ACTION[reason] + return out + + +def split( + rows: list[dict[str, str]], + *, + accept_unit_mismatch: bool = False, +) -> tuple[list[dict[str, str]], list[dict[str, str]]]: + """Return (finaliser_rows, clarification_rows). + + ``accept_unit_mismatch`` reshapes the ``unit_number_mismatch`` rows (a + near-miss like 9 -> 9A the client has already confirmed) into the finaliser + input instead of holding them back. + """ + uprn_counts: Counter[str] = Counter( + r.get(FOUND_UPRN_COL, "") for r in rows if r.get(FOUND_UPRN_COL) + ) + finaliser: list[dict[str, str]] = [] + clarify: list[dict[str, str]] = [] + for row in rows: + reason = clarification_reason(row, uprn_counts) + if reason is None or ( + accept_unit_mismatch and reason == "unit_number_mismatch" + ): + finaliser.append(to_finaliser_row(row)) + else: + clarify.append(to_clarify_row(row, reason)) + clarify.sort(key=lambda r: _REASON_ORDER.get(r[REASON_COL], 9)) + return finaliser, clarify + + +def write_csv(rows: list[dict[str, str]], path: Path, fieldnames: list[str]) -> None: + with path.open("w", newline="", encoding="utf-8") as fh: + writer = csv.DictWriter(fh, fieldnames=fieldnames, extrasaction="ignore") + writer.writeheader() + writer.writerows(rows) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--in", dest="inp", type=Path, default=_DEFAULT_IN) + parser.add_argument("--finaliser-out", type=Path, default=_DEFAULT_FINALISER) + parser.add_argument("--clarify-out", type=Path, default=_DEFAULT_CLARIFY) + parser.add_argument( + "--accept-unit-mismatch", + action="store_true", + help="reshape unit_number_mismatch rows (e.g. 9->9A) into the finaliser " + "input instead of holding them for the client", + ) + args = parser.parse_args() + + rows = read_rows(args.inp) + finaliser, clarify = split(rows, accept_unit_mismatch=args.accept_unit_mismatch) + + write_csv(finaliser, args.finaliser_out, _FINALISER_COLS) + write_csv(clarify, args.clarify_out, _CLARIFY_COLS) + + counts = Counter(r[REASON_COL] for r in clarify) + print(f"Read {len(rows)} step-1 rows.") + print(f" -> {len(finaliser)} confident rows reshaped -> {args.finaliser_out}") + print(f" -> {len(clarify)} held for client -> {args.clarify_out}") + for reason in _REASON_ORDER: + print(f" {reason}: {counts.get(reason, 0)}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/lisasrequest/review_flags.py b/scripts/lisasrequest/review_flags.py new file mode 100644 index 00000000..4bf710e2 --- /dev/null +++ b/scripts/lisasrequest/review_flags.py @@ -0,0 +1,135 @@ +"""Flag step-1 matches that need a human eye, for review before finalising. + +Reads durkan_domna_filled.csv (the step-1 output) and writes a review CSV of +only the rows carrying at least one flag, newest-doubt-first: + + not_found no UPRN resolved at all. + unit_not_in_match the input flat/house number does NOT appear in the matched + address — the high-precision "wrong property" signal. Two + shapes: a near-miss ("9 VANBRUGH" matched "9A, VANBRUGH") + or a flat collapsing onto its building ("FLAT 1, 20 WARWICK" + matched "20, WARWICK ROAD"). + dup_uprn the same UPRN was resolved for >1 input row — typically a + block of flats all collapsing onto the building UPRN; all + but one will be dropped at finalise. + low_score lexiscore < 0.70 (a weak match, just over the OS bar). NOTE: + on its own this is noisy — truncated EPC addresses and extra + locality tokens push correct matches below 0.70. Treat it as + informational unless paired with one of the flags above. + + python -m scripts.lisasrequest.review_flags +""" + +from __future__ import annotations + +import argparse +import csv +import re +import sys +from collections import Counter +from pathlib import Path + +_REPO_ROOT = Path(__file__).resolve().parents[2] + +ADDRESS_COL = "address" +POSTCODE_COL = "postcode" +FOUND_ADDRESS_COL = "domna_address_found" +FOUND_UPRN_COL = "domna_address_uprn" +LEXISCORE_COL = "domna_lexiscore" +SOURCE_COL = "domna_source" +LOW_SCORE = 0.70 + +_DEFAULT_IN = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_domna_filled.csv" +_DEFAULT_OUT = _REPO_ROOT / "scripts" / "lisasrequest" / "durkan_review_flags.csv" + +_REVIEW_COLS = [ + ADDRESS_COL, + POSTCODE_COL, + FOUND_ADDRESS_COL, + FOUND_UPRN_COL, + LEXISCORE_COL, + SOURCE_COL, + "flags", +] + + +def input_unit(address: str) -> str: + """The salient unit number of an input address: the FLAT number if present, + else the leading house number ("" if neither). Upper-cased.""" + upper = address.upper() + flat = re.search(r"\bFLAT\s+(\d+[A-Z]?)", upper) + if flat: + return flat.group(1) + lead = re.match(r"\s*(\d+[A-Z]?)\b", upper) + return lead.group(1) if lead else "" + + +def address_numbers(address: str) -> set[str]: + """All standalone number tokens in an address (e.g. {"3", "20"}). Upper-cased.""" + return set(re.findall(r"\b\d+[A-Z]?\b", address.upper())) + + +def _score(value: str) -> float: + try: + return float(value) + except (TypeError, ValueError): + return 0.0 + + +def flag_rows(rows: list[dict[str, str]]) -> list[dict[str, str]]: + """Return the flagged subset, each with a ';'-joined ``flags`` field.""" + uprn_counts = Counter( + r.get(FOUND_UPRN_COL, "") for r in rows if r.get(FOUND_UPRN_COL) + ) + + flagged: list[dict[str, str]] = [] + for row in rows: + uprn = row.get(FOUND_UPRN_COL, "") + source = row.get(SOURCE_COL, "") + flags: list[str] = [] + + if source == "not_found" or not uprn: + flags.append("not_found") + else: + unit = input_unit(row.get(ADDRESS_COL, "")) + if unit and unit not in address_numbers(row.get(FOUND_ADDRESS_COL, "")): + flags.append("unit_not_in_match") + if uprn_counts[uprn] > 1: + flags.append("dup_uprn") + if _score(row.get(LEXISCORE_COL, "")) < LOW_SCORE: + flags.append("low_score") + + if flags: + flagged.append({**{c: row.get(c, "") for c in _REVIEW_COLS[:-1]}, + "flags": ";".join(flags)}) + + # not_found first, then mismatches, then dup/low. + order = {"not_found": 0, "unit_not_in_match": 1, "dup_uprn": 2, "low_score": 3} + flagged.sort(key=lambda r: order.get(r["flags"].split(";")[0], 9)) + return flagged + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--in", dest="inp", type=Path, default=_DEFAULT_IN) + parser.add_argument("--out", type=Path, default=_DEFAULT_OUT) + args = parser.parse_args() + + with args.inp.open(newline="", encoding="utf-8-sig") as fh: + rows = [dict(r) for r in csv.DictReader(fh)] + + flagged = flag_rows(rows) + with args.out.open("w", newline="", encoding="utf-8") as fh: + writer = csv.DictWriter(fh, fieldnames=_REVIEW_COLS, extrasaction="ignore") + writer.writeheader() + writer.writerows(flagged) + + counts = Counter(f for r in flagged for f in r["flags"].split(";")) + print(f"{len(flagged)}/{len(rows)} rows flagged for review -> {args.out}") + for name in ("not_found", "unit_not_in_match", "dup_uprn", "low_score"): + print(f" {name}: {counts.get(name, 0)}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/resolve_uprns_for_finaliser.py b/scripts/resolve_uprns_for_finaliser.py new file mode 100644 index 00000000..c01a55ed --- /dev/null +++ b/scripts/resolve_uprns_for_finaliser.py @@ -0,0 +1,328 @@ +"""Resolve a CSV of addresses to UPRNs, ready to feed the bulk-upload finaliser. + +Takes a CSV with `Address 1/2/3` + `postcode` columns and, per row, resolves a +UPRN by trying — in order — the new EPC API (address2uprn), the historic EPC S3 +dataset, then the Ordnance Survey Places API as a fallback. Whichever source +wins, the result is written into the SAME three columns the finaliser reads +(`bulk_upload_finaliser_orchestrator`): + + address2uprn_uprn UPRN integer (empty when unresolved) + address2uprn_address the matched address + address2uprn_lexiscore the match score in [0, 1] + +A `resolution_source` diagnostic column (epc / epc_historic / ordnance_survey / +none) is appended too — the finaliser ignores unknown columns. All original +columns are preserved in their original order, so the output CSV drops straight +into the finaliser. + + python -m scripts.resolve_uprns_for_finaliser input.csv -o resolved.csv + + # OS-only / EPC-only, custom postcode column, custom OS score threshold + python -m scripts.resolve_uprns_for_finaliser in.csv -o out.csv --no-epc + python -m scripts.resolve_uprns_for_finaliser in.csv -o out.csv --postcode-col Postcode --os-threshold 0.6 + +Keys are read from backend/.env: OPEN_EPC_API_TOKEN (EPC) and +ORDNANCE_SURVEY_API_KEY (OS Places). Run from the worktree root (import trap). + +The module-level functions (`load_keys`, `read_rows`, `resolve_row`, `process`, +`write_rows`) are written to be driven line-by-line from a REPL as well as via +the CLI. +""" + +from __future__ import annotations + +import argparse +import csv +import os +import sys +from pathlib import Path +from typing import Optional + +import pandas as pd +from dotenv import load_dotenv + +_REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(_REPO_ROOT)) # worktree root first — avoid the import trap + +from backend.address2UPRN.main import ( # noqa: E402 + get_epc_data_with_postcode, + get_uprn_from_historic_epc, + get_uprn_with_epc_df, +) +from backend.ordnanceSurvey.helpers import ( # noqa: E402 + lookup_os_places, + os_places_results_to_dataframe, +) +from backend.utils.addressMatch import AddressMatch # noqa: E402 + +# Columns the finaliser reads (bulk_upload_finaliser_orchestrator). +UPRN_COL = "address2uprn_uprn" +MATCHED_ADDRESS_COL = "address2uprn_address" +LEXISCORE_COL = "address2uprn_lexiscore" +SOURCE_COL = "resolution_source" +_RESULT_COLS = (UPRN_COL, MATCHED_ADDRESS_COL, LEXISCORE_COL, SOURCE_COL) + +# A resolved hit: (uprn, matched_address, lexiscore, source). +Resolution = tuple[str, str, float, str] + + +def load_keys() -> tuple[Optional[str], Optional[str]]: + """Load (epc_token, os_api_key) from backend/.env (and the process env).""" + load_dotenv(_REPO_ROOT / "backend" / ".env") + epc_token = os.environ.get("OPEN_EPC_API_TOKEN") + os_api_key = os.environ.get("ORDNANCE_SURVEY_API_KEY") + return epc_token, os_api_key + + +def read_rows(path: Path) -> tuple[list[dict[str, str]], list[str]]: + """Read a CSV into (rows, fieldnames). Preserves column order.""" + with path.open(newline="", encoding="utf-8-sig") as fh: + reader = csv.DictReader(fh) + fieldnames = list(reader.fieldnames or []) + rows = [dict(row) for row in reader] + return rows, fieldnames + + +def clean_postcode(postcode: str) -> str: + """Sanitise to the no-space upper form the EPC/OS lookups expect (e.g. E84SQ).""" + return postcode.upper().replace(" ", "").strip() + + +def build_address(row: dict[str, str]) -> str: + """Concatenate Address 1/2/3 the same way the address2uprn lambda does.""" + return " ".join( + str(row.get(col, "") or "").strip() for col in ("Address 1", "Address 2", "Address 3") + ).strip() + + +def resolve_epc( + address: str, postcode_clean: str, epc_cache: dict[str, pd.DataFrame] +) -> Optional[Resolution]: + """Resolve via the new EPC API (cached per postcode), then historic EPC S3. + + `epc_cache` is mutated to memoise one EPC API call per postcode — pass the + same dict across rows so a postcode is only fetched once. + """ + epc_df = epc_cache.get(postcode_clean) + if epc_df is None: + epc_df = get_epc_data_with_postcode(postcode=postcode_clean) + epc_cache[postcode_clean] = epc_df + + result = get_uprn_with_epc_df( + user_inputed_address=address, epc_df=epc_df, verbose=True + ) + if isinstance(result, tuple): + uprn, matched, score = result + return str(uprn), str(matched), float(score), "epc" + + historic = get_uprn_from_historic_epc( + user_inputed_address=address, postcode=postcode_clean + ) + if historic is not None: + uprn, matched, score = historic + return str(uprn), str(matched), float(score), "epc_historic" + + return None + + +def resolve_os( + address: str, + postcode_clean: str, + os_api_key: str, + os_cache: dict[str, pd.DataFrame], + threshold: float, +) -> Optional[Resolution]: + """Resolve via the OS Places API: best-scoring address above `threshold`. + + `os_cache` memoises one OS Places call per postcode. + """ + places_df = os_cache.get(postcode_clean) + if places_df is None: + response = lookup_os_places(postcode_clean, os_api_key) + if response.get("status") != 200 or "data" not in response: + places_df = pd.DataFrame() + else: + places_df = os_places_results_to_dataframe(response["data"]) + os_cache[postcode_clean] = places_df + + if places_df.empty or "ADDRESS" not in places_df.columns: + return None + + # Iterate plain records — avoids pandas' partially-unknown indexing types. + records: list[dict[str, object]] = places_df.to_dict(orient="records") + best: Optional[Resolution] = None + for rec in records: + candidate = str(rec.get("ADDRESS", "")) + score = AddressMatch.score(address, candidate) + if score >= threshold and (best is None or score > best[2]): + best = (str(rec.get("UPRN", "")), candidate, score, "ordnance_survey") + return best + + +def resolve_row( + row: dict[str, str], + *, + epc_token: Optional[str], + os_api_key: Optional[str], + epc_cache: dict[str, pd.DataFrame], + os_cache: dict[str, pd.DataFrame], + postcode_col: str, + use_epc: bool, + use_os: bool, + os_threshold: float, + validate_postcode: bool, +) -> dict[str, str]: + """Resolve one row in place and return it with the finaliser columns filled. + + Tries EPC (new + historic) first, then OS Places. On no match the three + result columns are written empty and `resolution_source` is "none". + """ + address = build_address(row) + postcode_clean = clean_postcode(str(row.get(postcode_col, "") or "")) + + def write(res: Optional[Resolution]) -> dict[str, str]: + if res is None: + row[UPRN_COL] = "" + row[MATCHED_ADDRESS_COL] = "" + row[LEXISCORE_COL] = "" + row[SOURCE_COL] = "none" + else: + uprn, matched, score, source = res + row[UPRN_COL] = uprn + row[MATCHED_ADDRESS_COL] = matched + row[LEXISCORE_COL] = str(score) + row[SOURCE_COL] = source + return row + + if not address or not postcode_clean: + return write(None) + + if validate_postcode and not AddressMatch.is_valid_postcode(postcode_clean): + return write(None) + + if use_epc and epc_token: + try: + res = resolve_epc(address, postcode_clean, epc_cache) + if res is not None: + return write(res) + except Exception as exc: # keep going on a per-row API/lookup failure + print(f" EPC lookup failed for {address!r} / {postcode_clean}: {exc}") + + if use_os and os_api_key: + try: + res = resolve_os(address, postcode_clean, os_api_key, os_cache, os_threshold) + if res is not None: + return write(res) + except Exception as exc: + print(f" OS lookup failed for {address!r} / {postcode_clean}: {exc}") + + return write(None) + + +def process( + rows: list[dict[str, str]], + *, + epc_token: Optional[str], + os_api_key: Optional[str], + postcode_col: str = "postcode", + use_epc: bool = True, + use_os: bool = True, + os_threshold: float = 0.5, + validate_postcode: bool = True, +) -> list[dict[str, str]]: + """Resolve every row, printing a per-row line so REPL/CLI progress is visible.""" + epc_cache: dict[str, pd.DataFrame] = {} + os_cache: dict[str, pd.DataFrame] = {} + for i, row in enumerate(rows, start=1): + resolve_row( + row, + epc_token=epc_token, + os_api_key=os_api_key, + epc_cache=epc_cache, + os_cache=os_cache, + postcode_col=postcode_col, + use_epc=use_epc, + use_os=use_os, + os_threshold=os_threshold, + validate_postcode=validate_postcode, + ) + print( + f"[{i}/{len(rows)}] {build_address(row)!r} -> " + f"{row[UPRN_COL] or '(no match)'} ({row[SOURCE_COL]})" + ) + return rows + + +def write_rows(rows: list[dict[str, str]], path: Path, fieldnames: list[str]) -> None: + """Write rows to CSV, preserving input columns and appending the result columns.""" + out_fields = list(fieldnames) + for col in _RESULT_COLS: + if col not in out_fields: + out_fields.append(col) + with path.open("w", newline="", encoding="utf-8") as fh: + writer = csv.DictWriter(fh, fieldnames=out_fields, extrasaction="ignore") + writer.writeheader() + writer.writerows(rows) + + +def _parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("input", type=Path, help="input CSV (Address 1/2/3 + postcode)") + parser.add_argument( + "-o", "--out", type=Path, required=True, help="output CSV for the finaliser" + ) + parser.add_argument("--postcode-col", default="postcode", help="postcode column name") + parser.add_argument("--no-epc", action="store_true", help="skip EPC resolution") + parser.add_argument("--no-os", action="store_true", help="skip Ordnance Survey fallback") + parser.add_argument( + "--os-threshold", type=float, default=0.5, help="min OS match score (default 0.5)" + ) + parser.add_argument( + "--no-validate-postcode", + action="store_true", + help="skip the postcodes.io validity check (one HTTP call per postcode)", + ) + parser.add_argument("--limit", type=int, default=None, help="process only the first N rows") + return parser.parse_args() + + +def main() -> int: + args = _parse_args() + epc_token, os_api_key = load_keys() + + use_epc = not args.no_epc + use_os = not args.no_os + if use_epc and not epc_token: + print("OPEN_EPC_API_TOKEN not set (backend/.env) — EPC resolution disabled") + use_epc = False + if use_os and not os_api_key: + print("ORDNANCE_SURVEY_API_KEY not set (backend/.env) — OS fallback disabled") + use_os = False + if not use_epc and not use_os: + print("No resolver enabled (missing keys or both --no-* flags). Nothing to do.") + return 2 + + rows, fieldnames = read_rows(args.input) + if args.limit is not None: + rows = rows[: args.limit] + print(f"Loaded {len(rows)} rows from {args.input}") + + process( + rows, + epc_token=epc_token, + os_api_key=os_api_key, + postcode_col=args.postcode_col, + use_epc=use_epc, + use_os=use_os, + os_threshold=args.os_threshold, + validate_postcode=not args.no_validate_postcode, + ) + + write_rows(rows, args.out, fieldnames) + matched = sum(1 for r in rows if r.get(UPRN_COL)) + print(f"\nResolved {matched}/{len(rows)} rows. Wrote {args.out}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 7f8e2762d0487986df9ebdbfeac6e491d681eaaf Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:22:32 +0000 Subject: [PATCH 07/74] =?UTF-8?q?Decode=20landlord=20electricity/LPG/oil/c?= =?UTF-8?q?oal=20overrides=20to=20fuel=20codes=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_main_fuel_overlay.py | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py index 96072c1d..f3cf0007 100644 --- a/tests/domain/epc/test_main_fuel_overlay.py +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -6,6 +6,8 @@ reads from the dwelling's primary heating system; the overlay is whole-dwelling. from __future__ import annotations +import pytest + from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for @@ -17,3 +19,24 @@ def test_mains_gas_overlays_the_primary_fuel() -> None: assert simulation is not None assert simulation.heating is not None assert simulation.heating.main_fuel_type == 26 + + +@pytest.mark.parametrize( + ("main_fuel_value", "code"), + [ + ("electricity", 29), + ("LPG (bulk)", 27), + ("oil", 28), + ("house coal", 33), + ], +) +def test_fuels_decode_to_their_modern_not_community_codes( + main_fuel_value: str, code: int +) -> None: + # Act + simulation = fuel_overlay_for(main_fuel_value, 0) + + # Assert + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.main_fuel_type == code From a402a3858e868b67b4725a3b567916fa0c4d1dc6 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:22:44 +0000 Subject: [PATCH 08/74] =?UTF-8?q?Decode=20landlord=20electricity/LPG/oil/c?= =?UTF-8?q?oal=20overrides=20to=20fuel=20codes=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/property_overlays/main_fuel_overlay.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/domain/epc/property_overlays/main_fuel_overlay.py b/domain/epc/property_overlays/main_fuel_overlay.py index 9118c0c9..9b580860 100644 --- a/domain/epc/property_overlays/main_fuel_overlay.py +++ b/domain/epc/property_overlays/main_fuel_overlay.py @@ -18,6 +18,10 @@ from domain.modelling.simulation import EpcSimulation, HeatingOverlay # RdSAP-20/21 `main_fuel` `(not community)` codes (epc_codes.csv `main_fuel`). _FUEL_CODES: dict[str, int] = { "mains gas": 26, + "LPG (bulk)": 27, + "oil": 28, + "electricity": 29, + "house coal": 33, } From 39950d410c0aaba18f814f622ec2e52a59dfb4df Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:22:56 +0000 Subject: [PATCH 09/74] =?UTF-8?q?Map=20community=20mains=20gas=20to=20its?= =?UTF-8?q?=20distinct=20fuel=20code=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_main_fuel_overlay.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py index f3cf0007..3f6bfdeb 100644 --- a/tests/domain/epc/test_main_fuel_overlay.py +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -40,3 +40,13 @@ def test_fuels_decode_to_their_modern_not_community_codes( assert simulation is not None assert simulation.heating is not None assert simulation.heating.main_fuel_type == code + + +def test_community_mains_gas_is_a_distinct_fuel_code() -> None: + # Act + simulation = fuel_overlay_for("mains gas (community)", 0) + + # Assert — community mains gas is code 20, distinct from 26 (not community). + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.main_fuel_type == 20 From 07aea7ef9bb993b5abb653478b762a90f28eade1 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:23:06 +0000 Subject: [PATCH 10/74] =?UTF-8?q?Map=20community=20mains=20gas=20to=20its?= =?UTF-8?q?=20distinct=20fuel=20code=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/property_overlays/main_fuel_overlay.py | 1 + 1 file changed, 1 insertion(+) diff --git a/domain/epc/property_overlays/main_fuel_overlay.py b/domain/epc/property_overlays/main_fuel_overlay.py index 9b580860..c3145705 100644 --- a/domain/epc/property_overlays/main_fuel_overlay.py +++ b/domain/epc/property_overlays/main_fuel_overlay.py @@ -18,6 +18,7 @@ from domain.modelling.simulation import EpcSimulation, HeatingOverlay # RdSAP-20/21 `main_fuel` `(not community)` codes (epc_codes.csv `main_fuel`). _FUEL_CODES: dict[str, int] = { "mains gas": 26, + "mains gas (community)": 20, "LPG (bulk)": 27, "oil": 28, "electricity": 29, From 35b48cc8fcde6181969b8d84f3c734e588fdf438 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:23:25 +0000 Subject: [PATCH 11/74] =?UTF-8?q?Produce=20no=20overlay=20for=20an=20unres?= =?UTF-8?q?olvable=20landlord=20fuel=20value=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_main_fuel_overlay.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py index 3f6bfdeb..1b554f5b 100644 --- a/tests/domain/epc/test_main_fuel_overlay.py +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -50,3 +50,12 @@ def test_community_mains_gas_is_a_distinct_fuel_code() -> None: assert simulation is not None assert simulation.heating is not None assert simulation.heating.main_fuel_type == 20 + + +@pytest.mark.parametrize("main_fuel_value", ["Unknown", "", "no heating or hot water"]) +def test_unresolvable_fuel_produces_no_overlay(main_fuel_value: str) -> None: + # Act + simulation = fuel_overlay_for(main_fuel_value, 0) + + # Assert + assert simulation is None From 991eb741325cb3c2bd5a5a19f694c77e510a7548 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:23:37 +0000 Subject: [PATCH 12/74] =?UTF-8?q?Route=20a=20main=5Ffuel=20override=20row?= =?UTF-8?q?=20through=20the=20fuel=20overlay=20mapper=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property/test_landlord_override_overlays.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/repositories/property/test_landlord_override_overlays.py b/tests/repositories/property/test_landlord_override_overlays.py index 20c79c1f..4c4a3403 100644 --- a/tests/repositories/property/test_landlord_override_overlays.py +++ b/tests/repositories/property/test_landlord_override_overlays.py @@ -47,6 +47,21 @@ def test_each_resolvable_component_produces_an_overlay() -> None: assert len(overlays) == 4 +def test_main_fuel_row_produces_a_heating_fuel_overlay() -> None: + # Arrange + overrides = ResolvedPropertyOverrides( + rows=(ResolvedPropertyOverride("main_fuel", 0, "mains gas"),) + ) + + # Act + overlays = overlays_from(overrides) + + # Assert + assert len(overlays) == 1 + assert overlays[0].heating is not None + assert overlays[0].heating.main_fuel_type == 26 + + def test_unresolvable_rows_are_skipped() -> None: # Arrange — an "Unknown" property type and an unmapped wall material. overrides = ResolvedPropertyOverrides( From b85db926edeb3644f431b2b44fdb6b46922acd97 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:23:52 +0000 Subject: [PATCH 13/74] =?UTF-8?q?Route=20a=20main=5Ffuel=20override=20row?= =?UTF-8?q?=20through=20the=20fuel=20overlay=20mapper=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- repositories/property/landlord_override_overlays.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/repositories/property/landlord_override_overlays.py b/repositories/property/landlord_override_overlays.py index ab8d7ca3..9d0f2fc7 100644 --- a/repositories/property/landlord_override_overlays.py +++ b/repositories/property/landlord_override_overlays.py @@ -29,6 +29,7 @@ from domain.epc.property_overlays.attribute_overlay import ( built_form_overlay_for, property_type_overlay_for, ) +from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.epc.property_overlays.roof_type_overlay import roof_overlay_for from domain.epc.property_overlays.wall_type_overlay import wall_overlay_for from domain.modelling.simulation import EpcSimulation @@ -43,6 +44,7 @@ _COMPONENT_OVERLAYS: dict[str, Callable[[str, int], Optional[EpcSimulation]]] = "roof_type": roof_overlay_for, "property_type": property_type_overlay_for, "built_form_type": built_form_overlay_for, + "main_fuel": fuel_overlay_for, } From 3dab6fc4251fa37e4367be844bd4f72a75806569 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:24:31 +0000 Subject: [PATCH 14/74] =?UTF-8?q?Remap=20the=20EPC=20primary=20fuel=20from?= =?UTF-8?q?=20a=20landlord=20fuel=20override=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_main_fuel_overlay.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py index 1b554f5b..2ffd9e29 100644 --- a/tests/domain/epc/test_main_fuel_overlay.py +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -9,6 +9,10 @@ from __future__ import annotations import pytest from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for +from domain.modelling.scoring.overlay_applicator import apply_simulations +from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( + build_epc, +) def test_mains_gas_overlays_the_primary_fuel() -> None: @@ -59,3 +63,16 @@ def test_unresolvable_fuel_produces_no_overlay(main_fuel_value: str) -> None: # Assert assert simulation is None + + +def test_fuel_override_remaps_the_primary_systems_fuel_on_the_epc() -> None: + # Arrange — a landlord correction that the dwelling runs on electricity. + baseline = build_epc() + overlay = fuel_overlay_for("electricity", 0) + assert overlay is not None + + # Act + result = apply_simulations(baseline, [overlay]) + + # Assert — the calculator reads the primary fuel from main_heating_details[0]. + assert result.sap_heating.main_heating_details[0].main_fuel_type == 29 From 04dd2dd222ccdc717a2795eef06d0a702db19002 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:43:54 +0000 Subject: [PATCH 15/74] =?UTF-8?q?Classify=20the=20landlord=20Main=20Fuel?= =?UTF-8?q?=20column=20into=20a=20fuel=20category=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../__init__.py | 0 .../test_build_columns.py | 27 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/applications/landlord_description_overrides/__init__.py create mode 100644 tests/applications/landlord_description_overrides/test_build_columns.py diff --git a/tests/applications/landlord_description_overrides/__init__.py b/tests/applications/landlord_description_overrides/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/applications/landlord_description_overrides/test_build_columns.py b/tests/applications/landlord_description_overrides/test_build_columns.py new file mode 100644 index 00000000..aff2f290 --- /dev/null +++ b/tests/applications/landlord_description_overrides/test_build_columns.py @@ -0,0 +1,27 @@ +"""The landlord-description-overrides handler's column wiring (`_build_columns`). + +A `column_mapping` entry of ``{category -> source header}`` must produce a +ClassifiableColumn that reads the named header and classifies into the +category's enum. This pins the main_fuel category onto the wiring. +""" + +from __future__ import annotations + +from typing import cast + +from applications.landlord_description_overrides.handler import _build_columns +from infrastructure.chatgpt.chatgpt import ChatGPT + + +def test_build_columns_wires_a_main_fuel_classifier_column() -> None: + # Arrange — the factory only stores the injected collaborators, so a bare + # object stands in for the (I/O-bound) ChatGPT client and the DB session. + chat_gpt = cast(ChatGPT, object()) + + # Act + columns = _build_columns({"main_fuel": "Main Fuel"}, chat_gpt, None) + + # Assert — one column, named main_fuel, reading the "Main Fuel" header. + assert len(columns) == 1 + assert columns[0].name == "main_fuel" + assert columns[0].source_column == "Main Fuel" From dbfe9820a5a06a8d1b33d2457098096cef6e1491 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:44:56 +0000 Subject: [PATCH 16/74] =?UTF-8?q?Classify=20the=20landlord=20Main=20Fuel?= =?UTF-8?q?=20column=20into=20a=20fuel=20category=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landlord_description_overrides/handler.py | 14 ++++ domain/epc/main_fuel_type.py | 23 +++++++ .../landlord_main_fuel_override_table.py | 69 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 domain/epc/main_fuel_type.py create mode 100644 infrastructure/postgres/landlord_main_fuel_override_table.py diff --git a/applications/landlord_description_overrides/handler.py b/applications/landlord_description_overrides/handler.py index 5e689a45..7be4dba1 100644 --- a/applications/landlord_description_overrides/handler.py +++ b/applications/landlord_description_overrides/handler.py @@ -8,6 +8,7 @@ from applications.landlord_description_overrides.landlord_description_overrides_ LandlordDescriptionOverridesTriggerBody, ) from domain.epc.built_form_type import BuiltFormType +from domain.epc.main_fuel_type import MainFuelType from domain.epc.property_type import PropertyType from domain.epc.roof_type import RoofType from domain.epc.wall_type import WallType @@ -24,6 +25,9 @@ from infrastructure.postgres.engine import commit_scope, make_engine, make_sessi from infrastructure.postgres.landlord_built_form_type_override_table import ( LandlordBuiltFormTypeOverrideRow, ) +from infrastructure.postgres.landlord_main_fuel_override_table import ( + LandlordMainFuelOverrideRow, +) from infrastructure.postgres.landlord_property_type_override_table import ( LandlordPropertyTypeOverrideRow, ) @@ -102,6 +106,16 @@ def _build_columns( session, LandlordRoofTypeOverrideRow ), ), + "main_fuel": lambda src: ClassifiableColumn( + name="main_fuel", + source_column=src, + classifier=ChatGptColumnClassifier( + chat_gpt, MainFuelType, MainFuelType.UNKNOWN + ), + repo=LandlordOverridesRepository[MainFuelType]( + session, LandlordMainFuelOverrideRow + ), + ), } columns: list[ClassifiableColumn[Any]] = [] diff --git a/domain/epc/main_fuel_type.py b/domain/epc/main_fuel_type.py new file mode 100644 index 00000000..0ad575c3 --- /dev/null +++ b/domain/epc/main_fuel_type.py @@ -0,0 +1,23 @@ +from enum import Enum + + +class MainFuelType(Enum): + """A landlord-supplied main-fuel description, as resolved by the + landlord-description-overrides context. + + Each member's value is the canonical fuel description that the main-fuel + Simulation Overlay (``domain/epc/property_overlays/main_fuel_overlay.py``) + decomposes into the RdSAP ``main_fuel`` int code the calculator reads — so + the member values here MUST stay in lock-step with that overlay's + ``_FUEL_CODES`` keys. ``UNKNOWN`` covers values the classifier cannot + resolve, and also any fuel not yet given a verified overlay code (it leaves + the lodged cert's fuel untouched rather than guessing). + """ + + MAINS_GAS = "mains gas" + MAINS_GAS_COMMUNITY = "mains gas (community)" + ELECTRICITY = "electricity" + LPG_BULK = "LPG (bulk)" + OIL = "oil" + HOUSE_COAL = "house coal" + UNKNOWN = "Unknown" diff --git a/infrastructure/postgres/landlord_main_fuel_override_table.py b/infrastructure/postgres/landlord_main_fuel_override_table.py new file mode 100644 index 00000000..c046453b --- /dev/null +++ b/infrastructure/postgres/landlord_main_fuel_override_table.py @@ -0,0 +1,69 @@ +"""SQLModel mirror of the ``landlord_main_fuel_overrides`` Drizzle table. + +The schema source of truth lives in the ``assessment-model`` TS repo +(`src/app/db/schema/landlord_overrides.ts`). The migrations are owned there; +this row class only mirrors the columns so the Python lambda can read/write. +See ADR-0003. Shape mirrors ``LandlordWallTypeOverrideRow`` -- the only +differences are the table name, the ``main_fuel`` pgEnum on ``value``, and +the unique-constraint name. +""" + +from datetime import datetime, timezone +from typing import ClassVar +from uuid import UUID, uuid4 + +from sqlalchemy import BigInteger, Column, UniqueConstraint +from sqlalchemy import Enum as SAEnum +from sqlmodel import Field, SQLModel + +from domain.epc.main_fuel_type import MainFuelType +from infrastructure.postgres.landlord_override_enums import override_source_sa_enum + + +class LandlordMainFuelOverrideRow(SQLModel, table=True): + __tablename__: ClassVar[str] = "landlord_main_fuel_overrides" # pyright: ignore[reportIncompatibleVariableOverride] + __table_args__: ClassVar[tuple[UniqueConstraint, ...]] = ( # pyright: ignore[reportIncompatibleVariableOverride] + UniqueConstraint( + "portfolio_id", + "description", + name="landlord_main_fuel_overrides_portfolio_description_unique", + ), + ) + + id: UUID = Field(default_factory=uuid4, primary_key=True) + + # bigint to match the Drizzle ``portfolio_id`` FK; SQLModel's default int + # mapping is 32-bit Integer and would overflow once portfolio IDs exceed + # 2^31. The FK to ``portfolio.id`` is enforced by the Drizzle migration, + # not declared here -- the ``portfolio`` table is not modelled in Python. + portfolio_id: int = Field( + sa_column=Column(BigInteger, nullable=False, index=True), + ) + + description: str = Field(nullable=False) + + value: MainFuelType = Field( + sa_column=Column( + SAEnum( + MainFuelType, + name="main_fuel", + values_callable=lambda cls: [m.value for m in cls], # pyright: ignore[reportUnknownLambdaType, reportUnknownMemberType, reportUnknownVariableType] + ), + nullable=False, + ), + ) + + # Shared SAEnum -- see ``landlord_override_enums`` for why this single + # instance is reused by every ``landlord_*_overrides`` row class. + source: str = Field( + sa_column=Column(override_source_sa_enum, nullable=False), + ) + + created_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) + updated_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) From cab69bbca9209e582db110a93cf7f62d390e9f8b Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 12:45:22 +0000 Subject: [PATCH 17/74] =?UTF-8?q?Guarantee=20every=20classifier=20fuel=20v?= =?UTF-8?q?alue=20maps=20to=20an=20overlay=20code=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_main_fuel_overlay.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py index 2ffd9e29..6001ddc3 100644 --- a/tests/domain/epc/test_main_fuel_overlay.py +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -8,6 +8,7 @@ from __future__ import annotations import pytest +from domain.epc.main_fuel_type import MainFuelType from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.modelling.scoring.overlay_applicator import apply_simulations from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( @@ -76,3 +77,18 @@ def test_fuel_override_remaps_the_primary_systems_fuel_on_the_epc() -> None: # Assert — the calculator reads the primary fuel from main_heating_details[0]. assert result.sap_heating.main_heating_details[0].main_fuel_type == 29 + + +@pytest.mark.parametrize( + "member", [m for m in MainFuelType if m is not MainFuelType.UNKNOWN] +) +def test_every_resolvable_fuel_value_decodes_to_a_code(member: MainFuelType) -> None: + # A classifier emits a MainFuelType value; if the overlay can't decode it the + # override silently no-ops. Every non-UNKNOWN member must resolve. + + # Act + simulation = fuel_overlay_for(member.value, 0) + + # Assert + assert simulation is not None + From fd922a26c293dca75c375d7c72d24754400b3d36 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:01:07 +0000 Subject: [PATCH 18/74] =?UTF-8?q?Satisfy=20strict=20type-checking=20for=20?= =?UTF-8?q?the=20main=5Ffuel=20classifier=20wiring=20=F0=9F=9F=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landlord_description_overrides/test_build_columns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/applications/landlord_description_overrides/test_build_columns.py b/tests/applications/landlord_description_overrides/test_build_columns.py index aff2f290..02feaab6 100644 --- a/tests/applications/landlord_description_overrides/test_build_columns.py +++ b/tests/applications/landlord_description_overrides/test_build_columns.py @@ -9,7 +9,7 @@ from __future__ import annotations from typing import cast -from applications.landlord_description_overrides.handler import _build_columns +from applications.landlord_description_overrides.handler import _build_columns # pyright: ignore[reportPrivateUsage] from infrastructure.chatgpt.chatgpt import ChatGPT From f1c6825cae95bdd38b921ae0586602bfc724e19e Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:18:45 +0000 Subject: [PATCH 19/74] =?UTF-8?q?Resolve=20a=20landlord=20double-glazing?= =?UTF-8?q?=20override=20to=20its=20glazing=20code=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/property_overlays/glazing_overlay.py | 23 +++++++++++++++++++ domain/modelling/simulation.py | 23 +++++++++++++++++++ tests/domain/epc/test_glazing_overlay.py | 20 ++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 domain/epc/property_overlays/glazing_overlay.py create mode 100644 tests/domain/epc/test_glazing_overlay.py diff --git a/domain/epc/property_overlays/glazing_overlay.py b/domain/epc/property_overlays/glazing_overlay.py new file mode 100644 index 00000000..9da7582d --- /dev/null +++ b/domain/epc/property_overlays/glazing_overlay.py @@ -0,0 +1,23 @@ +"""Map a Landlord-Override glazing value to a glazing Simulation Overlay. + +A glazing value is one canonical glazing description carrying type + era +("Double glazing, 2002 or later", "Single glazing", "Triple glazing, 2002 or +later"). The calculator derives each window's U-value from its SAP10 +`glazing_type` code via the RdSAP Table 24 cascade, so the overlay decomposes +the value into that code and emits a whole-dwelling `GlazingOverlay` (a landlord +describes the dwelling's glazing as a whole, with no per-window geometry, so +`building_part` is ignored). `_fold_glazing` expands it across every window. +Unresolvable values produce no overlay. +""" + +from __future__ import annotations + +from typing import Optional + +from domain.modelling.simulation import EpcSimulation + + +def glazing_overlay_for( + glazing_value: str, building_part: int +) -> Optional[EpcSimulation]: + raise NotImplementedError diff --git a/domain/modelling/simulation.py b/domain/modelling/simulation.py index 624826f6..217d446b 100644 --- a/domain/modelling/simulation.py +++ b/domain/modelling/simulation.py @@ -73,6 +73,28 @@ class WindowOverlay: solar_transmittance: Optional[float] = None +@dataclass(frozen=True) +class GlazingOverlay: + """All-optional partial of the dwelling's whole-glazing state — the + correction a Landlord Override makes when the lodged glazing is wrong. + + Unlike a per-window `WindowOverlay` (keyed by `sap_windows` index), this + targets no single window: a landlord describes the dwelling's glazing as a + whole ("Double glazing, 2002 or later") with no per-window geometry, so the + overlay builder (which never sees the baseline window list) emits one of + these and `_fold_glazing` expands it across every `sap_windows` entry. + + `glazing_type` is the SAP10 glazing-type code (Table 24 / `u_window` + cascade: 1=single, 2=double 2002-2021, 3=double pre-2002, 9=triple 2002+, + …). The fold sets it on every window AND clears each window's lodged + transmission U-value, so the Table-24 cascade re-derives the corrected U + from the new type (the lodged U was for the OLD, mis-recorded glazing). + A `None` field means "leave the baseline value unchanged". + """ + + glazing_type: Optional[int] = None + + @dataclass(frozen=True) class LightingOverlay: """All-optional partial of the dwelling's fixed-lighting bulb counts — the @@ -220,6 +242,7 @@ class EpcSimulation: windows: Mapping[int, WindowOverlay] = field(default_factory=_no_windows) ventilation: Optional[VentilationOverlay] = None lighting: Optional[LightingOverlay] = None + glazing: Optional[GlazingOverlay] = None heating: Optional[HeatingOverlay] = None secondary_heating: Optional[SecondaryHeatingOverlay] = None solar: Optional[SolarOverlay] = None diff --git a/tests/domain/epc/test_glazing_overlay.py b/tests/domain/epc/test_glazing_overlay.py new file mode 100644 index 00000000..b54e134e --- /dev/null +++ b/tests/domain/epc/test_glazing_overlay.py @@ -0,0 +1,20 @@ +"""The Landlord-Override glazing → glazing Simulation Overlay mapping. + +A glazing value resolves to the SAP10 `glazing_type` code the calculator's +Table-24 cascade reads; the overlay is whole-dwelling (expanded across every +window by `_fold_glazing`). +""" + +from __future__ import annotations + +from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for + + +def test_double_glazing_post_2002_overlays_its_glazing_code() -> None: + # Act + simulation = glazing_overlay_for("Double glazing, 2002 or later", 0) + + # Assert — double glazing 2002-2021 is SAP10 glazing_type code 2. + assert simulation is not None + assert simulation.glazing is not None + assert simulation.glazing.glazing_type == 2 From 0fb86771dd0607b4d43e776ced5d807f0bf3d02a Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:19:02 +0000 Subject: [PATCH 20/74] =?UTF-8?q?Resolve=20a=20landlord=20double-glazing?= =?UTF-8?q?=20override=20to=20its=20glazing=20code=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/property_overlays/glazing_overlay.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/domain/epc/property_overlays/glazing_overlay.py b/domain/epc/property_overlays/glazing_overlay.py index 9da7582d..6ee05030 100644 --- a/domain/epc/property_overlays/glazing_overlay.py +++ b/domain/epc/property_overlays/glazing_overlay.py @@ -14,10 +14,19 @@ from __future__ import annotations from typing import Optional -from domain.modelling.simulation import EpcSimulation +from domain.modelling.simulation import EpcSimulation, GlazingOverlay + +# Canonical glazing description → SAP10 glazing-type code (the Table 24 / +# `u_window` cascade enum, `_GLAZING_CODE_TO_UWINDOW` in heat_transmission). +_GLAZING_CODES: dict[str, int] = { + "Double glazing, 2002 or later": 2, +} def glazing_overlay_for( glazing_value: str, building_part: int ) -> Optional[EpcSimulation]: - raise NotImplementedError + code = _GLAZING_CODES.get(glazing_value) + if code is None: + return None + return EpcSimulation(glazing=GlazingOverlay(glazing_type=code)) From 917627c8336151bb8525ca32f9aba5b57810d90c Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:19:33 +0000 Subject: [PATCH 21/74] =?UTF-8?q?Decode=20single/double/triple=20glazing?= =?UTF-8?q?=20overrides=20to=20SAP=20codes=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_glazing_overlay.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/domain/epc/test_glazing_overlay.py b/tests/domain/epc/test_glazing_overlay.py index b54e134e..a5a6699e 100644 --- a/tests/domain/epc/test_glazing_overlay.py +++ b/tests/domain/epc/test_glazing_overlay.py @@ -7,6 +7,8 @@ window by `_fold_glazing`). from __future__ import annotations +import pytest + from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for @@ -18,3 +20,24 @@ def test_double_glazing_post_2002_overlays_its_glazing_code() -> None: assert simulation is not None assert simulation.glazing is not None assert simulation.glazing.glazing_type == 2 + + +@pytest.mark.parametrize( + ("glazing_value", "code"), + [ + ("Single glazing", 1), + ("Double glazing, pre-2002", 3), + ("Triple glazing, 2002 or later", 9), + ("Triple glazing, pre-2002", 6), + ], +) +def test_glazing_types_decode_to_their_sap_codes( + glazing_value: str, code: int +) -> None: + # Act + simulation = glazing_overlay_for(glazing_value, 0) + + # Assert + assert simulation is not None + assert simulation.glazing is not None + assert simulation.glazing.glazing_type == code From 88a4badbf7873d90ae609cddc60d677ff176a0f9 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:19:44 +0000 Subject: [PATCH 22/74] =?UTF-8?q?Decode=20single/double/triple=20glazing?= =?UTF-8?q?=20overrides=20to=20SAP=20codes=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/property_overlays/glazing_overlay.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/domain/epc/property_overlays/glazing_overlay.py b/domain/epc/property_overlays/glazing_overlay.py index 6ee05030..d692181d 100644 --- a/domain/epc/property_overlays/glazing_overlay.py +++ b/domain/epc/property_overlays/glazing_overlay.py @@ -19,7 +19,11 @@ from domain.modelling.simulation import EpcSimulation, GlazingOverlay # Canonical glazing description → SAP10 glazing-type code (the Table 24 / # `u_window` cascade enum, `_GLAZING_CODE_TO_UWINDOW` in heat_transmission). _GLAZING_CODES: dict[str, int] = { + "Single glazing": 1, "Double glazing, 2002 or later": 2, + "Double glazing, pre-2002": 3, + "Triple glazing, pre-2002": 6, + "Triple glazing, 2002 or later": 9, } From 71bdcabb73a92e257f0704dafda136161d07d0db Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:19:56 +0000 Subject: [PATCH 23/74] =?UTF-8?q?Produce=20no=20overlay=20for=20an=20unres?= =?UTF-8?q?olvable=20landlord=20glazing=20value=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_glazing_overlay.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/domain/epc/test_glazing_overlay.py b/tests/domain/epc/test_glazing_overlay.py index a5a6699e..9668e3aa 100644 --- a/tests/domain/epc/test_glazing_overlay.py +++ b/tests/domain/epc/test_glazing_overlay.py @@ -41,3 +41,12 @@ def test_glazing_types_decode_to_their_sap_codes( assert simulation is not None assert simulation.glazing is not None assert simulation.glazing.glazing_type == code + + +@pytest.mark.parametrize("glazing_value", ["Unknown", ""]) +def test_unresolvable_glazing_produces_no_overlay(glazing_value: str) -> None: + # Act + simulation = glazing_overlay_for(glazing_value, 0) + + # Assert + assert simulation is None From 1810f09240457c5b312a4a020d9669d403b6f48c Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:20:09 +0000 Subject: [PATCH 24/74] =?UTF-8?q?Route=20a=20glazing=20override=20row=20th?= =?UTF-8?q?rough=20the=20glazing=20overlay=20mapper=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property/test_landlord_override_overlays.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/repositories/property/test_landlord_override_overlays.py b/tests/repositories/property/test_landlord_override_overlays.py index 4c4a3403..ce86e78a 100644 --- a/tests/repositories/property/test_landlord_override_overlays.py +++ b/tests/repositories/property/test_landlord_override_overlays.py @@ -62,6 +62,21 @@ def test_main_fuel_row_produces_a_heating_fuel_overlay() -> None: assert overlays[0].heating.main_fuel_type == 26 +def test_glazing_row_produces_a_glazing_overlay() -> None: + # Arrange + overrides = ResolvedPropertyOverrides( + rows=(ResolvedPropertyOverride("glazing", 0, "Double glazing, 2002 or later"),) + ) + + # Act + overlays = overlays_from(overrides) + + # Assert + assert len(overlays) == 1 + assert overlays[0].glazing is not None + assert overlays[0].glazing.glazing_type == 2 + + def test_unresolvable_rows_are_skipped() -> None: # Arrange — an "Unknown" property type and an unmapped wall material. overrides = ResolvedPropertyOverrides( From 5a1cf288927e63c3e6f60a08d2d8fcd8a20aaec9 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:20:25 +0000 Subject: [PATCH 25/74] =?UTF-8?q?Route=20a=20glazing=20override=20row=20th?= =?UTF-8?q?rough=20the=20glazing=20overlay=20mapper=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- repositories/property/landlord_override_overlays.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/repositories/property/landlord_override_overlays.py b/repositories/property/landlord_override_overlays.py index 9d0f2fc7..624487eb 100644 --- a/repositories/property/landlord_override_overlays.py +++ b/repositories/property/landlord_override_overlays.py @@ -29,6 +29,7 @@ from domain.epc.property_overlays.attribute_overlay import ( built_form_overlay_for, property_type_overlay_for, ) +from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.epc.property_overlays.roof_type_overlay import roof_overlay_for from domain.epc.property_overlays.wall_type_overlay import wall_overlay_for @@ -45,6 +46,7 @@ _COMPONENT_OVERLAYS: dict[str, Callable[[str, int], Optional[EpcSimulation]]] = "property_type": property_type_overlay_for, "built_form_type": built_form_overlay_for, "main_fuel": fuel_overlay_for, + "glazing": glazing_overlay_for, } From 8ce22a5ccb35fecbf1249d4922b62a8052cf3a9e Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:21:06 +0000 Subject: [PATCH 26/74] =?UTF-8?q?Remap=20every=20window's=20glazing=20from?= =?UTF-8?q?=20a=20landlord=20glazing=20override=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_glazing_overlay.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/domain/epc/test_glazing_overlay.py b/tests/domain/epc/test_glazing_overlay.py index 9668e3aa..d65220e7 100644 --- a/tests/domain/epc/test_glazing_overlay.py +++ b/tests/domain/epc/test_glazing_overlay.py @@ -10,6 +10,10 @@ from __future__ import annotations import pytest from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for +from domain.modelling.scoring.overlay_applicator import apply_simulations +from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( + build_epc, +) def test_double_glazing_post_2002_overlays_its_glazing_code() -> None: @@ -50,3 +54,20 @@ def test_unresolvable_glazing_produces_no_overlay(glazing_value: str) -> None: # Assert assert simulation is None + + +def test_glazing_override_remaps_every_window_and_clears_lodged_u() -> None: + # Arrange — baseline windows are double glazed (code 2, lodged U 2.8); the + # landlord corrects the whole dwelling to single glazing. + baseline = build_epc() + assert len(baseline.sap_windows) > 1 + overlay = glazing_overlay_for("Single glazing", 0) + assert overlay is not None + + # Act + result = apply_simulations(baseline, [overlay]) + + # Assert — every window flips to single (code 1) and its lodged transmission + # U is cleared so the Table-24 cascade re-derives U from the new type. + assert all(w.glazing_type == 1 for w in result.sap_windows) + assert all(w.window_transmission_details is None for w in result.sap_windows) From 608e96bb09b4c81204be04a4b8fba5622fa1b09f Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:21:42 +0000 Subject: [PATCH 27/74] =?UTF-8?q?Remap=20every=20window's=20glazing=20from?= =?UTF-8?q?=20a=20landlord=20glazing=20override=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/modelling/scoring/overlay_applicator.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/domain/modelling/scoring/overlay_applicator.py b/domain/modelling/scoring/overlay_applicator.py index 9c83724a..961f4e02 100644 --- a/domain/modelling/scoring/overlay_applicator.py +++ b/domain/modelling/scoring/overlay_applicator.py @@ -19,6 +19,7 @@ from datatypes.epc.domain.epc_property_data import ( ) from domain.modelling.simulation import ( EpcSimulation, + GlazingOverlay, HeatingOverlay, LightingOverlay, SecondaryHeatingOverlay, @@ -53,6 +54,8 @@ def apply_simulations( ) if simulation.lighting is not None: _fold_lighting(result, simulation.lighting) + if simulation.glazing is not None: + _fold_glazing(result, simulation.glazing) if simulation.heating is not None: _fold_heating(result, simulation.heating) if simulation.secondary_heating is not None: @@ -202,6 +205,21 @@ def _fold_window(window: SapWindow, overlay: WindowOverlay) -> None: details.solar_transmittance = overlay.solar_transmittance +def _fold_glazing(epc: EpcPropertyData, overlay: GlazingOverlay) -> None: + """Expand a whole-dwelling `GlazingOverlay` across every window: set each + window's `glazing_type` to the corrected SAP10 code AND clear its lodged + transmission U, so `heat_transmission`'s Table-24 cascade re-derives U from + the new type (the lodged U was for the old, mis-recorded glazing). A landlord + glazing override carries no per-window geometry, so it applies uniformly — + the expansion lives here because the baseline window list is known only at + fold time.""" + if overlay.glazing_type is None: + return + for window in epc.sap_windows: + window.glazing_type = overlay.glazing_type + window.window_transmission_details = None + + def _fold_ventilation( baseline: Optional[SapVentilation], overlay: VentilationOverlay ) -> SapVentilation: From 0b782bd1a60d1ce0029af3faba7399602f5cbbbf Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:35:39 +0000 Subject: [PATCH 28/74] =?UTF-8?q?Classify=20the=20landlord=20Glazing=20col?= =?UTF-8?q?umn=20into=20a=20glazing=20category=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_build_columns.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/applications/landlord_description_overrides/test_build_columns.py b/tests/applications/landlord_description_overrides/test_build_columns.py index 02feaab6..c6748728 100644 --- a/tests/applications/landlord_description_overrides/test_build_columns.py +++ b/tests/applications/landlord_description_overrides/test_build_columns.py @@ -25,3 +25,16 @@ def test_build_columns_wires_a_main_fuel_classifier_column() -> None: assert len(columns) == 1 assert columns[0].name == "main_fuel" assert columns[0].source_column == "Main Fuel" + + +def test_build_columns_wires_a_glazing_classifier_column() -> None: + # Arrange + chat_gpt = cast(ChatGPT, object()) + + # Act + columns = _build_columns({"glazing": "Glazing"}, chat_gpt, None) + + # Assert — one column, named glazing, reading the "Glazing" header. + assert len(columns) == 1 + assert columns[0].name == "glazing" + assert columns[0].source_column == "Glazing" From db95205fc53f85890b0d8318cb08f7f82a5cb187 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:36:34 +0000 Subject: [PATCH 29/74] =?UTF-8?q?Classify=20the=20landlord=20Glazing=20col?= =?UTF-8?q?umn=20into=20a=20glazing=20category=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landlord_description_overrides/handler.py | 14 ++++ domain/epc/glazing_type.py | 24 +++++++ .../landlord_glazing_override_table.py | 69 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 domain/epc/glazing_type.py create mode 100644 infrastructure/postgres/landlord_glazing_override_table.py diff --git a/applications/landlord_description_overrides/handler.py b/applications/landlord_description_overrides/handler.py index 7be4dba1..16dbb000 100644 --- a/applications/landlord_description_overrides/handler.py +++ b/applications/landlord_description_overrides/handler.py @@ -8,6 +8,7 @@ from applications.landlord_description_overrides.landlord_description_overrides_ LandlordDescriptionOverridesTriggerBody, ) from domain.epc.built_form_type import BuiltFormType +from domain.epc.glazing_type import GlazingType from domain.epc.main_fuel_type import MainFuelType from domain.epc.property_type import PropertyType from domain.epc.roof_type import RoofType @@ -25,6 +26,9 @@ from infrastructure.postgres.engine import commit_scope, make_engine, make_sessi from infrastructure.postgres.landlord_built_form_type_override_table import ( LandlordBuiltFormTypeOverrideRow, ) +from infrastructure.postgres.landlord_glazing_override_table import ( + LandlordGlazingOverrideRow, +) from infrastructure.postgres.landlord_main_fuel_override_table import ( LandlordMainFuelOverrideRow, ) @@ -116,6 +120,16 @@ def _build_columns( session, LandlordMainFuelOverrideRow ), ), + "glazing": lambda src: ClassifiableColumn( + name="glazing", + source_column=src, + classifier=ChatGptColumnClassifier( + chat_gpt, GlazingType, GlazingType.UNKNOWN + ), + repo=LandlordOverridesRepository[GlazingType]( + session, LandlordGlazingOverrideRow + ), + ), } columns: list[ClassifiableColumn[Any]] = [] diff --git a/domain/epc/glazing_type.py b/domain/epc/glazing_type.py new file mode 100644 index 00000000..ee3ad267 --- /dev/null +++ b/domain/epc/glazing_type.py @@ -0,0 +1,24 @@ +from enum import Enum + + +class GlazingType(Enum): + """A landlord-supplied glazing description, as resolved by the + landlord-description-overrides context. + + Each member's value is the canonical glazing description (type + era) that + the glazing Simulation Overlay + (``domain/epc/property_overlays/glazing_overlay.py``) decomposes into the + SAP10 ``glazing_type`` code the calculator's Table-24 cascade reads — so the + member values here MUST stay in lock-step with that overlay's + ``_GLAZING_CODES`` keys. The era matters: double-glazing pre-2002 and + 2002-onward resolve to different codes (and U-values). ``UNKNOWN`` covers + values the classifier cannot resolve, and any glazing not yet given a + verified overlay code (it leaves the lodged cert's glazing untouched). + """ + + SINGLE = "Single glazing" + DOUBLE_POST_2002 = "Double glazing, 2002 or later" + DOUBLE_PRE_2002 = "Double glazing, pre-2002" + TRIPLE_PRE_2002 = "Triple glazing, pre-2002" + TRIPLE_POST_2002 = "Triple glazing, 2002 or later" + UNKNOWN = "Unknown" diff --git a/infrastructure/postgres/landlord_glazing_override_table.py b/infrastructure/postgres/landlord_glazing_override_table.py new file mode 100644 index 00000000..f42a48d2 --- /dev/null +++ b/infrastructure/postgres/landlord_glazing_override_table.py @@ -0,0 +1,69 @@ +"""SQLModel mirror of the ``landlord_glazing_overrides`` Drizzle table. + +The schema source of truth lives in the ``assessment-model`` TS repo +(`src/app/db/schema/landlord_overrides.ts`). The migrations are owned there; +this row class only mirrors the columns so the Python lambda can read/write. +See ADR-0003. Shape mirrors ``LandlordWallTypeOverrideRow`` -- the only +differences are the table name, the ``glazing`` pgEnum on ``value``, and the +unique-constraint name. +""" + +from datetime import datetime, timezone +from typing import ClassVar +from uuid import UUID, uuid4 + +from sqlalchemy import BigInteger, Column, UniqueConstraint +from sqlalchemy import Enum as SAEnum +from sqlmodel import Field, SQLModel + +from domain.epc.glazing_type import GlazingType +from infrastructure.postgres.landlord_override_enums import override_source_sa_enum + + +class LandlordGlazingOverrideRow(SQLModel, table=True): + __tablename__: ClassVar[str] = "landlord_glazing_overrides" # pyright: ignore[reportIncompatibleVariableOverride] + __table_args__: ClassVar[tuple[UniqueConstraint, ...]] = ( # pyright: ignore[reportIncompatibleVariableOverride] + UniqueConstraint( + "portfolio_id", + "description", + name="landlord_glazing_overrides_portfolio_description_unique", + ), + ) + + id: UUID = Field(default_factory=uuid4, primary_key=True) + + # bigint to match the Drizzle ``portfolio_id`` FK; SQLModel's default int + # mapping is 32-bit Integer and would overflow once portfolio IDs exceed + # 2^31. The FK to ``portfolio.id`` is enforced by the Drizzle migration, + # not declared here -- the ``portfolio`` table is not modelled in Python. + portfolio_id: int = Field( + sa_column=Column(BigInteger, nullable=False, index=True), + ) + + description: str = Field(nullable=False) + + value: GlazingType = Field( + sa_column=Column( + SAEnum( + GlazingType, + name="glazing", + values_callable=lambda cls: [m.value for m in cls], # pyright: ignore[reportUnknownLambdaType, reportUnknownMemberType, reportUnknownVariableType] + ), + nullable=False, + ), + ) + + # Shared SAEnum -- see ``landlord_override_enums`` for why this single + # instance is reused by every ``landlord_*_overrides`` row class. + source: str = Field( + sa_column=Column(override_source_sa_enum, nullable=False), + ) + + created_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) + updated_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) From 5a6d9a4e5d0d8a0fb6441bf1cb1736cfe2567294 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:38:07 +0000 Subject: [PATCH 30/74] =?UTF-8?q?Guarantee=20every=20classifier=20glazing?= =?UTF-8?q?=20value=20maps=20to=20an=20overlay=20code=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_glazing_overlay.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/domain/epc/test_glazing_overlay.py b/tests/domain/epc/test_glazing_overlay.py index d65220e7..c7ba72a8 100644 --- a/tests/domain/epc/test_glazing_overlay.py +++ b/tests/domain/epc/test_glazing_overlay.py @@ -9,6 +9,7 @@ from __future__ import annotations import pytest +from domain.epc.glazing_type import GlazingType from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for from domain.modelling.scoring.overlay_applicator import apply_simulations from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( @@ -71,3 +72,19 @@ def test_glazing_override_remaps_every_window_and_clears_lodged_u() -> None: # U is cleared so the Table-24 cascade re-derives U from the new type. assert all(w.glazing_type == 1 for w in result.sap_windows) assert all(w.window_transmission_details is None for w in result.sap_windows) + + +@pytest.mark.parametrize( + "member", [m for m in GlazingType if m is not GlazingType.UNKNOWN] +) +def test_every_resolvable_glazing_value_decodes_to_a_code( + member: GlazingType, +) -> None: + # A classifier emits a GlazingType value; if the overlay can't decode it the + # override silently no-ops. Every non-UNKNOWN member must resolve. + + # Act + simulation = glazing_overlay_for(member.value, 0) + + # Assert + assert simulation is not None From 0135f0f27b33a1d0f9e871d5c6fa4c36a27155df Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:41:20 +0000 Subject: [PATCH 31/74] =?UTF-8?q?Resolve=20a=20landlord=20age-band=20overr?= =?UTF-8?q?ide=20onto=20the=20main=20building=20part=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../construction_age_band_overlay.py | 22 ++++++++++++++++++ domain/modelling/simulation.py | 6 +++++ .../epc/test_construction_age_band_overlay.py | 23 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 domain/epc/property_overlays/construction_age_band_overlay.py create mode 100644 tests/domain/epc/test_construction_age_band_overlay.py diff --git a/domain/epc/property_overlays/construction_age_band_overlay.py b/domain/epc/property_overlays/construction_age_band_overlay.py new file mode 100644 index 00000000..d4cc6eae --- /dev/null +++ b/domain/epc/property_overlays/construction_age_band_overlay.py @@ -0,0 +1,22 @@ +"""Map a Landlord-Override construction-age-band value to a fabric Simulation +Overlay. + +A construction-age-band value is the RdSAP England-&-Wales letter code (A..M) +the calculator's U-value cascades key on (`SapBuildingPart.construction_age_band`, +read via `.strip().upper()` against the letter-code bands). The overlay targets +the override's building part and sets the band; an unrecognised code produces no +overlay. Re-dating a part re-derives its construction-default U-values, so this +is the highest-leverage fabric override. +""" + +from __future__ import annotations + +from typing import Optional + +from domain.modelling.simulation import EpcSimulation + + +def age_band_overlay_for( + age_band_value: str, building_part: int +) -> Optional[EpcSimulation]: + raise NotImplementedError diff --git a/domain/modelling/simulation.py b/domain/modelling/simulation.py index 217d446b..caee5fb5 100644 --- a/domain/modelling/simulation.py +++ b/domain/modelling/simulation.py @@ -28,6 +28,12 @@ class BuildingPartOverlay: # The wall material (RdSAP `wall_construction` code). Left `None` by Measures # — insulating a wall doesn't change its material — but set by a Landlord # Override that corrects the construction itself (ADR-0032). + # RdSAP England-&-Wales construction age band — the letter code A..M the + # calculator's U-value cascades key on (`SapBuildingPart.construction_age_band`). + # Left `None` by Measures (retrofits don't change build era); set by a Landlord + # Override that corrects the lodged age band, which re-derives this part's + # fabric U-value defaults. Folds onto the part via the generic field loop. + construction_age_band: Optional[str] = None wall_construction: Optional[int] = None wall_insulation_type: Optional[int] = None # Added solid-wall insulation depth (mm) — drives the calculator's Table 6 diff --git a/tests/domain/epc/test_construction_age_band_overlay.py b/tests/domain/epc/test_construction_age_band_overlay.py new file mode 100644 index 00000000..066244a6 --- /dev/null +++ b/tests/domain/epc/test_construction_age_band_overlay.py @@ -0,0 +1,23 @@ +"""The Landlord-Override construction-age-band → fabric Simulation Overlay. + +An age-band value resolves to the RdSAP letter code the calculator's U-value +cascades read from `SapBuildingPart.construction_age_band`; the overlay targets +the override's building part. +""" + +from __future__ import annotations + +from datatypes.epc.domain.epc_property_data import BuildingPartIdentifier +from domain.epc.property_overlays.construction_age_band_overlay import ( + age_band_overlay_for, +) + + +def test_age_band_overlays_the_main_building_part() -> None: + # Act — band B (1900-1929) on the main building part. + simulation = age_band_overlay_for("B", 0) + + # Assert + assert simulation is not None + overlay = simulation.building_parts[BuildingPartIdentifier.MAIN] + assert overlay.construction_age_band == "B" From 406365753bcdf2b75a4ec66787aa375746896cb4 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:41:35 +0000 Subject: [PATCH 32/74] =?UTF-8?q?Resolve=20a=20landlord=20age-band=20overr?= =?UTF-8?q?ide=20onto=20the=20main=20building=20part=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../construction_age_band_overlay.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/domain/epc/property_overlays/construction_age_band_overlay.py b/domain/epc/property_overlays/construction_age_band_overlay.py index d4cc6eae..55054168 100644 --- a/domain/epc/property_overlays/construction_age_band_overlay.py +++ b/domain/epc/property_overlays/construction_age_band_overlay.py @@ -13,10 +13,27 @@ from __future__ import annotations from typing import Optional -from domain.modelling.simulation import EpcSimulation +from datatypes.epc.domain.epc_property_data import BuildingPartIdentifier +from domain.modelling.simulation import BuildingPartOverlay, EpcSimulation + +# RdSAP England-&-Wales construction age bands (letter codes A..M). +_VALID_AGE_BANDS: frozenset[str] = frozenset("ABCDEFGHIJKLM") def age_band_overlay_for( age_band_value: str, building_part: int ) -> Optional[EpcSimulation]: - raise NotImplementedError + band = age_band_value.strip().upper() + if band not in _VALID_AGE_BANDS: + return None + + identifier = ( + BuildingPartIdentifier.MAIN + if building_part == 0 + else BuildingPartIdentifier.extension(building_part) + ) + return EpcSimulation( + building_parts={ + identifier: BuildingPartOverlay(construction_age_band=band) + } + ) From cd14751fdb5a27c1cc50001f70e42986ee8de43d Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:42:02 +0000 Subject: [PATCH 33/74] =?UTF-8?q?Route=20age-band=20overrides=20to=20the?= =?UTF-8?q?=20right=20part,=20normalise,=20reject=20unknown=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/test_construction_age_band_overlay.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/domain/epc/test_construction_age_band_overlay.py b/tests/domain/epc/test_construction_age_band_overlay.py index 066244a6..bb66933e 100644 --- a/tests/domain/epc/test_construction_age_band_overlay.py +++ b/tests/domain/epc/test_construction_age_band_overlay.py @@ -7,6 +7,8 @@ the override's building part. from __future__ import annotations +import pytest + from datatypes.epc.domain.epc_property_data import BuildingPartIdentifier from domain.epc.property_overlays.construction_age_band_overlay import ( age_band_overlay_for, @@ -21,3 +23,38 @@ def test_age_band_overlays_the_main_building_part() -> None: assert simulation is not None overlay = simulation.building_parts[BuildingPartIdentifier.MAIN] assert overlay.construction_age_band == "B" + + +def test_age_band_overlay_targets_the_extension_building_part() -> None: + # Act — building_part 1 is the first extension. + simulation = age_band_overlay_for("L", 1) + + # Assert + assert simulation is not None + assert BuildingPartIdentifier.EXTENSION_1 in simulation.building_parts + assert ( + simulation.building_parts[BuildingPartIdentifier.EXTENSION_1] + .construction_age_band + == "L" + ) + + +def test_lowercase_age_band_is_normalised_to_its_letter_code() -> None: + # Act + simulation = age_band_overlay_for("d", 0) + + # Assert — the calculator upper-cases the band; the overlay stores it upper. + assert simulation is not None + assert ( + simulation.building_parts[BuildingPartIdentifier.MAIN].construction_age_band + == "D" + ) + + +@pytest.mark.parametrize("age_band_value", ["Z", "", "1900-1929", "Unknown"]) +def test_unrecognised_age_band_produces_no_overlay(age_band_value: str) -> None: + # Act + simulation = age_band_overlay_for(age_band_value, 0) + + # Assert + assert simulation is None From 55cdc1c7775ac45e79cc181c4a999356864d2fdd Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:42:19 +0000 Subject: [PATCH 34/74] =?UTF-8?q?Route=20a=20construction=5Fage=5Fband=20o?= =?UTF-8?q?verride=20row=20through=20its=20overlay=20mapper=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property/test_landlord_override_overlays.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/repositories/property/test_landlord_override_overlays.py b/tests/repositories/property/test_landlord_override_overlays.py index ce86e78a..2b687656 100644 --- a/tests/repositories/property/test_landlord_override_overlays.py +++ b/tests/repositories/property/test_landlord_override_overlays.py @@ -77,6 +77,21 @@ def test_glazing_row_produces_a_glazing_overlay() -> None: assert overlays[0].glazing.glazing_type == 2 +def test_construction_age_band_row_produces_a_building_part_overlay() -> None: + # Arrange + overrides = ResolvedPropertyOverrides( + rows=(ResolvedPropertyOverride("construction_age_band", 0, "B"),) + ) + + # Act + overlays = overlays_from(overrides) + + # Assert + assert len(overlays) == 1 + main = overlays[0].building_parts[BuildingPartIdentifier.MAIN] + assert main.construction_age_band == "B" + + def test_unresolvable_rows_are_skipped() -> None: # Arrange — an "Unknown" property type and an unmapped wall material. overrides = ResolvedPropertyOverrides( From b13166742dd0849b1b1acccae650eeefac52b14e Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:42:43 +0000 Subject: [PATCH 35/74] =?UTF-8?q?Route=20a=20construction=5Fage=5Fband=20o?= =?UTF-8?q?verride=20row=20through=20its=20overlay=20mapper=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- repositories/property/landlord_override_overlays.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/repositories/property/landlord_override_overlays.py b/repositories/property/landlord_override_overlays.py index 624487eb..fd6d5f68 100644 --- a/repositories/property/landlord_override_overlays.py +++ b/repositories/property/landlord_override_overlays.py @@ -29,6 +29,9 @@ from domain.epc.property_overlays.attribute_overlay import ( built_form_overlay_for, property_type_overlay_for, ) +from domain.epc.property_overlays.construction_age_band_overlay import ( + age_band_overlay_for, +) from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.epc.property_overlays.roof_type_overlay import roof_overlay_for @@ -47,6 +50,7 @@ _COMPONENT_OVERLAYS: dict[str, Callable[[str, int], Optional[EpcSimulation]]] = "built_form_type": built_form_overlay_for, "main_fuel": fuel_overlay_for, "glazing": glazing_overlay_for, + "construction_age_band": age_band_overlay_for, } From e71df5df99f38773db56c2bd5c18c32f92b8fbcb Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:43:28 +0000 Subject: [PATCH 36/74] =?UTF-8?q?Re-date=20a=20building=20part's=20EPC=20a?= =?UTF-8?q?ge=20band=20from=20a=20landlord=20override=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/test_construction_age_band_overlay.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/domain/epc/test_construction_age_band_overlay.py b/tests/domain/epc/test_construction_age_band_overlay.py index bb66933e..7527b9ea 100644 --- a/tests/domain/epc/test_construction_age_band_overlay.py +++ b/tests/domain/epc/test_construction_age_band_overlay.py @@ -13,6 +13,14 @@ from datatypes.epc.domain.epc_property_data import BuildingPartIdentifier from domain.epc.property_overlays.construction_age_band_overlay import ( age_band_overlay_for, ) +from domain.modelling.scoring.overlay_applicator import apply_simulations +from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( + build_epc, +) + + +def _part(epc, identifier): # type: ignore[no-untyped-def] + return next(p for p in epc.sap_building_parts if p.identifier is identifier) def test_age_band_overlays_the_main_building_part() -> None: @@ -58,3 +66,21 @@ def test_unrecognised_age_band_produces_no_overlay(age_band_value: str) -> None: # Assert assert simulation is None + + +def test_age_band_override_re_dates_the_main_part_only() -> None: + # Arrange — baseline main + extension are both band B; the landlord corrects + # the main building's age band to F (1976-1982). + baseline = build_epc() + overlay = age_band_overlay_for("F", 0) + assert overlay is not None + + # Act + result = apply_simulations(baseline, [overlay]) + + # Assert — the main part is re-dated (its U-value cascade now keys on F); the + # extension is left untouched. + assert _part(result, BuildingPartIdentifier.MAIN).construction_age_band == "F" + assert ( + _part(result, BuildingPartIdentifier.EXTENSION_1).construction_age_band == "B" + ) From fc591c65502c73a4464a0d35bc002b3da09245a2 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:43:47 +0000 Subject: [PATCH 37/74] =?UTF-8?q?Classify=20the=20landlord=20Age=20column?= =?UTF-8?q?=20into=20a=20construction-age-band=20category=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_build_columns.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/applications/landlord_description_overrides/test_build_columns.py b/tests/applications/landlord_description_overrides/test_build_columns.py index c6748728..8f50afce 100644 --- a/tests/applications/landlord_description_overrides/test_build_columns.py +++ b/tests/applications/landlord_description_overrides/test_build_columns.py @@ -38,3 +38,16 @@ def test_build_columns_wires_a_glazing_classifier_column() -> None: assert len(columns) == 1 assert columns[0].name == "glazing" assert columns[0].source_column == "Glazing" + + +def test_build_columns_wires_a_construction_age_band_classifier_column() -> None: + # Arrange + chat_gpt = cast(ChatGPT, object()) + + # Act + columns = _build_columns({"construction_age_band": "Age"}, chat_gpt, None) + + # Assert — one column, named construction_age_band, reading the "Age" header. + assert len(columns) == 1 + assert columns[0].name == "construction_age_band" + assert columns[0].source_column == "Age" From cb6a335382985ebd2fda9df31ecc1e8e378cdcf1 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:44:40 +0000 Subject: [PATCH 38/74] =?UTF-8?q?Classify=20the=20landlord=20Age=20column?= =?UTF-8?q?=20into=20a=20construction-age-band=20category=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landlord_description_overrides/handler.py | 14 ++++ domain/epc/construction_age_band.py | 31 +++++++++ ...rd_construction_age_band_override_table.py | 69 +++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 domain/epc/construction_age_band.py create mode 100644 infrastructure/postgres/landlord_construction_age_band_override_table.py diff --git a/applications/landlord_description_overrides/handler.py b/applications/landlord_description_overrides/handler.py index 16dbb000..2f83b81f 100644 --- a/applications/landlord_description_overrides/handler.py +++ b/applications/landlord_description_overrides/handler.py @@ -8,6 +8,7 @@ from applications.landlord_description_overrides.landlord_description_overrides_ LandlordDescriptionOverridesTriggerBody, ) from domain.epc.built_form_type import BuiltFormType +from domain.epc.construction_age_band import ConstructionAgeBand from domain.epc.glazing_type import GlazingType from domain.epc.main_fuel_type import MainFuelType from domain.epc.property_type import PropertyType @@ -26,6 +27,9 @@ from infrastructure.postgres.engine import commit_scope, make_engine, make_sessi from infrastructure.postgres.landlord_built_form_type_override_table import ( LandlordBuiltFormTypeOverrideRow, ) +from infrastructure.postgres.landlord_construction_age_band_override_table import ( + LandlordConstructionAgeBandOverrideRow, +) from infrastructure.postgres.landlord_glazing_override_table import ( LandlordGlazingOverrideRow, ) @@ -130,6 +134,16 @@ def _build_columns( session, LandlordGlazingOverrideRow ), ), + "construction_age_band": lambda src: ClassifiableColumn( + name="construction_age_band", + source_column=src, + classifier=ChatGptColumnClassifier( + chat_gpt, ConstructionAgeBand, ConstructionAgeBand.UNKNOWN + ), + repo=LandlordOverridesRepository[ConstructionAgeBand]( + session, LandlordConstructionAgeBandOverrideRow + ), + ), } columns: list[ClassifiableColumn[Any]] = [] diff --git a/domain/epc/construction_age_band.py b/domain/epc/construction_age_band.py new file mode 100644 index 00000000..83f6e9a8 --- /dev/null +++ b/domain/epc/construction_age_band.py @@ -0,0 +1,31 @@ +from enum import Enum + + +class ConstructionAgeBand(Enum): + """A landlord-supplied construction age band, as resolved by the + landlord-description-overrides context. + + Each member's value is the RdSAP England-&-Wales age-band **letter code** + (A..M) the calculator's U-value cascades read from + `SapBuildingPart.construction_age_band` — the same representation the gov-EPC + API lodges. The construction-age-band Simulation Overlay + (``domain/epc/property_overlays/construction_age_band_overlay.py``) sets the + letter directly, so these values MUST stay the bare letter codes. Member + names carry the year ranges for readability. ``UNKNOWN`` covers values the + classifier cannot resolve (it leaves the lodged cert's age band untouched). + """ + + A_BEFORE_1900 = "A" + B_1900_1929 = "B" + C_1930_1949 = "C" + D_1950_1966 = "D" + E_1967_1975 = "E" + F_1976_1982 = "F" + G_1983_1990 = "G" + H_1991_1995 = "H" + I_1996_2002 = "I" + J_2003_2006 = "J" + K_2007_2011 = "K" + L_2012_2022 = "L" + M_2023_ONWARDS = "M" + UNKNOWN = "Unknown" diff --git a/infrastructure/postgres/landlord_construction_age_band_override_table.py b/infrastructure/postgres/landlord_construction_age_band_override_table.py new file mode 100644 index 00000000..598bbf56 --- /dev/null +++ b/infrastructure/postgres/landlord_construction_age_band_override_table.py @@ -0,0 +1,69 @@ +"""SQLModel mirror of the ``landlord_construction_age_band_overrides`` Drizzle table. + +The schema source of truth lives in the ``assessment-model`` TS repo +(`src/app/db/schema/landlord_overrides.ts`). The migrations are owned there; +this row class only mirrors the columns so the Python lambda can read/write. +See ADR-0003. Shape mirrors ``LandlordWallTypeOverrideRow`` -- the only +differences are the table name, the ``construction_age_band`` pgEnum on +``value``, and the unique-constraint name. +""" + +from datetime import datetime, timezone +from typing import ClassVar +from uuid import UUID, uuid4 + +from sqlalchemy import BigInteger, Column, UniqueConstraint +from sqlalchemy import Enum as SAEnum +from sqlmodel import Field, SQLModel + +from domain.epc.construction_age_band import ConstructionAgeBand +from infrastructure.postgres.landlord_override_enums import override_source_sa_enum + + +class LandlordConstructionAgeBandOverrideRow(SQLModel, table=True): + __tablename__: ClassVar[str] = "landlord_construction_age_band_overrides" # pyright: ignore[reportIncompatibleVariableOverride] + __table_args__: ClassVar[tuple[UniqueConstraint, ...]] = ( # pyright: ignore[reportIncompatibleVariableOverride] + UniqueConstraint( + "portfolio_id", + "description", + name="landlord_construction_age_band_overrides_portfolio_description_unique", + ), + ) + + id: UUID = Field(default_factory=uuid4, primary_key=True) + + # bigint to match the Drizzle ``portfolio_id`` FK; SQLModel's default int + # mapping is 32-bit Integer and would overflow once portfolio IDs exceed + # 2^31. The FK to ``portfolio.id`` is enforced by the Drizzle migration, + # not declared here -- the ``portfolio`` table is not modelled in Python. + portfolio_id: int = Field( + sa_column=Column(BigInteger, nullable=False, index=True), + ) + + description: str = Field(nullable=False) + + value: ConstructionAgeBand = Field( + sa_column=Column( + SAEnum( + ConstructionAgeBand, + name="construction_age_band", + values_callable=lambda cls: [m.value for m in cls], # pyright: ignore[reportUnknownLambdaType, reportUnknownMemberType, reportUnknownVariableType] + ), + nullable=False, + ), + ) + + # Shared SAEnum -- see ``landlord_override_enums`` for why this single + # instance is reused by every ``landlord_*_overrides`` row class. + source: str = Field( + sa_column=Column(override_source_sa_enum, nullable=False), + ) + + created_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) + updated_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) From 46d1f8bbb22f9da3796db19e56556c2e8dbd275c Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:45:31 +0000 Subject: [PATCH 39/74] =?UTF-8?q?Guarantee=20every=20classifier=20age-band?= =?UTF-8?q?=20value=20maps=20to=20an=20overlay=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/test_construction_age_band_overlay.py | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/domain/epc/test_construction_age_band_overlay.py b/tests/domain/epc/test_construction_age_band_overlay.py index 7527b9ea..3408900b 100644 --- a/tests/domain/epc/test_construction_age_band_overlay.py +++ b/tests/domain/epc/test_construction_age_band_overlay.py @@ -9,7 +9,12 @@ from __future__ import annotations import pytest -from datatypes.epc.domain.epc_property_data import BuildingPartIdentifier +from datatypes.epc.domain.epc_property_data import ( + BuildingPartIdentifier, + EpcPropertyData, + SapBuildingPart, +) +from domain.epc.construction_age_band import ConstructionAgeBand from domain.epc.property_overlays.construction_age_band_overlay import ( age_band_overlay_for, ) @@ -19,7 +24,9 @@ from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( ) -def _part(epc, identifier): # type: ignore[no-untyped-def] +def _part( + epc: EpcPropertyData, identifier: BuildingPartIdentifier +) -> SapBuildingPart: return next(p for p in epc.sap_building_parts if p.identifier is identifier) @@ -84,3 +91,19 @@ def test_age_band_override_re_dates_the_main_part_only() -> None: assert ( _part(result, BuildingPartIdentifier.EXTENSION_1).construction_age_band == "B" ) + + +@pytest.mark.parametrize( + "member", [m for m in ConstructionAgeBand if m is not ConstructionAgeBand.UNKNOWN] +) +def test_every_resolvable_age_band_value_decodes_to_an_overlay( + member: ConstructionAgeBand, +) -> None: + # A classifier emits a ConstructionAgeBand value; if the overlay can't decode + # it the override silently no-ops. Every non-UNKNOWN member must resolve. + + # Act + simulation = age_band_overlay_for(member.value, 0) + + # Assert + assert simulation is not None From 89bb075ce6866ea1a0f9ec28f472d042fdc74a0b Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 13:52:28 +0000 Subject: [PATCH 40/74] =?UTF-8?q?Keep=20the=20age-band=20unique=20constrai?= =?UTF-8?q?nt=20within=20Postgres's=2063-char=20limit=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landlord_construction_age_band_override_table.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/infrastructure/postgres/landlord_construction_age_band_override_table.py b/infrastructure/postgres/landlord_construction_age_band_override_table.py index 598bbf56..91eec66e 100644 --- a/infrastructure/postgres/landlord_construction_age_band_override_table.py +++ b/infrastructure/postgres/landlord_construction_age_band_override_table.py @@ -23,10 +23,14 @@ from infrastructure.postgres.landlord_override_enums import override_source_sa_e class LandlordConstructionAgeBandOverrideRow(SQLModel, table=True): __tablename__: ClassVar[str] = "landlord_construction_age_band_overrides" # pyright: ignore[reportIncompatibleVariableOverride] __table_args__: ClassVar[tuple[UniqueConstraint, ...]] = ( # pyright: ignore[reportIncompatibleVariableOverride] + # NB: shortened (drop the redundant ``_overrides``) to stay within + # PostgreSQL's 63-char identifier limit -- the full + # ``landlord_construction_age_band_overrides_portfolio_description_unique`` + # is 68 chars and would be silently truncated, diverging from Drizzle. UniqueConstraint( "portfolio_id", "description", - name="landlord_construction_age_band_overrides_portfolio_description_unique", + name="landlord_construction_age_band_portfolio_description_unique", ), ) From 8f7a34470767ae4383abc941924959f79d1f7149 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:02:48 +0000 Subject: [PATCH 41/74] =?UTF-8?q?Resolve=20a=20landlord=20from-main-gas=20?= =?UTF-8?q?water-heating=20override=20to=20its=20codes=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../water_heating_overlay.py | 22 +++++++++++++++++++ .../domain/epc/test_water_heating_overlay.py | 22 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 domain/epc/property_overlays/water_heating_overlay.py create mode 100644 tests/domain/epc/test_water_heating_overlay.py diff --git a/domain/epc/property_overlays/water_heating_overlay.py b/domain/epc/property_overlays/water_heating_overlay.py new file mode 100644 index 00000000..b65db1b1 --- /dev/null +++ b/domain/epc/property_overlays/water_heating_overlay.py @@ -0,0 +1,22 @@ +"""Map a Landlord-Override water-heating value to a heating Simulation Overlay. + +A water-heating value is one canonical ", " description ("From main +system, mains gas", "Electric immersion, electricity"). The calculator reads the +hot-water arrangement from `sap_heating.water_heating_code` (the SAP Table 4a +system code) and `water_heating_fuel`, so the overlay decomposes the value into +those two int codes and emits a whole-dwelling `HeatingOverlay` (water heating is +not per-building-part, so `building_part` is ignored). It composes field-wise with +the main_fuel / main_heating overlays. Unresolvable values produce no overlay. +""" + +from __future__ import annotations + +from typing import Optional + +from domain.modelling.simulation import EpcSimulation + + +def water_heating_overlay_for( + water_heating_value: str, building_part: int +) -> Optional[EpcSimulation]: + raise NotImplementedError diff --git a/tests/domain/epc/test_water_heating_overlay.py b/tests/domain/epc/test_water_heating_overlay.py new file mode 100644 index 00000000..f9379184 --- /dev/null +++ b/tests/domain/epc/test_water_heating_overlay.py @@ -0,0 +1,22 @@ +"""The Landlord-Override water-heating → heating Simulation Overlay mapping. + +A water-heating value resolves to the SAP `water_heating_code` (system) and +`water_heating_fuel` the calculator reads; the overlay is whole-dwelling. +""" + +from __future__ import annotations + +from domain.epc.property_overlays.water_heating_overlay import ( + water_heating_overlay_for, +) + + +def test_from_main_system_mains_gas_overlays_water_heating() -> None: + # Act + simulation = water_heating_overlay_for("From main system, mains gas", 0) + + # Assert — "from main system" is water_heating_code 901, mains gas fuel 26. + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.water_heating_code == 901 + assert simulation.heating.water_heating_fuel == 26 From 7d70c1d298bbdeb16d554e274251360a06f762e3 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:03:03 +0000 Subject: [PATCH 42/74] =?UTF-8?q?Resolve=20a=20landlord=20from-main-gas=20?= =?UTF-8?q?water-heating=20override=20to=20its=20codes=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../water_heating_overlay.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/domain/epc/property_overlays/water_heating_overlay.py b/domain/epc/property_overlays/water_heating_overlay.py index b65db1b1..d75ea81c 100644 --- a/domain/epc/property_overlays/water_heating_overlay.py +++ b/domain/epc/property_overlays/water_heating_overlay.py @@ -13,10 +13,27 @@ from __future__ import annotations from typing import Optional -from domain.modelling.simulation import EpcSimulation +from domain.modelling.simulation import EpcSimulation, HeatingOverlay + +# Canonical ", " description → (water_heating_code, water_heating_fuel). +# water_heating_code: 901 "from main system" (SAP Table 4a inherit-from-main), +# 903 "electric immersion". Fuel codes are the modern RdSAP "(not community)" +# family (26 mains gas, 29 electricity), matching the main_fuel overlay. +_WATER_HEATING_CODES: dict[str, tuple[int, int]] = { + "From main system, mains gas": (901, 26), +} def water_heating_overlay_for( water_heating_value: str, building_part: int ) -> Optional[EpcSimulation]: - raise NotImplementedError + codes = _WATER_HEATING_CODES.get(water_heating_value) + if codes is None: + return None + water_heating_code, water_heating_fuel = codes + return EpcSimulation( + heating=HeatingOverlay( + water_heating_code=water_heating_code, + water_heating_fuel=water_heating_fuel, + ) + ) From a117e61b31d665a85c66fa80152b4eda2f1cba61 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:03:25 +0000 Subject: [PATCH 43/74] =?UTF-8?q?Decode=20more=20water-heating=20system/fu?= =?UTF-8?q?el=20overrides=20to=20their=20codes=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../domain/epc/test_water_heating_overlay.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/domain/epc/test_water_heating_overlay.py b/tests/domain/epc/test_water_heating_overlay.py index f9379184..49cfffbf 100644 --- a/tests/domain/epc/test_water_heating_overlay.py +++ b/tests/domain/epc/test_water_heating_overlay.py @@ -6,6 +6,8 @@ A water-heating value resolves to the SAP `water_heating_code` (system) and from __future__ import annotations +import pytest + from domain.epc.property_overlays.water_heating_overlay import ( water_heating_overlay_for, ) @@ -20,3 +22,34 @@ def test_from_main_system_mains_gas_overlays_water_heating() -> None: assert simulation.heating is not None assert simulation.heating.water_heating_code == 901 assert simulation.heating.water_heating_fuel == 26 + + +@pytest.mark.parametrize( + ("water_heating_value", "code", "fuel"), + [ + ("From main system, electricity", 901, 29), + ("Electric immersion, electricity", 903, 29), + ], +) +def test_water_heating_systems_decode_to_their_codes( + water_heating_value: str, code: int, fuel: int +) -> None: + # Act + simulation = water_heating_overlay_for(water_heating_value, 0) + + # Assert + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.water_heating_code == code + assert simulation.heating.water_heating_fuel == fuel + + +@pytest.mark.parametrize("water_heating_value", ["Unknown", ""]) +def test_unresolvable_water_heating_produces_no_overlay( + water_heating_value: str, +) -> None: + # Act + simulation = water_heating_overlay_for(water_heating_value, 0) + + # Assert + assert simulation is None From c6ab9ba38359379e22dc2dcee0476398a29423cd Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:03:36 +0000 Subject: [PATCH 44/74] =?UTF-8?q?Decode=20more=20water-heating=20system/fu?= =?UTF-8?q?el=20overrides=20to=20their=20codes=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/property_overlays/water_heating_overlay.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/domain/epc/property_overlays/water_heating_overlay.py b/domain/epc/property_overlays/water_heating_overlay.py index d75ea81c..e55a578e 100644 --- a/domain/epc/property_overlays/water_heating_overlay.py +++ b/domain/epc/property_overlays/water_heating_overlay.py @@ -21,6 +21,8 @@ from domain.modelling.simulation import EpcSimulation, HeatingOverlay # family (26 mains gas, 29 electricity), matching the main_fuel overlay. _WATER_HEATING_CODES: dict[str, tuple[int, int]] = { "From main system, mains gas": (901, 26), + "From main system, electricity": (901, 29), + "Electric immersion, electricity": (903, 29), } From 55e83c7f9f0ca104cf3d38a33070b5015fa30d2a Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:03:51 +0000 Subject: [PATCH 45/74] =?UTF-8?q?Route=20a=20water=5Fheating=20override=20?= =?UTF-8?q?row=20through=20its=20overlay=20mapper=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_landlord_override_overlays.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/repositories/property/test_landlord_override_overlays.py b/tests/repositories/property/test_landlord_override_overlays.py index 2b687656..b2b49d55 100644 --- a/tests/repositories/property/test_landlord_override_overlays.py +++ b/tests/repositories/property/test_landlord_override_overlays.py @@ -92,6 +92,26 @@ def test_construction_age_band_row_produces_a_building_part_overlay() -> None: assert main.construction_age_band == "B" +def test_water_heating_row_produces_a_heating_overlay() -> None: + # Arrange + overrides = ResolvedPropertyOverrides( + rows=( + ResolvedPropertyOverride( + "water_heating", 0, "From main system, mains gas" + ), + ) + ) + + # Act + overlays = overlays_from(overrides) + + # Assert + assert len(overlays) == 1 + assert overlays[0].heating is not None + assert overlays[0].heating.water_heating_code == 901 + assert overlays[0].heating.water_heating_fuel == 26 + + def test_unresolvable_rows_are_skipped() -> None: # Arrange — an "Unknown" property type and an unmapped wall material. overrides = ResolvedPropertyOverrides( From 805dfc70a28e4c2fd7f3101503347e38d7160b24 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:04:11 +0000 Subject: [PATCH 46/74] =?UTF-8?q?Route=20a=20water=5Fheating=20override=20?= =?UTF-8?q?row=20through=20its=20overlay=20mapper=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- repositories/property/landlord_override_overlays.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/repositories/property/landlord_override_overlays.py b/repositories/property/landlord_override_overlays.py index fd6d5f68..ebceb6cf 100644 --- a/repositories/property/landlord_override_overlays.py +++ b/repositories/property/landlord_override_overlays.py @@ -34,6 +34,9 @@ from domain.epc.property_overlays.construction_age_band_overlay import ( ) from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for +from domain.epc.property_overlays.water_heating_overlay import ( + water_heating_overlay_for, +) from domain.epc.property_overlays.roof_type_overlay import roof_overlay_for from domain.epc.property_overlays.wall_type_overlay import wall_overlay_for from domain.modelling.simulation import EpcSimulation @@ -51,6 +54,7 @@ _COMPONENT_OVERLAYS: dict[str, Callable[[str, int], Optional[EpcSimulation]]] = "main_fuel": fuel_overlay_for, "glazing": glazing_overlay_for, "construction_age_band": age_band_overlay_for, + "water_heating": water_heating_overlay_for, } From b5ef41ea62c242a56d90b682f9d4cd51e8f764d3 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:04:33 +0000 Subject: [PATCH 47/74] =?UTF-8?q?Remap=20the=20EPC=20hot-water=20arrangeme?= =?UTF-8?q?nt=20from=20a=20landlord=20override=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_water_heating_overlay.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/domain/epc/test_water_heating_overlay.py b/tests/domain/epc/test_water_heating_overlay.py index 49cfffbf..7dd8c2d0 100644 --- a/tests/domain/epc/test_water_heating_overlay.py +++ b/tests/domain/epc/test_water_heating_overlay.py @@ -11,6 +11,10 @@ import pytest from domain.epc.property_overlays.water_heating_overlay import ( water_heating_overlay_for, ) +from domain.modelling.scoring.overlay_applicator import apply_simulations +from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( + build_epc, +) def test_from_main_system_mains_gas_overlays_water_heating() -> None: @@ -53,3 +57,17 @@ def test_unresolvable_water_heating_produces_no_overlay( # Assert assert simulation is None + + +def test_water_heating_override_remaps_the_hot_water_arrangement() -> None: + # Arrange — landlord correction: HW is a separate electric immersion. + baseline = build_epc() + overlay = water_heating_overlay_for("Electric immersion, electricity", 0) + assert overlay is not None + + # Act + result = apply_simulations(baseline, [overlay]) + + # Assert — the calculator reads these off sap_heating. + assert result.sap_heating.water_heating_code == 903 + assert result.sap_heating.water_heating_fuel == 29 From 21afbefa9dbe3c597a8ec5559705f795c049092e Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:05:00 +0000 Subject: [PATCH 48/74] =?UTF-8?q?Resolve=20a=20landlord=20gas-combi=20heat?= =?UTF-8?q?ing=20override=20to=20its=20SAP=20code=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../main_heating_system_overlay.py | 28 +++++++++++++++++++ .../epc/test_main_heating_system_overlay.py | 21 ++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 domain/epc/property_overlays/main_heating_system_overlay.py create mode 100644 tests/domain/epc/test_main_heating_system_overlay.py diff --git a/domain/epc/property_overlays/main_heating_system_overlay.py b/domain/epc/property_overlays/main_heating_system_overlay.py new file mode 100644 index 00000000..6b7aca80 --- /dev/null +++ b/domain/epc/property_overlays/main_heating_system_overlay.py @@ -0,0 +1,28 @@ +"""Map a Landlord-Override main-heating-system value to a heating Simulation Overlay. + +A main-heating-system value is one canonical system archetype ("Gas boiler, +combi", "Electric storage heaters, fan"). The calculator reads the primary +system's `sap_main_heating_code` (SAP Table 4a/4b), so the overlay maps the +archetype to a representative code and emits a whole-dwelling `HeatingOverlay` +targeting `main_heating_details[0]` (`building_part` is ignored). It composes +field-wise with the main_fuel / water_heating overlays. + +The SEDBUK A-G efficiency band the Hyde "Heating" column carries is NOT honoured +yet (no efficiency slot on the overlay/MainHeatingDetail) -- archetypes map to +their modern/condensing Table 4b code, so an old low-rated boiler is currently +modelled at the condensing efficiency. Heat pumps and community heating (which +resolve via main_heating_index_number / community codes, not a Table 4b code) +are left UNKNOWN until modelled. Unresolvable values produce no overlay. +""" + +from __future__ import annotations + +from typing import Optional + +from domain.modelling.simulation import EpcSimulation + + +def main_heating_overlay_for( + main_heating_value: str, building_part: int +) -> Optional[EpcSimulation]: + raise NotImplementedError diff --git a/tests/domain/epc/test_main_heating_system_overlay.py b/tests/domain/epc/test_main_heating_system_overlay.py new file mode 100644 index 00000000..e1b7a90d --- /dev/null +++ b/tests/domain/epc/test_main_heating_system_overlay.py @@ -0,0 +1,21 @@ +"""The Landlord-Override main-heating-system → heating Simulation Overlay mapping. + +A main-heating-system value resolves to the SAP `sap_main_heating_code` the +calculator reads from the primary system; the overlay is whole-dwelling. +""" + +from __future__ import annotations + +from domain.epc.property_overlays.main_heating_system_overlay import ( + main_heating_overlay_for, +) + + +def test_gas_combi_overlays_the_primary_heating_code() -> None: + # Act + simulation = main_heating_overlay_for("Gas boiler, combi", 0) + + # Assert — condensing combi is SAP Table 4b code 104. + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.sap_main_heating_code == 104 From d6bde062eda53b3288c6d1a531daec0aa16b3047 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:05:14 +0000 Subject: [PATCH 49/74] =?UTF-8?q?Resolve=20a=20landlord=20gas-combi=20heat?= =?UTF-8?q?ing=20override=20to=20its=20SAP=20code=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../main_heating_system_overlay.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/domain/epc/property_overlays/main_heating_system_overlay.py b/domain/epc/property_overlays/main_heating_system_overlay.py index 6b7aca80..630c247a 100644 --- a/domain/epc/property_overlays/main_heating_system_overlay.py +++ b/domain/epc/property_overlays/main_heating_system_overlay.py @@ -19,10 +19,21 @@ from __future__ import annotations from typing import Optional -from domain.modelling.simulation import EpcSimulation +from domain.modelling.simulation import EpcSimulation, HeatingOverlay + +# Canonical system archetype → representative `sap_main_heating_code` (SAP Table +# 4b boiler rows / Table 4a). Codes map to the modern/condensing variant (A-G +# efficiency deferred): 102 regular condensing, 104 condensing combi, 120 CPSU, +# 404 fan storage heaters, 191 direct-acting electric boiler. +_MAIN_HEATING_CODES: dict[str, int] = { + "Gas boiler, combi": 104, +} def main_heating_overlay_for( main_heating_value: str, building_part: int ) -> Optional[EpcSimulation]: - raise NotImplementedError + code = _MAIN_HEATING_CODES.get(main_heating_value) + if code is None: + return None + return EpcSimulation(heating=HeatingOverlay(sap_main_heating_code=code)) From 2ede8591584725d167780025e8481d173a2be558 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:05:39 +0000 Subject: [PATCH 50/74] =?UTF-8?q?Decode=20regular/CPSU/storage/direct-elec?= =?UTF-8?q?tric=20heating=20overrides=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/test_main_heating_system_overlay.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/domain/epc/test_main_heating_system_overlay.py b/tests/domain/epc/test_main_heating_system_overlay.py index e1b7a90d..1a55de61 100644 --- a/tests/domain/epc/test_main_heating_system_overlay.py +++ b/tests/domain/epc/test_main_heating_system_overlay.py @@ -6,6 +6,8 @@ calculator reads from the primary system; the overlay is whole-dwelling. from __future__ import annotations +import pytest + from domain.epc.property_overlays.main_heating_system_overlay import ( main_heating_overlay_for, ) @@ -19,3 +21,41 @@ def test_gas_combi_overlays_the_primary_heating_code() -> None: assert simulation is not None assert simulation.heating is not None assert simulation.heating.sap_main_heating_code == 104 + + +@pytest.mark.parametrize( + ("main_heating_value", "code"), + [ + ("Gas boiler, regular", 102), + ("Gas CPSU", 120), + ("Electric storage heaters, fan", 404), + ("Direct-acting electric", 191), + ], +) +def test_heating_archetypes_decode_to_their_sap_codes( + main_heating_value: str, code: int +) -> None: + # Act + simulation = main_heating_overlay_for(main_heating_value, 0) + + # Assert + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.sap_main_heating_code == code + + +@pytest.mark.parametrize( + "main_heating_value", + ["Unknown", "", "Air source heat pump", "Community heating"], +) +def test_unresolvable_or_unmodelled_heating_produces_no_overlay( + main_heating_value: str, +) -> None: + # Heat pumps (main_heating_index_number) and community heating (community + # codes) don't map to a Table 4b sap_main_heating_code yet — no overlay. + + # Act + simulation = main_heating_overlay_for(main_heating_value, 0) + + # Assert + assert simulation is None From 10c670036670ea5a93250fed0b60a225011d3722 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:05:50 +0000 Subject: [PATCH 51/74] =?UTF-8?q?Decode=20regular/CPSU/storage/direct-elec?= =?UTF-8?q?tric=20heating=20overrides=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/property_overlays/main_heating_system_overlay.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/domain/epc/property_overlays/main_heating_system_overlay.py b/domain/epc/property_overlays/main_heating_system_overlay.py index 630c247a..5d61cb5a 100644 --- a/domain/epc/property_overlays/main_heating_system_overlay.py +++ b/domain/epc/property_overlays/main_heating_system_overlay.py @@ -27,6 +27,10 @@ from domain.modelling.simulation import EpcSimulation, HeatingOverlay # 404 fan storage heaters, 191 direct-acting electric boiler. _MAIN_HEATING_CODES: dict[str, int] = { "Gas boiler, combi": 104, + "Gas boiler, regular": 102, + "Gas CPSU": 120, + "Electric storage heaters, fan": 404, + "Direct-acting electric": 191, } From 6c2d1dce349ff07659e4c7810ff05d4e4abba611 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:06:04 +0000 Subject: [PATCH 52/74] =?UTF-8?q?Route=20a=20main=5Fheating=5Fsystem=20ove?= =?UTF-8?q?rride=20row=20through=20its=20overlay=20mapper=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property/test_landlord_override_overlays.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/repositories/property/test_landlord_override_overlays.py b/tests/repositories/property/test_landlord_override_overlays.py index b2b49d55..1f790aa8 100644 --- a/tests/repositories/property/test_landlord_override_overlays.py +++ b/tests/repositories/property/test_landlord_override_overlays.py @@ -112,6 +112,23 @@ def test_water_heating_row_produces_a_heating_overlay() -> None: assert overlays[0].heating.water_heating_fuel == 26 +def test_main_heating_system_row_produces_a_heating_overlay() -> None: + # Arrange + overrides = ResolvedPropertyOverrides( + rows=( + ResolvedPropertyOverride("main_heating_system", 0, "Gas boiler, combi"), + ) + ) + + # Act + overlays = overlays_from(overrides) + + # Assert + assert len(overlays) == 1 + assert overlays[0].heating is not None + assert overlays[0].heating.sap_main_heating_code == 104 + + def test_unresolvable_rows_are_skipped() -> None: # Arrange — an "Unknown" property type and an unmapped wall material. overrides = ResolvedPropertyOverrides( From 66bb29a8340d3c5102da92ea9e12a1f3ed0b5622 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:06:24 +0000 Subject: [PATCH 53/74] =?UTF-8?q?Route=20a=20main=5Fheating=5Fsystem=20ove?= =?UTF-8?q?rride=20row=20through=20its=20overlay=20mapper=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- repositories/property/landlord_override_overlays.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/repositories/property/landlord_override_overlays.py b/repositories/property/landlord_override_overlays.py index ebceb6cf..6c40d009 100644 --- a/repositories/property/landlord_override_overlays.py +++ b/repositories/property/landlord_override_overlays.py @@ -34,6 +34,9 @@ from domain.epc.property_overlays.construction_age_band_overlay import ( ) from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for +from domain.epc.property_overlays.main_heating_system_overlay import ( + main_heating_overlay_for, +) from domain.epc.property_overlays.water_heating_overlay import ( water_heating_overlay_for, ) @@ -55,6 +58,7 @@ _COMPONENT_OVERLAYS: dict[str, Callable[[str, int], Optional[EpcSimulation]]] = "glazing": glazing_overlay_for, "construction_age_band": age_band_overlay_for, "water_heating": water_heating_overlay_for, + "main_heating_system": main_heating_overlay_for, } From a6f2ae99df61a6475784a50b2f2c0602b1c2e390 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:06:52 +0000 Subject: [PATCH 54/74] =?UTF-8?q?Remap=20the=20primary=20heating=20system?= =?UTF-8?q?=20and=20compose=20the=20heating=20override=20trio=20?= =?UTF-8?q?=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/test_main_heating_system_overlay.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/domain/epc/test_main_heating_system_overlay.py b/tests/domain/epc/test_main_heating_system_overlay.py index 1a55de61..0710837e 100644 --- a/tests/domain/epc/test_main_heating_system_overlay.py +++ b/tests/domain/epc/test_main_heating_system_overlay.py @@ -8,9 +8,17 @@ from __future__ import annotations import pytest +from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.epc.property_overlays.main_heating_system_overlay import ( main_heating_overlay_for, ) +from domain.epc.property_overlays.water_heating_overlay import ( + water_heating_overlay_for, +) +from domain.modelling.scoring.overlay_applicator import apply_simulations +from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( + build_epc, +) def test_gas_combi_overlays_the_primary_heating_code() -> None: @@ -59,3 +67,39 @@ def test_unresolvable_or_unmodelled_heating_produces_no_overlay( # Assert assert simulation is None + + +def test_main_heating_override_remaps_the_primary_system_code() -> None: + # Arrange + baseline = build_epc() + overlay = main_heating_overlay_for("Gas boiler, regular", 0) + assert overlay is not None + + # Act + result = apply_simulations(baseline, [overlay]) + + # Assert — the calculator reads the code off main_heating_details[0]. + assert result.sap_heating.main_heating_details[0].sap_main_heating_code == 102 + + +def test_the_three_heating_overrides_compose_without_conflict() -> None: + # Arrange — main_fuel, water_heating and main_heating_system all fold onto one + # HeatingOverlay surface but set DISJOINT fields, so they compose (the + # field-disjoint design that makes precedence moot for these three). + baseline = build_epc() + overlays = [ + fuel_overlay_for("electricity", 0), + water_heating_overlay_for("Electric immersion, electricity", 0), + main_heating_overlay_for("Electric storage heaters, fan", 0), + ] + assert all(o is not None for o in overlays) + + # Act + result = apply_simulations(baseline, [o for o in overlays if o is not None]) + + # Assert — each override landed on its own field. + main = result.sap_heating.main_heating_details[0] + assert main.main_fuel_type == 29 + assert main.sap_main_heating_code == 404 + assert result.sap_heating.water_heating_code == 903 + assert result.sap_heating.water_heating_fuel == 29 From ad3b1f15a80f3192fc95f87242ed99a7afa58de9 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:07:14 +0000 Subject: [PATCH 55/74] =?UTF-8?q?Classify=20the=20landlord=20Hot=20Water?= =?UTF-8?q?=20and=20Heating=20columns=20into=20categories=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test_build_columns.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/applications/landlord_description_overrides/test_build_columns.py b/tests/applications/landlord_description_overrides/test_build_columns.py index 8f50afce..0e47ed8d 100644 --- a/tests/applications/landlord_description_overrides/test_build_columns.py +++ b/tests/applications/landlord_description_overrides/test_build_columns.py @@ -51,3 +51,29 @@ def test_build_columns_wires_a_construction_age_band_classifier_column() -> None assert len(columns) == 1 assert columns[0].name == "construction_age_band" assert columns[0].source_column == "Age" + + +def test_build_columns_wires_a_water_heating_classifier_column() -> None: + # Arrange + chat_gpt = cast(ChatGPT, object()) + + # Act + columns = _build_columns({"water_heating": "Hot Water"}, chat_gpt, None) + + # Assert + assert len(columns) == 1 + assert columns[0].name == "water_heating" + assert columns[0].source_column == "Hot Water" + + +def test_build_columns_wires_a_main_heating_system_classifier_column() -> None: + # Arrange + chat_gpt = cast(ChatGPT, object()) + + # Act + columns = _build_columns({"main_heating_system": "Heating"}, chat_gpt, None) + + # Assert + assert len(columns) == 1 + assert columns[0].name == "main_heating_system" + assert columns[0].source_column == "Heating" From cc228b3da5b87e5dffaaa676f99a0305f10426f6 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:09:05 +0000 Subject: [PATCH 56/74] =?UTF-8?q?Classify=20the=20landlord=20Hot=20Water?= =?UTF-8?q?=20and=20Heating=20columns=20into=20categories=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landlord_description_overrides/handler.py | 28 ++++++++ domain/epc/main_heating_system_type.py | 24 +++++++ domain/epc/water_heating_type.py | 21 ++++++ ...ord_override_reader_postgres_repository.py | 20 ++++++ ...lord_main_heating_system_override_table.py | 71 +++++++++++++++++++ .../landlord_water_heating_override_table.py | 69 ++++++++++++++++++ 6 files changed, 233 insertions(+) create mode 100644 domain/epc/main_heating_system_type.py create mode 100644 domain/epc/water_heating_type.py create mode 100644 infrastructure/postgres/landlord_main_heating_system_override_table.py create mode 100644 infrastructure/postgres/landlord_water_heating_override_table.py diff --git a/applications/landlord_description_overrides/handler.py b/applications/landlord_description_overrides/handler.py index 2f83b81f..1a99aea6 100644 --- a/applications/landlord_description_overrides/handler.py +++ b/applications/landlord_description_overrides/handler.py @@ -11,8 +11,10 @@ from domain.epc.built_form_type import BuiltFormType from domain.epc.construction_age_band import ConstructionAgeBand from domain.epc.glazing_type import GlazingType from domain.epc.main_fuel_type import MainFuelType +from domain.epc.main_heating_system_type import MainHeatingSystemType from domain.epc.property_type import PropertyType from domain.epc.roof_type import RoofType +from domain.epc.water_heating_type import WaterHeatingType from domain.epc.wall_type import WallType from domain.epc.wall_type_construction_dates import ( wall_type_construction_date_prompt_hint, @@ -36,6 +38,12 @@ from infrastructure.postgres.landlord_glazing_override_table import ( from infrastructure.postgres.landlord_main_fuel_override_table import ( LandlordMainFuelOverrideRow, ) +from infrastructure.postgres.landlord_main_heating_system_override_table import ( + LandlordMainHeatingSystemOverrideRow, +) +from infrastructure.postgres.landlord_water_heating_override_table import ( + LandlordWaterHeatingOverrideRow, +) from infrastructure.postgres.landlord_property_type_override_table import ( LandlordPropertyTypeOverrideRow, ) @@ -144,6 +152,26 @@ def _build_columns( session, LandlordConstructionAgeBandOverrideRow ), ), + "water_heating": lambda src: ClassifiableColumn( + name="water_heating", + source_column=src, + classifier=ChatGptColumnClassifier( + chat_gpt, WaterHeatingType, WaterHeatingType.UNKNOWN + ), + repo=LandlordOverridesRepository[WaterHeatingType]( + session, LandlordWaterHeatingOverrideRow + ), + ), + "main_heating_system": lambda src: ClassifiableColumn( + name="main_heating_system", + source_column=src, + classifier=ChatGptColumnClassifier( + chat_gpt, MainHeatingSystemType, MainHeatingSystemType.UNKNOWN + ), + repo=LandlordOverridesRepository[MainHeatingSystemType]( + session, LandlordMainHeatingSystemOverrideRow + ), + ), } columns: list[ClassifiableColumn[Any]] = [] diff --git a/domain/epc/main_heating_system_type.py b/domain/epc/main_heating_system_type.py new file mode 100644 index 00000000..ff3c4233 --- /dev/null +++ b/domain/epc/main_heating_system_type.py @@ -0,0 +1,24 @@ +from enum import Enum + + +class MainHeatingSystemType(Enum): + """A landlord-supplied main-heating-system description, as resolved by the + landlord-description-overrides context. + + Each member's value is the canonical system archetype that the main-heating + Simulation Overlay + (``domain/epc/property_overlays/main_heating_system_overlay.py``) maps to a + representative SAP ``sap_main_heating_code`` — so the member values MUST stay + in lock-step with that overlay's ``_MAIN_HEATING_CODES`` keys. The SEDBUK A-G + efficiency band the Hyde "Heating" column carries is NOT modelled yet + (deferred), so archetypes map to their modern/condensing code. ``UNKNOWN`` + covers values the classifier cannot resolve and the not-yet-modelled systems + (heat pumps, community heating). + """ + + GAS_COMBI = "Gas boiler, combi" + GAS_REGULAR = "Gas boiler, regular" + GAS_CPSU = "Gas CPSU" + ELECTRIC_STORAGE_FAN = "Electric storage heaters, fan" + DIRECT_ELECTRIC = "Direct-acting electric" + UNKNOWN = "Unknown" diff --git a/domain/epc/water_heating_type.py b/domain/epc/water_heating_type.py new file mode 100644 index 00000000..025c669a --- /dev/null +++ b/domain/epc/water_heating_type.py @@ -0,0 +1,21 @@ +from enum import Enum + + +class WaterHeatingType(Enum): + """A landlord-supplied water-heating description, as resolved by the + landlord-description-overrides context. + + Each member's value is the canonical ", " description that the + water-heating Simulation Overlay + (``domain/epc/property_overlays/water_heating_overlay.py``) decomposes into + the SAP ``water_heating_code`` + ``water_heating_fuel`` int codes the + calculator reads — so the member values MUST stay in lock-step with that + overlay's ``_WATER_HEATING_CODES`` keys. ``UNKNOWN`` covers values the + classifier cannot resolve, and any combination not yet given verified codes + (it leaves the lodged cert's hot-water arrangement untouched). + """ + + FROM_MAIN_MAINS_GAS = "From main system, mains gas" + FROM_MAIN_ELECTRICITY = "From main system, electricity" + ELECTRIC_IMMERSION = "Electric immersion, electricity" + UNKNOWN = "Unknown" diff --git a/infrastructure/landlord_overrides/landlord_override_reader_postgres_repository.py b/infrastructure/landlord_overrides/landlord_override_reader_postgres_repository.py index 79b851f3..4d02b0d5 100644 --- a/infrastructure/landlord_overrides/landlord_override_reader_postgres_repository.py +++ b/infrastructure/landlord_overrides/landlord_override_reader_postgres_repository.py @@ -25,9 +25,24 @@ from infrastructure.postgres.landlord_property_type_override_table import ( from infrastructure.postgres.landlord_roof_type_override_table import ( LandlordRoofTypeOverrideRow, ) +from infrastructure.postgres.landlord_construction_age_band_override_table import ( + LandlordConstructionAgeBandOverrideRow, +) +from infrastructure.postgres.landlord_glazing_override_table import ( + LandlordGlazingOverrideRow, +) +from infrastructure.postgres.landlord_main_fuel_override_table import ( + LandlordMainFuelOverrideRow, +) +from infrastructure.postgres.landlord_main_heating_system_override_table import ( + LandlordMainHeatingSystemOverrideRow, +) from infrastructure.postgres.landlord_wall_type_override_table import ( LandlordWallTypeOverrideRow, ) +from infrastructure.postgres.landlord_water_heating_override_table import ( + LandlordWaterHeatingOverrideRow, +) from repositories.landlord_overrides.landlord_override_reader import ( LandlordOverrideReader, ) @@ -38,6 +53,11 @@ _ROW_TYPES: dict[str, type] = { "built_form_type": LandlordBuiltFormTypeOverrideRow, "wall_type": LandlordWallTypeOverrideRow, "roof_type": LandlordRoofTypeOverrideRow, + "main_fuel": LandlordMainFuelOverrideRow, + "glazing": LandlordGlazingOverrideRow, + "construction_age_band": LandlordConstructionAgeBandOverrideRow, + "water_heating": LandlordWaterHeatingOverrideRow, + "main_heating_system": LandlordMainHeatingSystemOverrideRow, } diff --git a/infrastructure/postgres/landlord_main_heating_system_override_table.py b/infrastructure/postgres/landlord_main_heating_system_override_table.py new file mode 100644 index 00000000..a06c35c4 --- /dev/null +++ b/infrastructure/postgres/landlord_main_heating_system_override_table.py @@ -0,0 +1,71 @@ +"""SQLModel mirror of the ``landlord_main_heating_system_overrides`` Drizzle table. + +The schema source of truth lives in the ``assessment-model`` TS repo +(`src/app/db/schema/landlord_overrides.ts`). The migrations are owned there; +this row class only mirrors the columns so the Python lambda can read/write. +See ADR-0003. Shape mirrors ``LandlordWallTypeOverrideRow`` -- the only +differences are the table name, the ``main_heating_system`` pgEnum on ``value``, +and the unique-constraint name. +""" + +from datetime import datetime, timezone +from typing import ClassVar +from uuid import UUID, uuid4 + +from sqlalchemy import BigInteger, Column, UniqueConstraint +from sqlalchemy import Enum as SAEnum +from sqlmodel import Field, SQLModel + +from domain.epc.main_heating_system_type import MainHeatingSystemType +from infrastructure.postgres.landlord_override_enums import override_source_sa_enum + + +class LandlordMainHeatingSystemOverrideRow(SQLModel, table=True): + __tablename__: ClassVar[str] = "landlord_main_heating_system_overrides" # pyright: ignore[reportIncompatibleVariableOverride] + __table_args__: ClassVar[tuple[UniqueConstraint, ...]] = ( # pyright: ignore[reportIncompatibleVariableOverride] + # Shortened (drop the redundant ``_overrides``) to stay within + # PostgreSQL's 63-char identifier limit; mirrors the Drizzle name. + UniqueConstraint( + "portfolio_id", + "description", + name="landlord_main_heating_system_portfolio_description_unique", + ), + ) + + id: UUID = Field(default_factory=uuid4, primary_key=True) + + # bigint to match the Drizzle ``portfolio_id`` FK; SQLModel's default int + # mapping is 32-bit Integer and would overflow once portfolio IDs exceed + # 2^31. The FK to ``portfolio.id`` is enforced by the Drizzle migration, + # not declared here -- the ``portfolio`` table is not modelled in Python. + portfolio_id: int = Field( + sa_column=Column(BigInteger, nullable=False, index=True), + ) + + description: str = Field(nullable=False) + + value: MainHeatingSystemType = Field( + sa_column=Column( + SAEnum( + MainHeatingSystemType, + name="main_heating_system", + values_callable=lambda cls: [m.value for m in cls], # pyright: ignore[reportUnknownLambdaType, reportUnknownMemberType, reportUnknownVariableType] + ), + nullable=False, + ), + ) + + # Shared SAEnum -- see ``landlord_override_enums`` for why this single + # instance is reused by every ``landlord_*_overrides`` row class. + source: str = Field( + sa_column=Column(override_source_sa_enum, nullable=False), + ) + + created_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) + updated_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) diff --git a/infrastructure/postgres/landlord_water_heating_override_table.py b/infrastructure/postgres/landlord_water_heating_override_table.py new file mode 100644 index 00000000..c69a41d2 --- /dev/null +++ b/infrastructure/postgres/landlord_water_heating_override_table.py @@ -0,0 +1,69 @@ +"""SQLModel mirror of the ``landlord_water_heating_overrides`` Drizzle table. + +The schema source of truth lives in the ``assessment-model`` TS repo +(`src/app/db/schema/landlord_overrides.ts`). The migrations are owned there; +this row class only mirrors the columns so the Python lambda can read/write. +See ADR-0003. Shape mirrors ``LandlordWallTypeOverrideRow`` -- the only +differences are the table name, the ``water_heating`` pgEnum on ``value``, and +the unique-constraint name. +""" + +from datetime import datetime, timezone +from typing import ClassVar +from uuid import UUID, uuid4 + +from sqlalchemy import BigInteger, Column, UniqueConstraint +from sqlalchemy import Enum as SAEnum +from sqlmodel import Field, SQLModel + +from domain.epc.water_heating_type import WaterHeatingType +from infrastructure.postgres.landlord_override_enums import override_source_sa_enum + + +class LandlordWaterHeatingOverrideRow(SQLModel, table=True): + __tablename__: ClassVar[str] = "landlord_water_heating_overrides" # pyright: ignore[reportIncompatibleVariableOverride] + __table_args__: ClassVar[tuple[UniqueConstraint, ...]] = ( # pyright: ignore[reportIncompatibleVariableOverride] + UniqueConstraint( + "portfolio_id", + "description", + name="landlord_water_heating_overrides_portfolio_description_unique", + ), + ) + + id: UUID = Field(default_factory=uuid4, primary_key=True) + + # bigint to match the Drizzle ``portfolio_id`` FK; SQLModel's default int + # mapping is 32-bit Integer and would overflow once portfolio IDs exceed + # 2^31. The FK to ``portfolio.id`` is enforced by the Drizzle migration, + # not declared here -- the ``portfolio`` table is not modelled in Python. + portfolio_id: int = Field( + sa_column=Column(BigInteger, nullable=False, index=True), + ) + + description: str = Field(nullable=False) + + value: WaterHeatingType = Field( + sa_column=Column( + SAEnum( + WaterHeatingType, + name="water_heating", + values_callable=lambda cls: [m.value for m in cls], # pyright: ignore[reportUnknownLambdaType, reportUnknownMemberType, reportUnknownVariableType] + ), + nullable=False, + ), + ) + + # Shared SAEnum -- see ``landlord_override_enums`` for why this single + # instance is reused by every ``landlord_*_overrides`` row class. + source: str = Field( + sa_column=Column(override_source_sa_enum, nullable=False), + ) + + created_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) + updated_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc), + nullable=False, + ) From 9d0d12c278ccd8b100591f6eeb50b0262b26d2db Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:10:02 +0000 Subject: [PATCH 57/74] =?UTF-8?q?Lock=20heating-override=20value=20coverag?= =?UTF-8?q?e=20and=20reader/overlay=20registry=20parity=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/test_main_heating_system_overlay.py | 15 ++++++++++++ .../domain/epc/test_water_heating_overlay.py | 14 +++++++++++ .../test_override_component_consistency.py | 24 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tests/repositories/property/test_override_component_consistency.py diff --git a/tests/domain/epc/test_main_heating_system_overlay.py b/tests/domain/epc/test_main_heating_system_overlay.py index 0710837e..e161dbf5 100644 --- a/tests/domain/epc/test_main_heating_system_overlay.py +++ b/tests/domain/epc/test_main_heating_system_overlay.py @@ -8,6 +8,7 @@ from __future__ import annotations import pytest +from domain.epc.main_heating_system_type import MainHeatingSystemType from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.epc.property_overlays.main_heating_system_overlay import ( main_heating_overlay_for, @@ -103,3 +104,17 @@ def test_the_three_heating_overrides_compose_without_conflict() -> None: assert main.sap_main_heating_code == 404 assert result.sap_heating.water_heating_code == 903 assert result.sap_heating.water_heating_fuel == 29 + + +@pytest.mark.parametrize( + "member", + [m for m in MainHeatingSystemType if m is not MainHeatingSystemType.UNKNOWN], +) +def test_every_resolvable_main_heating_value_decodes( + member: MainHeatingSystemType, +) -> None: + # Act + simulation = main_heating_overlay_for(member.value, 0) + + # Assert + assert simulation is not None diff --git a/tests/domain/epc/test_water_heating_overlay.py b/tests/domain/epc/test_water_heating_overlay.py index 7dd8c2d0..6e0b1fdb 100644 --- a/tests/domain/epc/test_water_heating_overlay.py +++ b/tests/domain/epc/test_water_heating_overlay.py @@ -11,6 +11,7 @@ import pytest from domain.epc.property_overlays.water_heating_overlay import ( water_heating_overlay_for, ) +from domain.epc.water_heating_type import WaterHeatingType from domain.modelling.scoring.overlay_applicator import apply_simulations from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( build_epc, @@ -71,3 +72,16 @@ def test_water_heating_override_remaps_the_hot_water_arrangement() -> None: # Assert — the calculator reads these off sap_heating. assert result.sap_heating.water_heating_code == 903 assert result.sap_heating.water_heating_fuel == 29 + + +@pytest.mark.parametrize( + "member", [m for m in WaterHeatingType if m is not WaterHeatingType.UNKNOWN] +) +def test_every_resolvable_water_heating_value_decodes( + member: WaterHeatingType, +) -> None: + # Act + simulation = water_heating_overlay_for(member.value, 0) + + # Assert + assert simulation is not None diff --git a/tests/repositories/property/test_override_component_consistency.py b/tests/repositories/property/test_override_component_consistency.py new file mode 100644 index 00000000..df830cd0 --- /dev/null +++ b/tests/repositories/property/test_override_component_consistency.py @@ -0,0 +1,24 @@ +"""Every override component must be wired through the WHOLE chain. + +The finaliser reader (`_ROW_TYPES`, component -> landlord table) and the overlay +registry (`_COMPONENT_OVERLAYS`, component -> overlay mapper) must cover exactly +the same set of components. If a component is classified + stored but has no +reader entry, the finaliser silently never writes its `property_overrides` rows; +if it has no overlay entry, the row never reaches the calculator. This guard +keeps the two registries in lock-step (it would have caught the missing +main_fuel / glazing / construction_age_band reader entries). +""" + +from __future__ import annotations + +from infrastructure.landlord_overrides.landlord_override_reader_postgres_repository import ( # pyright: ignore[reportPrivateUsage] + _ROW_TYPES, +) +from repositories.property.landlord_override_overlays import ( # pyright: ignore[reportPrivateUsage] + _COMPONENT_OVERLAYS, +) + + +def test_reader_and_overlay_registries_cover_the_same_components() -> None: + # Assert + assert set(_ROW_TYPES) == set(_COMPONENT_OVERLAYS) From b7d2cff220b5b30689f19dfa4e51ddca2335cdc0 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:18:33 +0000 Subject: [PATCH 58/74] =?UTF-8?q?Decode=20bottled/special=20LPG,=20communi?= =?UTF-8?q?ty=20electric/biomass,=20dual-fuel,=20smokeless=20coal=20?= =?UTF-8?q?=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/domain/epc/test_main_fuel_overlay.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py index 6001ddc3..161078fb 100644 --- a/tests/domain/epc/test_main_fuel_overlay.py +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -47,6 +47,27 @@ def test_fuels_decode_to_their_modern_not_community_codes( assert simulation.heating.main_fuel_type == code +@pytest.mark.parametrize( + ("main_fuel_value", "code"), + [ + ("bottled LPG", 3), + ("LPG special condition", 17), + ("electricity (community)", 25), + ("biomass (community)", 31), + ("dual fuel (mineral and wood)", 10), + ("smokeless coal", 15), + ], +) +def test_more_fuels_decode_to_their_codes(main_fuel_value: str, code: int) -> None: + # Act + simulation = fuel_overlay_for(main_fuel_value, 0) + + # Assert + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.main_fuel_type == code + + def test_community_mains_gas_is_a_distinct_fuel_code() -> None: # Act simulation = fuel_overlay_for("mains gas (community)", 0) From 21bb55f4144c2cddaf05a2120c11baeb9bbaab84 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:18:55 +0000 Subject: [PATCH 59/74] =?UTF-8?q?Decode=20bottled/special=20LPG,=20communi?= =?UTF-8?q?ty=20electric/biomass,=20dual-fuel,=20smokeless=20coal=20?= =?UTF-8?q?=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/main_fuel_type.py | 6 ++++++ domain/epc/property_overlays/main_fuel_overlay.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/domain/epc/main_fuel_type.py b/domain/epc/main_fuel_type.py index 0ad575c3..8427b9cf 100644 --- a/domain/epc/main_fuel_type.py +++ b/domain/epc/main_fuel_type.py @@ -17,7 +17,13 @@ class MainFuelType(Enum): MAINS_GAS = "mains gas" MAINS_GAS_COMMUNITY = "mains gas (community)" ELECTRICITY = "electricity" + ELECTRICITY_COMMUNITY = "electricity (community)" LPG_BULK = "LPG (bulk)" + LPG_BOTTLED = "bottled LPG" + LPG_SPECIAL_CONDITION = "LPG special condition" OIL = "oil" HOUSE_COAL = "house coal" + SMOKELESS_COAL = "smokeless coal" + DUAL_FUEL_MINERAL_WOOD = "dual fuel (mineral and wood)" + BIOMASS_COMMUNITY = "biomass (community)" UNKNOWN = "Unknown" diff --git a/domain/epc/property_overlays/main_fuel_overlay.py b/domain/epc/property_overlays/main_fuel_overlay.py index c3145705..cc482122 100644 --- a/domain/epc/property_overlays/main_fuel_overlay.py +++ b/domain/epc/property_overlays/main_fuel_overlay.py @@ -20,9 +20,15 @@ _FUEL_CODES: dict[str, int] = { "mains gas": 26, "mains gas (community)": 20, "LPG (bulk)": 27, + "bottled LPG": 3, + "LPG special condition": 17, "oil": 28, "electricity": 29, + "electricity (community)": 25, "house coal": 33, + "smokeless coal": 15, + "dual fuel (mineral and wood)": 10, + "biomass (community)": 31, } From 49f783de45fa89602ba29efc6efcba5f1dc0d62b Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:20:02 +0000 Subject: [PATCH 60/74] =?UTF-8?q?Decode=20from-main=20oil/LPG/coal=20and?= =?UTF-8?q?=20gas=20boiler-circulator=20water=20heating=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../domain/epc/test_water_heating_overlay.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/domain/epc/test_water_heating_overlay.py b/tests/domain/epc/test_water_heating_overlay.py index 6e0b1fdb..12e6e8be 100644 --- a/tests/domain/epc/test_water_heating_overlay.py +++ b/tests/domain/epc/test_water_heating_overlay.py @@ -49,6 +49,30 @@ def test_water_heating_systems_decode_to_their_codes( assert simulation.heating.water_heating_fuel == fuel +@pytest.mark.parametrize( + ("water_heating_value", "code", "fuel"), + [ + ("From main system, oil", 901, 28), + ("From main system, LPG (bulk)", 901, 27), + ("From main system, bottled LPG", 901, 3), + ("From main system, house coal", 901, 33), + # "boiler/circulator for water heating only" is SAP Table 4a code 911. + ("Gas boiler/circulator, mains gas", 911, 26), + ], +) +def test_more_water_heating_combos_decode_to_their_codes( + water_heating_value: str, code: int, fuel: int +) -> None: + # Act + simulation = water_heating_overlay_for(water_heating_value, 0) + + # Assert + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.water_heating_code == code + assert simulation.heating.water_heating_fuel == fuel + + @pytest.mark.parametrize("water_heating_value", ["Unknown", ""]) def test_unresolvable_water_heating_produces_no_overlay( water_heating_value: str, From d8ab3f6ec7dea4b5d738e782ac4020181c23d58b Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:20:24 +0000 Subject: [PATCH 61/74] =?UTF-8?q?Decode=20from-main=20oil/LPG/coal=20and?= =?UTF-8?q?=20gas=20boiler-circulator=20water=20heating=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/property_overlays/water_heating_overlay.py | 6 ++++++ domain/epc/water_heating_type.py | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/domain/epc/property_overlays/water_heating_overlay.py b/domain/epc/property_overlays/water_heating_overlay.py index e55a578e..3ec952de 100644 --- a/domain/epc/property_overlays/water_heating_overlay.py +++ b/domain/epc/property_overlays/water_heating_overlay.py @@ -22,7 +22,13 @@ from domain.modelling.simulation import EpcSimulation, HeatingOverlay _WATER_HEATING_CODES: dict[str, tuple[int, int]] = { "From main system, mains gas": (901, 26), "From main system, electricity": (901, 29), + "From main system, oil": (901, 28), + "From main system, LPG (bulk)": (901, 27), + "From main system, bottled LPG": (901, 3), + "From main system, house coal": (901, 33), "Electric immersion, electricity": (903, 29), + # "boiler/circulator for water heating only" — SAP Table 4a code 911 (gas). + "Gas boiler/circulator, mains gas": (911, 26), } diff --git a/domain/epc/water_heating_type.py b/domain/epc/water_heating_type.py index 025c669a..e85a195d 100644 --- a/domain/epc/water_heating_type.py +++ b/domain/epc/water_heating_type.py @@ -17,5 +17,10 @@ class WaterHeatingType(Enum): FROM_MAIN_MAINS_GAS = "From main system, mains gas" FROM_MAIN_ELECTRICITY = "From main system, electricity" + FROM_MAIN_OIL = "From main system, oil" + FROM_MAIN_LPG_BULK = "From main system, LPG (bulk)" + FROM_MAIN_BOTTLED_LPG = "From main system, bottled LPG" + FROM_MAIN_HOUSE_COAL = "From main system, house coal" ELECTRIC_IMMERSION = "Electric immersion, electricity" + GAS_BOILER_CIRCULATOR_MAINS_GAS = "Gas boiler/circulator, mains gas" UNKNOWN = "Unknown" From 4fbd8d5999da6568d3997edcd362d522b4103249 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:20:41 +0000 Subject: [PATCH 62/74] =?UTF-8?q?Decode=20old/slimline/convector=20storage?= =?UTF-8?q?-heater=20heating=20overrides=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../epc/test_main_heating_system_overlay.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/domain/epc/test_main_heating_system_overlay.py b/tests/domain/epc/test_main_heating_system_overlay.py index e161dbf5..8b901616 100644 --- a/tests/domain/epc/test_main_heating_system_overlay.py +++ b/tests/domain/epc/test_main_heating_system_overlay.py @@ -53,6 +53,26 @@ def test_heating_archetypes_decode_to_their_sap_codes( assert simulation.heating.sap_main_heating_code == code +@pytest.mark.parametrize( + ("main_heating_value", "code"), + [ + ("Electric storage heaters, old", 401), + ("Electric storage heaters, slimline", 402), + ("Electric storage heaters, convector", 403), + ], +) +def test_storage_heater_subtypes_decode_to_their_codes( + main_heating_value: str, code: int +) -> None: + # Act + simulation = main_heating_overlay_for(main_heating_value, 0) + + # Assert + assert simulation is not None + assert simulation.heating is not None + assert simulation.heating.sap_main_heating_code == code + + @pytest.mark.parametrize( "main_heating_value", ["Unknown", "", "Air source heat pump", "Community heating"], From 2dbbcf0c7bbd727333d2204324bb690d22a8b508 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:21:01 +0000 Subject: [PATCH 63/74] =?UTF-8?q?Decode=20old/slimline/convector=20storage?= =?UTF-8?q?-heater=20heating=20overrides=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- domain/epc/main_heating_system_type.py | 3 +++ domain/epc/property_overlays/main_heating_system_overlay.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/domain/epc/main_heating_system_type.py b/domain/epc/main_heating_system_type.py index ff3c4233..bea14e6a 100644 --- a/domain/epc/main_heating_system_type.py +++ b/domain/epc/main_heating_system_type.py @@ -19,6 +19,9 @@ class MainHeatingSystemType(Enum): GAS_COMBI = "Gas boiler, combi" GAS_REGULAR = "Gas boiler, regular" GAS_CPSU = "Gas CPSU" + ELECTRIC_STORAGE_OLD = "Electric storage heaters, old" + ELECTRIC_STORAGE_SLIMLINE = "Electric storage heaters, slimline" + ELECTRIC_STORAGE_CONVECTOR = "Electric storage heaters, convector" ELECTRIC_STORAGE_FAN = "Electric storage heaters, fan" DIRECT_ELECTRIC = "Direct-acting electric" UNKNOWN = "Unknown" diff --git a/domain/epc/property_overlays/main_heating_system_overlay.py b/domain/epc/property_overlays/main_heating_system_overlay.py index 5d61cb5a..1f06eabc 100644 --- a/domain/epc/property_overlays/main_heating_system_overlay.py +++ b/domain/epc/property_overlays/main_heating_system_overlay.py @@ -29,6 +29,9 @@ _MAIN_HEATING_CODES: dict[str, int] = { "Gas boiler, combi": 104, "Gas boiler, regular": 102, "Gas CPSU": 120, + "Electric storage heaters, old": 401, + "Electric storage heaters, slimline": 402, + "Electric storage heaters, convector": 403, "Electric storage heaters, fan": 404, "Direct-acting electric": 191, } From 3a0a122b7f4e405037871d6e32778c895acea131 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 14:49:58 +0000 Subject: [PATCH 64/74] =?UTF-8?q?Group=20landlord=20property-override=20en?= =?UTF-8?q?ums=20under=20domain/epc/property=5Foverrides=20=F0=9F=9F=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../landlord_description_overrides/handler.py | 20 +++++++++---------- domain/epc/property_overrides/__init__.py | 4 ++++ .../built_form_type.py | 0 .../construction_age_band.py | 0 .../{ => property_overrides}/glazing_type.py | 0 .../main_fuel_type.py | 0 .../main_heating_system_type.py | 0 .../override_code_mapping.py | 0 .../{ => property_overrides}/property_type.py | 0 .../epc/{ => property_overrides}/roof_type.py | 0 .../epc/{ => property_overrides}/wall_type.py | 0 .../wall_type_construction_dates.py | 2 +- .../water_heating_type.py | 0 ...landlord_built_form_type_override_table.py | 2 +- ...rd_construction_age_band_override_table.py | 2 +- .../landlord_glazing_override_table.py | 2 +- .../landlord_main_fuel_override_table.py | 2 +- ...lord_main_heating_system_override_table.py | 2 +- .../landlord_property_type_override_table.py | 2 +- .../landlord_roof_type_override_table.py | 2 +- .../landlord_wall_type_override_table.py | 2 +- .../landlord_water_heating_override_table.py | 2 +- .../bulk_upload_finaliser_orchestrator.py | 8 ++++---- ...ide_backed_prediction_attributes_reader.py | 2 +- .../epc/test_construction_age_band_overlay.py | 2 +- tests/domain/epc/test_glazing_overlay.py | 2 +- tests/domain/epc/test_main_fuel_overlay.py | 2 +- .../epc/test_main_heating_system_overlay.py | 2 +- .../domain/epc/test_override_code_mapping.py | 6 +++--- .../domain/epc/test_water_heating_overlay.py | 2 +- .../chatgpt/test_chatgpt_column_classifier.py | 4 ++-- ...lord_description_overrides_orchestrator.py | 6 +++--- ..._landlord_overrides_postgres_repository.py | 4 ++-- 33 files changed, 44 insertions(+), 40 deletions(-) create mode 100644 domain/epc/property_overrides/__init__.py rename domain/epc/{ => property_overrides}/built_form_type.py (100%) rename domain/epc/{ => property_overrides}/construction_age_band.py (100%) rename domain/epc/{ => property_overrides}/glazing_type.py (100%) rename domain/epc/{ => property_overrides}/main_fuel_type.py (100%) rename domain/epc/{ => property_overrides}/main_heating_system_type.py (100%) rename domain/epc/{ => property_overrides}/override_code_mapping.py (100%) rename domain/epc/{ => property_overrides}/property_type.py (100%) rename domain/epc/{ => property_overrides}/roof_type.py (100%) rename domain/epc/{ => property_overrides}/wall_type.py (100%) rename domain/epc/{ => property_overrides}/wall_type_construction_dates.py (97%) rename domain/epc/{ => property_overrides}/water_heating_type.py (100%) diff --git a/applications/landlord_description_overrides/handler.py b/applications/landlord_description_overrides/handler.py index 1a99aea6..4020bc51 100644 --- a/applications/landlord_description_overrides/handler.py +++ b/applications/landlord_description_overrides/handler.py @@ -7,16 +7,16 @@ import boto3 from applications.landlord_description_overrides.landlord_description_overrides_trigger_body import ( LandlordDescriptionOverridesTriggerBody, ) -from domain.epc.built_form_type import BuiltFormType -from domain.epc.construction_age_band import ConstructionAgeBand -from domain.epc.glazing_type import GlazingType -from domain.epc.main_fuel_type import MainFuelType -from domain.epc.main_heating_system_type import MainHeatingSystemType -from domain.epc.property_type import PropertyType -from domain.epc.roof_type import RoofType -from domain.epc.water_heating_type import WaterHeatingType -from domain.epc.wall_type import WallType -from domain.epc.wall_type_construction_dates import ( +from domain.epc.property_overrides.built_form_type import BuiltFormType +from domain.epc.property_overrides.construction_age_band import ConstructionAgeBand +from domain.epc.property_overrides.glazing_type import GlazingType +from domain.epc.property_overrides.main_fuel_type import MainFuelType +from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType +from domain.epc.property_overrides.property_type import PropertyType +from domain.epc.property_overrides.roof_type import RoofType +from domain.epc.property_overrides.water_heating_type import WaterHeatingType +from domain.epc.property_overrides.wall_type import WallType +from domain.epc.property_overrides.wall_type_construction_dates import ( wall_type_construction_date_prompt_hint, ) from infrastructure.chatgpt.chatgpt import ChatGPT diff --git a/domain/epc/property_overrides/__init__.py b/domain/epc/property_overrides/__init__.py new file mode 100644 index 00000000..e11710a4 --- /dev/null +++ b/domain/epc/property_overrides/__init__.py @@ -0,0 +1,4 @@ +"""Landlord property-override classifier vocabulary — the category enums a +landlord description resolves into, plus their value→code helpers. The classifier +target for the property_overrides chain (mirrors the property_overrides table / +override_component pgEnum). Distinct from the EPC-context types of the same name.""" diff --git a/domain/epc/built_form_type.py b/domain/epc/property_overrides/built_form_type.py similarity index 100% rename from domain/epc/built_form_type.py rename to domain/epc/property_overrides/built_form_type.py diff --git a/domain/epc/construction_age_band.py b/domain/epc/property_overrides/construction_age_band.py similarity index 100% rename from domain/epc/construction_age_band.py rename to domain/epc/property_overrides/construction_age_band.py diff --git a/domain/epc/glazing_type.py b/domain/epc/property_overrides/glazing_type.py similarity index 100% rename from domain/epc/glazing_type.py rename to domain/epc/property_overrides/glazing_type.py diff --git a/domain/epc/main_fuel_type.py b/domain/epc/property_overrides/main_fuel_type.py similarity index 100% rename from domain/epc/main_fuel_type.py rename to domain/epc/property_overrides/main_fuel_type.py diff --git a/domain/epc/main_heating_system_type.py b/domain/epc/property_overrides/main_heating_system_type.py similarity index 100% rename from domain/epc/main_heating_system_type.py rename to domain/epc/property_overrides/main_heating_system_type.py diff --git a/domain/epc/override_code_mapping.py b/domain/epc/property_overrides/override_code_mapping.py similarity index 100% rename from domain/epc/override_code_mapping.py rename to domain/epc/property_overrides/override_code_mapping.py diff --git a/domain/epc/property_type.py b/domain/epc/property_overrides/property_type.py similarity index 100% rename from domain/epc/property_type.py rename to domain/epc/property_overrides/property_type.py diff --git a/domain/epc/roof_type.py b/domain/epc/property_overrides/roof_type.py similarity index 100% rename from domain/epc/roof_type.py rename to domain/epc/property_overrides/roof_type.py diff --git a/domain/epc/wall_type.py b/domain/epc/property_overrides/wall_type.py similarity index 100% rename from domain/epc/wall_type.py rename to domain/epc/property_overrides/wall_type.py diff --git a/domain/epc/wall_type_construction_dates.py b/domain/epc/property_overrides/wall_type_construction_dates.py similarity index 97% rename from domain/epc/wall_type_construction_dates.py rename to domain/epc/property_overrides/wall_type_construction_dates.py index 0eccc44c..04deda23 100644 --- a/domain/epc/wall_type_construction_dates.py +++ b/domain/epc/property_overrides/wall_type_construction_dates.py @@ -27,7 +27,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import Mapping, Optional -from domain.epc.wall_type import WallType +from domain.epc.property_overrides.wall_type import WallType @dataclass(frozen=True) diff --git a/domain/epc/water_heating_type.py b/domain/epc/property_overrides/water_heating_type.py similarity index 100% rename from domain/epc/water_heating_type.py rename to domain/epc/property_overrides/water_heating_type.py diff --git a/infrastructure/postgres/landlord_built_form_type_override_table.py b/infrastructure/postgres/landlord_built_form_type_override_table.py index ec93ba27..5f343613 100644 --- a/infrastructure/postgres/landlord_built_form_type_override_table.py +++ b/infrastructure/postgres/landlord_built_form_type_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.built_form_type import BuiltFormType +from domain.epc.property_overrides.built_form_type import BuiltFormType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_construction_age_band_override_table.py b/infrastructure/postgres/landlord_construction_age_band_override_table.py index 91eec66e..0c8f9119 100644 --- a/infrastructure/postgres/landlord_construction_age_band_override_table.py +++ b/infrastructure/postgres/landlord_construction_age_band_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.construction_age_band import ConstructionAgeBand +from domain.epc.property_overrides.construction_age_band import ConstructionAgeBand from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_glazing_override_table.py b/infrastructure/postgres/landlord_glazing_override_table.py index f42a48d2..b25dea54 100644 --- a/infrastructure/postgres/landlord_glazing_override_table.py +++ b/infrastructure/postgres/landlord_glazing_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.glazing_type import GlazingType +from domain.epc.property_overrides.glazing_type import GlazingType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_main_fuel_override_table.py b/infrastructure/postgres/landlord_main_fuel_override_table.py index c046453b..3012a2e9 100644 --- a/infrastructure/postgres/landlord_main_fuel_override_table.py +++ b/infrastructure/postgres/landlord_main_fuel_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.main_fuel_type import MainFuelType +from domain.epc.property_overrides.main_fuel_type import MainFuelType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_main_heating_system_override_table.py b/infrastructure/postgres/landlord_main_heating_system_override_table.py index a06c35c4..d9862089 100644 --- a/infrastructure/postgres/landlord_main_heating_system_override_table.py +++ b/infrastructure/postgres/landlord_main_heating_system_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.main_heating_system_type import MainHeatingSystemType +from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_property_type_override_table.py b/infrastructure/postgres/landlord_property_type_override_table.py index ae9377cd..2718fb34 100644 --- a/infrastructure/postgres/landlord_property_type_override_table.py +++ b/infrastructure/postgres/landlord_property_type_override_table.py @@ -14,7 +14,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.property_type import PropertyType +from domain.epc.property_overrides.property_type import PropertyType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_roof_type_override_table.py b/infrastructure/postgres/landlord_roof_type_override_table.py index 58bd61ff..659c5c64 100644 --- a/infrastructure/postgres/landlord_roof_type_override_table.py +++ b/infrastructure/postgres/landlord_roof_type_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.roof_type import RoofType +from domain.epc.property_overrides.roof_type import RoofType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_wall_type_override_table.py b/infrastructure/postgres/landlord_wall_type_override_table.py index b5097164..7a3c70ae 100644 --- a/infrastructure/postgres/landlord_wall_type_override_table.py +++ b/infrastructure/postgres/landlord_wall_type_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.wall_type import WallType +from domain.epc.property_overrides.wall_type import WallType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/infrastructure/postgres/landlord_water_heating_override_table.py b/infrastructure/postgres/landlord_water_heating_override_table.py index c69a41d2..039b5a62 100644 --- a/infrastructure/postgres/landlord_water_heating_override_table.py +++ b/infrastructure/postgres/landlord_water_heating_override_table.py @@ -16,7 +16,7 @@ from sqlalchemy import BigInteger, Column, UniqueConstraint from sqlalchemy import Enum as SAEnum from sqlmodel import Field, SQLModel -from domain.epc.water_heating_type import WaterHeatingType +from domain.epc.property_overrides.water_heating_type import WaterHeatingType from infrastructure.postgres.landlord_override_enums import override_source_sa_enum diff --git a/orchestration/bulk_upload_finaliser_orchestrator.py b/orchestration/bulk_upload_finaliser_orchestrator.py index 4aa49ab8..1d707a8d 100644 --- a/orchestration/bulk_upload_finaliser_orchestrator.py +++ b/orchestration/bulk_upload_finaliser_orchestrator.py @@ -14,10 +14,10 @@ from typing import Any, Optional from uuid import UUID -from domain.epc.built_form_type import BuiltFormType -from domain.epc.property_type import PropertyType -from domain.epc.roof_type import RoofType -from domain.epc.wall_type import WallType +from domain.epc.property_overrides.built_form_type import BuiltFormType +from domain.epc.property_overrides.property_type import PropertyType +from domain.epc.property_overrides.roof_type import RoofType +from domain.epc.property_overrides.wall_type import WallType from repositories.bulk_upload.bulk_upload_status_writer import BulkUploadStatusWriter from repositories.landlord_overrides.landlord_override_reader import ( LandlordOverrideReader, diff --git a/repositories/property/override_backed_prediction_attributes_reader.py b/repositories/property/override_backed_prediction_attributes_reader.py index 5befd3b3..1c5a4b71 100644 --- a/repositories/property/override_backed_prediction_attributes_reader.py +++ b/repositories/property/override_backed_prediction_attributes_reader.py @@ -13,7 +13,7 @@ from __future__ import annotations from typing import Optional -from domain.epc.override_code_mapping import ( +from domain.epc.property_overrides.override_code_mapping import ( built_form_to_code, property_type_to_code, ) diff --git a/tests/domain/epc/test_construction_age_band_overlay.py b/tests/domain/epc/test_construction_age_band_overlay.py index 3408900b..5ae822e6 100644 --- a/tests/domain/epc/test_construction_age_band_overlay.py +++ b/tests/domain/epc/test_construction_age_band_overlay.py @@ -14,7 +14,7 @@ from datatypes.epc.domain.epc_property_data import ( EpcPropertyData, SapBuildingPart, ) -from domain.epc.construction_age_band import ConstructionAgeBand +from domain.epc.property_overrides.construction_age_band import ConstructionAgeBand from domain.epc.property_overlays.construction_age_band_overlay import ( age_band_overlay_for, ) diff --git a/tests/domain/epc/test_glazing_overlay.py b/tests/domain/epc/test_glazing_overlay.py index c7ba72a8..3182d79c 100644 --- a/tests/domain/epc/test_glazing_overlay.py +++ b/tests/domain/epc/test_glazing_overlay.py @@ -9,7 +9,7 @@ from __future__ import annotations import pytest -from domain.epc.glazing_type import GlazingType +from domain.epc.property_overrides.glazing_type import GlazingType from domain.epc.property_overlays.glazing_overlay import glazing_overlay_for from domain.modelling.scoring.overlay_applicator import apply_simulations from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( diff --git a/tests/domain/epc/test_main_fuel_overlay.py b/tests/domain/epc/test_main_fuel_overlay.py index 161078fb..9a1b1335 100644 --- a/tests/domain/epc/test_main_fuel_overlay.py +++ b/tests/domain/epc/test_main_fuel_overlay.py @@ -8,7 +8,7 @@ from __future__ import annotations import pytest -from domain.epc.main_fuel_type import MainFuelType +from domain.epc.property_overrides.main_fuel_type import MainFuelType from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.modelling.scoring.overlay_applicator import apply_simulations from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( diff --git a/tests/domain/epc/test_main_heating_system_overlay.py b/tests/domain/epc/test_main_heating_system_overlay.py index 8b901616..8ccde2b9 100644 --- a/tests/domain/epc/test_main_heating_system_overlay.py +++ b/tests/domain/epc/test_main_heating_system_overlay.py @@ -8,7 +8,7 @@ from __future__ import annotations import pytest -from domain.epc.main_heating_system_type import MainHeatingSystemType +from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType from domain.epc.property_overlays.main_fuel_overlay import fuel_overlay_for from domain.epc.property_overlays.main_heating_system_overlay import ( main_heating_overlay_for, diff --git a/tests/domain/epc/test_override_code_mapping.py b/tests/domain/epc/test_override_code_mapping.py index b22ad0a5..5e462e08 100644 --- a/tests/domain/epc/test_override_code_mapping.py +++ b/tests/domain/epc/test_override_code_mapping.py @@ -12,12 +12,12 @@ from typing import Optional import pytest -from domain.epc.built_form_type import BuiltFormType -from domain.epc.override_code_mapping import ( +from domain.epc.property_overrides.built_form_type import BuiltFormType +from domain.epc.property_overrides.override_code_mapping import ( built_form_to_code, property_type_to_code, ) -from domain.epc.property_type import PropertyType +from domain.epc.property_overrides.property_type import PropertyType def test_house_maps_to_gov_code_zero() -> None: diff --git a/tests/domain/epc/test_water_heating_overlay.py b/tests/domain/epc/test_water_heating_overlay.py index 12e6e8be..a1955aa7 100644 --- a/tests/domain/epc/test_water_heating_overlay.py +++ b/tests/domain/epc/test_water_heating_overlay.py @@ -11,7 +11,7 @@ import pytest from domain.epc.property_overlays.water_heating_overlay import ( water_heating_overlay_for, ) -from domain.epc.water_heating_type import WaterHeatingType +from domain.epc.property_overrides.water_heating_type import WaterHeatingType from domain.modelling.scoring.overlay_applicator import apply_simulations from tests.domain.sap10_calculator.worksheet._elmhurst_worksheet_000490 import ( build_epc, diff --git a/tests/infrastructure/chatgpt/test_chatgpt_column_classifier.py b/tests/infrastructure/chatgpt/test_chatgpt_column_classifier.py index 425d2625..0070af49 100644 --- a/tests/infrastructure/chatgpt/test_chatgpt_column_classifier.py +++ b/tests/infrastructure/chatgpt/test_chatgpt_column_classifier.py @@ -5,8 +5,8 @@ from typing import Optional import pytest from domain.data_transformation.column_classifier import ClassificationError -from domain.epc.property_type import PropertyType -from domain.epc.wall_type import WallType +from domain.epc.property_overrides.property_type import PropertyType +from domain.epc.property_overrides.wall_type import WallType from infrastructure.chatgpt.chatgpt import ChatGPT from infrastructure.chatgpt.chatgpt_column_classifier import ( ChatGptColumnClassifier, diff --git a/tests/orchestration/test_landlord_description_overrides_orchestrator.py b/tests/orchestration/test_landlord_description_overrides_orchestrator.py index bf5b13ce..2339c615 100644 --- a/tests/orchestration/test_landlord_description_overrides_orchestrator.py +++ b/tests/orchestration/test_landlord_description_overrides_orchestrator.py @@ -4,9 +4,9 @@ from enum import Enum from typing import Any, Optional from domain.addresses.unstandardised_address import AddressList, UnstandardisedAddress -from domain.epc.built_form_type import BuiltFormType -from domain.epc.property_type import PropertyType -from domain.epc.wall_type import WallType +from domain.epc.property_overrides.built_form_type import BuiltFormType +from domain.epc.property_overrides.property_type import PropertyType +from domain.epc.property_overrides.wall_type import WallType from domain.postcode import Postcode from domain.data_transformation.column_classifier import ColumnClassifier from orchestration.classifiable_column import ClassifiableColumn diff --git a/tests/repositories/landlord_overrides/postgres/test_landlord_overrides_postgres_repository.py b/tests/repositories/landlord_overrides/postgres/test_landlord_overrides_postgres_repository.py index 1ce4e997..31ca2b17 100644 --- a/tests/repositories/landlord_overrides/postgres/test_landlord_overrides_postgres_repository.py +++ b/tests/repositories/landlord_overrides/postgres/test_landlord_overrides_postgres_repository.py @@ -25,8 +25,8 @@ import pytest from sqlalchemy import Engine, Table from sqlmodel import Session, SQLModel, select -from domain.epc.property_type import PropertyType -from domain.epc.wall_type import WallType +from domain.epc.property_overrides.property_type import PropertyType +from domain.epc.property_overrides.wall_type import WallType from infrastructure.landlord_overrides.landlord_overrides_postgres_repository import ( LandlordOverridesRepository, ) From f7ee47118b6a99be043de0d19a303d3b727753ce Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 18:18:12 +0000 Subject: [PATCH 65/74] =?UTF-8?q?Add=20the=205=20new=20components=20to=20t?= =?UTF-8?q?he=20override=5Fcomponent=20pgEnum=20mirror=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caught live writing property_overrides on portfolio 796: the Python override_component SAEnum lagged the DB enum, so reading a new-component row back threw LookupError. Guard it with a consistency test. Co-Authored-By: Claude Opus 4.8 (1M context) --- infrastructure/postgres/property_override_table.py | 5 +++++ .../property/test_override_component_consistency.py | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/infrastructure/postgres/property_override_table.py b/infrastructure/postgres/property_override_table.py index 3132ddf5..40490144 100644 --- a/infrastructure/postgres/property_override_table.py +++ b/infrastructure/postgres/property_override_table.py @@ -27,6 +27,11 @@ override_component_sa_enum = SAEnum( "roof_type", "property_type", "built_form_type", + "main_fuel", + "glazing", + "construction_age_band", + "water_heating", + "main_heating_system", name="override_component", ) diff --git a/tests/repositories/property/test_override_component_consistency.py b/tests/repositories/property/test_override_component_consistency.py index df830cd0..3f7f4d31 100644 --- a/tests/repositories/property/test_override_component_consistency.py +++ b/tests/repositories/property/test_override_component_consistency.py @@ -14,6 +14,7 @@ from __future__ import annotations from infrastructure.landlord_overrides.landlord_override_reader_postgres_repository import ( # pyright: ignore[reportPrivateUsage] _ROW_TYPES, ) +from infrastructure.postgres.property_override_table import override_component_sa_enum from repositories.property.landlord_override_overlays import ( # pyright: ignore[reportPrivateUsage] _COMPONENT_OVERLAYS, ) @@ -22,3 +23,10 @@ from repositories.property.landlord_override_overlays import ( # pyright: ignor def test_reader_and_overlay_registries_cover_the_same_components() -> None: # Assert assert set(_ROW_TYPES) == set(_COMPONENT_OVERLAYS) + + +def test_override_component_pgenum_covers_every_component() -> None: + # The property_overrides.override_component pgEnum mirror must list every + # component, or writing/reading a new-component row through it throws a + # LookupError against Postgres (caught live on the Hyde portfolio-796 run). + assert set(override_component_sa_enum.enums) == set(_COMPONENT_OVERLAYS) From e03fd27357578f941cfef30422a5c388d113a8e6 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 18:19:07 +0000 Subject: [PATCH 66/74] =?UTF-8?q?Type-clean=20the=20override=5Fcomponent?= =?UTF-8?q?=20consistency=20guard=20=F0=9F=9F=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/hyde/build_property_overrides.py | 437 ++++++++++++++++++ .../test_override_component_consistency.py | 13 +- .../test_build_property_overrides_smoke.py | 88 ++++ 3 files changed, 533 insertions(+), 5 deletions(-) create mode 100644 scripts/hyde/build_property_overrides.py create mode 100644 tests/scripts/test_build_property_overrides_smoke.py diff --git a/scripts/hyde/build_property_overrides.py b/scripts/hyde/build_property_overrides.py new file mode 100644 index 00000000..05d70d2d --- /dev/null +++ b/scripts/hyde/build_property_overrides.py @@ -0,0 +1,437 @@ +"""Build ``property_overrides`` for a portfolio from the Hyde Excel, bypassing the +frontend + lambdas, using the ``landlord_*_overrides`` tables as the durable +classification ledger. + +Why the ledger (not a throwaway cache): ``landlord_*_overrides`` stores +``(portfolio_id, description) -> value`` with a ``source`` (classifier|user). + * Re-runs classify only descriptions NOT already stored -> saves ChatGPT calls. + * Human corrections are stored as ``source=user`` and the classifier is + forbidden from overwriting them (ADR-0003) -> edits are permanent. +Then we resolve the vocab + match each row to a ``property.id`` by **org_ref** +(Excel "Organisation Reference" -> property.landlord_property_id) and upsert +``property_overrides`` (the fact layer the SAP overlay reads). + +Subcommands: + list-values print each component's valid override values (reference) + classify --excel f --portfolio-id 795 + PASS 1: classify cache-misses via ChatGPT, + upsert to landlord tables, write + overrides_unknowns.csv (with allowed_values) + validate --edits overrides_edits.csv + check a hand-edited file: every corrected_value + must be a valid enum value (suggests fixes) + apply-edits --edits overrides_edits.csv --portfolio-id 795 [--apply] + upsert validated corrections as source=user + write --excel f --portfolio-id 795 [--apply] + PASS 2: build + upsert property_overrides from vocab + +Env: POSTGRES_* (PostgresConfig.from_env) and OPENAI_API_KEY (ChatGPT). +""" + +from __future__ import annotations + +import argparse +import csv +import difflib +import logging +import os +from collections import Counter +from dataclasses import dataclass +from datetime import datetime, timezone +from enum import Enum +from typing import Any, Optional + +import pandas as pd +from sqlalchemy import Table, text +from sqlalchemy.dialects.postgresql import insert as pg_insert +from sqlmodel import SQLModel + +from domain.epc.property_overrides.built_form_type import BuiltFormType +from domain.epc.property_overrides.construction_age_band import ConstructionAgeBand +from domain.epc.property_overrides.glazing_type import GlazingType +from domain.epc.property_overrides.main_fuel_type import MainFuelType +from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType +from domain.epc.property_overrides.property_type import PropertyType +from domain.epc.property_overrides.roof_type import RoofType +from domain.epc.property_overrides.wall_type import WallType +from domain.epc.property_overrides.wall_type_construction_dates import ( + wall_type_construction_date_prompt_hint, +) +from domain.epc.property_overrides.water_heating_type import WaterHeatingType +from infrastructure.chatgpt.chatgpt import ChatGPT +from infrastructure.chatgpt.chatgpt_column_classifier import ChatGptColumnClassifier +from infrastructure.landlord_overrides.landlord_override_reader_postgres_repository import ( + LandlordOverrideReaderPostgresRepository, +) +from infrastructure.landlord_overrides.landlord_overrides_postgres_repository import ( + LandlordOverridesRepository, +) +from infrastructure.postgres.config import PostgresConfig +from infrastructure.postgres.engine import commit_scope, make_engine, make_session +from infrastructure.postgres.landlord_built_form_type_override_table import ( + LandlordBuiltFormTypeOverrideRow, +) +from infrastructure.postgres.landlord_construction_age_band_override_table import ( + LandlordConstructionAgeBandOverrideRow, +) +from infrastructure.postgres.landlord_glazing_override_table import ( + LandlordGlazingOverrideRow, +) +from infrastructure.postgres.landlord_main_fuel_override_table import ( + LandlordMainFuelOverrideRow, +) +from infrastructure.postgres.landlord_main_heating_system_override_table import ( + LandlordMainHeatingSystemOverrideRow, +) +from infrastructure.postgres.landlord_override_enums import OverrideSource +from infrastructure.postgres.landlord_property_type_override_table import ( + LandlordPropertyTypeOverrideRow, +) +from infrastructure.postgres.landlord_roof_type_override_table import ( + LandlordRoofTypeOverrideRow, +) +from infrastructure.postgres.landlord_wall_type_override_table import ( + LandlordWallTypeOverrideRow, +) +from infrastructure.postgres.landlord_water_heating_override_table import ( + LandlordWaterHeatingOverrideRow, +) +from repositories.property.landlord_override_overlays import overlays_from +from repositories.property.property_override_postgres_repository import ( + PropertyOverridePostgresRepository, +) +from repositories.property.property_override_repository import PropertyOverrideInsert +from repositories.property.property_overrides_postgres_reader import ( + PropertyOverridesPostgresReader, +) + +logging.basicConfig(level=logging.INFO, format="%(message)s") +logger = logging.getLogger("build_property_overrides") + +ORG_REF_COLUMN = "Organisation Reference" +UNKNOWNS_PATH = "overrides_unknowns.csv" + + +@dataclass(frozen=True) +class ComponentSpec: + component: str + enum_cls: type[Enum] + unknown: Enum + row_type: type[SQLModel] + excel_header: str + per_building_part: bool # comma = building parts (wall/roof/age) vs whole-dwelling + extra_instructions: Optional[str] = None + + def allowed_values(self) -> list[str]: + """Valid override values a human may pick (excludes UNKNOWN).""" + return sorted(m.value for m in self.enum_cls if m is not self.unknown) + + +def _component_specs() -> list[ComponentSpec]: + return [ + ComponentSpec("property_type", PropertyType, PropertyType.UNKNOWN, LandlordPropertyTypeOverrideRow, "Property Type", False), + ComponentSpec("built_form_type", BuiltFormType, BuiltFormType.UNKNOWN, LandlordBuiltFormTypeOverrideRow, "Property Type", False), + ComponentSpec("wall_type", WallType, WallType.UNKNOWN, LandlordWallTypeOverrideRow, "Walls", True, wall_type_construction_date_prompt_hint()), + ComponentSpec("roof_type", RoofType, RoofType.UNKNOWN, LandlordRoofTypeOverrideRow, "Roofs", True), + ComponentSpec("construction_age_band", ConstructionAgeBand, ConstructionAgeBand.UNKNOWN, LandlordConstructionAgeBandOverrideRow, "Age", True), + ComponentSpec("main_fuel", MainFuelType, MainFuelType.UNKNOWN, LandlordMainFuelOverrideRow, "Main Fuel", False), + ComponentSpec("glazing", GlazingType, GlazingType.UNKNOWN, LandlordGlazingOverrideRow, "Glazing", False), + ComponentSpec("water_heating", WaterHeatingType, WaterHeatingType.UNKNOWN, LandlordWaterHeatingOverrideRow, "Hot Water", False), + ComponentSpec("main_heating_system", MainHeatingSystemType, MainHeatingSystemType.UNKNOWN, LandlordMainHeatingSystemOverrideRow, "Heating", False), + ] + + +def _specs_by_component() -> dict[str, ComponentSpec]: + return {s.component: s for s in _component_specs()} + + +def _norm(s: Any) -> str: + """Vocab key normalisation — mirrors the orchestrator (strip + lower).""" + return str(s or "").strip().lower() + + +def _split_entries(cell: Any, per_building_part: bool) -> list[str]: + raw = "" if cell is None else str(cell) + if not raw.strip(): + return [] + if not per_building_part: + return [raw.strip()] + return [part.strip() for part in raw.split(",") if part.strip()] + + +def _load_rows(excel: str, sheet: str) -> list[dict[str, Any]]: + return pd.read_excel(excel, sheet_name=sheet).to_dict(orient="records") # type: ignore[return-value] + + +def _filter_rows(rows: list[dict[str, Any]], org_ref: Optional[str], + limit: Optional[int]) -> list[dict[str, Any]]: + """Narrow to one property (--org-ref) or the first N rows (--limit) for a + cheap smoke test before the full run.""" + if org_ref: + rows = [r for r in rows if str(r.get(ORG_REF_COLUMN, "")).strip() == org_ref] + if limit: + rows = rows[:limit] + return rows + + +def _distinct_entries(rows: list[dict[str, Any]], spec: ComponentSpec) -> Counter[str]: + counts: Counter[str] = Counter() + for row in rows: + for entry in _split_entries(row.get(spec.excel_header), spec.per_building_part): + counts[entry] += 1 + return counts + + +# --------------------------------------------------------------------------- # +def list_values(_: argparse.Namespace) -> None: + """Print the valid override values per component (the reference for edits).""" + for spec in _component_specs(): + print(f"\n## {spec.component} (Excel: {spec.excel_header})") + for v in spec.allowed_values(): + print(f" {v}") + + +def validate(args: argparse.Namespace) -> None: + """Check a hand-edited CSV: every corrected_value must be a valid enum value.""" + specs = _specs_by_component() + bad = 0 + with open(args.edits, newline="") as f: + for i, r in enumerate(csv.DictReader(f), start=2): + val = (r.get("corrected_value") or "").strip() + if not val: + continue + comp = (r.get("component") or "").strip() + spec = specs.get(comp) + if spec is None: + logger.error("row %d: unknown component %r", i, comp) + bad += 1 + continue + if val not in spec.allowed_values(): + hint = difflib.get_close_matches(val, spec.allowed_values(), n=2) + logger.error("row %d [%s]: %r is not a valid value.%s", + i, comp, val, + f" Did you mean: {hint}?" if hint else + " Run 'list-values' for the allowed set.") + bad += 1 + if bad: + raise SystemExit(f"{bad} invalid corrected_value(s) — fix them before apply-edits.") + logger.info("All corrected values are valid enum values. ✓") + + +def _db_session() -> Any: + return make_session(make_engine(PostgresConfig.from_env(os.environ))) + + +def classify(args: argparse.Namespace) -> None: + rows = _filter_rows(_load_rows(args.excel, args.sheet), args.org_ref, args.limit) + logger.info("Classifying over %d row(s).", len(rows)) + chat_gpt = ChatGPT() + session = _db_session() + reader = LandlordOverrideReaderPostgresRepository(session) + try: + vocab = reader.load_for_portfolio(args.portfolio_id) # {component: {desc: value}} + unknown_rows: list[tuple[str, str, int, str]] = [] + + for spec in _component_specs(): + counts = _distinct_entries(rows, spec) + known = vocab.get(spec.component, {}) # already-classified (cache) + to_classify = {d for d in counts if _norm(d) not in known} + logger.info("%-22s %4d distinct | %4d cached | %4d to classify", + spec.component, len(counts), len(counts) - len(to_classify), len(to_classify)) + + resolved: dict[str, Enum] = {} + if to_classify: + classifier: ChatGptColumnClassifier[Any] = ChatGptColumnClassifier( + chat_gpt, spec.enum_cls, spec.unknown, extra_instructions=spec.extra_instructions) + resolved = classifier.classify(to_classify) + repo: LandlordOverridesRepository[Any] = LandlordOverridesRepository(session, spec.row_type) + with commit_scope(session): + # store keyed on the normalised description (matches the reader/finaliser lookup) + repo.upsert_all(args.portfolio_id, {_norm(d): m for d, m in resolved.items()}) + + # collect UNKNOWNs (freshly classified + anything cached as UNKNOWN) for review + unk = spec.unknown.value + for desc, n in counts.items(): + v = resolved.get(desc).value if desc in resolved and resolved[desc] else known.get(_norm(desc)) # type: ignore[union-attr] + if v is None or v == unk: + allowed = " | ".join(spec.allowed_values()) + unknown_rows.append((spec.component, desc, n, allowed)) + + with open(UNKNOWNS_PATH, "w", newline="") as f: + w = csv.writer(f) + w.writerow(["component", "description", "count", "corrected_value", "allowed_values"]) + for comp, desc, n, allowed in sorted(unknown_rows, key=lambda r: (-r[2])): + w.writerow([comp, desc, n, "", allowed]) + logger.info("\nWrote %s — fill 'corrected_value' (must match 'allowed_values'), " + "then: validate -> apply-edits -> write.", UNKNOWNS_PATH) + finally: + session.close() + + +def _upsert_user_corrections(session: Any, portfolio_id: int, + by_component: dict[str, dict[str, str]]) -> int: + """Upsert validated human corrections as source=user (always wins on conflict).""" + specs = _specs_by_component() + n = 0 + now = datetime.now(timezone.utc) + for comp, mapping in by_component.items(): + spec = specs[comp] + table: Table = getattr(spec.row_type, "__table__") + rows = [{"portfolio_id": portfolio_id, "description": _norm(d), "value": v, + "source": OverrideSource.USER, "created_at": now, "updated_at": now} + for d, v in mapping.items()] + if not rows: + continue + stmt = pg_insert(table).values(rows) + stmt = stmt.on_conflict_do_update( + index_elements=["portfolio_id", "description"], + set_={"value": stmt.excluded.value, "source": stmt.excluded.source, + "updated_at": stmt.excluded.updated_at}) + session.execute(stmt) + n += len(rows) + return n + + +def apply_edits(args: argparse.Namespace) -> None: + validate(args) # fail before touching the DB + specs = _specs_by_component() + by_component: dict[str, dict[str, str]] = {} + with open(args.edits, newline="") as f: + for r in csv.DictReader(f): + val = (r.get("corrected_value") or "").strip() + if val and r["component"] in specs: + by_component.setdefault(r["component"], {})[r["description"]] = val + session = _db_session() + try: + if not args.apply: + total = sum(len(m) for m in by_component.values()) + logger.info("DRY RUN — %d user corrections ready. Re-run with --apply.", total) + return + with commit_scope(session): + n = _upsert_user_corrections(session, args.portfolio_id, by_component) + logger.info("Upserted %d user corrections (source=user).", n) + finally: + session.close() + + +def _org_ref_to_property_id(session: Any, portfolio_id: int) -> dict[str, int]: + stmt = text("SELECT landlord_property_id, id FROM property " + "WHERE portfolio_id = :pid AND landlord_property_id IS NOT NULL") + return {str(ref).strip(): int(pid) for ref, pid in session.execute(stmt, {"pid": portfolio_id})} + + +def write(args: argparse.Namespace) -> None: + rows = _filter_rows(_load_rows(args.excel, args.sheet), args.org_ref, args.limit) + logger.info("Writing over %d row(s).", len(rows)) + session = _db_session() + reader = LandlordOverrideReaderPostgresRepository(session) + try: + vocab = reader.load_for_portfolio(args.portfolio_id) + org_ref_map = _org_ref_to_property_id(session, args.portfolio_id) + logger.info("Portfolio %d: %d properties with org_ref.", args.portfolio_id, len(org_ref_map)) + + inserts: list[PropertyOverrideInsert] = [] + unmatched: Counter[str] = Counter() + unresolved: Counter[str] = Counter() + for row in rows: + org_ref = str(row.get(ORG_REF_COLUMN, "")).strip() + property_id = org_ref_map.get(org_ref) + if property_id is None: + unmatched[org_ref] += 1 + continue + for spec in _component_specs(): + comp_vocab = vocab.get(spec.component, {}) + for building_part, entry in enumerate( + _split_entries(row.get(spec.excel_header), spec.per_building_part)): + value = comp_vocab.get(_norm(entry)) + if not value or value == spec.unknown.value: + unresolved[f"{spec.component}: {entry}"] += 1 + continue + inserts.append(PropertyOverrideInsert( + property_id=property_id, portfolio_id=args.portfolio_id, + building_part=building_part, override_component=spec.component, + override_value=value, original_spreadsheet_description=entry)) + + logger.info("Built %d rows | %d unmatched org_refs | %d unresolved", + len(inserts), sum(unmatched.values()), sum(unresolved.values())) + if unresolved: + logger.info("Top unresolved (need apply-edits): %s", unresolved.most_common(10)) + if not args.apply: + logger.info("DRY RUN — not writing. Re-run with --apply.") + for ins in inserts[:10]: + logger.info(" %s", ins) + return + with commit_scope(session): + affected = PropertyOverridePostgresRepository(session).upsert_all(inserts) + logger.info("Upserted %d property_overrides.", affected) + finally: + session.close() + + +def verify(args: argparse.Namespace) -> None: + """For one property (by org_ref): show the persisted property_overrides rows + and the EpcSimulation overlays they produce — the end-to-end proof that the + chain reaches the SAP overlay surface.""" + session = _db_session() + try: + org_ref_map = _org_ref_to_property_id(session, args.portfolio_id) + property_id = org_ref_map.get(args.org_ref) + if property_id is None: + raise SystemExit(f"org_ref {args.org_ref!r} not found in portfolio {args.portfolio_id}.") + reader = PropertyOverridesPostgresReader(lambda: session) + resolved = reader.overrides_for(property_id) + logger.info("property_id %d — %d property_overrides rows:", property_id, len(resolved.rows)) + for r in resolved.rows: + logger.info(" part %d | %-22s = %s", r.building_part, r.override_component, r.override_value) + overlays = overlays_from(resolved) + logger.info("\n-> %d EpcSimulation overlay(s) produced (what the SAP calc applies):", len(overlays)) + for o in overlays: + logger.info(" %s", o) + finally: + session.close() + + +def main() -> None: + p = argparse.ArgumentParser(description=__doc__) + sub = p.add_subparsers(dest="cmd", required=True) + + sub.add_parser("list-values").set_defaults(func=list_values) + + v = sub.add_parser("validate") + v.add_argument("--edits", required=True) + v.set_defaults(func=validate) + + c = sub.add_parser("classify") + c.add_argument("--excel", required=True) + c.add_argument("--sheet", default="AddressProfilingResults") + c.add_argument("--portfolio-id", type=int, required=True) + c.add_argument("--org-ref", default=None, help="smoke test: only this property's org_ref") + c.add_argument("--limit", type=int, default=None, help="smoke test: first N rows") + c.set_defaults(func=classify) + + a = sub.add_parser("apply-edits") + a.add_argument("--edits", required=True) + a.add_argument("--portfolio-id", type=int, required=True) + a.add_argument("--apply", action="store_true") + a.set_defaults(func=apply_edits) + + w = sub.add_parser("write") + w.add_argument("--excel", required=True) + w.add_argument("--sheet", default="AddressProfilingResults") + w.add_argument("--portfolio-id", type=int, required=True) + w.add_argument("--org-ref", default=None, help="smoke test: only this property's org_ref") + w.add_argument("--limit", type=int, default=None, help="smoke test: first N rows") + w.add_argument("--apply", action="store_true") + w.set_defaults(func=write) + + vf = sub.add_parser("verify") + vf.add_argument("--portfolio-id", type=int, required=True) + vf.add_argument("--org-ref", required=True) + vf.set_defaults(func=verify) + + args = p.parse_args() + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/tests/repositories/property/test_override_component_consistency.py b/tests/repositories/property/test_override_component_consistency.py index 3f7f4d31..64957a2b 100644 --- a/tests/repositories/property/test_override_component_consistency.py +++ b/tests/repositories/property/test_override_component_consistency.py @@ -11,12 +11,14 @@ main_fuel / glazing / construction_age_band reader entries). from __future__ import annotations -from infrastructure.landlord_overrides.landlord_override_reader_postgres_repository import ( # pyright: ignore[reportPrivateUsage] - _ROW_TYPES, +from typing import cast + +from infrastructure.landlord_overrides.landlord_override_reader_postgres_repository import ( + _ROW_TYPES, # pyright: ignore[reportPrivateUsage] ) from infrastructure.postgres.property_override_table import override_component_sa_enum -from repositories.property.landlord_override_overlays import ( # pyright: ignore[reportPrivateUsage] - _COMPONENT_OVERLAYS, +from repositories.property.landlord_override_overlays import ( + _COMPONENT_OVERLAYS, # pyright: ignore[reportPrivateUsage] ) @@ -29,4 +31,5 @@ def test_override_component_pgenum_covers_every_component() -> None: # The property_overrides.override_component pgEnum mirror must list every # component, or writing/reading a new-component row through it throws a # LookupError against Postgres (caught live on the Hyde portfolio-796 run). - assert set(override_component_sa_enum.enums) == set(_COMPONENT_OVERLAYS) + pgenum_values = cast(list[str], override_component_sa_enum.enums) + assert set(pgenum_values) == set(_COMPONENT_OVERLAYS) diff --git a/tests/scripts/test_build_property_overrides_smoke.py b/tests/scripts/test_build_property_overrides_smoke.py new file mode 100644 index 00000000..77a458aa --- /dev/null +++ b/tests/scripts/test_build_property_overrides_smoke.py @@ -0,0 +1,88 @@ +"""End-to-end smoke of the Hyde override script for ONE property, against a real +(ephemeral) Postgres. Seeds the landlord vocab (simulating post-classify, so no +ChatGPT) + a minimal ``property`` row, then runs the script's real +``write`` + ``verify`` paths and asserts property_overrides + overlays land. +""" + +from __future__ import annotations + +import argparse +from typing import Any + +from sqlalchemy import Engine, text +from sqlmodel import Session + +import scripts.hyde.build_property_overrides as b +from domain.epc.property_overrides.built_form_type import BuiltFormType +from domain.epc.property_overrides.construction_age_band import ConstructionAgeBand +from domain.epc.property_overrides.glazing_type import GlazingType +from domain.epc.property_overrides.main_fuel_type import MainFuelType +from domain.epc.property_overrides.main_heating_system_type import MainHeatingSystemType +from domain.epc.property_overrides.property_type import PropertyType +from domain.epc.property_overrides.roof_type import RoofType +from domain.epc.property_overrides.wall_type import WallType +from domain.epc.property_overrides.water_heating_type import WaterHeatingType +from infrastructure.landlord_overrides.landlord_overrides_postgres_repository import ( + LandlordOverridesRepository, +) + +PORTFOLIO = 795 +ORG_REF = "55180004001" +EXCEL = "scripts/hyde/hyde_property_overrides.xlsx" + +# What ChatGPT WOULD resolve this property's 9 descriptions to (component -> +# (raw Excel entry, enum member)). Seeded into the landlord ledger. +SEED = { + "property_type": ("House: MidTerrace", PropertyType.HOUSE), + "built_form_type": ("House: MidTerrace", BuiltFormType.MID_TERRACE), + "wall_type": ("TimberFrame: AsBuilt", WallType.TIMBER_FRAME_AS_BUILT_NO_INSULATION_ASSUMED), + "roof_type": ("PitchedNormalLoftAccess: 300mm", RoofType.PITCHED_300_MM), + "construction_age_band": ("L: 2012-2022", ConstructionAgeBand.L_2012_2022), + "main_fuel": ("Gas: Mains Gas", MainFuelType.MAINS_GAS), + "glazing": ("100% Double glazing 2002 or later", GlazingType.DOUBLE_POST_2002), + "water_heating": ("From main heating system: Mains Gas", WaterHeatingType.FROM_MAIN_MAINS_GAS), + "main_heating_system": ("Boiler: C rated Combi", MainHeatingSystemType.GAS_COMBI), +} + + +def test_one_property_end_to_end(db_engine: Engine, monkeypatch: Any, capsys: Any) -> None: + specs = b._specs_by_component() + + # minimal FE-owned `property` table + the one row we'll match by org_ref + with Session(db_engine) as s: + s.execute(text( + "CREATE TABLE property (id bigint PRIMARY KEY, portfolio_id bigint, " + "landlord_property_id text)")) + s.execute(text("INSERT INTO property VALUES (1, :p, :ref)"), + {"p": PORTFOLIO, "ref": ORG_REF}) + # seed the classifier ledger (keyed on normalised description) + for comp, (raw, member) in SEED.items(): + LandlordOverridesRepository(s, specs[comp].row_type).upsert_all( + PORTFOLIO, {b._norm(raw): member}) + s.commit() + + # point the script at the ephemeral engine + monkeypatch.setattr(b, "_db_session", lambda: Session(db_engine)) + + # --- run the real write() for this one property --- + b.write(argparse.Namespace(excel=EXCEL, sheet="AddressProfilingResults", + portfolio_id=PORTFOLIO, org_ref=ORG_REF, limit=None, apply=True)) + + with Session(db_engine) as s: + rows = list(s.execute(text( + "SELECT override_component, building_part, override_value " + "FROM property_overrides WHERE property_id = 1 ORDER BY override_component"))) + got = {c: v for c, _, v in rows} + # every seeded component produced a property_overrides row with the resolved value + assert got["main_fuel"] == "mains gas" + assert got["glazing"] == "Double glazing, 2002 or later" + assert got["construction_age_band"] == "L" + assert got["main_heating_system"] == "Gas boiler, combi" + assert got["water_heating"] == "From main system, mains gas" + assert len(rows) == 9 # all 9 components + + # --- run the real verify() and confirm overlays are produced --- + b.verify(argparse.Namespace(portfolio_id=PORTFOLIO, org_ref=ORG_REF)) + out = capsys.readouterr().out + print(out) # surfaced with -s so we can eyeball the one-property result + assert "EpcSimulation overlay" in out From 85e43b373736e04a12e98db01363cb450efd9b08 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 18:19:32 +0000 Subject: [PATCH 67/74] =?UTF-8?q?Silence=20untyped=20SAEnum.enums=20access?= =?UTF-8?q?=20in=20the=20consistency=20guard=20=F0=9F=9F=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../property/test_override_component_consistency.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/repositories/property/test_override_component_consistency.py b/tests/repositories/property/test_override_component_consistency.py index 64957a2b..d3801b0d 100644 --- a/tests/repositories/property/test_override_component_consistency.py +++ b/tests/repositories/property/test_override_component_consistency.py @@ -31,5 +31,5 @@ def test_override_component_pgenum_covers_every_component() -> None: # The property_overrides.override_component pgEnum mirror must list every # component, or writing/reading a new-component row through it throws a # LookupError against Postgres (caught live on the Hyde portfolio-796 run). - pgenum_values = cast(list[str], override_component_sa_enum.enums) + pgenum_values = cast(list[str], getattr(override_component_sa_enum, "enums")) assert set(pgenum_values) == set(_COMPONENT_OVERLAYS) From c1ab179d5109f8f3fd086c86bdeff4ce545661c9 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 19:02:42 +0000 Subject: [PATCH 68/74] =?UTF-8?q?Add=20Hyde=20property=5Foverrides=20build?= =?UTF-8?q?=20script=20+=20creds-free=20smoke=20test=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two-pass org_ref-matched builder for property_overrides (classify via ChatGPT into the landlord ledger, validate+apply user edits, write idempotently); ephemeral-Postgres smoke proves the one-property chain without creds. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 5 +++ scripts/hyde/build_property_overrides.py | 2 +- .../test_build_property_overrides_smoke.py | 33 +++++++++++-------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 9c77b311..0bf9e0e9 100644 --- a/.gitignore +++ b/.gitignore @@ -313,3 +313,8 @@ scripts/eon/epc_cache.pkl scripts/hyde/.elmhurst-session/ scripts/hyde/elmhurst_downloads/ scripts/hyde/.elmhurst-creds.json + +# Hyde property-overrides script artifacts +overrides_cache.json +overrides_unknowns.csv +overrides_edits.csv diff --git a/scripts/hyde/build_property_overrides.py b/scripts/hyde/build_property_overrides.py index 05d70d2d..dc77b520 100644 --- a/scripts/hyde/build_property_overrides.py +++ b/scripts/hyde/build_property_overrides.py @@ -41,7 +41,7 @@ from datetime import datetime, timezone from enum import Enum from typing import Any, Optional -import pandas as pd +import pandas as pd # pyright: ignore[reportMissingTypeStubs] from sqlalchemy import Table, text from sqlalchemy.dialects.postgresql import insert as pg_insert from sqlmodel import SQLModel diff --git a/tests/scripts/test_build_property_overrides_smoke.py b/tests/scripts/test_build_property_overrides_smoke.py index 77a458aa..59db45e5 100644 --- a/tests/scripts/test_build_property_overrides_smoke.py +++ b/tests/scripts/test_build_property_overrides_smoke.py @@ -25,6 +25,10 @@ from domain.epc.property_overrides.water_heating_type import WaterHeatingType from infrastructure.landlord_overrides.landlord_overrides_postgres_repository import ( LandlordOverridesRepository, ) +from repositories.property.landlord_override_overlays import overlays_from +from repositories.property.property_overrides_postgres_reader import ( + PropertyOverridesPostgresReader, +) PORTFOLIO = 795 ORG_REF = "55180004001" @@ -36,7 +40,7 @@ SEED = { "property_type": ("House: MidTerrace", PropertyType.HOUSE), "built_form_type": ("House: MidTerrace", BuiltFormType.MID_TERRACE), "wall_type": ("TimberFrame: AsBuilt", WallType.TIMBER_FRAME_AS_BUILT_NO_INSULATION_ASSUMED), - "roof_type": ("PitchedNormalLoftAccess: 300mm", RoofType.PITCHED_300_MM), + "roof_type": ("PitchedNormalLoftAccess: 300mm", RoofType.PITCHED_LOFT_300MM), "construction_age_band": ("L: 2012-2022", ConstructionAgeBand.L_2012_2022), "main_fuel": ("Gas: Mains Gas", MainFuelType.MAINS_GAS), "glazing": ("100% Double glazing 2002 or later", GlazingType.DOUBLE_POST_2002), @@ -45,20 +49,21 @@ SEED = { } -def test_one_property_end_to_end(db_engine: Engine, monkeypatch: Any, capsys: Any) -> None: - specs = b._specs_by_component() +def test_one_property_end_to_end(db_engine: Engine, monkeypatch: Any) -> None: + specs = b._specs_by_component() # pyright: ignore[reportPrivateUsage] # minimal FE-owned `property` table + the one row we'll match by org_ref with Session(db_engine) as s: - s.execute(text( + s.execute(text( # pyright: ignore[reportDeprecated] "CREATE TABLE property (id bigint PRIMARY KEY, portfolio_id bigint, " "landlord_property_id text)")) - s.execute(text("INSERT INTO property VALUES (1, :p, :ref)"), + s.execute(text("INSERT INTO property VALUES (1, :p, :ref)"), # pyright: ignore[reportDeprecated] {"p": PORTFOLIO, "ref": ORG_REF}) # seed the classifier ledger (keyed on normalised description) for comp, (raw, member) in SEED.items(): - LandlordOverridesRepository(s, specs[comp].row_type).upsert_all( - PORTFOLIO, {b._norm(raw): member}) + repo: LandlordOverridesRepository[Any] = LandlordOverridesRepository( + s, specs[comp].row_type) + repo.upsert_all(PORTFOLIO, {b._norm(raw): member}) # pyright: ignore[reportPrivateUsage] s.commit() # point the script at the ephemeral engine @@ -69,7 +74,7 @@ def test_one_property_end_to_end(db_engine: Engine, monkeypatch: Any, capsys: An portfolio_id=PORTFOLIO, org_ref=ORG_REF, limit=None, apply=True)) with Session(db_engine) as s: - rows = list(s.execute(text( + rows = list(s.execute(text( # pyright: ignore[reportDeprecated] "SELECT override_component, building_part, override_value " "FROM property_overrides WHERE property_id = 1 ORDER BY override_component"))) got = {c: v for c, _, v in rows} @@ -81,8 +86,10 @@ def test_one_property_end_to_end(db_engine: Engine, monkeypatch: Any, capsys: An assert got["water_heating"] == "From main system, mains gas" assert len(rows) == 9 # all 9 components - # --- run the real verify() and confirm overlays are produced --- - b.verify(argparse.Namespace(portfolio_id=PORTFOLIO, org_ref=ORG_REF)) - out = capsys.readouterr().out - print(out) # surfaced with -s so we can eyeball the one-property result - assert "EpcSimulation overlay" in out + # --- the overrides reach the SAP overlay surface --- + b.verify(argparse.Namespace(portfolio_id=PORTFOLIO, org_ref=ORG_REF)) # exercises verify() + overlays = overlays_from( + PropertyOverridesPostgresReader(lambda: Session(db_engine)).overrides_for(1)) + assert len(overlays) == 9 + assert any(o.heating is not None and o.heating.main_fuel_type == 26 for o in overlays) + assert any(o.glazing is not None and o.glazing.glazing_type == 2 for o in overlays) From 36b8b7a9390f0b993a9fb0877f139cfe20d4ec98 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 19:57:34 +0000 Subject: [PATCH 69/74] =?UTF-8?q?Add=20Hyde=20portfolio-796=20unknowns=20r?= =?UTF-8?q?eview=20doc=20for=20Khalim=20sign-off=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/hyde/unknowns_review.md | 53 +++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 scripts/hyde/unknowns_review.md diff --git a/scripts/hyde/unknowns_review.md b/scripts/hyde/unknowns_review.md new file mode 100644 index 00000000..44514221 --- /dev/null +++ b/scripts/hyde/unknowns_review.md @@ -0,0 +1,53 @@ +# Hyde portfolio 796 — UNKNOWN overrides for review + +After ChatGPT classification, **19 distinct descriptions** did not auto-resolve (out of ~440 distinct across all components). Grouped below with a **proposed value** (must be one of the allowed enum values) + the row count it affects. Nothing is written to the DB until these are confirmed. + +## 1. construction_age_band — 29,829 rows (DETERMINISTIC, no judgement) + +The classifier didn't extract the band letter in batch, but the band IS the leading letter, so these are mapped mechanically (`"D: 1950-1966"` → `D`). Just confirm the approach. + +| description | → band | rows | +|---|---|---| +| D: 1950-1966 | `D` | 4,978 | +| K: 2007-2011 | `K` | 4,201 | +| I: 1996-2002 | `I` | 3,708 | +| B: 1900-1929 | `B` | 3,222 | +| H: 1991-1995 | `H` | 2,747 | +| E: 1967-1975 | `E` | 2,479 | +| J: 2003-2006 | `J` | 2,221 | +| F: 1976-1982 | `F` | 2,071 | +| C: 1930-1949 | `C` | 1,840 | +| G: 1983-1990 | `G` | 1,615 | +| A: pre-1900 | `A` | 615 | +| M: 2023 onwards | `M` | 132 | + +## 2. roof_type (flat roofs) — 1,473 rows (NEEDS KHALIM'S CALL) + +Flat-roof insulation drives the SAP roof U-value. **`Flat: As Built` (1,172) + `Flat: Unknown` (194) are the load-bearing decision** — proposed conservatively as *no insulation (assumed)*. + +| description | proposed value | rows | alt options | +|---|---|---|---| +| Flat: As Built | `Flat, no insulation (assumed)` | 1,172 | Flat, insulated (assumed) / Flat, limited insulation (assumed) / Flat, no insulation (assumed) | +| Flat: Unknown | `Flat, no insulation (assumed)` | 194 | Flat, insulated (assumed) / Flat, limited insulation (assumed) / Flat, no insulation (assumed) | +| Flat: 150mm | `Flat, insulated` | 59 | Flat, insulated (assumed) / Flat, limited insulation (assumed) / Flat, no insulation (assumed) | +| Flat: 100mm | `Flat, insulated` | 32 | Flat, insulated (assumed) / Flat, limited insulation (assumed) / Flat, no insulation (assumed) | +| Flat: 50mm | `Flat, limited insulation` | 13 | Flat, insulated (assumed) / Flat, limited insulation (assumed) / Flat, no insulation (assumed) | +| SameDwellingAbove | `(same dwelling above)` | 3 | Flat, insulated (assumed) / Flat, limited insulation (assumed) / Flat, no insulation (assumed) | + +## 3. wall_type — 7 rows + +| description | proposed value | rows | +|---|---|---| +| TimberFrame: Internal | `Timber frame, with additional insulation` | 7 | + +## How to apply after review + +Edit the `corrected_value` column of `overrides_edits.csv`, then: + +``` +python scripts/hyde/build_property_overrides.py validate --edits overrides_edits.csv +python scripts/hyde/build_property_overrides.py apply-edits --edits overrides_edits.csv --portfolio-id 796 --apply +python scripts/hyde/build_property_overrides.py write --excel scripts/hyde/hyde_property_overrides.xlsx --portfolio-id 796 --apply +``` + +> Note: a proper fix for the age classifier (a prompt hint so the production lambda extracts the band letter) is a separate follow-up; these script edits handle this run. \ No newline at end of file From 6c0545a8ee9c1e7e14883ffe63b29074189a44b0 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Fri, 19 Jun 2026 19:58:53 +0000 Subject: [PATCH 70/74] =?UTF-8?q?Add=20resume=20prompt=20to=20finish=20por?= =?UTF-8?q?tfolio-796=20run=20after=20Khalim=20review=20=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/hyde/RESUME_AFTER_KHALIM.md | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 scripts/hyde/RESUME_AFTER_KHALIM.md diff --git a/scripts/hyde/RESUME_AFTER_KHALIM.md b/scripts/hyde/RESUME_AFTER_KHALIM.md new file mode 100644 index 00000000..f2927577 --- /dev/null +++ b/scripts/hyde/RESUME_AFTER_KHALIM.md @@ -0,0 +1,44 @@ +# Resume prompt — finish the Hyde portfolio-796 property_overrides run (after Khalim review) + +Paste the block below to continue. It tells the assistant to review the unknown-override +decisions with me, verify them, confirm before writing, then run the remaining steps. + +--- + +We paused the Hyde property-overrides bulk load to review the UNKNOWN classifications with +Khalim. Pick it back up. + +**Context (already done):** +- Target is **portfolio 796** in DevAssessmentModelDB (NOT 795 — 795 is empty). +- Script: `scripts/hyde/build_property_overrides.py`. Pass 1 (`classify`) is DONE — the + `landlord_*_overrides` ledger is populated; re-running classify is free (cache hits). +- The 19 unresolved descriptions are documented in `scripts/hyde/unknowns_review.md`, with + proposed values already written to `overrides_edits.csv` (gitignored). +- Env (DB creds + `OPENAI_API_KEY`) is in `/workspaces/home/github/Model/.env`; load it with + python-dotenv and set `POSTGRES_DRIVER=psycopg2`. Writes are idempotent upserts (unique on + `property_id, override_component, building_part`) — safe to re-run, never duplicates. + +**Do this, in order:** +1. **Ask me what Khalim decided** for the unknowns. The one real judgement call is the + flat-roof reading: `Flat: As Built` (1,172 rows) + `Flat: Unknown` (194) → which of + `Flat, no insulation (assumed)` / `Flat, insulated (assumed)` / `Flat, limited insulation + (assumed)`. The `construction_age_band` bands (29,829 rows) are deterministic (band = first + letter) — keep as-is unless I say otherwise. Confirm the other roof/wall proposals too. +2. **Update `overrides_edits.csv`** (`corrected_value` column) to match Khalim's decisions. +3. Run `validate --edits overrides_edits.csv` and fix anything it rejects. +4. **Show me the final edits + the planned write counts, and WAIT for my explicit go-ahead + before any `--apply`.** Do not write to the DB before I confirm. +5. On my go-ahead: + - `apply-edits --edits overrides_edits.csv --portfolio-id 796 --apply` (user corrections → ledger) + - `write --excel scripts/hyde/hyde_property_overrides.xlsx --portfolio-id 796` (DRY RUN — + report unmatched org_refs + unresolved across all 31,773 first) + - then the same `write ... --apply` +6. `verify --portfolio-id 796 --org-ref ` to confirm property_overrides + + overlays landed. +7. Remind me about the deferred **age-classifier prompt-hint fix** for the production lambda + (the live frontend will hit the same `"D: 1950-1966"` → UNKNOWN until that lands). + +Every DB command loads env from `/workspaces/home/github/Model/.env`. Read-only checks +(`verify`, dry-run `write`) are fine to run unprompted; anything `--apply` needs my confirm. + +--- From 3044c70202c991a11caab7cc37e484cf7743a232 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Sat, 20 Jun 2026 07:25:42 +0000 Subject: [PATCH 71/74] sap score and elmhirst mapper optimsaiation --- .../reference/mapping.md | 23 ++- .../expand-sap-accuracy-corpus/SKILL.md | 162 ++++++++++++++++++ .../expand-sap-accuracy-corpus/worklist.md | 23 +-- .../uprn_68151071/elmhurst_summary.pdf | Bin 0 -> 64329 bytes .../uprn_68151071/elmhurst_worksheet.pdf | Bin 0 -> 45769 bytes .../uprn_10022893721/elmhurst_summary.pdf | Bin 0 -> 63214 bytes .../uprn_10022893721/elmhurst_worksheet.pdf | Bin 0 -> 44109 bytes .../uprn_10023443426/elmhurst_summary.pdf | Bin 0 -> 63493 bytes .../uprn_10023443426/elmhurst_worksheet.pdf | Bin 0 -> 44372 bytes .../uprn_100021985993/elmhurst_summary.pdf | Bin 0 -> 65075 bytes .../uprn_100021985993/elmhurst_worksheet.pdf | Bin 0 -> 43902 bytes .../uprn_100090182288/elmhurst_summary.pdf | Bin 0 -> 64262 bytes .../uprn_100090182288/elmhurst_worksheet.pdf | Bin 0 -> 44204 bytes .../uprn_10091568921/elmhurst_summary.pdf | Bin 0 -> 63519 bytes .../uprn_10091568921/elmhurst_worksheet.pdf | Bin 0 -> 43148 bytes .../uprn_10093115480/elmhurst_summary.pdf | Bin 0 -> 63491 bytes .../uprn_10093115480/elmhurst_worksheet.pdf | Bin 0 -> 42906 bytes .../uprn_10093412452/elmhurst_summary.pdf | Bin 0 -> 63525 bytes .../uprn_10093412452/elmhurst_worksheet.pdf | Bin 0 -> 43131 bytes .../uprn_10093718424/elmhurst_summary.pdf | Bin 0 -> 63520 bytes .../uprn_10093718424/elmhurst_worksheet.pdf | Bin 0 -> 43160 bytes .../sap10_calculator/rdsap/cert_to_inputs.py | 23 ++- scripts/hyde/elmhurst_download.py | 2 +- .../rdsap/test_cert_to_inputs.py | 49 ++++++ .../test_real_cert_sap_accuracy.py | 146 ++++++++++++++++ 25 files changed, 405 insertions(+), 23 deletions(-) create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-17.0/uprn_68151071/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-17.0/uprn_68151071/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-18.0/uprn_10022893721/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-18.0/uprn_10022893721/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10023443426/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10023443426/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100021985993/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100021985993/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100090182288/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100090182288/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10091568921/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10091568921/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093115480/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093115480/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093412452/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093412452/elmhurst_worksheet.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093718424/elmhurst_summary.pdf create mode 100644 backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093718424/elmhurst_worksheet.pdf diff --git a/.claude/skills/epc-to-elmhurst-rdsap-inputs/reference/mapping.md b/.claude/skills/epc-to-elmhurst-rdsap-inputs/reference/mapping.md index 1aab0298..245b357a 100644 --- a/.claude/skills/epc-to-elmhurst-rdsap-inputs/reference/mapping.md +++ b/.claude/skills/epc-to-elmhurst-rdsap-inputs/reference/mapping.md @@ -180,12 +180,23 @@ Table 32 unit costs, p/kWh (`domain/sap10_calculator/tables/table_32.py`): **`main_fuel_type` / `water_heating_fuel` 29 = off-peak (7-hour) electricity** → Elmhurst Electricity meter type = **Dual-rate / Economy 7 (7-hour)**, NOT Single. -⚠️ **Known over-rating bug:** the engine prices **100% of off-peak space heating -AND hot water at the 5.50p low rate** (`inputs.space_heating_fuel_cost_gbp_per_kwh` -= 0.055), instead of the SAP **Table 12a high/low split** (a portion at the 15.29p -high rate). This under-costs all-electric Economy-7 dwellings and inflates the SAP -score. Always surface this in the output's "Known divergences". Canonical case: -UPRN 10002468137 — lodged 55, engine 62. +✅ **Economy-7 high/low split — FIXED (PR #1217).** The engine now applies the SAP +**Table 12a Grid 1** (space) + **Table 13** (immersion DHW) high/low split rather +than pricing 100% at the 5.50p low rate. Electric STORAGE heaters legitimately get +a 0.00 SH high-rate fraction (100% low — spec value, not a bug); immersion HW takes +the cylinder-volume/occupancy/single-dual Table 13 blend (applied in +`cert_to_inputs._hot_water_fuel_cost_gbp_per_kwh` when volume + occupancy + +single/dual are all resolved; absent any of them it still falls back to 100% low — +a rarer edge). Verified: canonical UPRN 10002468137 engine 60.92 = Elmhurst 61 to +the penny (its lodged 55 is the OLD SAP-2012 schema, not comparable); UPRN +10022893721 engine 79 = lodged 79, Elmhurst (Dual meter) 81. + +⚠️ **When building in Elmhurst you MUST set the Economy-7 meter** (`main_fuel_type` +/ `water_heating_fuel` 29 = off-peak 7-hour → Electricity meter type **Dual**, NOT +Single). Elmhurst silently defaults to Single/Standard and prices at the 13.19p +standard rate, collapsing the worksheet SAP ~13 points — which can masquerade as an +engine "over-rating". The control is a hidden Meters sub-tab on the SpaceHeating +page (`TabPanelMeters_RadioButtonListElectricityType`). ## Water Heating diff --git a/.claude/skills/expand-sap-accuracy-corpus/SKILL.md b/.claude/skills/expand-sap-accuracy-corpus/SKILL.md index 437c305e..6d73c47f 100644 --- a/.claude/skills/expand-sap-accuracy-corpus/SKILL.md +++ b/.claude/skills/expand-sap-accuracy-corpus/SKILL.md @@ -19,6 +19,74 @@ score the property would get unchanged. Elmhurst is the accredited ground truth; its Input Summary (parsed back to `EpcPropertyData`) exposes mapper holes, and its worksheet exposes calculator holes. +## ⏩ Resume in a fresh context (autonomous run) + +If the user says "continue" / "next" / "keep going through the worklist", run this +loop **continuously without asking between certs** — report only `eng X / elm Y` +per cert and tick the worklist line as each is pinned. The build automation is +fully working (see `scripts/hyde/elmhurst_lib.py` helpers + the `build_.py` +templates); most certs build unattended end-to-end. + +**State (2026-06-19):** pinned this campaign — SAP-17.1 cohort + RdSAP-17.1/18.0 +(older) plus: **16.1** `100021943298` (76/75), **19.1.0** `10096028301` (82/82), +**16.3** `44012843` (79/78), **17.0** `10023444324` (80/80) + `10023444320` +(81/82), **RdSAP-20.0.0** `10090844932` (78/77), **16.2** `100090182288` (69/71, +semi house). Latest run (2026-06-19): **16.2** `100021985993` (74/72, end-terrace +bungalow), **17.1** `10091568921` (82/80, full-SAP end-terrace house combi 17615) ++ `10093718424` (81/80, semi sibling), **RdSAP-18.0** `10022893721` (79/81, first +NON-BOILER cert — electric storage heaters + immersion; storage-heater automation +now SOLVED incl. the Economy-7 Dual-meter step, see banked findings; engine 79 = +lodged, NO bug), **RdSAP-21.0.1** `10023443426` (76/79, native schema, combi house; +engine 76 = lodged EXACTLY; Elmhurst +3 = omitted-secondary build gap). Next `[ ]`: +`10093412452` (SAP-17.1), then `10090343335` (17.0) / `10093115480` (17.1) / +`68151071` (RdSAP-17.0). Skip `100020933699` (user said skip), `[⛔]` (NOT +MAPPABLE), `[⚠]` (flagged engine bugs: MVHR / heat-pump fuel-39). + +**Per-UPRN recipe** (all commands `DISPLAY=:99`, cwd `scripts/hyde`; run +`bash scripts/hyde/start_viewer.sh` once; creds in `.elmhurst-creds.json`; shared +assessment GUID `B44A0DB4-4C08-4241-B818-86F060172105`): +1. `PYTHONPATH=/workspaces/model python scripts/fetch_real_life_epc_sample.py ` + then scope: dwelling_type/built_form, age band, walls/roof/floor descriptions, + heating `main_heating_index_number`/category/`has_hot_water_cylinder`, window + total area (`sum(sap_windows w*h)`), party_wall_length, lighting %, MEV/AP50. +2. **Copy the closest `build_.py` template** and adjust values: + - combi flat → `build_100021943298.py`; regular-boiler+cylinder flat → + `build_44012843.py`; full-SAP combi flat (MEV+AP50) → `build_10096028301.py` + / `build_10023444324.py` (+party wall) / `build_10023444320.py` (mid-floor); + - combi house → `build_10090844932.py` (end-terrace, party wall) / + `build_100090182288.py` (semi, no party wall). + Adjust: property type/built-form, band (`_pick` by year, e.g. "1950"/"2012"/ + "2023"), two-floor dims + party wall, wall insulation, roof, floor, window m², + doors, lighting, boiler PCDB ref + search query, MEV/AP50 if present. +3. Run pages: `for p in property_description [flats] dimensions walls roofs floors + openings ventilation; do … build_.py $p; done` (one Save&Close each, + ~1 min/page; flats only for Flat property type). Then a window-verify/fix + snippet (re-add the combined window if the grid shows 0.00), then + `build_.py space_heating` and `water_heating`. +4. Heating uses the `elmhurst_lib` helpers: `E.select_boiler(page, "", + "")` (look up id/type in `domain/elmhurst/pcdb_gas_oil_boiler_codes.csv`; + the lodged `main_heating_index_number` IS the id); control + `E.set_heating_dialog(page, "…ButtonMainHeatingControls", "^Boilers", + "^Standard", "CBE Programmer, room thermostat and TRVs")` (=2106); water + `E.set_heating_dialog(page, "…ButtonWaterHeatingCode", "From Space Heating", + "From the primary heating system")`; combi → `E.clear_hot_water_cylinder(page)`. +5. Download: edit `elmhurst_download.py` `SAMPLE_DIR` to the cert's + `/uprn_` dir; first confirm Recommendations is clean (parse + `[id*=ContentPlaceHolder1] a` link text — Summary silently redirects to Address + until zero errors); `python scripts/hyde/elmhurst_download.py` (retry once; the + nav goes Address→Recommendations→Summary). +6. `PYTHONPATH=/workspaces/model python scripts/compare_epc_paths.py ` → + read **"gov-API inputs → SAP"** (engine) and **"Elmhurst's OWN engine + (worksheet …)"** (Elmhurst ground truth). Target ≤0.5–1. +7. **Pin** the engine value: add a `RealCertExpectation(schema, sample=uprn_, + cert_num, sap_score=)` in `tests/.../test_real_cert_sap_accuracy.py`; + run `…::test_real_cert_sap_score`. +8. Tick the worklist line `[x] … · eng X / elm Y (lodged Z) · PINNED …`. Next cert. + +See **Banked findings** below for the modal-dialog mechanics (all already encoded +in the helpers). New schema not mappable → add a dedicated `from_*_schema_*` +mapper first (per-schema convention) + guard with the RdSAP-21.0.1 corpus gauge. + ## The loop (one UPRN) 1. **Pick** the first `[ ]` UPRN in [worklist.md](worklist.md). @@ -93,6 +161,91 @@ Pattern: `with E.session() as (ctx,page): E.goto(...); E.set_text/set_select(... lines 17/18). This drove the first campaign mapper fix — see Banked findings. ## Banked findings (fold new ones in here as the corpus grows) +- **MAPPER GAP — cylinder insulation thickness dropped (RdSAP-17.0+):** the mapper + carries `cylinder_size` + `cylinder_insulation_type` but NOT + `cylinder_insulation_thickness` → `EpcPropertyData.sap_heating.cylinder_ + insulation_thickness_mm` stays None even when the cert lodges it (e.g. 50 mm). + The engine then assumes a poorly-insulated cylinder → over-counts HW cylinder + loss → under-rates. Confirmed uprn_68151071 (raw 50 mm → mapped None; engine HW + 3446 vs Elmhurst 2911 kWh; engine 68 vs lodged 70 / Elmhurst 71). FIX: map the + thickness in the RdSAP per-schema mapper; check blast radius (any pinned cylinder + cert may shift) + regress the RdSAP-21.0.1 corpus gauge. Leverage point — likely + improves every cylinder-with-lodged-thickness cert. Flagged, not yet fixed. +- **Party-wall type `_pick` gotcha:** matching `"filled"` ALSO matches "Cavity + masonry **UN**filled" (CU, U≈0.5) — the wrong type for a cert whose party wall is + U≈0. Match `"masonry filled"` to hit CF (Cavity masonry filled, U≈0). Affects + cavity builds (10090844932 / 10091568921 / 10093718424 / 10093412452 used the + loose `"filled"` and may have got CU in Elmhurst — only the Elmhurst cross-check, + not the pinned engine value which is validated against lodged). Fixed for + uprn_10093115480. +- **Shared-assessment reset: storage/electric → boiler cert.** The shared + assessment carries the PRIOR cert's heating system. Going storage→combi, the + boiler search dialog won't open while a SAP-table `MainHeatingCode` (e.g. SEB) is + set. Fix: JS-clear `MH1.TextBoxMainHeatingCode` to `''` + dispatch change, Save & + Close, then `select_boiler` works. Also RESET the electricity meter on the Meters + sub-tab (a prior off-peak cert leaves it Dual; gas certs want Single) and the + SECONDARY heating (a prior cert's secondary persists even when the calc shows + presence=No — set it explicitly or it pollutes the worksheet). +- **Secondary heating must be built in Elmhurst when lodged.** Certs lodge a + secondary (`sap_heating.secondary_heating_type`, e.g. 612 = mains-gas room heater + @ Table 4a seasonal efficiency 0.20 — a low-eff decorative/old gas fire). The + engine models it (fraction 0.1 from Table 11 ÷ the secondary efficiency → e.g. + 3065 kWh for code 612); omitting it in Elmhurst inflates the worksheet (uprn_ + 10023443426: omitted → 79 vs engine/lodged 76). Build via Secondary present=Yes → + `ButtonSecondaryHeatingCode` cascade (title "Select secondary heating"): fuel → + sub-fuel → appliance → type, e.g. Gas → Mains gas → Room Heaters → RGx (pick the + RGx whose efficiency matches the lodged code, ~0.20 = decorative/old gas fire). + ⚠ For a NATIVE RdSAP-21.0.1 cert, engine = lodged (exact, all components) is the + authoritative validation — if the Elmhurst rebuild diverges, suspect an omitted + lodged feature (secondary / meter), confirm via engine-on-Elmhurst-inputs ≈ + worksheet, and pin the engine = lodged value. +- **Non-boiler (storage-heater) main heating — SOLVED** (uprn_10022893721, RdSAP- + 18.0 GF flat, electric storage heaters + immersion). The SpaceHeating page has NO + inline system-type selector and a `ButtonMainHeatingCode` button only APPEARS + once the bound PCDF boiler is cleared. Two-pass recipe (one Save & Close each): + 1. **Clear the leftover PCDB boiler**: set `MH1.TextBoxPCDFBoilerReference` to + `"0"` via JS + dispatch `change`, then `save_close`. (It doesn't AutoPostBack; + the Save commits it. After reload, boilerRef="0", the boiler fuel/flue fields + vanish, and `MH1.ButtonMainHeatingCode` is now present.) + 2. **Select the SAP-table system** via `set_heating_dialog(..ButtonMainHeating + Code, "^Electric","^Electric","Storage","SEB Modern slimline")` (title "Select + heating code"; L1 Gas/Oil/Solid Fuel/Electric/Community/No heating; storage L4 + = SEA old large-volume / SEB modern slimline / SED fan / SEJ integrated / SEK + high-heat-retention). **Match the cert's `sap_main_heating_code`**: 402 = SEB. + Then the CONTROL via `set_heating_dialog(..ButtonMainHeatingControls, + "Storage Radiator","CSA Manual charge control")` (= SAP 2401). Secondary No. + Water: `set_heating_dialog(..ButtonWaterHeatingCode, "Water Heater","^Electric", + "Immersion")` (→ code HEI) — then the immersion code REQUIRES a cylinder: CHECK + `WH.CheckBoxHotWaterCylinder` (JS click+change, AutoPostBacks) or Recommendations + errors "must have a Hot Water Cylinder"; set `WH.DropDownListCylinderSize` + (size 2→Normal/110L, 3→Medium/160L, 4→Large/210L), `WH.DropDownListInsulated` + (Foam/Jacket), `WH.DropDownListInsulationThickness`, and `WH.RadioButton + ListImmersionHeater` (off-peak meter → Dual). See `build_10022893721.py` as the + template. ⚠ **CRITICAL — set the electricity meter type.** All-electric off-peak + certs MUST set the Economy-7 meter or Elmhurst silently defaults to Single / + Standard and prices everything at the 13.19p standard rate (worksheet collapses + ~13 SAP). The control is a HIDDEN sub-tab on the SpaceHeating page: + `E.click_tab(page,"TabContainer_TabPanelMeters")` then `E.set_select(page, + "TabContainer_TabPanelMeters_RadioButtonListElectricityType","Dual")` (options + Single/Dual/18 Hour/24 Hour/Unknown; cert `meter_type` 1→Dual=7-hour off-peak). + Verify in Elmhurst summary §14.2 "Electricity meter type" / worksheet + "Electricity Tariff" before trusting the worksheet SAP. +- **Economy-7 off-peak pricing is CORRECT — do NOT "fix" it** (was a real bug, FIXED + in PR #1217 via the Table 13 off-peak water-heating split + window-U fix). The + engine applies SAP Table 12a Grid 1 (space) + Table 13 (immersion DHW) high/low + splits properly: storage heaters' SH high-rate fraction is legitimately 0.00 + (100% low rate), immersion HW takes the volume/occupancy/single-dual blend. Proof: + uprn_10002468137 (canonical) engine 60.92 = Elmhurst 61 to the penny; + uprn_10022893721 engine 79 = lodged 79, Elmhurst (Dual meter) 81. ⚠ If you see a + big engine-over-Elmhurst gap on an all-electric off-peak cert, SUSPECT THE BUILD + (Elmhurst meter left on Single — see meter step above), not the calculator. The + `reference/mapping.md` "known over-rating bug (engine 62)" note is STALE (pre-PR + #1217). `cert_to_inputs.py` `_hot_water_fuel_cost_gbp_per_kwh` applies the immersion + Table 13 blend when cylinder volume + occupancy resolve; when `immersion_heating_ + type` is UNLODGED on an off-peak meter it now defaults to DUAL per RdSAP §10.5 + (was a 100%-low-rate fallback that under-costs — fixed, +regression test + `test_off_peak_immersion_unlodged_type_defaults_to_dual_table13_blend`). Only an + unresolvable cylinder volume / occupancy still falls back to 100% low. - **Air-permeability AP50 fix** (uprn_10093116528, the first campaign cert): the full-SAP mapper was routing the lodged q50 to the engine's AP4/Pulse formula (`0.263×AP4^0.924`) instead of the AP50 `/20` path — a big infiltration @@ -134,6 +287,15 @@ Pattern: `with E.session() as (ctx,page): E.goto(...); E.set_text/set_select(... cylinder()`, then set water method "From Space Heating → primary" via `set_heating_dialog(..ButtonWaterHeatingCode, 'From Space Heating', 'From the primary heating system')`. +- **Reduced-field (16.x) semi/terraced party wall.** 16.x lodges no + `party_wall_length`, so the engine models NO party wall (defaults 0). But + Elmhurst REJECTS a semi/terraced with a zero party wall ("At least one building + part must have a party wall length of non zero"). Enter the geometry-derived + length (solve `2w+d=heat_loss_perimeter`, `w*d=floor_area`; party wall = the + joined side `d`) on every floor + a filled-cavity party-wall type (CF), and + EXPECT engine to over-read Elmhurst by ~1–2 SAP (engine's no-party-wall vs + Elmhurst's forced one). That delta is the documented reduced-field gap, not a + bug — confirm via engine-on-Elmhurst-inputs ≈ worksheet. Pin the engine value. - **Main-heating control must match the boiler's system type.** Heat-pump leftover control (e.g. CHJ/2210, ctrl-group-2) is invalid for a gas boiler (ctrl-group-1) and blocks the report. For a boiler programmer+room-stat+TRVs (SAP 2106): diff --git a/.claude/skills/expand-sap-accuracy-corpus/worklist.md b/.claude/skills/expand-sap-accuracy-corpus/worklist.md index e4db5aa5..e40f2853 100644 --- a/.claude/skills/expand-sap-accuracy-corpus/worklist.md +++ b/.claude/skills/expand-sap-accuracy-corpus/worklist.md @@ -4,7 +4,8 @@ Process **one at a time**, top to bottom (see [SKILL.md](SKILL.md)). After each UPRN, tick it and annotate: `— · eng / elm · `. **Legend:** `[ ]` todo · `[x]` pinned (≤0.5) · `🔧` mapper extended · `⚠` xfail -(engine bug) · `⛔` blocked. +(engine bug) · `⛔` blocked · `[🔍]` flagged — engine vs Elmhurst-worksheet gap too +large, or a new/complex build pattern needed; NEEDS INVESTIGATION. **Worked reference (not in the 100):** `uprn_10092973954` (SAP-Schema-17.1, 2020 new-build flat) — full loop proven: eng 77 / elm 78, engine-on-Elmhurst- @@ -60,19 +61,19 @@ Skip the 🚩 MVHR / 🚩 heat-pump-fuel and ⛔ sparse certs. - [⚠] 10094601287 — SAP-18.0.0 · eng 80 / lodged 84 · 🚩 MVHR idx 500230 not credited (flagged) - [x] 10090844932 — RdSAP-20.0.0 (end-terrace HOUSE 2-storey, band L, combi PCDB 10327, party wall 4.93, 250mm loft) · eng 78 / elm 77 (lodged 78) · PINNED engine 78. Built in Elmhurst (House, boiler 10327 via search, control CBE/2106, water from primary, party wall 4.93 filled). Within ~1 (78.13 vs 77); engine-on-Elmhurst-inputs 77.24 ≈ 77 → faithful. - [⛔] 10090844948 — SAP-16.3 · NOT MAPPABLE (ValueError: RdSapSchema17_1: missing required field ) -- [ ] 100090182288 — SAP-16.2 · eng 71 / lodged 71 +- [x] 100090182288 — SAP-16.2 (semi-detached HOUSE 2-storey, band D, filled cavity, combi PCDB 10327, double glazed) · eng 71 / elm 69 (lodged 71) · PINNED engine 71. Built in Elmhurst (semi, boiler 10327, control CBE/2106, water from primary, party wall 4.28 filled — Elmhurst requires non-zero for a semi). +2 vs Elmhurst = documented 16.2 reduced-field party-wall gap (gov-API lodges no party_wall_length → engine models none); engine-on-Elmhurst-inputs 69.35 ≈ worksheet 69 → calculator faithful. - [⚠] 10093114053 — SAP-17.0 · eng 93 / lodged 79 · 🚩 heat-pump fuel-39 (flagged) -- [ ] 10091568921 — SAP-17.1 · eng 82 / lodged 85 -- [ ] 10093718424 — SAP-17.1 · eng 81 / lodged 84 -- [ ] 10022893721 — RdSAP-18.0 · eng 79 / lodged 79 -- [ ] 10023443426 — RdSAP-21.0.1 · eng 76 / lodged 76 -- [ ] 10093412452 — SAP-17.1 · eng 81 / lodged 84 +- [x] 10091568921 — SAP-17.1 (full-SAP END-TERRACE HOUSE 2-storey, band L 2018, combi PCDB 17615 Potterton Promax Ultra, party wall 40.56m², natural vent + 3 extract fans, AP50 4.45, 20 LED, measured U 0.18/0.10/0.15) · eng 82 / elm 80 (lodged 85) · PINNED engine 82. Built in Elmhurst (end-terrace house, boiler 17615, CBE/2106, water from primary, party wall 8.45 filled, AP50 Blower Door 4.45+cert). +2 = documented full-SAP→RdSAP residual (measured U beats band-L defaults); engine-on-Elmhurst-inputs 80.16 ≈ worksheet 80 → faithful. has_hot_water_cylinder lodged true but combi PCDB + no cylinder detail → built combi. No mapper change. +- [x] 10093718424 — SAP-17.1 (full-SAP SEMI-DETACHED HOUSE 2-storey, band L, combi PCDB 17615, party wall 40.89m², natural vent + 3 extract fans, AP50 4.18, 20 LED, measured U 0.25/0.13/0.16; sibling of 10091568921) · eng 81 / elm 80 (lodged 84) · PINNED engine 81. +1 = documented full-SAP→RdSAP residual; engine-on-Elmhurst-inputs 80.12 ≈ worksheet 80 → faithful. Built combi (cylinder lodged true but combi PCDB). No mapper change. +- [x] 10022893721 — RdSAP-18.0 (GF FLAT, band I, cavity insulated, ELECTRIC STORAGE HEATERS SAP 402 SEB Modern slimline + manual charge CSA/2401, immersion off-peak dual + cylinder Normal/110L foam 50mm, party wall 21.48) · eng 79 / elm 81 (lodged 79) · PINNED engine 79 = lodged. Built in Elmhurst (storage SEB, CSA control, immersion dual + cylinder, **Dual electricity meter / Economy 7**). engine -2 vs Elmhurst, within tolerance; engine-on-Elmhurst-inputs 78.76 ≈ 79 → faithful. Economy-7 off-peak pricing is CORRECT (Table 12a/13, fixed PR #1217) — NOT a bug. ⚠ Earlier mis-build left Elmhurst meter on Single/Standard → bogus worksheet 66; fixed by setting Dual meter on the Meters sub-tab. 🔧 First non-boiler cert — SOLVED storage-heater automation (see banked findings: clear PCDB boiler → ButtonMainHeatingCode Electric→Electric→Storage→SEB; set Dual meter). build_10022893721.py complete. +- [x] 10023443426 — RdSAP-21.0.1 (END-TERRACE HOUSE 2-storey, band L, cavity insulated, combi PCDB 17045 Ideal Logic ES35, 300mm loft, party wall 9.2 lodged, 11 dbl-glazed windows ~10.3m², 9 LED, mains-gas room-heater SECONDARY code 612 eff 0.20) · eng 76 / elm 79 (lodged 76) · PINNED engine 76 = lodged EXACTLY (native RdSAP-21.0.1 schema; reproduces every component: space 6129/main 6247/HW 2752/CO2 2232). Elmhurst +3 is a BUILD gap — my build omitted the lodged secondary gas fire (engine models it 3065 kWh = 0.1÷0.20); engine-on-Elmhurst-inputs 79.29 ≈ worksheet 79 → calculator faithful. NB: shared-assessment storage→combi reset needed (clear leftover MainHeatingCode) + meter reset to Single. build_10023443426.py. +- [x] 10093412452 — SAP-17.1 (full-SAP END-TERRACE HOUSE 2-storey, band L, combi PCDB 17615, party wall 41.01m², natural vent + 3 extract fans, AP50 4.62, 20 LED, measured U 0.25/0.13/0.16; sibling of 10093718424/10091568921) · eng 81 / elm 80 (lodged 84) · PINNED engine 81. +1 = documented full-SAP→RdSAP residual; engine-on-Elmhurst-inputs 79.91 ≈ worksheet 80 → faithful. Built combi (cylinder lodged true but combi PCDB). No mapper change. - [⛔] 10014314798 — SAP-16.2 · NOT MAPPABLE (ValueError: RdSapSchema17_1: missing required field ) - [⚠] 10094601294 — SAP-18.0.0 · eng 81 / lodged 84 · 🚩 MVHR idx 500230 not credited (flagged) -- [ ] 10090343335 — SAP-17.0 · eng 86 / lodged 88 -- [ ] 10093115480 — SAP-17.1 · eng 81 / lodged 81 -- [ ] 68151071 — RdSAP-17.0 · eng 68 / lodged 70 -- [ ] 100021985993 — SAP-16.2 · eng 74 / lodged 70 +- [🔍] 10090343335 — SAP-17.0 (full-SAP SEMI-DETACHED HOUSE, 3-storey incl. ROOM-IN-ROOF top floor h1.95, combi PCDB 16841 Vaillant ecoTEC plus 824, party wall 48.51m², 10 windows 18.46m² + 1 ROOF WINDOW type-12 2.31m², 3 doors, AP50 3.98, 10 LED, measured U walls 0.18/roof 0.15/floor 0.13, TFA 122) · eng 86 / lodged 88 · 🔍 FLAGGED — NEEDS NEW BUILD PATTERN: room-in-roof + roof-window not covered by templates (Elmhurst DIM panel only exposes 2 floors; room-in-roof entered via RoomInRoofMain age-band + separate RiR dimensions TBD; roof window type-12 entry TBD). Elmhurst build + worksheet comparison pending. Skipped in autonomous sweep to keep momentum; revisit with a dedicated room-in-roof build. +- [x] 10093115480 — SAP-17.1 (full-SAP END-TERRACE BUNGALOW single-storey, band L 2016, combi PCDB 16841, party wall 10.99m² CF filled, natural vent + 2 fans, AP50 3.85, 9 LED, measured U 0.19/0.11/0.12, TFA 56) · eng 81 / elm 78 (lodged 81) · PINNED engine 81 = lodged EXACT. +3 = documented full-SAP→RdSAP residual (measured U beats band-L defaults); engine-on-Elmhurst-inputs 78.29 ≈ worksheet 78 → faithful. Built combi. No mapper change. +- [🔍] 68151071 — RdSAP-17.0 (semi-detached BUNGALOW single-storey, band H 1991-1995, cavity insulated, REGULAR boiler PCDB 17550 Worcester Greenstar 18Ri + cylinder size2/foam/50mm, pitched 200mm loft, suspended uninsulated floor, party wall 9.48 lodged, TFA 50) · eng 68 / elm 71 (lodged 70) · 🔍 FLAGGED — MAPPER GAP (cylinder insulation thickness dropped). engine -3 vs Elmhurst, -2 vs lodged; engine HW 3446 kWh vs Elmhurst 2911. ROOT CAUSE confirmed: raw cert lodges sap_heating.cylinder_insulation_thickness=50 but the RdSAP-17.0 mapper maps cylinder_size + cylinder_insulation_type only, leaving EpcPropertyData.sap_heating.cylinder_insulation_thickness_mm=None → engine assumes a poorly-insulated cylinder → over-counts HW cylinder loss → under-rates. FIX: carry cylinder_insulation_thickness → cylinder_insulation_thickness_mm in the RdSAP mapper (check blast radius across schemas + regression). engine-on-Elmhurst-inputs 71.34 ≈ worksheet 71 → calculator faithful (gap is purely the dropped input). build_68151071.py + evidence saved. +- [x] 100021985993 — SAP-16.2 (END-TERRACE BUNGALOW single-storey, band C, solid-brick internal insulation, combi PCDB 10328, double glazed, 100mm loft, suspended uninsulated floor) · eng 74 / elm 72 (lodged 70) · PINNED engine 74. Built in Elmhurst (end-terrace, boiler 10328, control CBE/2106, water from primary, party wall 6.89 solid masonry — Elmhurst requires non-zero for an end-terrace). +2 vs Elmhurst = documented 16.2 reduced-field party-wall gap (gov-API lodges no party_wall_length → engine models none; worksheet's only extra element is party wall 16.19m²×U0.25=4.05 W/K ≈ 2 SAP). engine-on-Elmhurst-PDF-inputs 67 is PDF-parser noise (HW over-parsed), not a calc bug. - [ ] 100020665611 — RdSAP-20.0.0 · eng 36 / lodged 37 - [⚠] 10093388044 — SAP-17.1 · eng 87 / lodged 93 · 🚩 heat-pump fuel-39 (flagged) - [ ] 10090944225 — SAP-17.0 · eng 81 / lodged 82 diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-17.0/uprn_68151071/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-17.0/uprn_68151071/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f30539c7f30876e126f1ec1db11790853a27332d GIT binary patch literal 64329 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 l40Ce28if4CNkn(=5~(n8;f?Sg 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

f2_on5RI=Nsz9}n4}LSa%YetD2G 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 literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-18.0/uprn_10022893721/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-18.0/uprn_10022893721/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2a7cab925f5673daefe91230eb4c1a6abba2d84c GIT binary patch literal 44109 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 z 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 ZR3Ct~H{jo=iJwn^n-7(NL0(hg{{TYFT&Dm4 literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10023443426/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/RdSAP-Schema-21.0.1/uprn_10023443426/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5989896d74d62c73635308a025c617affc39c0cb GIT binary patch literal 63493 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 T%ip_+lY<)wM53maRFwJ;-q!v( literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100021985993/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100021985993/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b9f25bb4051d5fc67c94f0145d2e110ad0a21917 GIT binary patch literal 65075 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 IEq%5B1EQ(iy8r+H literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100021985993/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100021985993/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..53e01bf96c2fa17c514061a8d80e4d059de7ac5c GIT binary patch literal 43902 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

UfI(sh_@N4aF}2O}Pe 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 O2n+!Ov9ijj%Ki_VL|@SW literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100090182288/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-16.2/uprn_100090182288/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..65951fc43a30f3760deb8961daff7eec43a35b38 GIT binary patch literal 44204 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 Qi5tkn4aA|RmwqerA9t*llK=n! literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093115480/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093115480/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f1e38755115ef314207dc8625ebf1e519ea7f9d3 GIT binary patch literal 63491 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 literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093115480/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093115480/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dd214b03ce47b61fc8ab0a8d028ea63445b622fb GIT binary patch literal 42906 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 literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093412452/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093412452/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0cdfe5af5866e7e2c89755efef008505bf7d36d5 GIT binary patch literal 63525 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 W)7IVduP*`$k(H69=I2+}z5Xx81sA>m literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093412452/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093412452/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..818e3b5079ba056d99629892982b882f19dce03e GIT binary patch literal 43131 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 O=>h;zXlbQYW&Q)UQ>|hE literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093718424/elmhurst_summary.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093718424/elmhurst_summary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..01f488b6a339b14b852710262af6198a78dcb41e GIT binary patch literal 63520 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 T|N0}~!V(Bk02h~vw(5TYQ#%A~ literal 0 HcmV?d00001 diff --git a/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093718424/elmhurst_worksheet.pdf b/backend/epc_api/json_samples/real_life_examples/SAP-Schema-17.1/uprn_10093718424/elmhurst_worksheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9e212df0ac058e799711ef5875bb8202f97b77f2 GIT binary patch literal 43160 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 None: + # Arrange — electric immersion DHW (WHC 903) on a Dual / Economy-7 (7-hour) + # meter with a cylinder present (Normal / 110 L), but the cert does NOT lodge + # `immersion_heating_type`. RdSAP 10 §10.5 (PDF p.54) assumes a DUAL immersion + # on a dual / off-peak meter, so the hot-water scalar rate must be the SAP + # 10.2 Table 13 DUAL high/low blend (a small high-rate fraction at 15.29 p + + # the remainder at 5.50 p), NOT the 100%-low-rate (5.50 p) fallback that an + # unlodged type previously triggered. The fallback under-costs the DHW and + # over-rates the dwelling — cf. uprn_10022893721, whose Elmhurst worksheet + # bills the immersion at a 0.1386 high-rate fraction, not 100% low. + from dataclasses import replace + + main = MainHeatingDetail( + has_fghrs=False, + main_fuel_type=29, # electricity + heat_emitter_type=0, + emitter_temperature=1, + main_heating_control=2401, + main_heating_category=7, # electric storage heaters + sap_main_heating_code=401, + ) + base = make_minimal_sap10_epc( + total_floor_area_m2=_TYPICAL_TFA_M2, + habitable_rooms_count=4, + country_code="ENG", + has_hot_water_cylinder=True, + sap_building_parts=[make_building_part(construction_age_band="E")], + sap_heating=make_sap_heating( + main_heating_details=[main], + water_heating_code=903, # electric immersion + water_heating_fuel=29, # off-peak electricity + cylinder_size=2, # Normal / 110 L + immersion_heating_type=None, # UNLODGED -> assume dual on off-peak + ), + ) + epc = replace( + base, + sap_energy_source=replace(base.sap_energy_source, meter_type="1"), # Dual + ) + + # Act + inputs = cert_to_inputs(epc) + + # Assert — the Table 13 DUAL blend applied, not the 100%-low-rate fallback. + rate = inputs.hot_water_fuel_cost_gbp_per_kwh + assert rate > 0.0550 + 1e-6 # NOT the 100%-low-rate bug value (5.50 p/kWh) + assert rate < 0.0900 # a small DUAL high-rate fraction, not single (~11 p) + + def test_non_integrated_storage_heater_bills_100_percent_low_rate() -> None: # Arrange — same off-peak storage cert but SAP code 401 ("other storage # heaters"): Table 12a Grid 1 gives a 0.00 high-rate fraction → the heat 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 7deb4449..935715a8 100644 --- a/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py +++ b/tests/domain/sap10_calculator/test_real_cert_sap_accuracy.py @@ -364,6 +364,152 @@ _EXPECTATIONS: Final[tuple[RealCertExpectation, ...]] = ( cert_num="0646-3008-6208-0619-6204", sap_score=78, ), + # UPRN 100090182288 → cert 0068-1092-7237-0157-9954. SAP-Schema-16.2 — + # reduced-field SEMI-DETACHED HOUSE, 2-storey, band D (1950-1966), filled + # cavity, pitched roof 250 mm, solid uninsulated floor, mains-gas COMBI (PCDB + # 10327 Vaillant Ecotec Plus 831), double glazed, TFA 73.4 m². Lodged 71; + # engine 71. Built in Elmhurst RdSAP10 (evidence saved): Elmhurst worksheet 69. + # The +2 (engine 71 vs Elmhurst 69) is the documented 16.2 reduced-field + # PARTY-WALL gap: gov-API 16.2 lodges no party_wall_length → the engine models + # NO party wall, but Elmhurst requires one for a semi (entered the geometry- + # derived 4.28 m, filled cavity). Calculator confirmed faithful: engine on + # Elmhurst's own parsed inputs (which include the party wall) = 69.35 ≈ worksheet + # 69. PINNED to the observed 71 (= lodged) — mapping untuned; the Elmhurst delta + # is the reduced-field missing-party-wall-data gap, not a calculator bug. + RealCertExpectation( + schema="SAP-Schema-16.2", + sample="uprn_100090182288", + cert_num="0068-1092-7237-0157-9954", + sap_score=71, + ), + # UPRN 100021985993 → cert 9658-2087-7277-0667-1910. SAP-Schema-16.2 — + # reduced-field END-TERRACE BUNGALOW, single-storey, band C (1930-1949), + # solid-brick internal insulation, pitched roof 100 mm loft, suspended + # uninsulated floor, mains-gas COMBI (PCDB 10328 Vaillant Ecotec Pro 28), + # double glazed, TFA 76.54 m². Lodged 70; engine 74. Built in Elmhurst RdSAP10 + # (evidence saved): Elmhurst worksheet 72. The +2 (engine 74 vs Elmhurst 72) is + # the documented 16.2 reduced-field PARTY-WALL gap: gov-API 16.2 lodges no + # party_wall_length → the engine models NO party wall, but Elmhurst requires one + # for an end-terrace (entered the geometry-derived 6.89 m, solid masonry; the + # worksheet's only extra heat-loss element is the party wall at 16.19 m² × U0.25 + # = 4.05 W/K ≈ the 2-SAP gap). Calculator faithful: engine-on-gov-API 74 minus + # that omitted party-wall heat loss ≈ 72 = worksheet. (Engine on Elmhurst's + # PDF-parsed inputs = 67 here — lower than the worksheet — is PDF-parser noise: + # hot water over-parsed to 2998 kWh/£684; not a calculator divergence.) PINNED + # to the observed 74 — mapping untuned; the Elmhurst delta is the reduced-field + # missing-party-wall-data gap, not a calculator bug. + RealCertExpectation( + schema="SAP-Schema-16.2", + sample="uprn_100021985993", + cert_num="9658-2087-7277-0667-1910", + sap_score=74, + ), + # UPRN 10091568921 → cert 8806-5635-1239-5807-8283. SAP-Schema-17.1 — full-SAP + # END-TERRACE HOUSE, 2-storey, 2018 (band L), measured U walls 0.18 / roof 0.10 + # / floor 0.15, mains-gas COMBI (PCDB 17615 Potterton Promax Ultra Combi 28, + # 88.5%), double glazed, party wall 40.56 m², natural vent + 3 extract fans, + # AP50 4.45 (tested), 20 LED outlets, TFA 78.7 m². has_hot_water_cylinder lodged + # true but cylinder detail all None + PCDB combi → built as combi (water from + # primary). Lodged 85; engine 82. Built in Elmhurst RdSAP10 (evidence saved): + # worksheet 80. The +2 (engine 82 vs Elmhurst 80) is the documented full-SAP→ + # RdSAP residual (cert's measured U-values beat RdSAP band-L age defaults). + # Calculator confirmed faithful: engine on Elmhurst's own parsed inputs = 80.16 + # ≈ worksheet 80. PINNED to the observed 82 — mapping untuned. (Control: cert + # 2110 time+temp zone vs Elmhurst CBE 2106; sub-0.5 SAP, in the noise.) + RealCertExpectation( + schema="SAP-Schema-17.1", + sample="uprn_10091568921", + cert_num="8806-5635-1239-5807-8283", + sap_score=82, + ), + # UPRN 10093718424 → cert 0369-3892-7678-2690-7475. SAP-Schema-17.1 — full-SAP + # SEMI-DETACHED HOUSE, 2-storey, band L, measured U walls 0.25 / roof 0.13 / + # floor 0.16, mains-gas COMBI (PCDB 17615 Potterton Promax Ultra Combi 28), + # double glazed, party wall 40.89 m², natural vent + 3 extract fans, AP50 4.18 + # (tested), 20 LED outlets, TFA 79.9 m². Sibling of uprn_10091568921 (same + # development/boiler); built combi (cylinder lodged true but combi PCDB). + # Lodged 84; engine 81. Built in Elmhurst RdSAP10 (evidence saved): worksheet + # 80. The +1 (engine 81 vs Elmhurst 80) is the documented full-SAP→RdSAP + # residual. Calculator faithful: engine on Elmhurst's own parsed inputs = 80.12 + # ≈ worksheet 80. PINNED to the observed 81 — mapping untuned. + RealCertExpectation( + schema="SAP-Schema-17.1", + sample="uprn_10093718424", + cert_num="0369-3892-7678-2690-7475", + sap_score=81, + ), + # UPRN 10022893721 → cert 8078-7422-5930-5662-8922. RdSAP-Schema-18.0 — GROUND- + # FLOOR FLAT, band I (1996-2002), cavity insulated, ELECTRIC STORAGE HEATERS + # (SAP code 402 = SEB Modern slimline, manual charge control 2401) + electric + # immersion off-peak (dual-rate) hot water with cylinder (Normal/110 L, foam + # 50 mm), party wall 21.48 m, TFA 54.29. First non-boiler corpus cert. Lodged + # 79; engine 79. Built in Elmhurst RdSAP10 (evidence saved): worksheet 81 — + # engine -2, within tolerance; engine on Elmhurst's own parsed inputs = 78.76 ≈ + # engine 79 → calculator faithful. The Economy-7 off-peak pricing is CORRECT + # (Table 12a/13 split, fixed in PR #1217): storage SH high-rate fraction 0.00 → + # 100% low rate is the spec value, and immersion HW takes the Table 13 blend. + # (An earlier build mistakenly left Elmhurst's meter on Single/Standard, pricing + # at 13.19p → bogus worksheet 66; corrected by setting the Dual meter. NOT an + # engine bug.) PINNED to the observed engine 79 = lodged. + RealCertExpectation( + schema="RdSAP-Schema-18.0", + sample="uprn_10022893721", + cert_num="8078-7422-5930-5662-8922", + sap_score=79, + ), + # UPRN 10023443426 → cert 4106-3336-4002-1402-2202. RdSAP-Schema-21.0.1 (the + # engine's NATIVE schema) — END-TERRACE HOUSE, 2-storey, band L, cavity + # insulated, mains-gas COMBI (PCDB 17045 Ideal Logic Combi ES35), 300 mm loft, + # solid insulated floor, party wall 9.2 m (lodged), 11 double-glazed windows + # (~10.3 m²), 9 LED, mains-gas room-heater SECONDARY (SAP code 612, seasonal + # efficiency 0.20 per Table 4a — a low-efficiency decorative/old gas fire), + # TFA 98. Engine 76 = lodged 76 EXACTLY (and reproduces every component: space + # 6129, main fuel 6247, HW 2752, CO2 2232 kWh/kg) — the authoritative validation + # for a native-schema cert. Built in Elmhurst RdSAP10 (evidence saved): + # worksheet 79. The +3 is a BUILD gap, not a calculator error — my Elmhurst + # build omitted the lodged secondary gas fire (engine models it at 3065 kWh = + # 0.1 fraction ÷ 0.20 eff; Elmhurst secondary 0). engine on Elmhurst's own + # parsed inputs (also no secondary) = 79.29 ≈ worksheet 79 → calculator faithful + # to its inputs. PINNED to the observed engine 76 = lodged; mapping untuned. + RealCertExpectation( + schema="RdSAP-Schema-21.0.1", + sample="uprn_10023443426", + cert_num="4106-3336-4002-1402-2202", + sap_score=76, + ), + # UPRN 10093412452 → cert 8306-7575-5832-6507-9803. SAP-Schema-17.1 — full-SAP + # END-TERRACE HOUSE, 2-storey, band L, measured U walls 0.25 / roof 0.13 / + # floor 0.16, mains-gas COMBI (PCDB 17615 Potterton Promax Ultra Combi 28), + # double glazed (~12.3 m²), party wall 41.01 m², natural vent + 3 extract fans, + # AP50 4.62, 20 LED, no secondary, TFA 79.8 m². Same Emsworth development as the + # 10091568921 / 10093718424 siblings (cylinder lodged true but combi PCDB → + # built combi). Lodged 84; engine 81. Built in Elmhurst RdSAP10 (evidence + # saved): worksheet 80. The +1 (engine 81 vs Elmhurst 80) is the documented + # full-SAP→RdSAP residual; engine on Elmhurst's own parsed inputs = 79.91 ≈ + # worksheet 80 → calculator faithful. PINNED to the observed 81 — mapping + # untuned. + RealCertExpectation( + schema="SAP-Schema-17.1", + sample="uprn_10093412452", + cert_num="8306-7575-5832-6507-9803", + sap_score=81, + ), + # UPRN 10093115480 → cert 8393-7438-5230-3319-1996. SAP-Schema-17.1 — full-SAP + # END-TERRACE BUNGALOW (single-storey), 2016 (band L), measured U walls 0.19 / + # roof 0.11 / floor 0.12, mains-gas COMBI (PCDB 16841 Vaillant ecoTEC plus 824), + # double glazed (~11.9 m²), party wall 10.99 m² (CF filled, U≈0), natural vent + + # 2 extract fans, AP50 3.85, 9 LED, TFA 56 m². Lodged 81; engine 81 (EXACT + # match). Built in Elmhurst RdSAP10 (evidence saved): worksheet 78. The +3 + # (engine 81 vs Elmhurst 78) is the documented full-SAP→RdSAP residual — the + # cert's measured U-values beat Elmhurst's RdSAP band-L age defaults; engine on + # Elmhurst's own parsed inputs = 78.29 ≈ worksheet 78 → calculator faithful. + # PINNED to the observed engine 81 = lodged — mapping untuned. + RealCertExpectation( + schema="SAP-Schema-17.1", + sample="uprn_10093115480", + cert_num="8393-7438-5230-3319-1996", + sap_score=81, + ), ) From a3e25663789b4f56e959aefc7a618dcb827a64c8 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Sat, 20 Jun 2026 12:57:54 +0000 Subject: [PATCH 72/74] landlord override data added --- .../property_overlays/roof_type_overlay.py | 61 +++++++++---- .../property_overlays/wall_type_overlay.py | 8 ++ domain/modelling/simulation.py | 6 ++ .../property/landlord_override_overlays.py | 21 +++-- scripts/hyde/build_property_overrides.py | 46 +++++++++- scripts/hyde/elmhurst_lib.py | 85 +++++++++++++++++++ tests/domain/epc/test_roof_type_overlay.py | 69 ++++++++++++++- tests/domain/epc/test_wall_type_overlay.py | 14 ++- .../modelling/test_overlay_applicator.py | 21 +++++ 9 files changed, 299 insertions(+), 32 deletions(-) diff --git a/domain/epc/property_overlays/roof_type_overlay.py b/domain/epc/property_overlays/roof_type_overlay.py index 88837988..aadcc387 100644 --- a/domain/epc/property_overlays/roof_type_overlay.py +++ b/domain/epc/property_overlays/roof_type_overlay.py @@ -1,12 +1,21 @@ -"""Map a Landlord-Override `RoofType` value to a roof Simulation Overlay (ADR-0032). +"""Map a Landlord-Override `RoofType` value to a roof Simulation Overlay (ADR-0032/0033). -The calculator derives the roof U-value from the building part's loft-insulation -depth, so a `roof_type` override moves the score only via -`BuildingPartOverlay.roof_insulation_thickness` (mm). The resolvable family is -the explicit `"Pitched, N mm loft insulation"` values — N is parsed out. -Everything else (flat roofs, room-in-roof, "Unknown loft insulation", -"Another Premises Above" — a flat with a dwelling above, no roof to insulate) has -no clean loft depth, so it produces no overlay. +Two resolvable families: + +* `"Pitched, N mm loft insulation"` — the loft depth N maps to + `BuildingPartOverlay.roof_insulation_thickness` (mm); the calculator scores the + roof from that depth. +* `"Flat, …"` — a flat roof carries no loft depth, so its U-value comes from the + age-band default (`_FLAT_ROOF_BY_AGE`, ADR-0033). The calculator's flat path + keys on the `roof_construction_type` *string* (`"flat" in …`), so the overlay + sets that to `"Flat"` and leaves thickness `None` for the (separately overlaid) + construction age band to drive the U-value. No flat `RoofType` value carries an + explicit mm depth, confirmed by the Elmhurst sweep (As Built / Unknown ≡ + age-band default). + +Everything else (room-in-roof, "Unknown loft insulation", party-ceiling adjacency +markers like "Another Premises Above") has no clean depth or shape correction, so +it produces no overlay. """ from __future__ import annotations @@ -23,8 +32,8 @@ _LOFT_MM = re.compile(r"(\d+)\+?\s*mm loft insulation") def roof_overlay_for( roof_type_value: str, building_part: int ) -> Optional[EpcSimulation]: - match = _LOFT_MM.search(roof_type_value) - if match is None: + overlay = _overlay_for(roof_type_value) + if overlay is None: return None identifier = ( @@ -32,10 +41,28 @@ def roof_overlay_for( if building_part == 0 else BuildingPartIdentifier.extension(building_part) ) - return EpcSimulation( - building_parts={ - identifier: BuildingPartOverlay( - roof_insulation_thickness=int(match.group(1)) - ) - } - ) + return EpcSimulation(building_parts={identifier: overlay}) + + +def _overlay_for(roof_type_value: str) -> Optional[BuildingPartOverlay]: + match = _LOFT_MM.search(roof_type_value) + if match is not None: + return BuildingPartOverlay(roof_insulation_thickness=int(match.group(1))) + if roof_type_value.startswith("Flat,"): + # Flat roof: U-value is the age-band default; flag the shape and let the + # age-band overlay drive `_FLAT_ROOF_BY_AGE` (ADR-0033). + return BuildingPartOverlay(roof_construction_type="Flat") + if roof_type_value == "Pitched, Unknown loft insulation": + # Unknown loft depth: U-value is the pitched age-band default. Assert the + # pitched shape (keeps `is_flat_roof`/`is_sloping_ceiling` False) and leave + # thickness None so the age-band overlay drives `_ROOF_BY_AGE` (ADR-0033). + return BuildingPartOverlay(roof_construction_type="Pitched") + if roof_type_value.startswith("Pitched, no insulation"): + # Genuinely uninsulated pitched roof → 2.30 (Table 16 row 0). Thickness 0 + # drives the calculator's thickness path and, unlike "Unknown", overrides + # any lodged numeric thickness (ADR-0033). Pitched text is load-bearing + # here — it does NOT take the age-band default (rdsap_uvalues §5.11 note). + return BuildingPartOverlay( + roof_construction_type="Pitched", roof_insulation_thickness=0 + ) + return None diff --git a/domain/epc/property_overlays/wall_type_overlay.py b/domain/epc/property_overlays/wall_type_overlay.py index 63ac6aa0..0620819c 100644 --- a/domain/epc/property_overlays/wall_type_overlay.py +++ b/domain/epc/property_overlays/wall_type_overlay.py @@ -34,8 +34,16 @@ _MATERIAL_CONSTRUCTION: dict[str, int] = { # RdSAP `wall_insulation_type` codes by insulation-state suffix # (domain/sap10_ml/rdsap_uvalues.py): external 1, filled-cavity 2, internal 3, # as-built/uninsulated 4, cavity+external 6, cavity+internal 7. +# All three "as built (assumed)" variants resolve to the same as-built code (4); +# the construction-age-band overlay supplies the U-value, so "partial" / "insulated" +# need no distinct code (ADR-0033, confirmed by the full A–M Elmhurst sweep in +# scripts/hyde/uvalue_probe_walls.csv — cavity As Built ≡ (CAVITY,0) by age band, +# e.g. band F → 1.0 = "partial"). The bare "as built" covers Cob / Park home. _STATE_INSULATION: dict[str, int] = { + "as built": 4, "as built, no insulation (assumed)": 4, + "as built, partial insulation (assumed)": 4, + "as built, insulated (assumed)": 4, "with internal insulation": 3, "with external insulation": 1, "filled cavity": 2, diff --git a/domain/modelling/simulation.py b/domain/modelling/simulation.py index caee5fb5..77ce2537 100644 --- a/domain/modelling/simulation.py +++ b/domain/modelling/simulation.py @@ -41,6 +41,12 @@ class BuildingPartOverlay: # IWI (`wall_insulation_type=3`); λ defaults to 0.04 W/m·K in the calculator. wall_insulation_thickness: Optional[int] = None roof_insulation_thickness: Optional[int] = None + # The roof shape string the calculator's flat-roof path keys on + # (`heat_transmission.py`: `"flat" in roof_construction_type`). Left `None` + # by Measures (insulating a roof doesn't change its shape); set by a Landlord + # Override that corrects a roof to flat so the `_FLAT_ROOF_BY_AGE` age-band + # default applies (ADR-0033). Folds onto the part via the generic field loop. + roof_construction_type: Optional[str] = None floor_insulation_thickness: Optional[int] = None floor_insulation_type_str: Optional[str] = None diff --git a/repositories/property/landlord_override_overlays.py b/repositories/property/landlord_override_overlays.py index 6c40d009..b65cf5d2 100644 --- a/repositories/property/landlord_override_overlays.py +++ b/repositories/property/landlord_override_overlays.py @@ -7,18 +7,23 @@ type — `domain/` never imports `repositories/`. Per-component and partial — an override produces an overlay only where a component mapping exists and the value resolves; anything else is left to the -lodged EPC. All four `override_component`s are mapped: +lodged EPC. Every `override_component` is mapped: * `wall_type` → fabric overlay (`wall_construction` + `wall_insulation_type`) -* `roof_type` → fabric overlay (`roof_insulation_thickness`, loft-depth family) +* `roof_type` → fabric overlay (`roof_insulation_thickness` / `roof_construction_type`) +* `construction_age_band` → per-part `construction_age_band` — the U-value lever + for the "as built / assumed / Unknown" fabric states (ADR-0033) * `property_type` / `built_form_type` → whole-dwelling categorical correction +* `main_fuel` / `glazing` / `water_heating` / `main_heating_system` → whole-dwelling -Two value families deliberately resolve to *no* overlay rather than a guess: the -`"(assumed) insulated"` / `"partial insulation (assumed)"` wall states (RdSAP -infers their U-value from the build-era age band, so there is no single -`wall_insulation_type` code for them — they need Elmhurst validation, ADR-0032), -and `"Unknown"` categorical values. Roofs with no clean loft depth (flat, -room-in-roof, "another premises above") likewise produce no overlay. +Since ADR-0033 the "as built (assumed)" wall states resolve to the as-built code +(4) and flat / pitched-Unknown / pitched-no-insulation roofs produce an overlay — +their U-value comes from the per-part `construction_age_band`, not a per-state +code. Values that still resolve to *no* overlay (left to the lodged EPC): bare +`"Unknown"` categoricals, party-ceiling roofs ("another/same dwelling above" — a +party ceiling has ≈0 heat loss), room-in-roof, and the residue logged in ADR-0033. +The `audit_override_coverage.py` / `audit_hyde_rows.py` pair reports exactly which +values are live vs no-op before any write. """ from __future__ import annotations diff --git a/scripts/hyde/build_property_overrides.py b/scripts/hyde/build_property_overrides.py index dc77b520..4a554586 100644 --- a/scripts/hyde/build_property_overrides.py +++ b/scripts/hyde/build_property_overrides.py @@ -111,6 +111,21 @@ logger = logging.getLogger("build_property_overrides") ORG_REF_COLUMN = "Organisation Reference" UNKNOWNS_PATH = "overrides_unknowns.csv" +# A "party ceiling" roof (another/same dwelling or premises above) means the +# dwelling has no exposed roof, which is only physically valid for a Flat or +# Maisonette. When the property type says House/Bungalow the two landlord fields +# contradict (a house has nothing above it). Per Khalim these may be houses split +# into flats — leave them entirely as-is for joint review, so we SKIP the whole +# property (write NO overrides for it) and record the org_refs for that review +# (ADR-0033; surfaced by scripts/hyde/audit_hyde_rows.py). +_PARTY_CEILING_ROOF_VALUES: frozenset[str] = frozenset({ + "(another dwelling above)", "(same dwelling above)", + "(other premises above)", "(another premises above)", + "Another Premises Above", +}) +_FLAT_PTYPE_PREFIXES: tuple[str, ...] = ("flat", "maisonette") +SKIPPED_PATH = "skipped_contradictory_properties.csv" + @dataclass(frozen=True) class ComponentSpec: @@ -330,15 +345,32 @@ def write(args: argparse.Namespace) -> None: org_ref_map = _org_ref_to_property_id(session, args.portfolio_id) logger.info("Portfolio %d: %d properties with org_ref.", args.portfolio_id, len(org_ref_map)) + ptype_header = _specs_by_component()["property_type"].excel_header + roof_header = _specs_by_component()["roof_type"].excel_header + roof_vocab = vocab.get("roof_type", {}) inserts: list[PropertyOverrideInsert] = [] unmatched: Counter[str] = Counter() unresolved: Counter[str] = Counter() + skipped: list[tuple[str, str, str]] = [] # (org_ref, property_type, roof) for row in rows: org_ref = str(row.get(ORG_REF_COLUMN, "")).strip() property_id = org_ref_map.get(org_ref) if property_id is None: unmatched[org_ref] += 1 continue + ptype_raw = str(row.get(ptype_header) or "").strip() + roof_raw = str(row.get(roof_header) or "").strip() + row_is_flat = ptype_raw.lower().startswith(_FLAT_PTYPE_PREFIXES) + roof_resolved = { + roof_vocab.get(_norm(e)) + for e in _split_entries(row.get(roof_header), True) + } + if not row_is_flat and roof_resolved & _PARTY_CEILING_ROOF_VALUES: + # Party-ceiling roof on a non-flat dwelling — contradictory source + # data (maybe a house split into flats). Leave the property fully + # as-is for joint review: write NO overrides, record it (see above). + skipped.append((org_ref, ptype_raw, roof_raw)) + continue for spec in _component_specs(): comp_vocab = vocab.get(spec.component, {}) for building_part, entry in enumerate( @@ -352,8 +384,18 @@ def write(args: argparse.Namespace) -> None: building_part=building_part, override_component=spec.component, override_value=value, original_spreadsheet_description=entry)) - logger.info("Built %d rows | %d unmatched org_refs | %d unresolved", - len(inserts), sum(unmatched.values()), sum(unresolved.values())) + logger.info("Built %d rows | %d unmatched org_refs | %d unresolved | " + "%d contradictory properties skipped (left as-is)", + len(inserts), sum(unmatched.values()), sum(unresolved.values()), + len(skipped)) + if skipped: + out = os.path.join(os.path.dirname(args.excel) or ".", SKIPPED_PATH) + with open(out, "w", newline="") as f: + w = csv.writer(f) + w.writerow(["org_ref", "property_type", "roof"]) + w.writerows(sorted(skipped)) + logger.info("Recorded %d skipped properties -> %s (for joint review)", + len(skipped), out) if unresolved: logger.info("Top unresolved (need apply-edits): %s", unresolved.most_common(10)) if not args.apply: diff --git a/scripts/hyde/elmhurst_lib.py b/scripts/hyde/elmhurst_lib.py index 088b7258..0336cca3 100644 --- a/scripts/hyde/elmhurst_lib.py +++ b/scripts/hyde/elmhurst_lib.py @@ -49,6 +49,7 @@ from __future__ import annotations import json import os +import re from contextlib import contextmanager from pathlib import Path from typing import Callable, Generator, Optional @@ -162,6 +163,30 @@ def set_select(page: Page, suffix: str, value: str, autopostback: bool = True) - loc.select_option(value) +def select_options(page: Page, suffix: str) -> list[tuple[str, str]]: + """Return [(value, visible_text), …] for the