Commit graph

1550 commits

Author SHA1 Message Date
Khalim Conn-Kowlessar
fec714a406 fix(property-meta): resolve in-process, drop self-fetch to process.env.URL
getPropertyMeta self-fetched process.env.URL + /api/property-meta. That URL can
resolve to a different deployment (e.g. production), so the building-passport
pages were reading property meta from OLD code — the backfilled headline SAP/EPC
never arrived and the current rating rendered blank, regardless of caching.

Extract resolvePropertyMeta() and call it directly from both the route and
getPropertyMeta, so the page runs identical in-process logic. JSON round-trip
through serializeBigInt preserves the previous shape (bigints/dates as strings).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:40:17 +00:00
Khalim Conn-Kowlessar
e1d56cc773 fix(building-passport): don't cache property-meta fetch
getPropertyMeta self-fetched /api/property-meta with revalidate:60 (despite a
comment saying it shouldn't cache). Vercel's Data Cache served a stale response
from before the headline backfill, so the current EPC rating / SAP rendered
blank on the plans and plan-detail pages even though the API now returns them.
Use cache:"no-store" so backfilled headline values propagate immediately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:31:38 +00:00
Khalim Conn-Kowlessar
a184127cd4 fix(plan-detail): read recommendations denormalised, not via plan_recommendations
getRecommendations read the retired plan_recommendations join table, which is
empty for new-approach plans, so the plan detail page showed no recommendations.
Read the recommendation table directly. Because recommendation.plan_id is
unindexed (26M rows), key off the plan's property_id (indexed) and filter
plan_id in memory — fast for any plan, default or not.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:25:41 +00:00
Khalim Conn-Kowlessar
5d87481b6b fix(plans): source headline SAP/EPC from baseline for new properties
The plans page computed the plan uplift as postSapPoints - currentSapPoints,
but current_sap_points is unwritten on the property row for new-approach
properties (null -> 0), so the uplift showed the full post score (e.g. +71.39)
and no current rating.

property-meta now backfills currentSapPoints / currentEpcRating from
property_baseline_performance (lodged_sap_score / lodged_epc_band) for
new-approach properties, fixing every propertyMeta consumer (plans page, hero
cards, building passport). e.g. 709634: current 60 (D), uplift now +11.39.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:20:49 +00:00
Khalim Conn-Kowlessar
14f06abb6d perf(properties): LATERAL lookups + recommendation by property_id
/api/properties timed out (15s) on just 12 properties: joining the 26M-row
recommendation table on the unindexed plan_id forced a full-table hash, and the
multi-million-row plan/funding joins compounded it.

Rewrite getProperties/getPropertiesCount to read the denormalised model (no
plan_recommendations / recommendation_materials): one-row LATERAL lookups for
target/plan/funding and a recommendation aggregate keyed by the INDEXED
recommendation.property_id, dropping the GROUP BY entirely. ~1s -> instant for a
12-property portfolio.

Also fix the reporting page for new-approach properties (current_sap_points /
current_epc_rating on the property row are unwritten): source avg SAP and the
EPC band distribution from property_baseline_performance (lodged_sap_score /
lodged_epc_band) via new sapSql / epcBandSql helpers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:07:09 +00:00
Khalim Conn-Kowlessar
f3e00429f9 fix(epc): source baseline carbon/energy/bills from lodged columns
Per domain semantics: lodged_* on property_baseline_performance is the
gov-registry (actual) figure, effective_* is the modelling-adjusted baseline.
Use the lodged columns for the "current" carbon/primary-energy display and the
individual cost columns (summed) for bills. Bills return NULL when no baseline
row exists, so they're excluded from AVG/SUM rather than shown as £0.

(property_baseline_performance is still unwritten DB-wide; this makes the reads
correct for when the pipeline populates it.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 01:07:00 +00:00
Khalim Conn-Kowlessar
ef55c49e43 fix(epc): tolerate absent EPC data + read recommendations via plan_id
For new-approach properties the modelling pipeline currently writes only
epc_property + epc_energy_element + plan/recommendation — property_baseline_
performance, epc_property_energy_performance metrics and the property-row
headline columns are not yet populated.

- layout: guard propertyMeta.detailsEpc?.estimated (detailsEpc can be absent)
- resolveConditionReport: degrade to an all-Unknown report instead of throwing
  when the EPC graph/legacy row is missing (no more 500s)
- getProperties: join recommendation via recommendation.plan_id instead of the
  retired plan_recommendations table, so Plan Cost / recommendation SAP populate

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 01:00:31 +00:00
Khalim Conn-Kowlessar
6026944fe5 feat(epc): read new EPC graph for new-approach properties via resolver
The new modelling pipeline no longer writes property_details_epc. Route all
EPC reads through src/lib/services/epcSources.ts, which branches on the cutoff
(property.updated_at >= 2026-06-01): legacy rows keep reading
property_details_epc; new-approach rows read epc_property (+ children),
property_baseline_performance, and plan/recommendation.

- per-property: resolveConditionReport (building passport),
  resolveDetailsEpcMeta (/api/property-meta)
- aggregates: shared carbon/bills/energy/estimated/expired/floor-area/
  lodgement/mainfuel SQL fragments + newApproachJoins, wired into the
  portfolio list + filters, reporting metrics, and both scenario metrics routes

estimated = predicted-only EPC. Gracefully omits gap fields for new
properties (mainfuel, energyTariff, floorHeight, installed-measures bill
adjustment, SAP-05 likely-downgrade).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:40:37 +00:00
Jun-te Kim
e606006e6b
Merge pull request #321 from Hestia-Homes/feature/epc-prediction-source-column
feat(db): add epc_property.source for predicted-EPC slot (ADR-0031)
2026-06-16 14:51:07 +01:00
Jun-te Kim
ae74133575 feat(db): add epc_property.source for predicted-EPC slot (ADR-0031)
Adds a `source` discriminator to `epc_property` so a property can hold a
lodged and a predicted EPC at the same time, per the EPC Prediction
production-wiring branch in the Model repo (docs/MIGRATION_NOTE_predicted_epc_source.md).

- `source` text NOT NULL default 'lodged' — backfills every existing row as
  a real lodged EPC.
- Unique index becomes (property_id, portfolio_id, source) so lodged +
  predicted rows can coexist for the same property/portfolio.
- New (property_id, source) index — lodged/predicted reads filter on both.

Allowed values: 'lodged' | 'predicted'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:46:19 +00:00
Daniel Roth
7feec70c98
Merge pull request #320 from Hestia-Homes/feature/document-viewing-settings
Fix expected file types unit tests
2026-06-15 14:43:31 +01:00
Daniel Roth
e3ee1480aa dont hardcode expected file count in tests 2026-06-15 13:42:03 +00:00
Daniel Roth
8e9e093def fix brokn unit tests 2026-06-15 13:38:01 +00:00
Daniel Roth
273932eb30
Merge pull request #318 from Hestia-Homes/feature/document-viewing-settings
Don't include PAR photopack in MIssing Documents list
2026-06-15 14:32:08 +01:00
Daniel Roth
86642de2a2 Don't include PAR photopack in MIssing Documents list 2026-06-15 13:06:28 +00:00
Daniel Roth
f0bb2b237a
Merge pull request #316 from Hestia-Homes/feature/new-cols-in-property-export
Additional columns in property export
2026-06-15 13:08:15 +01:00
Daniel Roth
2a9da6765b Switch EPC SAP (Potential) data source from epcSapScorePotential to potentialPostSapScoreDropdown 2026-06-15 11:57:39 +00:00
Daniel Roth
5ad99df044 correct typo 2026-06-15 09:54:15 +00:00
Daniel Roth
32bb2e39ef Merge branch 'main' into feature/new-cols-in-property-export 2026-06-15 09:50:16 +00:00
Daniel Roth
c72b7c1625 Add coordination comments, damp/mould, and Domna survey columns to property table and CSV export
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 09:48:41 +00:00
Daniel Roth
2b380d83d8
Merge pull request #315 from Hestia-Homes/remove-duplicate-hs-col
Remove "osmosis_survey_required" column as it is already in the db as "domna_survey_required"
2026-06-15 10:21:10 +01:00
Daniel Roth
10f7d4c188 migration 2026-06-15 08:59:46 +00:00
Daniel Roth
db0b3670f4 delete col 2026-06-15 08:59:24 +00:00
Daniel Roth
462cd36c3f
Merge pull request #314 from Hestia-Homes/feature/new-hs-deal-cols
Add "osmosis_survey_required" to hs deal table
2026-06-15 09:57:10 +01:00
Daniel Roth
954fb5b16e migration 2026-06-15 08:52:41 +00:00
Daniel Roth
a3ee12a418 osmosis_survey_required column 2026-06-15 08:50:41 +00:00
Daniel Roth
4ea1fa48d4
Merge pull request #313 from Hestia-Homes/feature/hs-last_submission_date
last_submission_date column on hubspot deals table
2026-06-11 10:59:06 +01:00
Daniel Roth
3425dae3cc migration files 2026-06-10 14:25:37 +00:00
Daniel Roth
a5e07ffa1c add last_submission_date to hs deal table 2026-06-10 14:23:55 +00:00
Jun-te Kim
23a275ae85
Merge pull request #312 from Hestia-Homes/feature/new-file-type-and-source-for-audits
New file type and source for audits
2026-06-09 15:21:39 +01:00
Daniel Roth
2e9ec32c48 migration files 2026-06-09 13:57:31 +00:00
Daniel Roth
de963bbc39 add file type and file source 2026-06-09 13:56:52 +00:00
Jun-te Kim
d0d5ec0366
Merge pull request #310 from Hestia-Homes/feature/frontend_landlord_overrides
Feature/frontend landlord overrides
2026-06-08 16:23:21 +01:00
Jun-te Kim
c6091af34c
Merge pull request #311 from Hestia-Homes/feature/additional_hubspot_proeprties
Feature/additional hubspot proeprties
2026-06-08 16:12:18 +01:00
Jun-te Kim
c2b7e00075 new table for new deal proeprties we want 2026-06-08 14:42:50 +00:00
Jun-te Kim
e974aef858 dynamic file tree 2026-06-08 14:08:48 +00:00
Jun-te Kim
cc134f8ce9
Merge branch 'main' into feature/frontend_landlord_overrides 2026-06-08 14:00:20 +01:00
Daniel Roth
974a5e5ef5
Merge pull request #309 from Hestia-Homes/feature/magicplan-ventilation-tables
New tables for magicplan ventilation and move opening type to window ventilation table
2026-06-08 13:23:41 +01:00
Daniel Roth
7e2be3efbd Merge branch 'main' into feature/magicplan-ventilation-tables 2026-06-08 12:21:22 +00:00
Daniel Roth
f1f48cf851
Merge pull request #308 from Hestia-Homes/feature/efficient-recommendation-backfill
Make recommendation denormalisation backfill safe and online
2026-06-08 13:20:53 +01:00
Jun-te Kim
567c3f59c5 settings .local.json updated 2026-06-08 12:01:13 +00:00
Jun-te Kim
b5d0de4069 Merge remote-tracking branch 'refs/remotes/origin/feature/frontend_landlord_overrides' into feature/frontend_landlord_overrides 2026-06-08 09:45:42 +00:00
Jun-te Kim
30d3e727d1 route of the address2uprn problem of float value 2026-06-08 09:38:48 +00:00
Jun-te Kim
f6545c2fa0 property override 2026-06-08 09:38:48 +00:00
Jun-te Kim
744bfa2287 Add v2 handover doc for property_overrides population
Self-contained brief to start a fresh context implementing the per-Property fact
layer in the bulk_upload_finaliser: locked decisions, the four-input assembly,
the two open hazards (classifier-CSV↔combiner-output join key; property_id for
no-UPRN rows), candidate architectures, and a first-steps list. v1 (async
finalise writing `property`) is shipped and working.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:38:48 +00:00
Jun-te Kim
b9bbd916b5 Render finalising status on the bulk-upload page and auto-advance to complete
The async finaliser (ADR-0005) introduced the `finalising` status, but the
server page's STATUS_CONFIG had no entry for it, so it fell through to the
`ready_for_processing` fallback ("Awaiting column mapping") and never mounted the
live poller — the page looked stuck even though the Lambda had inserted the
properties and written `complete`.

- Add the `finalising` card ("Uploading to ARA") to STATUS_CONFIG.
- Render OnboardingProgress during `finalising` so it polls live.
- Refresh the server page once when the poll first sees a terminal status
  (guarded by a new `serverStatus` prop to avoid a loop; uses react-query v4
  onSuccess, no useEffect) so it advances to the "Processing complete" card.
- Add a `finalising` → "Uploading to ARA" badge on the uploads list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:38:48 +00:00
Jun-te Kim
87aca96dfa bulk upload finaliser 2026-06-08 09:38:48 +00:00
Jun-te Kim
dff86b1ec2 save current progress 2026-06-08 09:38:48 +00:00
Jun-te Kim
22375e1746 Add Step 1 "Verify classification" to bulk-upload review (ADR-0004)
For uploads with classifier columns, surface the classifier's
description→enum assumptions on the awaiting_review screen so the user can
correct any (written source='user') and acknowledge before Finalise.
Previously only the multi-entry order step existed, so non-multi-entry
uploads got no classification review at all and the assumptions were
applied silently.

- detectMultiEntry: capture a sample whenever classifier columns are
  mapped (largest-count row if multi-entry, else first classified row);
  the sample now carries all classifier columns. "sample != null" means
  "there is something to verify"; largestCount >= 2 stays the multi-entry
  signal.
- setVerifyAck + verify-classification PATCH route + useConfirmVerification.
- VerifyClassificationPanel (Step 1); MultiEntryOrderingPanel slimmed to
  order-only with read-only classification annotation; canFinalize gated
  on both steps where each applies.
- Unit tests for detectMultiEntry + ordering helpers.

The verify_ack column + 0219 migration landed separately via #303.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 09:38:48 +00:00
Jun-te Kim
c9b7d71843 Show + edit sample classifications on awaiting_review (#298, #299)
#298: read the classifier's resolved enums for the multi-entry sample's
entries (joined from landlord_*_overrides by normalized description) and show
each beside the raw text, or "not classified" when absent.

#299: make each classification editable — a dropdown of the category's valid
enum values whose selection upserts the override by (portfolio, description)
with source='user', so the classifier never re-clobbers it. UI notes the
portfolio-wide blast radius. Verification ack is folded into the existing
order-confirm (no separate flag/migration); editing is optional review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 09:38:48 +00:00