diff --git a/api/src/modules/calculations/assumptions.repository.ts b/api/src/modules/calculations/assumptions.repository.ts index 173fbf8a..c0ea68f0 100644 --- a/api/src/modules/calculations/assumptions.repository.ts +++ b/api/src/modules/calculations/assumptions.repository.ts @@ -6,8 +6,37 @@ import { GetOverridableAssumptionsDTO } from '@shared/dtos/custom-projects/get-o import { ACTIVITY } from '@shared/entities/activity.enum'; import { ECOSYSTEM } from '@shared/entities/ecosystem.enum'; +export enum ECOSYSTEM_RESTORATION_RATE_NAMES { + MANGROVE = 'Mangrove restoration rate', + SEAGRASS = 'Seagrass restoration rate', + SALT_MARSH = 'Salt marsh restoration rate', +} + +export enum ACTIVITY_PROJECT_LENGTH_NAMES { + CONSERVATION = 'Conservation project length', + RESTORATION = 'Restoration project length', +} + +export const COMMON_OVERRIDABLE_ASSUMPTION_NAMES = [ + 'Baseline reassessment frequency', + 'Buffer', + 'Carbon price increase', + 'Discount rate', + 'Verification frequency', +] as const; + @Injectable() export class AssumptionsRepository extends Repository { + map: Record< + ACTIVITY & ECOSYSTEM, + ECOSYSTEM_RESTORATION_RATE_NAMES & ACTIVITY_PROJECT_LENGTH_NAMES + > = { + [ACTIVITY.CONSERVATION]: ACTIVITY_PROJECT_LENGTH_NAMES.CONSERVATION, + [ACTIVITY.RESTORATION]: ACTIVITY_PROJECT_LENGTH_NAMES.RESTORATION, + [ECOSYSTEM.MANGROVE]: ECOSYSTEM_RESTORATION_RATE_NAMES.MANGROVE, + [ECOSYSTEM.SEAGRASS]: ECOSYSTEM_RESTORATION_RATE_NAMES.SEAGRASS, + [ECOSYSTEM.SALT_MARSH]: ECOSYSTEM_RESTORATION_RATE_NAMES.SALT_MARSH, + }; constructor( @InjectRepository(ModelAssumptions) private repo: Repository, @@ -16,44 +45,27 @@ export class AssumptionsRepository extends Repository { } async getOverridableModelAssumptions(dto: GetOverridableAssumptionsDTO) { - const queryBuilder = this.createQueryBuilder('assumptions') + const assumptions = await this.createQueryBuilder('model_assumptions') .select(['name', 'unit', 'value']) .where({ - name: In([ - 'Verification frequency', - 'Baseline reassessment frequency', - 'Carbon price increase', - 'Buffer', - 'Discount rate', - ]), - }); - - if (dto.activity === ACTIVITY.CONSERVATION) { - queryBuilder.andWhere('name = :activity', { - activity: 'Conservation project length', - }); - } - if (dto.activity === ACTIVITY.RESTORATION) { - queryBuilder.andWhere('name = :activity', { - activity: 'Restoration project length', - }); + name: In(this.getAssumptionNamesByCountryAndEcosystem(dto)), + }) + .orderBy('name', 'ASC') + .getRawMany(); + if (assumptions.length !== 7) { + throw new Error('Not all required overridable assumptions were found'); } + return assumptions; + } - if (dto.ecosystem === ECOSYSTEM.MANGROVE) { - queryBuilder.andWhere('name = :ecosystem', { - ecosystem: 'Mangrove restoration rate', - }); - } - if (dto.ecosystem === ECOSYSTEM.SEAGRASS) { - queryBuilder.andWhere('name = :ecosystem', { - ecosystem: 'Seagrass restoration rate', - }); - } - if (dto.ecosystem === ECOSYSTEM.SALT_MARSH) { - queryBuilder.andWhere('name = :ecosystem', { - ecosystem: 'Salt marsh restoration rate', - }); - } + private getAssumptionNamesByCountryAndEcosystem( + dto: GetOverridableAssumptionsDTO, + ): string[] { + const { ecosystem, activity } = dto; + const assumptions = [...COMMON_OVERRIDABLE_ASSUMPTION_NAMES] as string[]; + assumptions.push(this.map[ecosystem]); + assumptions.push(this.map[activity]); + return assumptions; } async getAllModelAssumptions() { diff --git a/api/src/modules/calculations/data.repository.ts b/api/src/modules/calculations/data.repository.ts index 7d1a6e31..85f53555 100644 --- a/api/src/modules/calculations/data.repository.ts +++ b/api/src/modules/calculations/data.repository.ts @@ -23,7 +23,6 @@ export type CarbonInputs = { export class DataRepository extends Repository { constructor( @InjectRepository(BaseDataView) private repo: Repository, - private readonly assumptionsRepository: AssumptionsRepository, ) { super(repo.target, repo.manager, repo.queryRunner); } diff --git a/api/test/integration/custom-projects/custom-projects-setup.spec.ts b/api/test/integration/custom-projects/custom-projects-setup.spec.ts index 4d2845db..3ad14150 100644 --- a/api/test/integration/custom-projects/custom-projects-setup.spec.ts +++ b/api/test/integration/custom-projects/custom-projects-setup.spec.ts @@ -2,6 +2,10 @@ import { TestManager } from '../../utils/test-manager'; import { customProjectContract } from '@shared/contracts/custom-projects.contract'; import { ECOSYSTEM } from '@shared/entities/ecosystem.enum'; import { ACTIVITY } from '@shared/entities/activity.enum'; +import { + ACTIVITY_PROJECT_LENGTH_NAMES, + ECOSYSTEM_RESTORATION_RATE_NAMES, +} from '@api/modules/calculations/assumptions.repository'; describe('Create Custom Projects - Setup', () => { let testManager: TestManager; @@ -20,6 +24,31 @@ describe('Create Custom Projects - Setup', () => { await testManager.close(); }); + describe('Get Overridable Model Assumptions', () => { + test('Should return overridable model assumptions based on ecosystem and activity', async () => { + const response = await testManager + .request() + .get(customProjectContract.getDefaultAssumptions.path) + .query({ + ecosystem: ECOSYSTEM.MANGROVE, + activity: ACTIVITY.CONSERVATION, + }); + + expect(response.body.data).toHaveLength(7); + expect(response.body.data.map((assumptions) => assumptions.name)).toEqual( + [ + 'Baseline reassessment frequency', + 'Buffer', + 'Carbon price increase', + 'Conservation project length', + 'Discount rate', + 'Mangrove restoration rate', + 'Verification frequency', + ], + ); + }); + }); + test('Should return the list of countries that are available to create a custom project', async () => { const response = await testManager .request() @@ -27,13 +56,6 @@ describe('Create Custom Projects - Setup', () => { expect(response.body.data).toHaveLength(9); }); - test('Should return default model assumptions', async () => { - const response = await testManager - .request() - .get(customProjectContract.getDefaultAssumptions.path); - - expect(response.body.data).toHaveLength(18); - }); test('Should return default cost inputs given required filters', async () => { const response = await testManager