# Elmhurst RdSAP entry-tool automation (POC) Automates most of the one manual step in `validate-cert-sap-accuracy`: re-keying `elmhurst_inputs.md` into Elmhurst's web RdSAP entry tool and exporting the **Input Summary** + **SAP Worksheets** PDFs (which `compare_epc_paths.py` then consumes). Built on Playwright (Python). Proven end-to-end on UPRN 10092973954: filled most pages automatically, downloaded both PDFs, and `compare_epc_paths.py` reconciled to **our engine 77 vs Elmhurst worksheet 78** (engine-on-Elmhurst-inputs 79 — the calculator reproduces accredited Elmhurst within ~1 SAP on identical inputs). ## Scripts | Script | Does | |---|---| | `start_viewer.sh` | Xvfb→x11vnc→noVNC desktop on **port 6080** so you can SEE/click the headed browser (`DISPLAY=:99`). `bash scripts/hyde/start_viewer.sh` | | `elmhurst_session.py` | `login` / `open` / `status` — persistent login (MFA by hand once; session in `.elmhurst-session/`, gitignored) | | `elmhurst_explore.py` | dump a page's DOM (field ids, options, autopostback) or `--all` sections — how specs are built | | `elmhurst_fill.py` | `--page [--commit] [--commit-mode saveclose\|next]` — fill/clear a page from its `PageSpec` | | `elmhurst_download.py` | downloads Input Summary + SAP Worksheets → the cert's corpus dir. **Never clicks Submit** (code-enforced) | Typical run (browser appears on the noVNC desktop at port 6080): ```bash bash scripts/hyde/start_viewer.sh DISPLAY=:99 python scripts/hyde/elmhurst_session.py login --url https://members.elmhurstenergy.co.uk/ DISPLAY=:99 python scripts/hyde/elmhurst_fill.py --page property_description --commit DISPLAY=:99 python scripts/hyde/elmhurst_download.py ``` ## Hard-won mechanics (ASP.NET WebForms) - Enter via the Guid URL (`…online…/WebFormAddress.aspx?Guid=…`); section nav is full-form `__doPostBack` to a Guid-less subdomain — use `expect_navigation`. - **Almost every field AutoPostBacks** (whole-page reload): set one field, wait, re-locate the next. A 600 ms settle after each interaction stops flake. - **Never re-click the active tab** (double-postback misbehaves) — `goto_section` is current-page-aware. - **Navigating away saves**; **Save & Close commits to the DATABASE** (visible to other sessions). Next > only saves the in-progress session. - Fields **auto-disable** when an upstream choice removes them (Room-in-Roof once no room-in-roof; cylinder once combi) — skip them, don't fight them. - Button ids vary per page → match by id suffix (`[id$='_ButtonSaveClose']`). - Setup (done in container): `python -m playwright install chromium` + `sudo python -m playwright install-deps chromium`. ## What's automated vs manual **Automated** (in `PAGES` + special actions): Property Description, Dimensions, Flats (position/floor/corridor), Walls (main + clear alt-wall), Roofs, Floors, Space Heating (**boiler** via the cascade dialog → BGW combi, flue, secondary), Water Heating (code; cylinder auto-clears with the combi), New Tech/Conservatory (none) — plus the consolidated **clears** from the markdown. The **boiler cascade dialog** is driven by `select_boiler_combi()`: open the Main-Heating-code modal, set the leaf dropdown to *BGW Post 98 Combi condens.*, click OK. The generic combi (SAP 104) moves SAP by ~0 vs the cert's exact PCDB model, so it's accurate enough. **Manual (🔸):** - **Exact PCDB boiler model** (e.g. 17929) — its search field is *disabled* (`aspNetDisabled`) in this UI state; the cascade's generic combi is the automatable substitute (negligible SAP impact). - **Control code 2110** and the **MV unit** — same modal-dialog pattern; can be automated the same way as the boiler when wanted (open dialog → select → OK). All 🔸 fields are flagged in `elmhurst_inputs.md`. ## Adding a field/page 1. `elmhurst_explore.py _Link>` to dump ids/options. 2. Add a `Field(...)` (or new `PageSpec`) in `elmhurst_fill.py`. 3. `--page ` (dry-run, screenshots to `elmhurst_dom/fill_.png`), verify, then `--commit`.