mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
fixed filtering logic
This commit is contained in:
parent
1864cce8d1
commit
dce30edf00
3 changed files with 101 additions and 35 deletions
|
|
@ -25,6 +25,14 @@ type UpgradedAggregates = {
|
|||
total_funding: number | null;
|
||||
};
|
||||
|
||||
type PortfolioAggregates = {
|
||||
avg_sap: number | null;
|
||||
avg_carbon: number | null;
|
||||
avg_bills: number | null;
|
||||
total_carbon: number | null;
|
||||
total_bills: number | null;
|
||||
};
|
||||
|
||||
type EpcRow = {
|
||||
effective_sap: number | null;
|
||||
};
|
||||
|
|
@ -87,7 +95,7 @@ export async function GET(
|
|||
: null;
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
QUERY 1 — Scenario metrics (plans ONLY)
|
||||
QUERY 1 — Scenario metrics (PLANS ONLY)
|
||||
---------------------------------------------------------- */
|
||||
const scenarioMetricsResult = await db.execute(sql`
|
||||
WITH latest_plans AS (
|
||||
|
|
@ -124,19 +132,10 @@ export async function GET(
|
|||
JOIN property p ON p.id = lp.property_id;
|
||||
`);
|
||||
|
||||
const scenarioAgg = scenarioMetricsResult.rows[0] as
|
||||
| ScenarioAggregates
|
||||
| undefined;
|
||||
|
||||
if (!scenarioAgg) {
|
||||
return NextResponse.json(
|
||||
{ error: "No scenario metrics found" },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
const scenarioAgg = scenarioMetricsResult.rows[0] as ScenarioAggregates;
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
QUERY 1b — Upgrade costs (still plan-only)
|
||||
QUERY 1b — Upgrade costs (PLANS ONLY)
|
||||
---------------------------------------------------------- */
|
||||
const upgradedResult = await db.execute(sql`
|
||||
WITH latest_plans AS (
|
||||
|
|
@ -170,14 +169,78 @@ export async function GET(
|
|||
const upgraded = upgradedResult.rows[0] as UpgradedAggregates;
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
QUERY 2 — EPC distribution (ALL properties)
|
||||
★ This is the important new one
|
||||
QUERY 2 — Portfolio AFTER scenario (ALL properties)
|
||||
---------------------------------------------------------- */
|
||||
const portfolioMetricsResult = await db.execute(sql`
|
||||
SELECT
|
||||
AVG(effective_sap)::float AS avg_sap,
|
||||
AVG(effective_carbon)::float AS avg_carbon,
|
||||
AVG(effective_bills)::float AS avg_bills,
|
||||
SUM(effective_carbon)::float AS total_carbon,
|
||||
SUM(effective_bills)::float AS total_bills
|
||||
FROM (
|
||||
SELECT
|
||||
/* ---------- SAP ---------- */
|
||||
CASE
|
||||
WHEN lp.id IS NOT NULL THEN lp.post_sap_points
|
||||
ELSE p.current_sap_points
|
||||
END AS effective_sap,
|
||||
|
||||
/* ---------- Carbon ---------- */
|
||||
CASE
|
||||
WHEN lp.id IS NOT NULL THEN lp.post_co2_emissions
|
||||
ELSE e.co2_emissions
|
||||
END AS effective_carbon,
|
||||
|
||||
/* ---------- Bills ---------- */
|
||||
CASE
|
||||
WHEN lp.id IS NOT NULL THEN lp.post_energy_bill
|
||||
ELSE (
|
||||
e.heating_cost_current +
|
||||
e.hot_water_cost_current +
|
||||
e.lighting_cost_current +
|
||||
e.appliances_cost_current +
|
||||
e.gas_standing_charge +
|
||||
e.electricity_standing_charge -
|
||||
COALESCE(e.installed_measures_total_energy_bill_adjustment, 0)
|
||||
)
|
||||
END AS effective_bills
|
||||
|
||||
FROM property p
|
||||
LEFT JOIN property_details_epc e
|
||||
ON e.property_id = p.id
|
||||
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT *
|
||||
FROM plan
|
||||
WHERE plan.property_id = p.id
|
||||
AND plan.portfolio_id = ${pid}
|
||||
AND plan.scenario_id = ${sid}
|
||||
AND (
|
||||
${hideNonCompliant} = false
|
||||
OR (
|
||||
${minSap}::float IS NOT NULL
|
||||
AND plan.post_sap_points >= ${minSap}::float
|
||||
)
|
||||
)
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
) lp ON true
|
||||
|
||||
WHERE p.portfolio_id = ${pid}
|
||||
) q;
|
||||
`);
|
||||
|
||||
const portfolioAgg = portfolioMetricsResult.rows[0] as PortfolioAggregates;
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
QUERY 3 — EPC band distribution (ALL properties)
|
||||
---------------------------------------------------------- */
|
||||
const epcRows = await db.execute(sql`
|
||||
SELECT
|
||||
CASE
|
||||
WHEN lp.id IS NOT NULL THEN lp.post_sap_points
|
||||
ELSE COALESCE(p.current_sap_points, 0)
|
||||
ELSE p.current_sap_points
|
||||
END AS effective_sap
|
||||
FROM property p
|
||||
LEFT JOIN LATERAL (
|
||||
|
|
@ -218,30 +281,35 @@ export async function GET(
|
|||
/* ----------------------------------------------------------
|
||||
RESPONSE
|
||||
---------------------------------------------------------- */
|
||||
const pc_cost = (upgraded.total_cost ?? 0) * 0.3;
|
||||
|
||||
const constructionCost = upgraded.total_cost ?? 0;
|
||||
const nUpgraded = upgraded.n_units_upgraded ?? 0;
|
||||
const pc_cost = constructionCost * 0.3;
|
||||
|
||||
return NextResponse.json({
|
||||
/* -------- portfolio-after-scenario -------- */
|
||||
avg_sap:
|
||||
scenarioAgg.avg_sap !== null
|
||||
? Number(scenarioAgg.avg_sap).toFixed(1)
|
||||
portfolioAgg.avg_sap !== null
|
||||
? Number(portfolioAgg.avg_sap).toFixed(1)
|
||||
: null,
|
||||
avg_carbon: scenarioAgg.avg_carbon,
|
||||
avg_bills: scenarioAgg.avg_bills,
|
||||
total_carbon: scenarioAgg.total_carbon,
|
||||
total_bills: scenarioAgg.total_bills,
|
||||
n_units: scenarioAgg.n_units,
|
||||
scenario_epc_counts,
|
||||
pc_cost,
|
||||
avg_carbon: portfolioAgg.avg_carbon,
|
||||
avg_bills: portfolioAgg.avg_bills,
|
||||
total_carbon: portfolioAgg.total_carbon,
|
||||
total_bills: portfolioAgg.total_bills,
|
||||
|
||||
n_units_upgraded: upgraded.n_units_upgraded,
|
||||
construction_cost: upgraded.total_cost ?? 0,
|
||||
/* -------- scenario-only -------- */
|
||||
n_units: scenarioAgg.n_units,
|
||||
n_units_upgraded: nUpgraded,
|
||||
construction_cost: constructionCost,
|
||||
contingency: upgraded.contingency ?? 0,
|
||||
total_funding: upgraded.total_funding ?? 0,
|
||||
net_cost: (upgraded.total_cost ?? 0) - (upgraded.total_funding ?? 0),
|
||||
gross_per_unit:
|
||||
upgraded.n_units_upgraded > 0
|
||||
? ((upgraded.total_cost ?? 0) + pc_cost) / upgraded.n_units_upgraded
|
||||
: 0,
|
||||
net_cost: constructionCost - (upgraded.total_funding ?? 0),
|
||||
total_sap_uplift: scenarioAgg.total_sap_uplift ?? 0,
|
||||
gross_per_unit:
|
||||
nUpgraded > 0 ? (constructionCost + pc_cost) / nUpgraded : 0,
|
||||
|
||||
/* -------- shared -------- */
|
||||
scenario_epc_counts,
|
||||
pc_cost,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ export default async function ReportingPage(props: {
|
|||
]);
|
||||
const scenarios = await getScenarios(Number(portfolioId));
|
||||
|
||||
console.log("Baseline EPC counts", baseline.epcBands);
|
||||
|
||||
return (
|
||||
<div className="max-w-8xl mx-auto px-6 pb-10 space-y-4 pt-4">
|
||||
<div className="mb-6">
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export async function middleware(req: NextRequest) {
|
|||
|
||||
export const config = {
|
||||
matcher: [
|
||||
// Protect only your app’s authenticated areas
|
||||
// Protect only app’s authenticated areas
|
||||
"/home/:path*",
|
||||
"/portfolio/:path*",
|
||||
"/search/:path*",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue