diff --git a/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts b/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts index 5a39372..e4f4157 100644 --- a/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts +++ b/src/app/api/portfolio/[portfolioId]/scenario/[scenarioId]/metrics/route.ts @@ -10,6 +10,7 @@ type BaselineAggregates = { avg_bills: number | null; total_carbon: number | null; total_bills: number | null; + total_sap_uplift: number | null; sap_points_array: (number | null)[]; }; @@ -35,26 +36,39 @@ export async function GET( // const baselineResult = await db.execute(sql` WITH latest_plans AS ( - SELECT DISTINCT ON (property_id) - * - FROM plan - WHERE portfolio_id = ${pid} - AND scenario_id = ${sid} - ORDER BY property_id, created_at DESC - ) + SELECT DISTINCT ON (property_id) + * + FROM plan + WHERE portfolio_id = ${pid} + AND scenario_id = ${sid} + ORDER BY property_id, created_at DESC +) - SELECT - COUNT(*)::int AS n_units, +SELECT + COUNT(*)::int AS n_units, - AVG(post_sap_points)::float AS avg_sap, - AVG(post_co2_emissions)::float AS avg_carbon, - AVG(post_energy_bill)::float AS avg_bills, + AVG(lp.post_sap_points)::float AS avg_sap, + AVG(lp.post_co2_emissions)::float AS avg_carbon, + AVG(lp.post_energy_bill)::float AS avg_bills, - SUM(post_co2_emissions)::float AS total_carbon, - SUM(post_energy_bill)::float AS total_bills, + SUM(lp.post_co2_emissions)::float AS total_carbon, + SUM(lp.post_energy_bill)::float AS total_bills, - ARRAY_AGG(post_sap_points) AS sap_points_array - FROM latest_plans; + SUM( + CASE + WHEN lp.cost_of_works > 0.01 + AND p.current_sap_points IS NOT NULL + AND lp.post_sap_points IS NOT NULL + THEN lp.post_sap_points - p.current_sap_points + ELSE 0 + END + )::float AS total_sap_uplift, + + ARRAY_AGG(lp.post_sap_points) AS sap_points_array + +FROM latest_plans lp +JOIN property p + ON p.id = lp.property_id; `); const baseline = baselineResult.rows[0] as BaselineAggregates | undefined; @@ -114,6 +128,7 @@ export async function GET( const total_funding = upgraded.total_funding ?? 0; const net_cost = construction_cost - total_funding; const pc_cost = construction_cost * 0.3; // Placeholder for PC cost + const total_sap_uplift = baseline.total_sap_uplift ?? 0; // // ---------------------------------------------------------- @@ -161,5 +176,6 @@ export async function GET( n_units_upgraded > 0 ? (construction_cost + pc_cost) / n_units_upgraded : 0, + total_sap_uplift, }); } diff --git a/src/app/portfolio/[slug]/(portfolio)/reporting/BreakdownChart.tsx b/src/app/portfolio/[slug]/(portfolio)/reporting/BreakdownChart.tsx index ea0c5da..173e3c7 100644 --- a/src/app/portfolio/[slug]/(portfolio)/reporting/BreakdownChart.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/reporting/BreakdownChart.tsx @@ -57,7 +57,7 @@ export function BreakdownChart({ // Baseline (stacked) rows.push({ - label: `${epc} (baseline)`, + label: `${epc}`, [friendlyKeys.actual]: d.actual ?? 0, [friendlyKeys.estimated]: d.estimated ?? 0, [friendlyKeys.scenario]: 0, @@ -114,6 +114,7 @@ export function BreakdownChart({ stack={selected === "epc"} customTooltip={MyTooltip} className="h-64" + showGridLines={false} /> diff --git a/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx b/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx index 64268d1..509493c 100644 --- a/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/reporting/ReportingClientArea.tsx @@ -144,6 +144,7 @@ export function ReportingClientArea({ // ---------------------------------------- // Scenario specific metrics that appear in the drawer (from API) and cannot be overlayed on baseline // ---------------------------------------- + const scenarioSpecific = scenarioData ? { constructionCost: scenarioData.construction_cost, @@ -151,14 +152,14 @@ export function ReportingClientArea({ contingency: scenarioData.contingency, funding: scenarioData.total_funding, costPerSap: - scenarioData.construction_cost > 0 - ? scenarioData.gross_per_unit / - (scenarioData.avg_sap - (baseline.averages.avg_sap ?? 0)) + scenarioData.total_sap_uplift && scenarioData.total_sap_uplift > 0 + ? (scenarioData.construction_cost + scenarioData.pc_cost) / + scenarioData.total_sap_uplift : 0, costPerCo2: scenarioData.construction_cost > 0 ? (scenarioData.construction_cost + scenarioData.pc_cost) / - scenarioData.total_carbon + ((baseline.totals.total_carbon ?? 0) - scenarioData.total_carbon) : 0, netCost: scenarioData.net_cost, grossPerUnit: scenarioData.gross_per_unit, diff --git a/src/app/portfolio/[slug]/utils.ts b/src/app/portfolio/[slug]/utils.ts index 9850739..76cbc2e 100644 --- a/src/app/portfolio/[slug]/utils.ts +++ b/src/app/portfolio/[slug]/utils.ts @@ -449,6 +449,7 @@ export async function getProperties( LEFT JOIN recommendation r ON r.id = pr.recommendation_id AND r.default = true + and r.already_installed = false WHERE p.portfolio_id = ${portfolioId} GROUP BY p.id,