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>
This commit is contained in:
Khalim Conn-Kowlessar 2026-06-17 01:00:31 +00:00
parent 6026944fe5
commit ef55c49e43
3 changed files with 9 additions and 15 deletions

View file

@ -65,7 +65,7 @@ export default async function DashboardLayout(props: {
decentHomes={decentHomes}
/>
</div>
{propertyMeta.detailsEpc.estimated && <EstimatedDataNotification />}
{propertyMeta.detailsEpc?.estimated && <EstimatedDataNotification />}
{children}
</div>
</section>

View file

@ -736,10 +736,11 @@ export async function getProperties(
AND pl.is_default = true
LEFT JOIN funding_package fp
ON fp.plan_id = pl.id
LEFT JOIN plan_recommendations pr
ON pr.plan_id = pl.id
-- Recommendations link to their plan via recommendation.plan_id (the
-- plan_recommendations join table is retired). Using plan_id is what makes
-- Plan Cost / recommendation SAP populate for new-approach properties.
LEFT JOIN recommendation r
ON r.id = pr.recommendation_id
ON r.plan_id = pl.id
AND r.default = true
AND r.already_installed = false
LEFT JOIN property_details_epc epc

View file

@ -342,22 +342,15 @@ export async function resolveConditionReport(
});
if (prop && isNewApproach(prop.updatedAt)) {
const resolved = await resolveNewConditionReport(id);
if (!resolved) {
throw new Error(
`No epc_property graph found for new-approach property ${propertyId}`,
);
}
return resolved;
// Degrade gracefully when the epc_property graph is missing — the screens
// render "Unknown" rather than 500ing.
return (await resolveNewConditionReport(id)) ?? legacyConditionReport({});
}
const legacy = await db.query.propertyDetailsEpc.findFirst({
where: eq(propertyDetailsEpc.propertyId, id),
});
if (!legacy) {
throw new Error(`No property_details_epc row for property ${propertyId}`);
}
return legacyConditionReport(legacy as Record<string, unknown>);
return legacyConditionReport((legacy ?? {}) as Record<string, unknown>);
}
/** The minimal EPC meta the `/api/property-meta` route embeds as `detailsEpc`. */