Skip to content

Commit

Permalink
fix community benefit and sharing costs, estimated revenue costs, cre…
Browse files Browse the repository at this point in the history
…dits issued plan
  • Loading branch information
alexeh committed Feb 7, 2025
1 parent b4dd3f4 commit 3e27ce5
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 17 deletions.
8 changes: 7 additions & 1 deletion api/src/modules/calculations/cost.calculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,14 +403,20 @@ export class CostCalculator {
});

const yearlyBreakdown: YearlyBreakdown[] = [];
// TODO: Double check prototype as some costs seem to not calculate totalCost and totalNPV
const costsWithNoNPV = [
'creditsIssuedPlan',
// 'cumulativeNetIncomePlan',
// 'cumulativeNetIncomeCapexOpex',
];
for (const costName in yearNormalizedCostPlans) {
const costValues = yearNormalizedCostPlans[costName];
const totalCost = sum(Object.values(costValues));
const totalNPV = this.calculateNpv(costValues, discountRate);
yearlyBreakdown.push({
costName: costName as YearlyBreakdownCostName,
totalCost,
totalNPV,
totalNPV: costsWithNoNPV.includes(costName) ? 0 : totalNPV,
costValues,
});
}
Expand Down
44 changes: 29 additions & 15 deletions api/src/modules/calculations/sequestration-rate.calculator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Injectable } from '@nestjs/common';
import { ProjectInput } from '@api/modules/calculations/cost.calculator';
import { ACTIVITY } from '@shared/entities/activity.enum';
import {
ACTIVITY,
RESTORATION_ACTIVITY_SUBTYPE,
} from '@shared/entities/activity.enum';
import { NonOverridableModelAssumptions } from '@api/modules/calculations/assumptions.repository';
import { AdditionalBaseData } from '@api/modules/calculations/data.repository';
import { CostPlanMap } from '@shared/dtos/custom-projects/custom-project-output.dto';
Expand Down Expand Up @@ -38,15 +41,15 @@ export class SequestrationRateCalculator {
}

calculateEstimatedCreditsIssuedPlan(): CostPlanMap {
const estCreditsIssuedPlan: { [year: number]: number } = {};
const estCreditsIssuedPlan: CostPlanMap = {};

for (let year = -1; year <= this.defaultProjectLength; year++) {
if (year !== 0) {
estCreditsIssuedPlan[year] = 0;
}
}

const netEmissionsReductions: { [year: number]: number } =
const netEmissionsReductions: CostPlanMap =
this.calculateNetEmissionsReductions();

for (const yearStr in estCreditsIssuedPlan) {
Expand Down Expand Up @@ -108,24 +111,33 @@ export class SequestrationRateCalculator {
return netEmissionReductionsPlan;
}

private _calculateRestorationEmissions(netEmissionReductionsPlan: {
[year: number]: number;
}): CostPlanMap {
const areaRestoredOrConservedPlan: { [year: number]: number } =
private _calculateRestorationEmissions(
netEmissionReductionsPlan: CostPlanMap,
): CostPlanMap {
const areaRestoredOrConservedPlan: CostPlanMap =
this.calculateAreaRestoredOrConserved();
const sequestrationRate: number = this.sequestrationRate;
let restorationActivity: RESTORATION_ACTIVITY_SUBTYPE;
if (this.projectInput instanceof RestorationProjectInput) {
restorationActivity = this.projectInput.restorationActivity;
}

for (const yearStr in netEmissionReductionsPlan) {
const year = Number(yearStr);
const sortedYears = Object.keys(netEmissionReductionsPlan)
.map(Number)
.sort((a, b) => a - b);

for (const year of sortedYears) {
if (year <= this.projectLength) {
if (year === -1) {
netEmissionReductionsPlan[year] = 0;
// } else if (this.projectInput.restoration_activity === 'Planting') {
// netEmissionReductionsPlan[year] = this._calculatePlantingEmissions(
// areaRestoredOrConservedPlan,
// sequestrationRate,
// year,
// );
} else if (
restorationActivity === RESTORATION_ACTIVITY_SUBTYPE.PLANTING
) {
netEmissionReductionsPlan[year] = this._calculatePlantingEmissions(
areaRestoredOrConservedPlan,
sequestrationRate,
year,
);
} else {
if (year === 1) {
netEmissionReductionsPlan[year] =
Expand Down Expand Up @@ -218,6 +230,8 @@ export class SequestrationRateCalculator {
cumulativeHaRestoredInYear[year] = 0;
}
}
// TODO: We could use a Map to ensure the order of the years
// This applies to all methods/parts that generate a CostPlanMap
const yearsInOrder = Object.keys(cumulativeHaRestoredInYear)
.map(Number)
.sort((a, b) => a - b);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ describe('Calculations Restoration', () => {
);
expect(estimatedRevenue).toBeCloseToObject(expectedEstimatedRevenue, 800);

// TODO: DOUBLE CHECK IF EXPECTED TOTAL NPV IS CORRECT
expect(creditsIssuedPlan).toBeCloseToObject(expectedCreditsIssuedPlan);
});
});
Expand Down

0 comments on commit 3e27ce5

Please sign in to comment.