diff --git a/.gitignore b/.gitignore index 033fe1e2..e7f878d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# adminjs +.adminjs/ + # Logs logs *.log diff --git a/admin/datasource.ts b/admin/datasource.ts index d781153e..642c051f 100644 --- a/admin/datasource.ts +++ b/admin/datasource.ts @@ -2,37 +2,36 @@ import { DataSource } from "typeorm"; import { User } from "@shared/entities/users/user.entity.js"; import { ApiEventsEntity } from "@api/modules/api-events/api-events.entity.js"; import { Country } from "@shared/entities/country.entity.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { ProjectSize } from "@shared/entities/project-size.entity.js"; -import { FeasibilityAnalysis } from "@shared/entities/feasability-analysis.entity.js"; -import { ConservationPlanningAndAdmin } from "@shared/entities/conservation-and-planning-admin.entity.js"; -import { DataCollectionAndFieldCosts } from "@shared/entities/data-collection-and-field-costs.entity.js"; -import { CarbonStandardFees } from "@shared/entities/carbon-standard-fees.entity.js"; -import { CommunityBenefitSharingFund } from "@shared/entities/community-benefit-sharing-fund.entity.js"; -import { CommunityCashFlow } from "@shared/entities/community-cash-flow.entity.js"; -import { CommunityRepresentation } from "@shared/entities/community-representation.entity.js"; -import { EcosystemLoss } from "@shared/entities/ecosystem-loss.entity.js"; -import { CarbonRights } from "@shared/entities/establishing-carbon-rights.entity.js"; -import { FinancingCost } from "@shared/entities/financing-cost.entity.js"; -import { ImplementationLaborCost } from "@shared/entities/implementation-labor.entity.js"; -import { Maintenance } from "@shared/entities/maintenance.entity.js"; -import { MonitoringCost } from "@shared/entities/monitoring.entity.js"; -import { RestorableLand } from "@shared/entities/restorable-land.entity.js"; -import { ValidationCost } from "@shared/entities/validation.entity.js"; -import { BaselineReassessment } from "@shared/entities/baseline-reassessment.entity.js"; -import { BlueCarbonProjectPlanning } from "@shared/entities/blue-carbon-project-planning.entity.js"; -import { EmissionFactors } from "@shared/entities/emission-factors.entity.js"; -import { LongTermProjectOperating } from "@shared/entities/long-term-project-operating.entity.js"; -import { MRV } from "@shared/entities/mrv.entity.js"; -import { SequestrationRate } from "@shared/entities/sequestration-rate.entity.js"; import { Project } from "@shared/entities/projects.entity.js"; +import { EcosystemExtent } from "@shared/entities/carbon-inputs/ecosystem-extent.entity.js"; +import { EcosystemLoss } from "@shared/entities/carbon-inputs/ecosystem-loss.entity.js"; +import { EmissionFactors } from "@shared/entities/carbon-inputs/emission-factors.entity.js"; +import { RestorableLand } from "@shared/entities/carbon-inputs/restorable-land.entity.js"; +import { SequestrationRate } from "@shared/entities/carbon-inputs/sequestration-rate.entity.js"; +import { BaselineReassessment } from "@shared/entities/cost-inputs/baseline-reassessment.entity.js"; +import { BlueCarbonProjectPlanning } from "@shared/entities/cost-inputs/blue-carbon-project-planning.entity.js"; +import { CarbonStandardFees } from "@shared/entities/cost-inputs/carbon-standard-fees.entity.js"; +import { CommunityBenefitSharingFund } from "@shared/entities/cost-inputs/community-benefit-sharing-fund.entity.js"; +import { CommunityCashFlow } from "@shared/entities/cost-inputs/community-cash-flow.entity.js"; +import { CommunityRepresentation } from "@shared/entities/cost-inputs/community-representation.entity.js"; +import { ConservationPlanningAndAdmin } from "@shared/entities/cost-inputs/conservation-and-planning-admin.entity.js"; +import { DataCollectionAndFieldCosts } from "@shared/entities/cost-inputs/data-collection-and-field-costs.entity.js"; +import { CarbonRights } from "@shared/entities/cost-inputs/establishing-carbon-rights.entity.js"; +import { FeasibilityAnalysis } from "@shared/entities/cost-inputs/feasability-analysis.entity.js"; +import { FinancingCost } from "@shared/entities/cost-inputs/financing-cost.entity.js"; +import { LongTermProjectOperating } from "@shared/entities/cost-inputs/long-term-project-operating.entity.js"; +import { Maintenance } from "@shared/entities/cost-inputs/maintenance.entity.js"; +import { MonitoringCost } from "@shared/entities/cost-inputs/monitoring.entity.js"; +import { MRV } from "@shared/entities/cost-inputs/mrv.entity.js"; +import { ProjectSize } from "@shared/entities/cost-inputs/project-size.entity.js"; +import { ValidationCost } from "@shared/entities/cost-inputs/validation.entity.js"; +import { ImplementationLaborCost } from "@shared/entities/cost-inputs/implementation-labor-cost.entity.js"; // TODO: If we import the COMMON_DATABASE_ENTITIES from shared, we get an error where DataSouce is not set for a given entity export const ADMINJS_ENTITIES = [ User, ApiEventsEntity, Country, - BaseData, ProjectSize, FeasibilityAnalysis, ConservationPlanningAndAdmin, @@ -44,7 +43,6 @@ export const ADMINJS_ENTITIES = [ EcosystemLoss, CarbonRights, FinancingCost, - ImplementationLaborCost, Maintenance, MonitoringCost, RestorableLand, @@ -55,7 +53,9 @@ export const ADMINJS_ENTITIES = [ LongTermProjectOperating, MRV, SequestrationRate, + EcosystemExtent, Project, + ImplementationLaborCost, ]; export const dataSource = new DataSource({ diff --git a/admin/index.ts b/admin/index.ts index 8b0983fd..a7458beb 100644 --- a/admin/index.ts +++ b/admin/index.ts @@ -6,7 +6,6 @@ import * as AdminJSTypeorm from "@adminjs/typeorm"; import { dataSource } from "./datasource.js"; import { AuthProvider } from "./providers/auth.provider.js"; import { UserResource } from "./resources/users/user.resource.js"; -import { ProjectSizeResource } from "./resources/project-size/project-size.resource.js"; import { Country } from "@shared/entities/country.entity.js"; import { FeasibilityAnalysisResource } from "./resources/feasability-analysis/feasability-analysis.resource.js"; import { ConservationAndPlanningAdminResource } from "./resources/conservation-and-planning-admin/conservation-and-planning-admin.resource.js"; @@ -14,7 +13,6 @@ import { CommunityRepresentationResource } from "./resources/community-represent import { CarbonRightsResource } from "./resources/carbon-righs/carbon-rights.resource.js"; import { FinancingCostResource } from "./resources/financing-cost/financing-cost.resource.js"; import { ValidationCostResource } from "./resources/validation-cost/validation-cost.resource.js"; -import { ImplementationLaborCostResource } from "./resources/implementation-labor/implementation-labor-cost.resource.js"; import { MonitoringCostResource } from "./resources/monitoring-cost/monitoring-cost.resource.js"; import { MaintenanceResource } from "./resources/maintenance/maintenance.resource.js"; import { DataCollectionAndFieldCostResource } from "./resources/data-collection-and-field-cost/data-collection-and-field-cost.resource.js"; @@ -30,6 +28,8 @@ import { BlueCarbonProjectPlanningResource } from "./resources/blue-carbon-proje import { LongTermProjectOperatingResource } from "./resources/long-term-project-operating/long-term-project-operating.resource.js"; import { SequestrationRateResource } from "./resources/sequestration-rate/sequestration-rate.resource.js"; import { ProjectsResource } from "./resources/projects/projects.resource.js"; +import { ProjectSizeResource } from "./resources/project-size/project-size.resource.js"; +import { ImplementationLaborCostResource } from "./resources/implementation-labor-cost/implementation-labor-cost.resource.js"; AdminJS.registerAdapter({ Database: AdminJSTypeorm.Database, @@ -63,7 +63,6 @@ const start = async () => { CarbonRightsResource, FinancingCostResource, ValidationCostResource, - ImplementationLaborCostResource, MonitoringCostResource, MaintenanceResource, DataCollectionAndFieldCostResource, @@ -79,6 +78,7 @@ const start = async () => { LongTermProjectOperatingResource, SequestrationRateResource, ProjectsResource, + ImplementationLaborCostResource, { resource: Country, name: "Country", @@ -113,7 +113,7 @@ const start = async () => { app.listen(PORT, () => { console.log( - `AdminJS started on http://localhost:${PORT}${admin.options.rootPath}`, + `AdminJS started on http://localhost:${PORT}${admin.options.rootPath}` ); }); }; diff --git a/admin/resources/baseline-reassesment/baseline-reassesment.resource.ts b/admin/resources/baseline-reassesment/baseline-reassesment.resource.ts index aa80fbcc..6d59252b 100644 --- a/admin/resources/baseline-reassesment/baseline-reassesment.resource.ts +++ b/admin/resources/baseline-reassesment/baseline-reassesment.resource.ts @@ -1,26 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { BaselineReassessment } from "@shared/entities/baseline-reassessment.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { BaselineReassessment } from "@shared/entities/cost-inputs/baseline-reassessment.entity.js"; export const BaselineReassessmentResource: ResourceWithOptions = { resource: BaselineReassessment, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "baselineReassessmentCost", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "baselineReassessmentCost", direction: "desc", @@ -29,46 +12,5 @@ export const BaselineReassessmentResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - BaselineReassessment, - "r", - "baseData.baselineReassessment = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.baselineReassessmentCost", "baselineReassessmentCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/blue-carbon-project-planning/blue-carbon-project-planning.resource.ts b/admin/resources/blue-carbon-project-planning/blue-carbon-project-planning.resource.ts index e5c8ca3a..300e1b35 100644 --- a/admin/resources/blue-carbon-project-planning/blue-carbon-project-planning.resource.ts +++ b/admin/resources/blue-carbon-project-planning/blue-carbon-project-planning.resource.ts @@ -1,80 +1,39 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { BlueCarbonProjectPlanning } from "@shared/entities/blue-carbon-project-planning.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { BlueCarbonProjectPlanning } from "@shared/entities/cost-inputs/blue-carbon-project-planning.entity.js"; +import { ResourceWithOptions } from "adminjs"; export const BlueCarbonProjectPlanningResource: ResourceWithOptions = { resource: BlueCarbonProjectPlanning, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "inputSelection", - "input1", - "input2", - "input3", - "countryName", - "ecosystem", - "activity", - ], + properties: { + id: { + isVisible: { list: false, show: false, edit: false, filter: false }, + }, + country: { + isVisible: { list: true, show: true, edit: true, filter: true }, + }, + inputSelection: { + isVisible: { list: true, show: true, edit: true, filter: true }, + }, + input1: { + isVisible: { list: true, show: true, edit: true, filter: true }, + }, + input2: { + isVisible: { list: true, show: true, edit: true, filter: true }, + }, + input3: { + isVisible: { list: true, show: true, edit: true, filter: true }, + }, + blueCarbon: { + isVisible: { list: true, show: true, edit: false, filter: true }, + }, + }, sort: { - sortBy: "inputSelection", - direction: "asc", + sortBy: "blueCarbon", + direction: "desc", }, navigation: { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - BlueCarbonProjectPlanning, - "r", - "baseData.blueCarbonProjectPlanning = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.inputSelection", "inputSelection") - .addSelect("r.input1", "input1") - .addSelect("r.input2", "input2") - .addSelect("r.input3", "input3") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/carbon-estandard-fees/carbon-estandard-fees.resource.ts b/admin/resources/carbon-estandard-fees/carbon-estandard-fees.resource.ts index 5424dd62..28d5beea 100644 --- a/admin/resources/carbon-estandard-fees/carbon-estandard-fees.resource.ts +++ b/admin/resources/carbon-estandard-fees/carbon-estandard-fees.resource.ts @@ -1,26 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { CarbonStandardFees } from "@shared/entities/carbon-standard-fees.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { CarbonStandardFees } from "@shared/entities/cost-inputs/carbon-standard-fees.entity.js"; export const CarbonStandardFeesResource: ResourceWithOptions = { resource: CarbonStandardFees, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "carbonStandardFee", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "carbonStandardFee", direction: "desc", @@ -29,46 +12,5 @@ export const CarbonStandardFeesResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - CarbonStandardFees, - "r", - "baseData.carbonStandardFees = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.carbonStandardFee", "carbonStandardFee") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/carbon-righs/carbon-rights.resource.ts b/admin/resources/carbon-righs/carbon-rights.resource.ts index 1c6f721e..42716a1d 100644 --- a/admin/resources/carbon-righs/carbon-rights.resource.ts +++ b/admin/resources/carbon-righs/carbon-rights.resource.ts @@ -1,26 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { CarbonRights } from "@shared/entities/establishing-carbon-rights.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { CarbonRights } from "@shared/entities/cost-inputs/establishing-carbon-rights.entity.js"; export const CarbonRightsResource: ResourceWithOptions = { resource: CarbonRights, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "carbonRightsCost", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "carbonRightsCost", direction: "desc", @@ -29,42 +12,5 @@ export const CarbonRightsResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(CarbonRights, "r", "baseData.carbonRights = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.carbonRightsCost", "carbonRightsCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/community-benefit/community-benefit.resource.ts b/admin/resources/community-benefit/community-benefit.resource.ts index 2ae7437e..b0e89282 100644 --- a/admin/resources/community-benefit/community-benefit.resource.ts +++ b/admin/resources/community-benefit/community-benefit.resource.ts @@ -1,74 +1,16 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { CommunityBenefitSharingFund } from "@shared/entities/community-benefit-sharing-fund.entity.js"; +import { CommunityBenefitSharingFund } from "@shared/entities/cost-inputs/community-benefit-sharing-fund.entity.js"; +import { ResourceWithOptions } from "adminjs"; export const CommunityBenefitResource: ResourceWithOptions = { resource: CommunityBenefitSharingFund, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "benefitSharingFund", - "countryName", - "ecosystem", - "activity", - ], sort: { - sortBy: "benefitSharingFund", + sortBy: "communityBenefitSharingFund", direction: "desc", }, navigation: { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - CommunityBenefitSharingFund, - "r", - "baseData.communityBenefit = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.benefitSharingFund", "benefitSharingFund") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/community-cash-flow/community-cash-flow.resource.ts b/admin/resources/community-cash-flow/community-cash-flow.resource.ts index d0ddebcd..20eb64af 100644 --- a/admin/resources/community-cash-flow/community-cash-flow.resource.ts +++ b/admin/resources/community-cash-flow/community-cash-flow.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { CommunityCashFlow } from "@shared/entities/community-cash-flow.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { CommunityCashFlow } from "@shared/entities/cost-inputs/community-cash-flow.entity.js"; +import { ResourceWithOptions } from "adminjs"; export const CommunityCashFlowResource: ResourceWithOptions = { resource: CommunityCashFlow, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["cashflowType", "countryName", "ecosystem", "activity"], sort: { sortBy: "cashflowType", direction: "asc", @@ -24,46 +12,5 @@ export const CommunityCashFlowResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - CommunityCashFlow, - "r", - "baseData.communityCashFlow = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.cashflowType", "cashflowType") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/community-representation/community-representation.resource.ts b/admin/resources/community-representation/community-representation.resource.ts index e221f706..28a4fe0d 100644 --- a/admin/resources/community-representation/community-representation.resource.ts +++ b/admin/resources/community-representation/community-representation.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { CommunityRepresentation } from "@shared/entities/community-representation.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { CommunityRepresentation } from "@shared/entities/cost-inputs/community-representation.entity.js"; export const CommunityRepresentationResource: ResourceWithOptions = { resource: CommunityRepresentation, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["liaisonCost", "countryName", "ecosystem", "activity"], sort: { sortBy: "liaisonCost", direction: "desc", @@ -24,46 +12,5 @@ export const CommunityRepresentationResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - CommunityRepresentation, - "r", - "baseData.communityRepresentation = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.liaisonCost", "liaisonCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/conservation-and-planning-admin/conservation-and-planning-admin.resource.ts b/admin/resources/conservation-and-planning-admin/conservation-and-planning-admin.resource.ts index 5175d982..a83a4405 100644 --- a/admin/resources/conservation-and-planning-admin/conservation-and-planning-admin.resource.ts +++ b/admin/resources/conservation-and-planning-admin/conservation-and-planning-admin.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { ConservationPlanningAndAdmin } from "@shared/entities/conservation-and-planning-admin.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { ConservationPlanningAndAdmin } from "@shared/entities/cost-inputs/conservation-and-planning-admin.entity.js"; export const ConservationAndPlanningAdminResource: ResourceWithOptions = { resource: ConservationPlanningAndAdmin, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["planningCost", "countryName", "ecosystem", "activity"], sort: { sortBy: "planningCost", direction: "desc", @@ -24,46 +12,5 @@ export const ConservationAndPlanningAdminResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - ConservationPlanningAndAdmin, - "cpa", - "baseData.conservationPlanningAndAdmin = cpa.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("cpa.id", "id") - .addSelect("cpa.planningCost", "planningCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("cpa.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/data-collection-and-field-cost/data-collection-and-field-cost.resource.ts b/admin/resources/data-collection-and-field-cost/data-collection-and-field-cost.resource.ts index 12e50f43..b2971cb4 100644 --- a/admin/resources/data-collection-and-field-cost/data-collection-and-field-cost.resource.ts +++ b/admin/resources/data-collection-and-field-cost/data-collection-and-field-cost.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { DataCollectionAndFieldCosts } from "@shared/entities/data-collection-and-field-costs.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { DataCollectionAndFieldCosts } from "@shared/entities/cost-inputs/data-collection-and-field-costs.entity.js"; export const DataCollectionAndFieldCostResource: ResourceWithOptions = { resource: DataCollectionAndFieldCosts, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["fieldCost", "countryName", "ecosystem", "activity"], sort: { sortBy: "fieldCost", direction: "desc", @@ -24,46 +12,5 @@ export const DataCollectionAndFieldCostResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - DataCollectionAndFieldCosts, - "r", - "baseData.dataCollectionAndFieldCosts = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.fieldCost", "fieldCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/ecosystem-loss/ecosystem-loss.resource.ts b/admin/resources/ecosystem-loss/ecosystem-loss.resource.ts index 43f59634..44b70cfe 100644 --- a/admin/resources/ecosystem-loss/ecosystem-loss.resource.ts +++ b/admin/resources/ecosystem-loss/ecosystem-loss.resource.ts @@ -1,26 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { EcosystemLoss } from "@shared/entities/ecosystem-loss.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { EcosystemLoss } from "@shared/entities/carbon-inputs/ecosystem-loss.entity.js"; export const EcosystemLossResource: ResourceWithOptions = { resource: EcosystemLoss, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "ecosystemLossRate", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "ecosystemLossRate", direction: "desc", @@ -29,42 +12,5 @@ export const EcosystemLossResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(EcosystemLoss, "r", "baseData.ecosystemLoss = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.ecosystemLossRate", "ecosystemLossRate") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/emission-factors/emission-factors.resource.ts b/admin/resources/emission-factors/emission-factors.resource.ts index eec82894..f21955ee 100644 --- a/admin/resources/emission-factors/emission-factors.resource.ts +++ b/admin/resources/emission-factors/emission-factors.resource.ts @@ -1,29 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { EmissionFactors } from "@shared/entities/emission-factors.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { EmissionFactors } from "@shared/entities/carbon-inputs/emission-factors.entity.js"; export const EmissionFactorsResource: ResourceWithOptions = { resource: EmissionFactors, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "tierSelector", - "tier1Factor", - "tier2AGBFactor", - "tier2SOCFactor", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "tierSelector", direction: "asc", @@ -32,45 +12,5 @@ export const EmissionFactorsResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(EmissionFactors, "r", "baseData.emissionFactors = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.tierSelector", "tierSelector") - .addSelect("r.tier1Factor", "tier1Factor") - .addSelect("r.tier2AGBFactor", "tier2AGBFactor") - .addSelect("r.tier2SOCFactor", "tier2SOCFactor") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/feasability-analysis/feasability-analysis.resource.ts b/admin/resources/feasability-analysis/feasability-analysis.resource.ts index bc6d3f01..3f526cfb 100644 --- a/admin/resources/feasability-analysis/feasability-analysis.resource.ts +++ b/admin/resources/feasability-analysis/feasability-analysis.resource.ts @@ -1,78 +1,16 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { FeasibilityAnalysis } from "@shared/entities/feasability-analysis.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { FeasibilityAnalysis } from "@shared/entities/cost-inputs/feasability-analysis.entity.js"; export const FeasibilityAnalysisResource: ResourceWithOptions = { resource: FeasibilityAnalysis, options: { - properties: { - countryName: { - isVisible: { list: true, show: true, edit: false, filter: true }, - }, - ecosystem: { - isVisible: { list: true, show: true, edit: false, filter: true }, - }, - activity: { - isVisible: { list: true, show: true, edit: false, filter: true }, - }, - }, - listProperties: ["analysisScore", "countryName", "ecosystem", "activity"], sort: { - sortBy: "analysisScore", + sortBy: "analysisCost", direction: "desc", }, navigation: { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - FeasibilityAnalysis, - "fa", - "baseData.feasibilityAnalysis = fa.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("fa.id", "id") - .addSelect("fa.analysisScore", "analysisScore") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("fa.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/financing-cost/financing-cost.resource.ts b/admin/resources/financing-cost/financing-cost.resource.ts index 0d022924..f3d1328e 100644 --- a/admin/resources/financing-cost/financing-cost.resource.ts +++ b/admin/resources/financing-cost/financing-cost.resource.ts @@ -1,26 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { FinancingCost } from "@shared/entities/financing-cost.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { FinancingCost } from "@shared/entities/cost-inputs/financing-cost.entity.js"; export const FinancingCostResource: ResourceWithOptions = { resource: FinancingCost, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "financingCostCapexPercent", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "financingCostCapexPercent", direction: "desc", @@ -29,45 +12,5 @@ export const FinancingCostResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(FinancingCost, "r", "baseData.financingCost = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect( - "r.financingCostCapexPercent", - "financingCostCapexPercent", - ) - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/implementation-labor-cost/implementation-labor-cost.resource.ts b/admin/resources/implementation-labor-cost/implementation-labor-cost.resource.ts new file mode 100644 index 00000000..e270318d --- /dev/null +++ b/admin/resources/implementation-labor-cost/implementation-labor-cost.resource.ts @@ -0,0 +1,16 @@ +import { ResourceWithOptions } from "adminjs"; +import { ImplementationLaborCost } from "@shared/entities/cost-inputs/implementation-labor-cost.entity.js"; + +export const ImplementationLaborCostResource: ResourceWithOptions = { + resource: ImplementationLaborCost, + options: { + sort: { + sortBy: "plantingCost", + direction: "desc", + }, + navigation: { + name: "Data Management", + icon: "Database", + }, + }, +}; diff --git a/admin/resources/implementation-labor/implementation-labor-cost.resource.ts b/admin/resources/implementation-labor/implementation-labor-cost.resource.ts deleted file mode 100644 index b54cead5..00000000 --- a/admin/resources/implementation-labor/implementation-labor-cost.resource.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { ImplementationLaborCost } from "@shared/entities/implementation-labor.entity.js"; - -export const ImplementationLaborCostResource: ResourceWithOptions = { - resource: ImplementationLaborCost, - options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "implementationLaborCost", - "countryName", - "ecosystem", - "activity", - ], - sort: { - sortBy: "implementationLaborCost", - direction: "desc", - }, - navigation: { - name: "Data Management", - icon: "Database", - }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - ImplementationLaborCost, - "r", - "baseData.implementationLaborCost = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.implementationLaborCost", "implementationLaborCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, - }, -}; diff --git a/admin/resources/long-term-project-operating/long-term-project-operating.resource.ts b/admin/resources/long-term-project-operating/long-term-project-operating.resource.ts index cc03f5d2..9346eb79 100644 --- a/admin/resources/long-term-project-operating/long-term-project-operating.resource.ts +++ b/admin/resources/long-term-project-operating/long-term-project-operating.resource.ts @@ -1,26 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { LongTermProjectOperating } from "@shared/entities/long-term-project-operating.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { LongTermProjectOperating } from "@shared/entities/cost-inputs/long-term-project-operating.entity.js"; export const LongTermProjectOperatingResource: ResourceWithOptions = { resource: LongTermProjectOperating, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "longTermProjectOperatingCost", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "longTermProjectOperatingCost", direction: "desc", @@ -29,49 +12,5 @@ export const LongTermProjectOperatingResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - LongTermProjectOperating, - "r", - "baseData.longTermProjectOperating = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect( - "r.longTermProjectOperatingCost", - "longTermProjectOperatingCost", - ) - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/maintenance/maintenance.resource.ts b/admin/resources/maintenance/maintenance.resource.ts index ada712da..3f7922fb 100644 --- a/admin/resources/maintenance/maintenance.resource.ts +++ b/admin/resources/maintenance/maintenance.resource.ts @@ -1,27 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { Maintenance } from "@shared/entities/maintenance.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { Maintenance } from "@shared/entities/cost-inputs/maintenance.entity.js"; export const MaintenanceResource: ResourceWithOptions = { resource: Maintenance, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "maintenanceCost", - "maintenanceDuration", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "maintenanceCost", direction: "desc", @@ -30,43 +12,5 @@ export const MaintenanceResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(Maintenance, "r", "baseData.maintenance = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.maintenanceCost", "maintenanceCost") - .addSelect("r.maintenanceDuration", "maintenanceDuration") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/monitoring-cost/monitoring-cost.resource.ts b/admin/resources/monitoring-cost/monitoring-cost.resource.ts index d563409d..f79fad37 100644 --- a/admin/resources/monitoring-cost/monitoring-cost.resource.ts +++ b/admin/resources/monitoring-cost/monitoring-cost.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { MonitoringCost } from "@shared/entities/monitoring.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { MonitoringCost } from "@shared/entities/cost-inputs/monitoring.entity.js"; export const MonitoringCostResource: ResourceWithOptions = { resource: MonitoringCost, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["monitoringCost", "countryName", "ecosystem", "activity"], sort: { sortBy: "monitoringCost", direction: "desc", @@ -24,42 +12,5 @@ export const MonitoringCostResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(MonitoringCost, "r", "baseData.monitoringCost = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.monitoringCost", "monitoringCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/mrv/mrv.resource.ts b/admin/resources/mrv/mrv.resource.ts index 7f9f871d..ad05b1ed 100644 --- a/admin/resources/mrv/mrv.resource.ts +++ b/admin/resources/mrv/mrv.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { MRV } from "@shared/entities/mrv.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { MRV } from "@shared/entities/cost-inputs/mrv.entity.js"; export const MRVResource: ResourceWithOptions = { resource: MRV, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["mrvCost", "countryName", "ecosystem", "activity"], sort: { sortBy: "mrvCost", direction: "desc", @@ -24,42 +12,5 @@ export const MRVResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(MRV, "r", "baseData.mrv = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.mrvCost", "mrvCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/project-size/project-size.resource.ts b/admin/resources/project-size/project-size.resource.ts index dd11552b..c21e6436 100644 --- a/admin/resources/project-size/project-size.resource.ts +++ b/admin/resources/project-size/project-size.resource.ts @@ -1,30 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { ProjectSize } from "@shared/entities/project-size.entity.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { ProjectSize } from "@shared/entities/cost-inputs/project-size.entity.js"; export const ProjectSizeResource: ResourceWithOptions = { resource: ProjectSize, options: { - properties: { - countryName: { - isVisible: { list: true, show: true, edit: false, filter: true }, - }, - ecosystem: { - isVisible: { list: true, show: true, edit: false, filter: true }, - }, - activity: { - isVisible: { list: true, show: true, edit: false, filter: true }, - }, - }, - listProperties: ["sizeHa", "countryName", "ecosystem", "activity"], sort: { sortBy: "sizeHa", direction: "desc", @@ -33,46 +12,5 @@ export const ProjectSizeResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - ProjectSize, - "projectSize", - "baseData.projectSize = projectSize.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("projectSize.id", "id") - .addSelect("projectSize.sizeHa", "sizeHa") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("projectSize.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/projects/projects.resource.ts b/admin/resources/projects/projects.resource.ts index 84edf535..e825e72e 100644 --- a/admin/resources/projects/projects.resource.ts +++ b/admin/resources/projects/projects.resource.ts @@ -6,9 +6,9 @@ import { ResourceWithOptions, } from "adminjs"; import { dataSource } from "../../datasource.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; import { Project } from "@shared/entities/projects.entity.js"; import { Country } from "@shared/entities/country.entity.js"; +import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; export const ProjectsResource: ResourceWithOptions = { resource: Project, @@ -39,7 +39,7 @@ export const ProjectsResource: ResourceWithOptions = { after: async ( request: ActionRequest, response: ActionResponse, - context: ActionContext, + context: ActionContext ) => { const { records } = context; const projectDataRepo = dataSource.getRepository(Project); @@ -62,7 +62,7 @@ export const ProjectsResource: ResourceWithOptions = { .addSelect("project.priceType", "priceType") .addSelect( "project.initialPriceAssumption", - "initialPriceAssumption", + "initialPriceAssumption" ); if (records?.length) { diff --git a/admin/resources/restorable-land/restorable-land.resource.ts b/admin/resources/restorable-land/restorable-land.resource.ts index 4182e43e..70994daa 100644 --- a/admin/resources/restorable-land/restorable-land.resource.ts +++ b/admin/resources/restorable-land/restorable-land.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { RestorableLand } from "@shared/entities/restorable-land.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { RestorableLand } from "@shared/entities/carbon-inputs/restorable-land.entity.js"; export const RestorableLandResource: ResourceWithOptions = { resource: RestorableLand, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["restorableLand", "countryName", "ecosystem", "activity"], sort: { sortBy: "restorableLand", direction: "desc", @@ -24,42 +12,5 @@ export const RestorableLandResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(RestorableLand, "r", "baseData.restorableLand = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.restorableLand", "restorableLand") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/sequestration-rate/sequestration-rate.resource.ts b/admin/resources/sequestration-rate/sequestration-rate.resource.ts index 150ea278..a59efa7d 100644 --- a/admin/resources/sequestration-rate/sequestration-rate.resource.ts +++ b/admin/resources/sequestration-rate/sequestration-rate.resource.ts @@ -1,28 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { SequestrationRate } from "@shared/entities/sequestration-rate.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; +import { ResourceWithOptions } from "adminjs"; +import { SequestrationRate } from "@shared/entities/carbon-inputs/sequestration-rate.entity.js"; export const SequestrationRateResource: ResourceWithOptions = { resource: SequestrationRate, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: [ - "tierSelector", - "tier1Factor", - "tier2Factor", - "countryName", - "ecosystem", - "activity", - ], sort: { sortBy: "tierSelector", direction: "asc", @@ -31,48 +12,5 @@ export const SequestrationRateResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin( - SequestrationRate, - "r", - "baseData.sequestrationRate = r.id", - ) - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.tierSelector", "tierSelector") - .addSelect("r.tier1Factor", "tier1Factor") - .addSelect("r.tier2Factor", "tier2Factor") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/admin/resources/validation-cost/validation-cost.resource.ts b/admin/resources/validation-cost/validation-cost.resource.ts index c7693e63..56b7216e 100644 --- a/admin/resources/validation-cost/validation-cost.resource.ts +++ b/admin/resources/validation-cost/validation-cost.resource.ts @@ -1,21 +1,9 @@ -import { - ActionContext, - ActionRequest, - ActionResponse, - BaseRecord, - ResourceWithOptions, -} from "adminjs"; -import { dataSource } from "../../datasource.js"; -import { BaseData } from "@shared/entities/base-data.entity.js"; -import { Country } from "@shared/entities/country.entity.js"; -import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js"; -import { ValidationCost } from "@shared/entities/validation.entity.js"; +import { ResourceWithOptions } from "adminjs"; +import { ValidationCost } from "@shared/entities/cost-inputs/validation.entity.js"; export const ValidationCostResource: ResourceWithOptions = { resource: ValidationCost, options: { - properties: COMMON_RESOURCE_LIST_PROPERTIES, - listProperties: ["validationCost", "countryName", "ecosystem", "activity"], sort: { sortBy: "validationCost", direction: "desc", @@ -24,43 +12,5 @@ export const ValidationCostResource: ResourceWithOptions = { name: "Data Management", icon: "Database", }, - actions: { - list: { - after: async ( - request: ActionRequest, - response: ActionResponse, - context: ActionContext, - ) => { - const { records } = context; - console.log("records", records); - const baseDataRepo = dataSource.getRepository(BaseData); - const queryBuilder = baseDataRepo - .createQueryBuilder("baseData") - .leftJoin(ValidationCost, "r", "baseData.validationCost = r.id") - .leftJoin(Country, "country", "country.code = baseData.countryCode") - .select("r.id", "id") - .addSelect("r.validationCost", "validationCost") - .addSelect("country.name", "countryName") - .addSelect("baseData.ecosystem", "ecosystem") - .addSelect("baseData.activity", "activity"); - - if (records?.length) { - queryBuilder.andWhere("r.id IN (:...ids)", { - ids: records.map((r) => r.params.id), - }); - } - - const result = await queryBuilder.getRawMany(); - - return { - ...request, - records: records!.map((record: BaseRecord) => { - record.params = result.find((q) => q.id === record.params.id); - return record; - }), - }; - }, - }, - }, }, }; diff --git a/api/src/modules/import/excel-base-data.dto.ts b/api/src/modules/import/dtos/excel-base-data.dto.ts similarity index 85% rename from api/src/modules/import/excel-base-data.dto.ts rename to api/src/modules/import/dtos/excel-base-data.dto.ts index c7a82a9f..781ce741 100644 --- a/api/src/modules/import/excel-base-data.dto.ts +++ b/api/src/modules/import/dtos/excel-base-data.dto.ts @@ -1,5 +1,6 @@ -import { ACTIVITY, ECOSYSTEM } from '@shared/entities/base-data.entity'; -import { COMMUNITY_CASH_FLOW_TYPES } from '@shared/entities/community-cash-flow.entity'; +import { ACTIVITY } from '@shared/entities/activity.enum'; +import { COMMUNITY_CASH_FLOW_TYPES } from '@shared/entities/cost-inputs/community-cash-flow.entity'; +import { ECOSYSTEM } from '@shared/entities/ecosystem.enum'; export type ExcelMasterTable = { country: string; diff --git a/api/src/modules/import/dtos/excel-baseline-reassessment.dto.ts b/api/src/modules/import/dtos/excel-baseline-reassessment.dto.ts new file mode 100644 index 00000000..9da49a5e --- /dev/null +++ b/api/src/modules/import/dtos/excel-baseline-reassessment.dto.ts @@ -0,0 +1,5 @@ +export type ExcelBaselineReassessment = { + Country: string; + 'Country code': string; + 'Baseline reassessment': number; +}; diff --git a/api/src/modules/import/dtos/excel-blue-carbon-project-planning.dto.ts b/api/src/modules/import/dtos/excel-blue-carbon-project-planning.dto.ts new file mode 100644 index 00000000..dbbb9e40 --- /dev/null +++ b/api/src/modules/import/dtos/excel-blue-carbon-project-planning.dto.ts @@ -0,0 +1,9 @@ +export type ExcelBlueCarbonProjectPlanning = { + Country: string; + 'Country code': string; + 'Input selection': string; + 'Input 1': number; + 'Input 2': number; + 'Input 3': number; + 'Blue carbon': number; +}; diff --git a/api/src/modules/import/dtos/excel-carbon-standard-fees.dto.ts b/api/src/modules/import/dtos/excel-carbon-standard-fees.dto.ts new file mode 100644 index 00000000..7e4606ec --- /dev/null +++ b/api/src/modules/import/dtos/excel-carbon-standard-fees.dto.ts @@ -0,0 +1,5 @@ +export type ExcelCarbonStandardFees = { + Country: string; + 'Country code': string; + 'Carbon standard fees': number; +}; diff --git a/api/src/modules/import/dtos/excel-ccosystem-loss.dto.ts b/api/src/modules/import/dtos/excel-ccosystem-loss.dto.ts new file mode 100644 index 00000000..7539d772 --- /dev/null +++ b/api/src/modules/import/dtos/excel-ccosystem-loss.dto.ts @@ -0,0 +1,7 @@ +export type ExcelEcosystemLoss = { + Country: string; + 'Country code': string; + 'Mangrove loss rate': number; + 'Seagrass loss rate': number; + 'Salt marsh loss rate': number; +}; diff --git a/api/src/modules/import/dtos/excel-community-benefit-sharing-fund.dto.ts b/api/src/modules/import/dtos/excel-community-benefit-sharing-fund.dto.ts new file mode 100644 index 00000000..dd8e79b5 --- /dev/null +++ b/api/src/modules/import/dtos/excel-community-benefit-sharing-fund.dto.ts @@ -0,0 +1,5 @@ +export type ExcelCommunityBenefitSharingFund = { + Country: string; + 'Country code': string; + 'Community benefit sharing fund': number; +}; diff --git a/api/src/modules/import/dtos/excel-community-cash-flow.dto.ts b/api/src/modules/import/dtos/excel-community-cash-flow.dto.ts new file mode 100644 index 00000000..b55114da --- /dev/null +++ b/api/src/modules/import/dtos/excel-community-cash-flow.dto.ts @@ -0,0 +1,5 @@ +export type ExcelCommunityCashFlow = { + Country: string; + 'Country code': string; + 'Other community cash flow': number; +}; diff --git a/api/src/modules/import/dtos/excel-community-representation.dto.ts b/api/src/modules/import/dtos/excel-community-representation.dto.ts new file mode 100644 index 00000000..fca74a2d --- /dev/null +++ b/api/src/modules/import/dtos/excel-community-representation.dto.ts @@ -0,0 +1,7 @@ +export type ExcelCommunityRepresentation = { + Country: string; + 'Country code': string; + 'Mangrove community representation / liaison': number; + 'Seagrass Community representation / liaison': number; + 'Salt marsh Community representation / liaison': number; +}; diff --git a/api/src/modules/import/dtos/excel-conservation-planning-and-admin.dto.ts b/api/src/modules/import/dtos/excel-conservation-planning-and-admin.dto.ts new file mode 100644 index 00000000..3551efa4 --- /dev/null +++ b/api/src/modules/import/dtos/excel-conservation-planning-and-admin.dto.ts @@ -0,0 +1,7 @@ +export type ExcelConservationPlanningAndAdmin = { + Country: string; + 'Country code': string; + 'Mangrove conservation planning and admin': number; + 'Seagrass conservation planning and admin': number; + 'Salt marsh conservation planning and admin': number; +}; diff --git a/api/src/modules/import/dtos/excel-data-collection-field-cost.dto.ts b/api/src/modules/import/dtos/excel-data-collection-field-cost.dto.ts new file mode 100644 index 00000000..3e315ec8 --- /dev/null +++ b/api/src/modules/import/dtos/excel-data-collection-field-cost.dto.ts @@ -0,0 +1,7 @@ +export type ExcelDataCollectionAndFieldCosts = { + Country: string; + 'Country code': string; + 'Mangrove data collection and field costs': number; + 'Seagrass data collection and field costs': number; + 'Salt marsh data collection and field costs': number; +}; diff --git a/api/src/modules/import/dtos/excel-ecosystem-extent.dto.ts b/api/src/modules/import/dtos/excel-ecosystem-extent.dto.ts new file mode 100644 index 00000000..06b464bf --- /dev/null +++ b/api/src/modules/import/dtos/excel-ecosystem-extent.dto.ts @@ -0,0 +1,10 @@ +export type ExcelEcosystemExtent = { + Country: string; + 'Country code': string; + 'Mangrove extent': number; + 'Mangrove extent historic': number; + 'Seagrass extent': number; + 'Seagrass extent historic': number; + 'Salt marsh extent': number; + 'Salt marsh extent historic': number; +}; diff --git a/api/src/modules/import/dtos/excel-emission-factors.dto.ts b/api/src/modules/import/dtos/excel-emission-factors.dto.ts new file mode 100644 index 00000000..f4cb2543 --- /dev/null +++ b/api/src/modules/import/dtos/excel-emission-factors.dto.ts @@ -0,0 +1,28 @@ +export type ExcelEmissionFactors = { + Country: string; + 'Country code': string; + + 'Selection (only for mangroves)': string; + 'Mangrove emission factor': number; + 'Mangrove emission factor - AGB': number; + 'Mangrove emission factor - SOC': number; + 'Mangrove - Tier 1 - Global emission factor': number; + 'Mangrove - Tier 2 - Country-specific emission factor - AGB': number; + 'Mangrove - Tier 2 - Country-specific emission factor - SOC': number; + + 'Selection (only for seagrass)': string; + 'Seagrass emission factor': number; + 'Seagrass emission factor - AGB': number; + 'Seagrass emission factor - SOC': number; + 'Seagrass - Tier 1 - Global emission factor': number; + 'Seagrass - Tier 2 - Country-specific emission factor - AGB': number; + 'Seagrass - Tier 2 - Country-specific emission factor - SOC': number; + + 'Selection (only for salt marsh)': string; + 'Salt marsh emission factor': number; + 'Salt Marsh emission factor - AGB': number; + 'Salt Marsh emission factor - SOC': number; + 'Salt marsh - Tier 1 - Global emission factor': number; + 'Salt Marsh - Tier 2 - Country-specific emission factor - AGB': number; + 'Salt Marsh - Tier 2 - Country-specific emission factor - SOC': number; +}; diff --git a/api/src/modules/import/dtos/excel-establishing-carbon-rights.dto.ts b/api/src/modules/import/dtos/excel-establishing-carbon-rights.dto.ts new file mode 100644 index 00000000..466429bb --- /dev/null +++ b/api/src/modules/import/dtos/excel-establishing-carbon-rights.dto.ts @@ -0,0 +1,5 @@ +export type ExcelEstablishingCarbonRights = { + Country: string; + 'Country code': string; + 'Establishing carbon rights': number; +}; diff --git a/api/src/modules/import/dtos/excel-feasibility-analysis.dto.ts b/api/src/modules/import/dtos/excel-feasibility-analysis.dto.ts new file mode 100644 index 00000000..7656d4d3 --- /dev/null +++ b/api/src/modules/import/dtos/excel-feasibility-analysis.dto.ts @@ -0,0 +1,7 @@ +export type ExcelFeasibilityAnalysis = { + Country: string; + 'Country code': string; + 'Mangrove feasibility analysis': number; + 'Seagrass feasibility analysis': number; + 'Salt marsh feasibility analysis': number; +}; diff --git a/api/src/modules/import/dtos/excel-financing-cost.dto.ts b/api/src/modules/import/dtos/excel-financing-cost.dto.ts new file mode 100644 index 00000000..a01e91a1 --- /dev/null +++ b/api/src/modules/import/dtos/excel-financing-cost.dto.ts @@ -0,0 +1,5 @@ +export type ExcelFinancingCost = { + Country: string; + 'Country code': string; + 'Financing cost': number; +}; diff --git a/api/src/modules/import/dtos/excel-implementation-labor.dto.ts b/api/src/modules/import/dtos/excel-implementation-labor.dto.ts new file mode 100644 index 00000000..2401bfa5 --- /dev/null +++ b/api/src/modules/import/dtos/excel-implementation-labor.dto.ts @@ -0,0 +1,13 @@ +export type ExcelImplementationLaborCost = { + Country: string; + 'Country code': string; + 'Mangrove planting': number; + 'Mangrove hybrid': number; + 'Mangrove hydrology': number; + 'Seagrass planting': number; + 'Seagrass hybrid': number; + 'Seagrass hydrology': number; + 'Salt marsh planting': number; + 'Salt marsh hybrid': number; + 'Salt marsh hydrology': number; +}; diff --git a/api/src/modules/import/dtos/excel-long-term-project-operating.dto.ts b/api/src/modules/import/dtos/excel-long-term-project-operating.dto.ts new file mode 100644 index 00000000..fb799c7e --- /dev/null +++ b/api/src/modules/import/dtos/excel-long-term-project-operating.dto.ts @@ -0,0 +1,7 @@ +export type ExcelLongTermProjectOperating = { + Country: string; + 'Country code': string; + 'Mangrove long-term project operating': number; + 'Seagrass long-term project operating': number; + 'Salt marsh long-term project operating': number; +}; diff --git a/api/src/modules/import/dtos/excel-maintenance.dto.ts b/api/src/modules/import/dtos/excel-maintenance.dto.ts new file mode 100644 index 00000000..faf77c73 --- /dev/null +++ b/api/src/modules/import/dtos/excel-maintenance.dto.ts @@ -0,0 +1,6 @@ +export type ExcelMaintenance = { + Country: string; + 'Country code': string; + Maintenance: number; + 'Maintenance duration': number; +}; diff --git a/api/src/modules/import/dtos/excel-monitoring.dto.ts b/api/src/modules/import/dtos/excel-monitoring.dto.ts new file mode 100644 index 00000000..a311493f --- /dev/null +++ b/api/src/modules/import/dtos/excel-monitoring.dto.ts @@ -0,0 +1,7 @@ +export type ExcelMonitoring = { + Country: string; + 'Country code': string; + 'Mangrove monitoring': number; + 'Seagrass monitoring': number; + 'Salt marsh monitoring': number; +}; diff --git a/api/src/modules/import/dtos/excel-mrv.dto.ts b/api/src/modules/import/dtos/excel-mrv.dto.ts new file mode 100644 index 00000000..88c89530 --- /dev/null +++ b/api/src/modules/import/dtos/excel-mrv.dto.ts @@ -0,0 +1,5 @@ +export type ExcelMRV = { + Country: string; + 'Country code': string; + MRV: number; +}; diff --git a/api/src/modules/import/dtos/excel-project-size.dto.ts b/api/src/modules/import/dtos/excel-project-size.dto.ts new file mode 100644 index 00000000..69591b85 --- /dev/null +++ b/api/src/modules/import/dtos/excel-project-size.dto.ts @@ -0,0 +1,10 @@ +export type ExcelProjectSize = { + Country: string; + 'Country code': string; + 'Mangrove restored area': number; + 'Seagrass restored area': number; + 'Salt marsh restored area': number; + 'Mangrove conserved area': number; + 'Seagrass conserved area': number; + 'Salt marsh conserved area': number; +}; diff --git a/api/src/modules/import/dtos/excel-projects.dto.ts b/api/src/modules/import/dtos/excel-projects.dto.ts new file mode 100644 index 00000000..dbcf8dea --- /dev/null +++ b/api/src/modules/import/dtos/excel-projects.dto.ts @@ -0,0 +1,22 @@ +import { ACTIVITY } from '@shared/entities/activity.enum'; +import { ECOSYSTEM } from '@shared/entities/ecosystem.enum'; +import { PROJECT_PRICE_TYPE } from '@shared/entities/projects.entity'; + +export type ExcelProjects = { + project_name: string; + continent: string; + Country: string; + country_code: string; + ecosystem: ECOSYSTEM; + activity: ACTIVITY; + activity_type: string; + project_size_ha: number; + project_size_filter: string; + aAbatement_potential: number; + total_cost_NPV: number; + total_cost: number; + '$/tCO2e (NPV)': number; + '$/tCO2e': number; + initial_price_assumption: string; + price_type: PROJECT_PRICE_TYPE; +}; diff --git a/api/src/modules/import/dtos/excel-restorable-land.dto.ts b/api/src/modules/import/dtos/excel-restorable-land.dto.ts new file mode 100644 index 00000000..abe7bf22 --- /dev/null +++ b/api/src/modules/import/dtos/excel-restorable-land.dto.ts @@ -0,0 +1,7 @@ +export type ExcelRestorableLand = { + Country: string; + 'Country code': string; + 'Mangrove restorable land': number; + 'Seagrass restorable land': number; + 'Salt marsh restorable land': number; +}; diff --git a/api/src/modules/import/dtos/excel-sequestration-rate.dto.ts b/api/src/modules/import/dtos/excel-sequestration-rate.dto.ts new file mode 100644 index 00000000..739b786b --- /dev/null +++ b/api/src/modules/import/dtos/excel-sequestration-rate.dto.ts @@ -0,0 +1,16 @@ +export type ExcelSequestrationRate = { + Country: string; + 'Country code': string; + 'Input used (mangrove only)': string; + 'Mangrove sequestration rate': number; + 'Mangrove Tier 1 - IPCC default value': number; + 'Mangrove Tier 2 - country-specific rate': number; + 'Input used (seagrass only)': string; + 'Seagrass sequestration rate': number; + 'Seagrass Tier 1 - IPCC default value': number; + 'Seagrass Tier 2 - country-specific rate': number; + 'Input used (salt marsh only)': string; + 'Salt marsh sequestration rate': number; + 'Salt marsh Tier 1 - IPCC default value': number; + 'Salt marsh Tier 2 - country-specific rate': number; +}; diff --git a/api/src/modules/import/dtos/excel-validation.dto.ts b/api/src/modules/import/dtos/excel-validation.dto.ts new file mode 100644 index 00000000..9d10c20f --- /dev/null +++ b/api/src/modules/import/dtos/excel-validation.dto.ts @@ -0,0 +1,5 @@ +export type ExcelValidation = { + Country: string; + 'Country code': string; + Validation: number; +}; diff --git a/api/src/modules/import/excel-projects.dto.ts b/api/src/modules/import/excel-projects.dto.ts deleted file mode 100644 index 74d87493..00000000 --- a/api/src/modules/import/excel-projects.dto.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ACTIVITY, ECOSYSTEM } from '@shared/entities/base-data.entity'; -import { PROJECT_PRICE_TYPE } from '@shared/entities/projects.entity'; - -export type ExcelProjects = { - Project_name: string; - Continent: string; - Country: string; - 'Country code': string; - Ecosystem: ECOSYSTEM; - Activity: ACTIVITY; - Activity_type: string; - Project_size: number; - Project_size_filter: string; - Abatement_potential: number; - Total_cost_NPV: number; - Total_cost: number; - '$/tCO2e (NPV)': number; - '$/tCO2e': number; - 'Initial price assumption': string; - 'Price type': PROJECT_PRICE_TYPE; -}; diff --git a/api/src/modules/import/import.module.ts b/api/src/modules/import/import.module.ts index 94437a64..d5355111 100644 --- a/api/src/modules/import/import.module.ts +++ b/api/src/modules/import/import.module.ts @@ -4,13 +4,12 @@ import { MulterModule } from '@nestjs/platform-express'; import { ImportController } from '@api/modules/import/import.controller'; import { XlsxParser } from '@api/modules/import/services/xlsx.parser'; import { EntityPreprocessor } from '@api/modules/import/services/entity.preprocessor'; -import { ModelModule } from '@api/modules/model/model.module'; import { ExcelParserToken } from '@api/modules/import/services/excel-parser.interface'; import { ImportRepository } from '@api/modules/import/import.repostiory'; import { ImportEventHandler } from '@api/modules/import/events/handlers/import-event.handler'; @Module({ - imports: [MulterModule.register({}), ModelModule], + imports: [MulterModule.register({})], controllers: [ImportController], providers: [ ImportService, diff --git a/api/src/modules/import/import.repostiory.ts b/api/src/modules/import/import.repostiory.ts index 9842ea76..5146e3ea 100644 --- a/api/src/modules/import/import.repostiory.ts +++ b/api/src/modules/import/import.repostiory.ts @@ -1,32 +1,89 @@ import { Injectable } from '@nestjs/common'; import { DataSource } from 'typeorm'; -import { BaseData } from '@shared/entities/base-data.entity'; import { Project } from '@shared/entities/projects.entity'; -import { Country } from '@shared/entities/country.entity'; +import { ProjectSize } from '@shared/entities/cost-inputs/project-size.entity'; +import { FeasibilityAnalysis } from '@shared/entities/cost-inputs/feasability-analysis.entity'; +import { EcosystemExtent } from '@shared/entities/carbon-inputs/ecosystem-extent.entity'; +import { EcosystemLoss } from '@shared/entities/carbon-inputs/ecosystem-loss.entity'; +import { EmissionFactors } from '@shared/entities/carbon-inputs/emission-factors.entity'; +import { RestorableLand } from '@shared/entities/carbon-inputs/restorable-land.entity'; +import { SequestrationRate } from '@shared/entities/carbon-inputs/sequestration-rate.entity'; +import { BaselineReassessment } from '@shared/entities/cost-inputs/baseline-reassessment.entity'; +import { BlueCarbonProjectPlanning } from '@shared/entities/cost-inputs/blue-carbon-project-planning.entity'; +import { CarbonStandardFees } from '@shared/entities/cost-inputs/carbon-standard-fees.entity'; +import { CommunityBenefitSharingFund } from '@shared/entities/cost-inputs/community-benefit-sharing-fund.entity'; +import { CommunityCashFlow } from '@shared/entities/cost-inputs/community-cash-flow.entity'; +import { CommunityRepresentation } from '@shared/entities/cost-inputs/community-representation.entity'; +import { ConservationPlanningAndAdmin } from '@shared/entities/cost-inputs/conservation-and-planning-admin.entity'; +import { DataCollectionAndFieldCosts } from '@shared/entities/cost-inputs/data-collection-and-field-costs.entity'; +import { CarbonRights } from '@shared/entities/cost-inputs/establishing-carbon-rights.entity'; +import { FinancingCost } from '@shared/entities/cost-inputs/financing-cost.entity'; +import { LongTermProjectOperating } from '@shared/entities/cost-inputs/long-term-project-operating.entity'; +import { Maintenance } from '@shared/entities/cost-inputs/maintenance.entity'; +import { MonitoringCost } from '@shared/entities/cost-inputs/monitoring.entity'; +import { MRV } from '@shared/entities/cost-inputs/mrv.entity'; +import { ValidationCost } from '@shared/entities/cost-inputs/validation.entity'; +import { ImplementationLaborCost } from '@shared/entities/cost-inputs/implementation-labor-cost.entity'; @Injectable() export class ImportRepository { constructor(private readonly dataSource: DataSource) {} - async ingest(importData: { baseData: BaseData[]; projects: Project[] }) { + async ingest(importData: { + projects: Project[]; + projectSize: ProjectSize[]; + feasibilityAnalysis: FeasibilityAnalysis[]; + conservationPlanningAndAdmin: ConservationPlanningAndAdmin[]; + dataCollectionAndFieldCosts: DataCollectionAndFieldCosts[]; + communityRepresentation: CommunityRepresentation[]; + blueCarbonProjectPlanning: BlueCarbonProjectPlanning[]; + establishingCarbonRights: CarbonRights[]; + financingCost: FinancingCost[]; + validationCost: ValidationCost[]; + monitoringCost: MonitoringCost[]; + maintenanceCost: Maintenance[]; + communityBenefit: CommunityBenefitSharingFund[]; + baselineReassessment: BaselineReassessment[]; + mrv: MRV[]; + longTermProjectOperating: LongTermProjectOperating[]; + carbonStandardFees: CarbonStandardFees[]; + communityCashFlow: CommunityCashFlow[]; + ecosystemExtent: EcosystemExtent[]; + ecosystemLoss: EcosystemLoss[]; + restorableLand: RestorableLand[]; + sequestrationRate: SequestrationRate[]; + emissionFactors: EmissionFactors[]; + implementationLaborCost: ImplementationLaborCost[]; + }) { return this.dataSource.transaction(async (manager) => { - // TODO: Workaround as there are N/A country codes in the excel file - const existingCountries = await manager - .createQueryBuilder() - .select('countries.code', 'countryCode') - .from(Country, 'countries') - .getRawMany(); - const countryFilteredBaseData: BaseData[] = []; - existingCountries.forEach(({ countryCode }) => { - const countryData = importData.baseData.find( - (data) => data.country.code === countryCode, - ); - if (countryData) { - countryFilteredBaseData.push(countryData); - } - }); - await manager.save(countryFilteredBaseData); await manager.save(importData.projects); + + // Cost inputs ingestion + await manager.save(importData.projectSize); + await manager.save(importData.feasibilityAnalysis); + await manager.save(importData.conservationPlanningAndAdmin); + await manager.save(importData.dataCollectionAndFieldCosts); + await manager.save(importData.communityRepresentation); + await manager.save(importData.blueCarbonProjectPlanning); + await manager.save(importData.establishingCarbonRights); + await manager.save(importData.financingCost); + await manager.save(importData.validationCost); + await manager.save(importData.monitoringCost); + await manager.save(importData.maintenanceCost); + await manager.save(importData.communityBenefit); + await manager.save(importData.baselineReassessment); + await manager.save(importData.mrv); + await manager.save(importData.longTermProjectOperating); + await manager.save(importData.carbonStandardFees); + await manager.save(importData.communityCashFlow); + await manager.save(importData.implementationLaborCost); + + // Carbon inputs ingestion + await manager.save(importData.ecosystemExtent); + await manager.save(importData.ecosystemLoss); + await manager.save(importData.restorableLand); + await manager.save(importData.sequestrationRate); + await manager.save(importData.emissionFactors); }); } } diff --git a/api/src/modules/import/services/entity.preprocessor.ts b/api/src/modules/import/services/entity.preprocessor.ts index b869268d..774b3048 100644 --- a/api/src/modules/import/services/entity.preprocessor.ts +++ b/api/src/modules/import/services/entity.preprocessor.ts @@ -1,36 +1,95 @@ +import { ExcelEstablishingCarbonRights } from './../dtos/excel-establishing-carbon-rights.dto'; import { Injectable } from '@nestjs/common'; -import { BaseData } from '@shared/entities/base-data.entity'; import { Country } from '@shared/entities/country.entity'; -import { ExcelMasterTable } from '@api/modules/import/excel-base-data.dto'; -import { ProjectSize } from '@shared/entities/project-size.entity'; -import { FeasibilityAnalysis } from '@shared/entities/feasability-analysis.entity'; -import { ConservationPlanningAndAdmin } from '@shared/entities/conservation-and-planning-admin.entity'; -import { CommunityRepresentation } from '@shared/entities/community-representation.entity'; -import { CarbonRights } from '@shared/entities/establishing-carbon-rights.entity'; -import { FinancingCost } from '@shared/entities/financing-cost.entity'; -import { ValidationCost } from '@shared/entities/validation.entity'; -import { ImplementationLaborCost } from '@shared/entities/implementation-labor.entity'; -import { MonitoringCost } from '@shared/entities/monitoring.entity'; -import { Maintenance } from '@shared/entities/maintenance.entity'; -import { DataCollectionAndFieldCosts } from '@shared/entities/data-collection-and-field-costs.entity'; -import { CommunityBenefitSharingFund } from '@shared/entities/community-benefit-sharing-fund.entity'; -import { CarbonStandardFees } from '@shared/entities/carbon-standard-fees.entity'; -import { CommunityCashFlow } from '@shared/entities/community-cash-flow.entity'; -import { EcosystemLoss } from '@shared/entities/ecosystem-loss.entity'; -import { RestorableLand } from '@shared/entities/restorable-land.entity'; -import { EmissionFactors } from '@shared/entities/emission-factors.entity'; -import { BaselineReassessment } from '@shared/entities/baseline-reassessment.entity'; -import { MRV } from '@shared/entities/mrv.entity'; -import { BlueCarbonProjectPlanning } from '@shared/entities/blue-carbon-project-planning.entity'; -import { LongTermProjectOperating } from '@shared/entities/long-term-project-operating.entity'; -import { SequestrationRate } from '@shared/entities/sequestration-rate.entity'; +import { ExcelMasterTable } from '@api/modules/import/dtos/excel-base-data.dto'; import { Project } from '@shared/entities/projects.entity'; -import { ExcelProjects } from '@api/modules/import/excel-projects.dto'; +import { ExcelProjects } from '@api/modules/import/dtos/excel-projects.dto'; +import { ExcelProjectSize } from '@api/modules/import/dtos/excel-project-size.dto'; +import { ACTIVITY } from '@shared/entities/activity.enum'; +import { ECOSYSTEM } from '@shared/entities/ecosystem.enum'; +import { ExcelFeasibilityAnalysis } from '../dtos/excel-feasibility-analysis.dto'; +import { ExcelConservationPlanningAndAdmin } from '../dtos/excel-conservation-planning-and-admin.dto'; +import { ExcelDataCollectionAndFieldCosts } from '../dtos/excel-data-collection-field-cost.dto'; +import { ExcelCommunityRepresentation } from '../dtos/excel-community-representation.dto'; +import { + BlueCarbonProjectPlanning, + INPUT_SELECTION, +} from '@shared/entities/cost-inputs/blue-carbon-project-planning.entity'; +import { ExcelBlueCarbonProjectPlanning } from '../dtos/excel-blue-carbon-project-planning.dto'; +import { ExcelFinancingCost } from '../dtos/excel-financing-cost.dto'; +import { ExcelValidation } from '../dtos/excel-validation.dto'; +import { ExcelMonitoring } from '../dtos/excel-monitoring.dto'; +import { ExcelMaintenance } from '../dtos/excel-maintenance.dto'; +import { ExcelCommunityBenefitSharingFund } from '../dtos/excel-community-benefit-sharing-fund.dto'; +import { ExcelBaselineReassessment } from '../dtos/excel-baseline-reassessment.dto'; +import { ExcelMRV } from '../dtos/excel-mrv.dto'; +import { ExcelLongTermProjectOperating } from '../dtos/excel-long-term-project-operating.dto'; +import { ExcelCarbonStandardFees } from '../dtos/excel-carbon-standard-fees.dto'; +import { ExcelCommunityCashFlow } from '../dtos/excel-community-cash-flow.dto'; +import { + COMMUNITY_CASH_FLOW_TYPES, + CommunityCashFlow, +} from '@shared/entities/cost-inputs/community-cash-flow.entity'; +import { ExcelEcosystemExtent } from '../dtos/excel-ecosystem-extent.dto'; +import { ExcelEcosystemLoss } from '../dtos/excel-ccosystem-loss.dto'; +import { ExcelRestorableLand } from '../dtos/excel-restorable-land.dto'; +import { ExcelSequestrationRate } from '../dtos/excel-sequestration-rate.dto'; +import { + SEQUESTRATION_RATE_TIER_TYPES, + SequestrationRate, +} from '@shared/entities/carbon-inputs/sequestration-rate.entity'; +import { + EMISSION_FACTORS_TIER_TYPES, + EmissionFactors, +} from '@shared/entities/carbon-inputs/emission-factors.entity'; +import { ExcelEmissionFactors } from '../dtos/excel-emission-factors.dto'; +import { EcosystemExtent } from '@shared/entities/carbon-inputs/ecosystem-extent.entity'; +import { EcosystemLoss } from '@shared/entities/carbon-inputs/ecosystem-loss.entity'; +import { RestorableLand } from '@shared/entities/carbon-inputs/restorable-land.entity'; +import { BaselineReassessment } from '@shared/entities/cost-inputs/baseline-reassessment.entity'; +import { CarbonStandardFees } from '@shared/entities/cost-inputs/carbon-standard-fees.entity'; +import { CommunityBenefitSharingFund } from '@shared/entities/cost-inputs/community-benefit-sharing-fund.entity'; +import { CommunityRepresentation } from '@shared/entities/cost-inputs/community-representation.entity'; +import { ConservationPlanningAndAdmin } from '@shared/entities/cost-inputs/conservation-and-planning-admin.entity'; +import { DataCollectionAndFieldCosts } from '@shared/entities/cost-inputs/data-collection-and-field-costs.entity'; +import { CarbonRights } from '@shared/entities/cost-inputs/establishing-carbon-rights.entity'; +import { FeasibilityAnalysis } from '@shared/entities/cost-inputs/feasability-analysis.entity'; +import { FinancingCost } from '@shared/entities/cost-inputs/financing-cost.entity'; +import { LongTermProjectOperating } from '@shared/entities/cost-inputs/long-term-project-operating.entity'; +import { Maintenance } from '@shared/entities/cost-inputs/maintenance.entity'; +import { MonitoringCost } from '@shared/entities/cost-inputs/monitoring.entity'; +import { MRV } from '@shared/entities/cost-inputs/mrv.entity'; +import { ProjectSize } from '@shared/entities/cost-inputs/project-size.entity'; +import { ValidationCost } from '@shared/entities/cost-inputs/validation.entity'; +import { ExcelImplementationLaborCost } from '../dtos/excel-implementation-labor.dto'; +import { ImplementationLaborCost } from '@shared/entities/cost-inputs/implementation-labor-cost.entity'; export type ParsedDBEntities = { - baseData: BaseData[]; projects: Project[]; + projectSize: ProjectSize[]; + feasibilityAnalysis: FeasibilityAnalysis[]; + conservationPlanningAndAdmin: ConservationPlanningAndAdmin[]; + dataCollectionAndFieldCosts: DataCollectionAndFieldCosts[]; + communityRepresentation: CommunityRepresentation[]; + blueCarbonProjectPlanning: BlueCarbonProjectPlanning[]; + establishingCarbonRights: CarbonRights[]; + financingCost: FinancingCost[]; + validationCost: ValidationCost[]; + monitoringCost: MonitoringCost[]; + maintenanceCost: Maintenance[]; + communityBenefit: CommunityBenefitSharingFund[]; + baselineReassessment: BaselineReassessment[]; + mrv: MRV[]; + longTermProjectOperating: LongTermProjectOperating[]; + carbonStandardFees: CarbonStandardFees[]; + communityCashFlow: CommunityCashFlow[]; + ecosystemExtent: EcosystemExtent[]; + ecosystemLoss: EcosystemLoss[]; + restorableLand: RestorableLand[]; + sequestrationRate: SequestrationRate[]; + emissionFactors: EmissionFactors[]; + implementationLaborCost: ImplementationLaborCost[]; }; @Injectable() @@ -38,124 +97,886 @@ export class EntityPreprocessor { toDbEntities(raw: { master_table: ExcelMasterTable[]; Projects: ExcelProjects[]; + 'Project size': ExcelProjectSize[]; + 'Feasibility analysis': ExcelFeasibilityAnalysis[]; + 'Conservation planning and admin': ExcelConservationPlanningAndAdmin[]; + 'Data collection and field costs': ExcelDataCollectionAndFieldCosts[]; + 'Community representation': ExcelCommunityRepresentation[]; + 'Blue carbon project planning': ExcelBlueCarbonProjectPlanning[]; + 'Establishing carbon rights': ExcelEstablishingCarbonRights[]; + 'Financing cost': ExcelFinancingCost[]; + Validation: ExcelValidation[]; + Monitoring: ExcelMonitoring[]; + Maintenance: ExcelMaintenance[]; + 'Community benefit sharing fund': ExcelCommunityBenefitSharingFund[]; + 'Baseline reassessment': ExcelBaselineReassessment[]; + MRV: ExcelMRV[]; + 'Long-term project operating': ExcelLongTermProjectOperating[]; + 'Carbon standard fees': ExcelCarbonStandardFees[]; + 'Community cash flow': ExcelCommunityCashFlow[]; + 'Ecosystem extent': ExcelEcosystemExtent[]; + 'Ecosystem loss': ExcelEcosystemLoss[]; + 'Restorable land': ExcelRestorableLand[]; + 'Sequestration rate': ExcelSequestrationRate[]; + 'Emission factors': ExcelEmissionFactors[]; + 'Implementation labor': ExcelImplementationLaborCost[]; }): ParsedDBEntities { - const parsedBaseData = this.processBaseData(raw.master_table); const processedProjects = this.processProjects(raw.Projects); + + // process cost inputs + const projectSize = this.processProjectSize(raw['Project size']); + const feasabilityAnalysis = this.processFeasabilityAnalysis( + raw['Feasibility analysis'], + ); + const conservationPlanningAndAdmin = + this.processConservationPlanningAndAdmin( + raw['Conservation planning and admin'], + ); + const dataCollectionAndFieldCosts = this.processDataCollectionAndFieldCosts( + raw['Data collection and field costs'], + ); + const communityRepresentation = this.processCommunityRepresentation( + raw['Community representation'], + ); + const blueCarbonProjectPlanning = this.processBlueCarbonProjectPlanning( + raw['Blue carbon project planning'], + ); + const establishingCarbonRights = this.processEstablishingCarbonRights( + raw['Establishing carbon rights'], + ); + const financingCost = this.processFinancingCost(raw['Financing cost']); + const validationCost = this.processValidationCost(raw['Validation']); + const monitoringCost = this.processMonitoringCost(raw.Monitoring); + const maintenanceCost = this.processMaintenanceCost(raw.Maintenance); + const communityBenefit = this.processCommunityBenefit( + raw['Community benefit sharing fund'], + ); + const baselineReassessment = this.processBaselineReassessment( + raw['Baseline reassessment'], + ); + const mrv = this.processMRV(raw.MRV); + const longTermProjectOperating = this.processLongTermProjectOperating( + raw['Long-term project operating'], + ); + const carbonStandardFees = this.processCarbonStandardFees( + raw['Carbon standard fees'], + ); + const communityCashFlow = this.processCommunityCashFlow( + raw['Community cash flow'], + ); + const implementationLaborCost = this.processImplementationLaborCost( + raw['Implementation labor'], + ); + + // proess carbon inputs + const ecosystemExtent = this.processEcosystemExtent( + raw['Ecosystem extent'], + ); + const ecosystemLoss = this.processEcosystemLoss(raw['Ecosystem loss']); + const restorableLand = this.processRestorableLand(raw['Restorable land']); + const sequestrationRate = this.processSequestrationRate( + raw['Sequestration rate'], + ); + const emissionFactors = this.processEmissionFactors( + raw['Emission factors'], + ); + return { - baseData: parsedBaseData, projects: processedProjects, + projectSize: projectSize, + feasibilityAnalysis: feasabilityAnalysis, + conservationPlanningAndAdmin: conservationPlanningAndAdmin, + dataCollectionAndFieldCosts: dataCollectionAndFieldCosts, + communityRepresentation: communityRepresentation, + blueCarbonProjectPlanning: blueCarbonProjectPlanning, + establishingCarbonRights: establishingCarbonRights, + financingCost: financingCost, + validationCost: validationCost, + monitoringCost: monitoringCost, + maintenanceCost: maintenanceCost, + communityBenefit: communityBenefit, + baselineReassessment: baselineReassessment, + mrv: mrv, + longTermProjectOperating: longTermProjectOperating, + carbonStandardFees: carbonStandardFees, + communityCashFlow: communityCashFlow, + ecosystemExtent: ecosystemExtent, + ecosystemLoss: ecosystemLoss, + restorableLand: restorableLand, + sequestrationRate: sequestrationRate, + emissionFactors: emissionFactors, + implementationLaborCost: implementationLaborCost, }; } - private processBaseData(raw: ExcelMasterTable[]) { - const parsedArray: BaseData[] = []; - raw.forEach((row: ExcelMasterTable) => { - const baseData = new BaseData(); - - baseData.country = { code: row.country_code } as Country; - baseData.activity = row.activity; - baseData.ecosystem = row.ecosystem; - - baseData.projectSize = { - sizeHa: this.emptyStringToZero(row.project_size_ha), - } as ProjectSize; - baseData.feasibilityAnalysis = { - analysisScore: this.emptyStringToZero(row.feasibility_analysis), - } as FeasibilityAnalysis; - baseData.conservationPlanningAndAdmin = { - planningCost: this.emptyStringToZero( - row.conservation_planning_and_admin, - ), - } as ConservationPlanningAndAdmin; - baseData.communityRepresentation = { - liaisonCost: this.emptyStringToZero(row.community_representation), - } as CommunityRepresentation; - baseData.carbonRights = { - carbonRightsCost: this.emptyStringToZero( - row.establishing_carbon_rights, - ), - } as CarbonRights; - baseData.financingCost = { - financingCostCapexPercent: this.emptyStringToZero(row.financing_cost), - } as FinancingCost; - baseData.validationCost = { - validationCost: this.emptyStringToZero(row.validation), - } as ValidationCost; - baseData.implementationLaborCost = { - implementationLaborCost: this.emptyStringToZero( - row.implementation_labor_planting, - ), - } as ImplementationLaborCost; - baseData.monitoringCost = { - monitoringCost: this.emptyStringToZero(row.monitoring), - } as MonitoringCost; - baseData.maintenance = { - maintenanceCost: this.emptyStringToZero(row.maintenance), - maintenanceDuration: this.emptyStringToZero(row.maintenance_duration), - } as Maintenance; - baseData.dataCollectionAndFieldCosts = { - fieldCost: this.emptyStringToZero(row.data_collection_and_field_costs), - } as DataCollectionAndFieldCosts; - baseData.communityBenefit = { - benefitSharingFund: this.emptyStringToZero( - row.community_benefit_sharing_fund, - ), - } as CommunityBenefitSharingFund; - baseData.carbonStandardFees = { - carbonStandardFee: this.emptyStringToZero(row.carbon_standard_fees), - } as CarbonStandardFees; - baseData.communityCashFlow = { - cashflowType: this.emptyStringToNull(row.other_community_cash_flow), - } as CommunityCashFlow; - baseData.ecosystemLoss = { - ecosystemLossRate: this.emptyStringToZero(row.ecosystem_loss_rate), - } as EcosystemLoss; - baseData.restorableLand = { - restorableLand: this.emptyStringToZero(row.restorable_land), - } as RestorableLand; - // TODO: Since this is the value that is selected in the corresponding tab within different tiers, maybe the naming is a bit confusing, talk with Elena - // since still is not clear how to handle the "selectable entities" we will populate all of them for now - const emissionFactorvalue = this.emptyStringToZero( - row.tier_1_emission_factor, - ); - baseData.emissionFactors = { - tier1Factor: emissionFactorvalue, - tier2AGBFactor: this.emptyStringToZero(row.emission_factor_AGB), - tier2SOCFactor: this.emptyStringToZero(row.emission_factor_SOC), - } as EmissionFactors; - baseData.baselineReassessment = { - baselineReassessmentCost: this.emptyStringToZero( - row.baseline_reassessment, - ), - } as BaselineReassessment; - baseData.mrv = { - mrvCost: this.emptyStringToZero(row.MRV), - } as MRV; - // TODO: This is also a selectable entity, we need to talk about how to handle this - const blueCarbonProjectPlanningValue = this.emptyStringToZero( - row.blue_carbon_project_planning, - ); - baseData.blueCarbonProjectPlanning = { - input1: blueCarbonProjectPlanningValue, - input2: blueCarbonProjectPlanningValue, - input3: blueCarbonProjectPlanningValue, - } as BlueCarbonProjectPlanning; - - baseData.longTermProjectOperating = { - longTermProjectOperatingCost: this.emptyStringToZero( - row.long_term_project_operating_cost, - ), - } as LongTermProjectOperating; - // TODO: This is also a selectable entity, we need to talk about how to handle this - const sequestrationRateValue = this.emptyStringToZero( - row.sequestration_rate, - ); - baseData.sequestrationRate = { - tier1Factor: this.emptyStringToZero(row.sequestration_rate), - tier2Factor: sequestrationRateValue, - } as SequestrationRate; - - parsedArray.push(baseData); + private processImplementationLaborCost(raw: ExcelImplementationLaborCost[]) { + const parsedArray: ImplementationLaborCost[] = []; + raw.forEach((row: ExcelImplementationLaborCost) => { + // mangrove implementation labor cost + const mangroveImplementationLaborCost = new ImplementationLaborCost(); + mangroveImplementationLaborCost.ecosystem = ECOSYSTEM.MANGROVE; + mangroveImplementationLaborCost.country = { + code: row['Country code'], + } as Country; + mangroveImplementationLaborCost.plantingCost = this.stringToNumeric( + row['Mangrove planting'], + ); + mangroveImplementationLaborCost.hybridCost = this.stringToNumeric( + row['Mangrove hybrid'], + ); + mangroveImplementationLaborCost.hydrologyCost = this.stringToNumeric( + row['Mangrove hydrology'], + ); + parsedArray.push(mangroveImplementationLaborCost); + + // seagrass implementation labor cost + const seagrassImplementationLaborCost = new ImplementationLaborCost(); + seagrassImplementationLaborCost.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassImplementationLaborCost.country = { + code: row['Country code'], + } as Country; + seagrassImplementationLaborCost.plantingCost = this.stringToNumeric( + row['Seagrass planting'], + ); + seagrassImplementationLaborCost.hybridCost = this.stringToNumeric( + row['Seagrass hybrid'], + ); + seagrassImplementationLaborCost.hydrologyCost = this.stringToNumeric( + row['Seagrass hydrology'], + ); + parsedArray.push(seagrassImplementationLaborCost); + + // salt marsh implementation labor cost + const saltMarshImplementationLaborCost = new ImplementationLaborCost(); + saltMarshImplementationLaborCost.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshImplementationLaborCost.country = { + code: row['Country code'], + } as Country; + saltMarshImplementationLaborCost.plantingCost = this.stringToNumeric( + row['Salt marsh planting'], + ); + saltMarshImplementationLaborCost.hybridCost = this.stringToNumeric( + row['Salt marsh hybrid'], + ); + saltMarshImplementationLaborCost.hydrologyCost = this.stringToNumeric( + row['Salt marsh hydrology'], + ); + parsedArray.push(saltMarshImplementationLaborCost); + }); + return parsedArray; + } + + private processEmissionFactors(raw: ExcelEmissionFactors[]) { + const parsedArray: EmissionFactors[] = []; + raw.forEach((row: ExcelEmissionFactors) => { + // mangrove emission factors + const mangroveEmissionFactors = new EmissionFactors(); + mangroveEmissionFactors.ecosystem = ECOSYSTEM.MANGROVE; + mangroveEmissionFactors.country = { + code: row['Country code'], + } as Country; + mangroveEmissionFactors.tierSelector = row[ + 'Selection (only for mangroves)' + ] as EMISSION_FACTORS_TIER_TYPES; + mangroveEmissionFactors.global = this.stringToNumeric( + row['Mangrove - Tier 1 - Global emission factor'], + ); + mangroveEmissionFactors.t2CountrySpecificAGB = this.stringToNumeric( + row['Mangrove - Tier 2 - Country-specific emission factor - AGB'], + ); + mangroveEmissionFactors.t2CountrySpecificSOC = this.stringToNumeric( + row['Mangrove - Tier 2 - Country-specific emission factor - SOC'], + ); + parsedArray.push(mangroveEmissionFactors); + + // seagrass emission factors + const seagrassEmissionFactors = new EmissionFactors(); + seagrassEmissionFactors.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassEmissionFactors.country = { + code: row['Country code'], + } as Country; + seagrassEmissionFactors.tierSelector = row[ + 'Selection (only for seagrass)' + ] as EMISSION_FACTORS_TIER_TYPES; + seagrassEmissionFactors.global = this.stringToNumeric( + row['Seagrass - Tier 1 - Global emission factor'], + ); + seagrassEmissionFactors.t2CountrySpecificAGB = this.stringToNumeric( + row['Seagrass - Tier 2 - Country-specific emission factor - AGB'], + ); + seagrassEmissionFactors.t2CountrySpecificSOC = this.stringToNumeric( + row['Seagrass - Tier 2 - Country-specific emission factor - SOC'], + ); + parsedArray.push(seagrassEmissionFactors); + + // salt marsh emission factors + const saltMarshEmissionFactors = new EmissionFactors(); + saltMarshEmissionFactors.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshEmissionFactors.country = { + code: row['Country code'], + } as Country; + saltMarshEmissionFactors.tierSelector = row[ + 'Selection (only for salt marsh)' + ] as EMISSION_FACTORS_TIER_TYPES; + saltMarshEmissionFactors.global = this.stringToNumeric( + row['Salt marsh - Tier 1 - Global emission factor'], + ); + saltMarshEmissionFactors.t2CountrySpecificAGB = this.stringToNumeric( + row['Salt marsh - Tier 2 - Country-specific emission factor - AGB'], + ); + saltMarshEmissionFactors.t2CountrySpecificSOC = this.stringToNumeric( + row['Salt marsh - Tier 2 - Country-specific emission factor - SOC'], + ); + parsedArray.push(saltMarshEmissionFactors); + }); + return parsedArray; + } + + private processSequestrationRate(raw: ExcelSequestrationRate[]) { + const parsedArray: SequestrationRate[] = []; + raw.forEach((row: ExcelSequestrationRate) => { + // mangrove sequestration rate + const mangroveSequestrationRate = new SequestrationRate(); + mangroveSequestrationRate.ecosystem = ECOSYSTEM.MANGROVE; + mangroveSequestrationRate.country = { + code: row['Country code'], + } as Country; + mangroveSequestrationRate.tierSelector = row[ + 'Input used (mangrove only)' + ] as SEQUESTRATION_RATE_TIER_TYPES; + mangroveSequestrationRate.tier1Factor = this.stringToNumeric( + row['Mangrove Tier 1 - IPCC default value'], + ); + mangroveSequestrationRate.tier2Factor = this.stringToNumeric( + row['Mangrove Tier 2 - country-specific rate'], + ); + parsedArray.push(mangroveSequestrationRate); + + // seagrass sequestration rate + const seagrassSequestrationRate = new SequestrationRate(); + seagrassSequestrationRate.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassSequestrationRate.country = { + code: row['Country code'], + } as Country; + seagrassSequestrationRate.tierSelector = row[ + 'Input used (seagrass only)' + ] as SEQUESTRATION_RATE_TIER_TYPES; + seagrassSequestrationRate.tier1Factor = this.stringToNumeric( + row['Seagrass Tier 1 - IPCC default value'], + ); + seagrassSequestrationRate.tier2Factor = this.stringToNumeric( + row['Seagrass Tier 2 - country-specific rate'], + ); + parsedArray.push(seagrassSequestrationRate); + + // salt marsh sequestration rate + const saltMarshSequestrationRate = new SequestrationRate(); + saltMarshSequestrationRate.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshSequestrationRate.country = { + code: row['Country code'], + } as Country; + saltMarshSequestrationRate.tierSelector = row[ + 'Input used (salt marsh only)' + ] as SEQUESTRATION_RATE_TIER_TYPES; + saltMarshSequestrationRate.tier1Factor = this.stringToNumeric( + row['Salt marsh Tier 1 - IPCC default value'], + ); + saltMarshSequestrationRate.tier2Factor = this.stringToNumeric( + row['Salt marsh Tier 2 - country-specific rate'], + ); + parsedArray.push(saltMarshSequestrationRate); + }); + return parsedArray; + } + + private processRestorableLand(raw: ExcelRestorableLand[]) { + const parsedArray: RestorableLand[] = []; + raw.forEach((row: ExcelRestorableLand) => { + // mangrove restorable land + const mangroveRestorableLand = new RestorableLand(); + mangroveRestorableLand.ecosystem = ECOSYSTEM.MANGROVE; + mangroveRestorableLand.country = { + code: row['Country code'], + } as Country; + mangroveRestorableLand.restorableLand = this.stringToNumeric( + row['Mangrove restorable land'], + ); + parsedArray.push(mangroveRestorableLand); + + // seagrass restorable land + const seagrassRestorableLand = new RestorableLand(); + seagrassRestorableLand.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassRestorableLand.country = { + code: row['Country code'], + } as Country; + seagrassRestorableLand.restorableLand = this.stringToNumeric( + row['Seagrass restorable land'], + ); + parsedArray.push(seagrassRestorableLand); + + // salt marsh restorable land + const saltMarshRestorableLand = new RestorableLand(); + saltMarshRestorableLand.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshRestorableLand.country = { + code: row['Country code'], + } as Country; + saltMarshRestorableLand.restorableLand = this.stringToNumeric( + row['Salt marsh restorable land'], + ); + parsedArray.push(saltMarshRestorableLand); + }); + return parsedArray; + } + + private processEcosystemLoss(raw: ExcelEcosystemLoss[]) { + const parsedArray: EcosystemLoss[] = []; + raw.forEach((row: ExcelEcosystemLoss) => { + // mangrove ecosystem loss + const mangroveEcosystemLoss = new EcosystemLoss(); + mangroveEcosystemLoss.ecosystem = ECOSYSTEM.MANGROVE; + mangroveEcosystemLoss.country = { + code: row['Country code'], + } as Country; + mangroveEcosystemLoss.ecosystemLossRate = this.percentToNumber( + row['Mangrove loss rate'], + ); + parsedArray.push(mangroveEcosystemLoss); + + // seagrass ecosystem loss + const seagrassEcosystemLoss = new EcosystemLoss(); + seagrassEcosystemLoss.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassEcosystemLoss.country = { + code: row['Country code'], + } as Country; + seagrassEcosystemLoss.ecosystemLossRate = this.percentToNumber( + row['Seagrass loss rate'], + ); + parsedArray.push(seagrassEcosystemLoss); + + // salt marsh ecosystem loss + const saltMarshEcosystemLoss = new EcosystemLoss(); + saltMarshEcosystemLoss.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshEcosystemLoss.country = { + code: row['Country code'], + } as Country; + saltMarshEcosystemLoss.ecosystemLossRate = this.percentToNumber( + row['Salt marsh loss rate'], + ); + parsedArray.push(saltMarshEcosystemLoss); + }); + return parsedArray; + } + + private processEcosystemExtent(raw: ExcelEcosystemExtent[]) { + const parsedArray: EcosystemExtent[] = []; + raw.forEach((row: ExcelEcosystemExtent) => { + // mangrove ecosystem extent + const mangroveEcosystemExtent = new EcosystemExtent(); + mangroveEcosystemExtent.ecosystem = ECOSYSTEM.MANGROVE; + mangroveEcosystemExtent.country = { + code: row['Country code'], + } as Country; + mangroveEcosystemExtent.extent = this.stringToNumeric( + row[' Mangrove extent'], + ); + mangroveEcosystemExtent.historicExtent = this.stringToNumeric( + row[' Mangrove extent historic'], + ); + parsedArray.push(mangroveEcosystemExtent); + + // seagrass ecosystem extent + const seagrassEcosystemExtent = new EcosystemExtent(); + seagrassEcosystemExtent.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassEcosystemExtent.country = { + code: row['Country code'], + } as Country; + seagrassEcosystemExtent.extent = this.stringToNumeric( + row[' Seagrass extent'], + ); + seagrassEcosystemExtent.historicExtent = this.stringToNumeric( + row[' Seagrass extent historic'], + ); + parsedArray.push(seagrassEcosystemExtent); + + // salt marsh ecosystem extent + const saltMarshEcosystemExtent = new EcosystemExtent(); + saltMarshEcosystemExtent.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshEcosystemExtent.country = { + code: row['Country code'], + } as Country; + saltMarshEcosystemExtent.extent = this.stringToNumeric( + row[' Salt marsh extent'], + ); + saltMarshEcosystemExtent.historicExtent = this.stringToNumeric( + row['Salt marsh extent historic'], + ); + parsedArray.push(saltMarshEcosystemExtent); + }); + return parsedArray; + } + + private processCommunityCashFlow(raw: ExcelCommunityCashFlow[]) { + const parsedArray: CommunityCashFlow[] = []; + raw.forEach((row: ExcelCommunityCashFlow) => { + const communityCashFlow = new CommunityCashFlow(); + communityCashFlow.country = { + code: row['Country code'], + } as Country; + communityCashFlow.cashflowType = this.emptyStringToNull( + row['Other community cash flow'], + ) as COMMUNITY_CASH_FLOW_TYPES; + parsedArray.push(communityCashFlow); + }); + return parsedArray; + } + + private processCarbonStandardFees(raw: ExcelCarbonStandardFees[]) { + const parsedArray: CarbonStandardFees[] = []; + raw.forEach((row: ExcelCarbonStandardFees) => { + const carbonStandardFees = new CarbonStandardFees(); + carbonStandardFees.country = { + code: row['Country code'], + } as Country; + carbonStandardFees.carbonStandardFee = this.stringToNumeric( + row['Carbon standard fees'], + ); + parsedArray.push(carbonStandardFees); + }); + return parsedArray; + } + + private processLongTermProjectOperating( + raw: ExcelLongTermProjectOperating[], + ) { + const parsedArray: LongTermProjectOperating[] = []; + raw.forEach((row: ExcelLongTermProjectOperating) => { + // mangrove long term project operating + const mangroveLongTermProjectOperating = new LongTermProjectOperating(); + mangroveLongTermProjectOperating.ecosystem = ECOSYSTEM.MANGROVE; + mangroveLongTermProjectOperating.country = { + code: row['Country code'], + } as Country; + mangroveLongTermProjectOperating.longTermProjectOperatingCost = + this.emptyStringToZero(row['Mangrove long-term project operating']); + parsedArray.push(mangroveLongTermProjectOperating); + + // seagrass long term project operating + const seagrassLongTermProjectOperating = new LongTermProjectOperating(); + seagrassLongTermProjectOperating.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassLongTermProjectOperating.country = { + code: row['Country code'], + } as Country; + seagrassLongTermProjectOperating.longTermProjectOperatingCost = + this.emptyStringToZero(row['Seagrass long-term project operating']); + parsedArray.push(seagrassLongTermProjectOperating); + + // salt marsh long term project operating + const saltMarshLongTermProjectOperating = new LongTermProjectOperating(); + saltMarshLongTermProjectOperating.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshLongTermProjectOperating.country = { + code: row['Country code'], + } as Country; + saltMarshLongTermProjectOperating.longTermProjectOperatingCost = + this.emptyStringToZero(row['Salt marsh long-term project operating']); + parsedArray.push(saltMarshLongTermProjectOperating); + }); + return parsedArray; + } + + private processMRV(raw: ExcelMRV[]) { + const parsedArray: MRV[] = []; + raw.forEach((row: ExcelMRV) => { + const mrv = new MRV(); + mrv.country = { + code: row['Country code'], + } as Country; + mrv.mrvCost = this.emptyStringToZero(row.MRV); + parsedArray.push(mrv); + }); + return parsedArray; + } + + private processBaselineReassessment(raw: ExcelBaselineReassessment[]) { + const parsedArray: BaselineReassessment[] = []; + raw.forEach((row: ExcelBaselineReassessment) => { + const baselineReassessment = new BaselineReassessment(); + baselineReassessment.country = { + code: row['Country code'], + } as Country; + baselineReassessment.baselineReassessmentCost = this.emptyStringToZero( + row['Baseline reassessment'], + ); + parsedArray.push(baselineReassessment); + }); + return parsedArray; + } + + private processCommunityBenefit(raw: ExcelCommunityBenefitSharingFund[]) { + const parsedArray: CommunityBenefitSharingFund[] = []; + raw.forEach((row: ExcelCommunityBenefitSharingFund) => { + const communityBenefit = new CommunityBenefitSharingFund(); + communityBenefit.country = { + code: row['Country code'], + } as Country; + communityBenefit.communityBenefitSharingFund = this.percentToNumber( + row['Community benefit sharing fund'], + ); + parsedArray.push(communityBenefit); + }); + return parsedArray; + } + + private processMaintenanceCost(raw: ExcelMaintenance[]) { + const parsedArray: Maintenance[] = []; + raw.forEach((row: ExcelMaintenance) => { + const maintenanceCost = new Maintenance(); + maintenanceCost.country = { + code: row['Country code'], + } as Country; + maintenanceCost.maintenanceCost = this.percentToNumber( + row['Maintenance'], + ); + maintenanceCost.maintenanceDuration = this.emptyStringToZero( + row['Maintenance duration'], + ); + parsedArray.push(maintenanceCost); + }); + return parsedArray; + } + + private processMonitoringCost(raw: ExcelMonitoring[]) { + const parsedArray: MonitoringCost[] = []; + raw.forEach((row: ExcelMonitoring) => { + // mangrove monitoring + const mangroveMonitoring = new MonitoringCost(); + mangroveMonitoring.ecosystem = ECOSYSTEM.MANGROVE; + mangroveMonitoring.country = { + code: row['Country code'], + } as Country; + mangroveMonitoring.monitoringCost = this.emptyStringToZero( + row['Mangrove monitoring'], + ); + parsedArray.push(mangroveMonitoring); + + // seagrass monitoring + const seagrassMonitoring = new MonitoringCost(); + seagrassMonitoring.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassMonitoring.country = { + code: row['Country code'], + } as Country; + seagrassMonitoring.monitoringCost = this.emptyStringToZero( + row['Seagrass monitoring'], + ); + parsedArray.push(seagrassMonitoring); + + // salt marsh monitoring + const saltMarshMonitoring = new MonitoringCost(); + saltMarshMonitoring.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshMonitoring.country = { + code: row['Country code'], + } as Country; + saltMarshMonitoring.monitoringCost = this.emptyStringToZero( + row['Salt marsh monitoring'], + ); + parsedArray.push(saltMarshMonitoring); + }); + return parsedArray; + } + + private processValidationCost(raw: ExcelValidation[]) { + const parsedArray: ValidationCost[] = []; + raw.forEach((row: ExcelValidation) => { + const validationCost = new ValidationCost(); + validationCost.country = { + code: row['Country code'], + } as Country; + validationCost.validationCost = this.emptyStringToZero(row['Validation']); + parsedArray.push(validationCost); + }); + return parsedArray; + } + + private processFinancingCost(raw: ExcelFinancingCost[]) { + const parsedArray: FinancingCost[] = []; + raw.forEach((row: ExcelFinancingCost) => { + const financingCost = new FinancingCost(); + financingCost.country = { + code: row['Country code'], + } as Country; + financingCost.financingCostCapexPercent = this.percentToNumber( + row['Financing cost'], + ); + parsedArray.push(financingCost); + }); + return parsedArray; + } + + private processEstablishingCarbonRights( + raw: ExcelEstablishingCarbonRights[], + ) { + const parsedArray: CarbonRights[] = []; + raw.forEach((row: ExcelEstablishingCarbonRights) => { + const carbonRights = new CarbonRights(); + carbonRights.country = { + code: row['Country code'], + } as Country; + carbonRights.carbonRightsCost = this.emptyStringToZero( + row['Establishing carbon rights'], + ); + parsedArray.push(carbonRights); + }); + return parsedArray; + } + + private processBlueCarbonProjectPlanning( + raw: ExcelBlueCarbonProjectPlanning[], + ) { + const parsedArray: BlueCarbonProjectPlanning[] = []; + raw.forEach((row: ExcelBlueCarbonProjectPlanning) => { + const blueCarbonProjectPlanning = new BlueCarbonProjectPlanning(); + blueCarbonProjectPlanning.country = { + code: row['Country code'], + } as Country; + blueCarbonProjectPlanning.inputSelection = this.emptyStringToNull( + row['Input selection'], + ) as INPUT_SELECTION; + blueCarbonProjectPlanning.input1 = this.emptyStringToZero(row['Input 1']); + blueCarbonProjectPlanning.input2 = this.emptyStringToZero(row['Input 2']); + blueCarbonProjectPlanning.input3 = this.emptyStringToZero(row['Input 3']); + parsedArray.push(blueCarbonProjectPlanning); + }); + + return parsedArray; + } + + private processCommunityRepresentation(raw: ExcelCommunityRepresentation[]) { + const parsedArray: CommunityRepresentation[] = []; + raw.forEach((row: ExcelCommunityRepresentation) => { + // mangrove community representation + const mangroveCommunityRepresentation = new CommunityRepresentation(); + mangroveCommunityRepresentation.ecosystem = ECOSYSTEM.MANGROVE; + mangroveCommunityRepresentation.country = { + code: row['Country code'], + } as Country; + mangroveCommunityRepresentation.liaisonCost = this.emptyStringToZero( + row['Mangrove community representation / liaison'], + ); + parsedArray.push(mangroveCommunityRepresentation); + + // seagrass community representation + const seagrassCommunityRepresentation = new CommunityRepresentation(); + seagrassCommunityRepresentation.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassCommunityRepresentation.country = { + code: row['Country code'], + } as Country; + seagrassCommunityRepresentation.liaisonCost = this.emptyStringToZero( + row['Seagrass Community representation / liaison'], + ); + parsedArray.push(seagrassCommunityRepresentation); + + // salt marsh community representation + const saltMarshCommunityRepresentation = new CommunityRepresentation(); + saltMarshCommunityRepresentation.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshCommunityRepresentation.country = { + code: row['Country code'], + } as Country; + saltMarshCommunityRepresentation.liaisonCost = this.emptyStringToZero( + row['Salt marsh Community representation / liaison'], + ); + parsedArray.push(saltMarshCommunityRepresentation); + }); + return parsedArray; + } + + private processDataCollectionAndFieldCosts( + raw: ExcelDataCollectionAndFieldCosts[], + ) { + const parsedArray: DataCollectionAndFieldCosts[] = []; + raw.forEach((row: ExcelDataCollectionAndFieldCosts) => { + // mangrove data collection and field costs + const mangroveDataCollectionAndFieldCosts = + new DataCollectionAndFieldCosts(); + mangroveDataCollectionAndFieldCosts.ecosystem = ECOSYSTEM.MANGROVE; + mangroveDataCollectionAndFieldCosts.country = { + code: row['Country code'], + } as Country; + mangroveDataCollectionAndFieldCosts.fieldCost = this.emptyStringToZero( + row['Mangrove data collection and field costs'], + ); + parsedArray.push(mangroveDataCollectionAndFieldCosts); + + // seagrass data collection and field costs + const seagrassDataCollectionAndFieldCosts = + new DataCollectionAndFieldCosts(); + seagrassDataCollectionAndFieldCosts.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassDataCollectionAndFieldCosts.country = { + code: row['Country code'], + } as Country; + seagrassDataCollectionAndFieldCosts.fieldCost = this.emptyStringToZero( + row['Seagrass data collection and field costs'], + ); + parsedArray.push(seagrassDataCollectionAndFieldCosts); + + // salt marsh data collection and field costs + const saltMarshDataCollectionAndFieldCosts = + new DataCollectionAndFieldCosts(); + saltMarshDataCollectionAndFieldCosts.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshDataCollectionAndFieldCosts.country = { + code: row['Country code'], + } as Country; + saltMarshDataCollectionAndFieldCosts.fieldCost = this.emptyStringToZero( + row['Salt marsh data collection and field costs'], + ); + parsedArray.push(saltMarshDataCollectionAndFieldCosts); + }); + return parsedArray; + } + + private processConservationPlanningAndAdmin( + raw: ExcelConservationPlanningAndAdmin[], + ) { + const parsedArray: ConservationPlanningAndAdmin[] = []; + raw.forEach((row: ExcelConservationPlanningAndAdmin) => { + // mangrove conservation planning and admin + const mangroveConservationPlanningAndAdmin = + new ConservationPlanningAndAdmin(); + mangroveConservationPlanningAndAdmin.ecosystem = ECOSYSTEM.MANGROVE; + mangroveConservationPlanningAndAdmin.country = { + code: row['Country code'], + } as Country; + mangroveConservationPlanningAndAdmin.planningCost = + this.emptyStringToZero(row['Mangrove conservation planning and admin']); + parsedArray.push(mangroveConservationPlanningAndAdmin); + + // seagrass conservation planning and admin + const seagrassConservationPlanningAndAdmin = + new ConservationPlanningAndAdmin(); + seagrassConservationPlanningAndAdmin.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassConservationPlanningAndAdmin.country = { + code: row['Country code'], + } as Country; + seagrassConservationPlanningAndAdmin.planningCost = + this.emptyStringToZero(row['Seagrass conservation planning and admin']); + parsedArray.push(seagrassConservationPlanningAndAdmin); + + // salt marsh conservation planning and admin + const saltMarshConservationPlanningAndAdmin = + new ConservationPlanningAndAdmin(); + saltMarshConservationPlanningAndAdmin.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshConservationPlanningAndAdmin.country = { + code: row['Country code'], + } as Country; + saltMarshConservationPlanningAndAdmin.planningCost = + this.emptyStringToZero( + row['Salt marsh conservation planning and admin'], + ); + parsedArray.push(saltMarshConservationPlanningAndAdmin); + }); + return parsedArray; + } + + private processFeasabilityAnalysis(raw: ExcelFeasibilityAnalysis[]) { + const parsedArray: FeasibilityAnalysis[] = []; + raw.forEach((row: ExcelFeasibilityAnalysis) => { + // mangrove feasibility analysis + const mangroveFeasibilityAnalysis = new FeasibilityAnalysis(); + mangroveFeasibilityAnalysis.ecosystem = ECOSYSTEM.MANGROVE; + mangroveFeasibilityAnalysis.country = { + code: row['Country code'], + } as Country; + mangroveFeasibilityAnalysis.analysisCost = this.emptyStringToZero( + row['Mangrove feasibility analysis'], + ); + parsedArray.push(mangroveFeasibilityAnalysis); + + // seagrass feasibility + const seagrassFeasibilityAnalysis = new FeasibilityAnalysis(); + seagrassFeasibilityAnalysis.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassFeasibilityAnalysis.country = { + code: row['Country code'], + } as Country; + seagrassFeasibilityAnalysis.analysisCost = this.emptyStringToZero( + row['Seagrass feasibility analysis'], + ); + parsedArray.push(seagrassFeasibilityAnalysis); + + // salt marsh feasibility + const saltMarshFeasibilityAnalysis = new FeasibilityAnalysis(); + saltMarshFeasibilityAnalysis.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshFeasibilityAnalysis.country = { + code: row['Country code'], + } as Country; + saltMarshFeasibilityAnalysis.analysisCost = this.emptyStringToZero( + row['Salt marsh feasibility analysis'], + ); + parsedArray.push(saltMarshFeasibilityAnalysis); + }); + + return parsedArray; + } + + private processProjectSize(raw: ExcelProjectSize[]) { + const parsedArray: ProjectSize[] = []; + raw.forEach((row: ExcelProjectSize) => { + // mangrove restored + const mangroveRestoredArea = new ProjectSize(); + mangroveRestoredArea.activity = ACTIVITY.RESTORATION; + mangroveRestoredArea.ecosystem = ECOSYSTEM.MANGROVE; + mangroveRestoredArea.country = { code: row['Country code'] } as Country; + mangroveRestoredArea.sizeHa = this.emptyStringToZero( + row['Mangrove restored area'], + ); + parsedArray.push(mangroveRestoredArea); + + // mangrove conserved + const mangroveConservedArea = new ProjectSize(); + mangroveConservedArea.activity = ACTIVITY.CONSERVATION; + mangroveConservedArea.ecosystem = ECOSYSTEM.MANGROVE; + mangroveConservedArea.country = { code: row['Country code'] } as Country; + mangroveConservedArea.sizeHa = this.emptyStringToZero( + row['Mangrove conserved area'], + ); + parsedArray.push(mangroveConservedArea); + + // seagrass restored + const seagrassRestoredArea = new ProjectSize(); + seagrassRestoredArea.activity = ACTIVITY.RESTORATION; + seagrassRestoredArea.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassRestoredArea.country = { code: row['Country code'] } as Country; + seagrassRestoredArea.sizeHa = this.emptyStringToZero( + row['Seagrass restored area'], + ); + parsedArray.push(seagrassRestoredArea); + + // seagrass conserved + const seagrassConservedArea = new ProjectSize(); + seagrassConservedArea.activity = ACTIVITY.CONSERVATION; + seagrassConservedArea.ecosystem = ECOSYSTEM.SEAGRASS; + seagrassConservedArea.country = { code: row['Country code'] } as Country; + seagrassConservedArea.sizeHa = this.emptyStringToZero( + row['Seagrass conserved area'], + ); + parsedArray.push(seagrassConservedArea); + + // salt marsh restored + const saltMarshRestoredArea = new ProjectSize(); + saltMarshRestoredArea.activity = ACTIVITY.RESTORATION; + saltMarshRestoredArea.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshRestoredArea.country = { code: row['Country code'] } as Country; + saltMarshRestoredArea.sizeHa = this.emptyStringToZero( + row['Salt marsh restored area'], + ); + parsedArray.push(saltMarshRestoredArea); + + // salt marsh conserved + const saltMarshConservedArea = new ProjectSize(); + saltMarshConservedArea.activity = ACTIVITY.CONSERVATION; + saltMarshConservedArea.ecosystem = ECOSYSTEM.SALT_MARSH; + saltMarshConservedArea.country = { code: row['Country code'] } as Country; + saltMarshConservedArea.sizeHa = this.emptyStringToZero( + row['Salt marsh conserved area'], + ); + parsedArray.push(saltMarshConservedArea); }); return parsedArray; } @@ -164,20 +985,20 @@ export class EntityPreprocessor { const parsedArray: Project[] = []; raw.forEach((row: ExcelProjects) => { const project = new Project(); - project.projectName = row.Project_name; - project.countryCode = row['Country code']; - project.ecosystem = row.Ecosystem; - project.activity = row.Activity; - project.activitySubtype = row.Activity_type; - project.projectSize = row.Project_size; - project.projectSizeFilter = row.Project_size_filter; - project.abatementPotential = row.Abatement_potential; - project.totalCostNPV = row.Total_cost_NPV; - project.totalCost = row.Total_cost; + project.projectName = row.project_name; + project.countryCode = row.country_code; + project.ecosystem = row.ecosystem; + project.activity = row.activity; + project.activitySubtype = row.activity_type; + project.projectSize = row.project_size_ha; + project.projectSizeFilter = row.project_size_filter; + project.abatementPotential = row.aAbatement_potential; + project.totalCostNPV = row.total_cost_NPV; + project.totalCost = row.total_cost; project.costPerTCO2eNPV = row['$/tCO2e (NPV)']; project.costPerTCO2e = row['$/tCO2e']; - project.initialPriceAssumption = row['Initial price assumption']; - project.priceType = row['Price type']; + project.initialPriceAssumption = row.initial_price_assumption; + project.priceType = row.price_type; parsedArray.push(project); }); @@ -191,4 +1012,12 @@ export class EntityPreprocessor { private emptyStringToZero(value: any): any | 0 { return value || 0; } + + private percentToNumber(value: any, defaultReturn: number = 0): number { + return value ? parseFloat(value) : defaultReturn; + } + + private stringToNumeric(value: any): number { + return value ? parseFloat(value) : 0; + } } diff --git a/api/src/modules/import/services/excel-parser.interface.ts b/api/src/modules/import/services/excel-parser.interface.ts index 9ecfc3b3..642be941 100644 --- a/api/src/modules/import/services/excel-parser.interface.ts +++ b/api/src/modules/import/services/excel-parser.interface.ts @@ -1,5 +1,31 @@ export const ExcelParserToken = Symbol('ExcelParserInterface'); -export const SHEETS_TO_PARSE = ['master_table', 'Projects'] as const; +export const SHEETS_TO_PARSE = [ + 'master_table', + 'Projects', + 'Project size', + 'Feasibility analysis', + 'Conservation planning and admin', + 'Data collection and field costs', + 'Community representation', + 'Blue carbon project planning', + 'Establishing carbon rights', + 'Financing cost', + 'Validation', + 'Monitoring', + 'Maintenance', + 'Community benefit sharing fund', + 'Baseline reassessment', + 'MRV', + 'Long-term project operating', + 'Carbon standard fees', + 'Community cash flow', + 'Ecosystem extent', + 'Ecosystem loss', + 'Restorable land', + 'Sequestration rate', + 'Emission factors', + 'Implementation labor', +] as const; export interface ExcelParserInterface { parseExcel(data: Buffer): Promise; diff --git a/api/src/modules/import/services/xlsx.parser.ts b/api/src/modules/import/services/xlsx.parser.ts index 7d32b5b9..3cb2ff27 100644 --- a/api/src/modules/import/services/xlsx.parser.ts +++ b/api/src/modules/import/services/xlsx.parser.ts @@ -4,7 +4,7 @@ import { ExcelParserInterface, SHEETS_TO_PARSE, } from './excel-parser.interface'; -import { ExcelMasterTable } from '@api/modules/import/excel-base-data.dto'; +import { ExcelMasterTable } from '@api/modules/import/dtos/excel-base-data.dto'; @Injectable() export class XlsxParser implements ExcelParserInterface { diff --git a/api/src/modules/model/base-data.repository.ts b/api/src/modules/model/base-data.repository.ts deleted file mode 100644 index 70f1ef42..00000000 --- a/api/src/modules/model/base-data.repository.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { DataSource, Repository } from 'typeorm'; -import { Injectable } from '@nestjs/common'; -import { BaseData } from '@shared/entities/base-data.entity'; -import { Country } from '@shared/entities/country.entity'; - -@Injectable() -export class BaseDataRepository extends Repository { - constructor(private datasource: DataSource) { - super(BaseData, datasource.createEntityManager()); - } - - async saveBaseData(baseData: BaseData[]): Promise { - // TODO: This is a workaround to filter base data by countries that are present in the DB. THis should be removed once we have proper country data - const existingCountries = await this.datasource - .createQueryBuilder() - .select('countries.code', 'countryCode') - .from(Country, 'countries') - .getRawMany(); - const toSave: BaseData[] = []; - existingCountries.forEach(({ countryCode }) => { - const countryData = baseData.find( - (data) => data.country.code === countryCode, - ); - if (countryData) { - toSave.push(countryData); - } - }); - - return this.save(toSave); - } -} diff --git a/api/src/modules/model/model.module.ts b/api/src/modules/model/model.module.ts deleted file mode 100644 index 0ba17b86..00000000 --- a/api/src/modules/model/model.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { BaseDataRepository } from '@api/modules/model/base-data.repository'; -import { BaseData } from '@shared/entities/base-data.entity'; - -@Module({ - imports: [TypeOrmModule.forFeature([BaseData])], - providers: [BaseDataRepository], - exports: [BaseDataRepository], -}) -export class ModelModule {} diff --git a/api/test/integration/import/import.spec.ts b/api/test/integration/import/import.spec.ts index fb5bc6a8..60af4827 100644 --- a/api/test/integration/import/import.spec.ts +++ b/api/test/integration/import/import.spec.ts @@ -4,14 +4,14 @@ import { adminContract } from '@shared/contracts/admin.contract'; import { ROLES } from '@shared/entities/users/roles.enum'; import * as path from 'path'; import * as fs from 'fs'; -import { BaseData } from '@shared/entities/base-data.entity'; +import { BaseDataView } from '@shared/entities/base-data.view'; describe('Import Tests', () => { let testManager: TestManager; let testUserToken: string; const testFilePath = path.join( __dirname, - '../../../../data/excel/data_ingestion.xlsm', + '../../../../data/excel/data_ingestion_WIP.xlsm', ); const fileBuffer = fs.readFileSync(testFilePath); @@ -54,26 +54,26 @@ describe('Import Tests', () => { .request() .post(adminContract.uploadFile.path) .set('Authorization', `Bearer ${jwtToken}`) - .attach('file', fileBuffer, 'data_ingestion.xlsm'); + .attach('file', fileBuffer, 'data_ingestion_WIP.xlsm'); expect(response.status).toBe(HttpStatus.FORBIDDEN); }); }); describe('Import Data', () => { - it('should import data from an excel file', async () => { + it('should import cost data from an excel file', async () => { await testManager.ingestCountries(); await testManager .request() .post(adminContract.uploadFile.path) .set('Authorization', `Bearer ${testUserToken}`) - .attach('file', fileBuffer, 'data_ingestion.xlsm'); + .attach('file', fileBuffer, 'data_ingestion_WIP.xlsm'); - const baseData = await testManager + const baseDataView = await testManager .getDataSource() - .getRepository(BaseData) + .getRepository(BaseDataView) .find(); - expect(baseData).toHaveLength(222); + expect(baseDataView).toHaveLength(54); }, 30000); }); }); diff --git a/api/test/integration/project-map/project-map.spec.ts b/api/test/integration/project-map/project-map.spec.ts index 7eacbf4a..710c39b5 100644 --- a/api/test/integration/project-map/project-map.spec.ts +++ b/api/test/integration/project-map/project-map.spec.ts @@ -3,7 +3,7 @@ import { HttpStatus } from '@nestjs/common'; import { Project } from '@shared/entities/projects.entity'; import { Country } from '@shared/entities/country.entity'; import { projectsContract } from '@shared/contracts/projects.contract'; -import { ECOSYSTEM } from '@shared/entities/base-data.entity'; +import { ECOSYSTEM } from '@shared/entities/ecosystem.enum'; describe('Project Map', () => { let testManager: TestManager; diff --git a/api/test/utils/test-manager.ts b/api/test/utils/test-manager.ts index 63249c63..8e619451 100644 --- a/api/test/utils/test-manager.ts +++ b/api/test/utils/test-manager.ts @@ -12,18 +12,15 @@ import { User } from '@shared/entities/users/user.entity'; import { IEmailServiceToken } from '@api/modules/notifications/email/email-service.interface'; import { MockEmailService } from './mocks/mock-email.service'; import { ROLES } from '@shared/entities/users/roles.enum'; -import { - createBaseData, - createProject, - createUser, -} from '@shared/lib/entity-mocks'; + +import { createProject, createUser } from '@shared/lib/entity-mocks'; import { clearTablesByEntities, clearTestDataFromDatabase, } from '@shared/lib/db-helpers'; + import * as path from 'path'; import * as fs from 'fs'; -import { BaseData } from '@shared/entities/base-data.entity'; import { Project } from '@shared/entities/projects.entity'; /** * @description: Abstraction for NestJS testing workflow. For now its a basic implementation to create a test app, but can be extended to encapsulate @@ -115,8 +112,6 @@ export class TestManager { return { createUser: (additionalData?: Partial) => createUser(this.getDataSource(), additionalData), - createBaseData: async (additionalData?: Partial) => - createBaseData(this.getDataSource(), additionalData), createProject: async (additionalData?: Partial) => createProject(this.getDataSource(), additionalData), }; diff --git a/data/excel/data_ingestion_WIP.xlsm b/data/excel/data_ingestion_WIP.xlsm new file mode 100644 index 00000000..e8772f9f Binary files /dev/null and b/data/excel/data_ingestion_WIP.xlsm differ diff --git a/package.json b/package.json index f2edc4a9..e2ddd3f5 100644 --- a/package.json +++ b/package.json @@ -16,4 +16,4 @@ "all:prod": "pnpm run build:client && pnpm run build:api && pnpm run start:client:prod & pnpm run start:api:prod & pnpm run start:admin:prod" }, "packageManager": "pnpm@9.9.0+sha512.60c18acd138bff695d339be6ad13f7e936eea6745660d4cc4a776d5247c540d0edee1a563695c183a66eb917ef88f2b4feb1fc25f32a7adcadc7aaf3438e99c1" -} +} \ No newline at end of file diff --git a/shared/dtos/projects/projects-map.dto.ts b/shared/dtos/projects/projects-map.dto.ts index 4aba437d..bf83e828 100644 --- a/shared/dtos/projects/projects-map.dto.ts +++ b/shared/dtos/projects/projects-map.dto.ts @@ -1,11 +1,12 @@ import { z } from "zod"; import { FeatureCollection, Geometry } from "geojson"; import { ProjectGeoPropertiesSchema } from "@shared/schemas/geometries/projects"; -import { ACTIVITY, ECOSYSTEM } from "@shared/entities/base-data.entity"; import { PROJECT_PRICE_TYPE, PROJECT_SIZE_FILTER, } from "@shared/entities/projects.entity"; +import { ACTIVITY } from "@shared/entities/activity.enum"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; export type ProjectGeoProperties = z.infer; diff --git a/shared/entities/activity.enum.ts b/shared/entities/activity.enum.ts new file mode 100644 index 00000000..2e0cb11a --- /dev/null +++ b/shared/entities/activity.enum.ts @@ -0,0 +1,4 @@ +export enum ACTIVITY { + RESTORATION = "Restoration", + CONSERVATION = "Conservation", +} diff --git a/shared/entities/base-data.entity.ts b/shared/entities/base-data.entity.ts deleted file mode 100644 index bb61bc76..00000000 --- a/shared/entities/base-data.entity.ts +++ /dev/null @@ -1,369 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - ManyToOne, - JoinColumn, - BaseEntity, - OneToOne, - Index, -} from "typeorm"; -import { Country } from "@shared/entities/country.entity"; -import { ProjectSize } from "@shared/entities/project-size.entity"; -import { FeasibilityAnalysis } from "@shared/entities/feasability-analysis.entity"; -import { ConservationPlanningAndAdmin } from "@shared/entities/conservation-and-planning-admin.entity"; -import { DataCollectionAndFieldCosts } from "@shared/entities/data-collection-and-field-costs.entity"; -import { CommunityRepresentation } from "./community-representation.entity"; -import { CarbonRights } from "./establishing-carbon-rights.entity"; -import { FinancingCost } from "./financing-cost.entity"; -import { ValidationCost } from "./validation.entity"; -import { ImplementationLaborCost } from "./implementation-labor.entity"; -import { MonitoringCost } from "./monitoring.entity"; -import { Maintenance } from "./maintenance.entity"; -import { CommunityBenefitSharingFund } from "./community-benefit-sharing-fund.entity"; -import { CarbonStandardFees } from "./carbon-standard-fees.entity"; -import { EcosystemLoss } from "./ecosystem-loss.entity"; -import { RestorableLand } from "./restorable-land.entity"; -import { EmissionFactors } from "./emission-factors.entity"; -import { BaselineReassessment } from "./baseline-reassessment.entity"; -import { MRV } from "./mrv.entity"; -import { BlueCarbonProjectPlanning } from "./blue-carbon-project-planning.entity"; -import { LongTermProjectOperating } from "./long-term-project-operating.entity"; -import { SequestrationRate } from "./sequestration-rate.entity"; -import { CommunityCashFlow } from "@shared/entities/community-cash-flow.entity"; - -export enum ECOSYSTEM { - MANGROVE = "Mangrove", - SEAGRASS = "Seagrass", - SALT_MARSH = "Salt marsh", -} - -export enum ACTIVITY { - RESTORATION = "Restoration", - CONSERVATION = "Conservation", -} - -@Entity("base_data") -@Index( - "compose_idx_countrycode_ecosystem_activity", - ["ecosystem", "activity", "countryCode"], - { unique: true }, -) -export class BaseData extends BaseEntity { - // TODO: We could use a integer value as primary to match the excel rows so that we know if there are new values or something is being updated - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) - ecosystem: ECOSYSTEM; - - @Column({ name: "activity", enum: ACTIVITY, type: "enum" }) - activity: ACTIVITY; - - @Column({ name: "country_code", length: 3, nullable: true, type: "char" }) - countryCode: string; - - // Unidirectional relation - @ManyToOne(() => Country) - @JoinColumn({ name: "country_code" }) - country: Country; - - // Using a string reference to avoid AdminJS crashing when no metadata for this entity is found through BaseData - @OneToOne("ProjectSize", (projectSize: ProjectSize) => projectSize.baseData, { - cascade: ["insert"], - onDelete: "CASCADE", - }) - @JoinColumn({ name: "project_size", referencedColumnName: "id" }) - projectSize: ProjectSize; - - @OneToOne( - "FeasibilityAnalysis", - (feasibilityAnalysis: FeasibilityAnalysis) => feasibilityAnalysis.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ name: "feasibility_analysis", referencedColumnName: "id" }) - feasibilityAnalysis: FeasibilityAnalysis; - - @OneToOne( - "ConservationPlanningAndAdmin", - (conservationPlanningAndAdmin: ConservationPlanningAndAdmin) => - conservationPlanningAndAdmin.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "conservation_planning_and_admin", - referencedColumnName: "id", - }) - conservationPlanningAndAdmin: ConservationPlanningAndAdmin; - - @OneToOne( - "CommunityRepresentation", - (communityRepresentation: CommunityRepresentation) => - communityRepresentation.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "community_representation", - referencedColumnName: "id", - }) - communityRepresentation: CommunityRepresentation; - - @OneToOne( - "CarbonRights", - (carbonRights: CarbonRights) => carbonRights.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "carbon_rights", - referencedColumnName: "id", - }) - carbonRights: CarbonRights; - - @OneToOne( - "FinancingCost", - (financingCost: FinancingCost) => financingCost.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "financing_cost", - referencedColumnName: "id", - }) - financingCost: FinancingCost; - - @OneToOne( - "ValidationCost", - (validationCost: ValidationCost) => validationCost.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "validation_cost", - referencedColumnName: "id", - }) - validationCost: ValidationCost; - - @OneToOne( - "ImplementationLaborCost", - (implementationLaborCost: ImplementationLaborCost) => - implementationLaborCost.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "implementation_labor_cost", - referencedColumnName: "id", - }) - implementationLaborCost: ImplementationLaborCost; - - @OneToOne( - "MonitoringCost", - (monitoringCost: MonitoringCost) => monitoringCost.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "monitoring_cost", - referencedColumnName: "id", - }) - monitoringCost: MonitoringCost; - - @OneToOne("Maintenance", (maintenance: Maintenance) => maintenance.baseData, { - cascade: ["insert"], - onDelete: "CASCADE", - }) - @JoinColumn({ - name: "maintenance", - referencedColumnName: "id", - }) - maintenance: Maintenance; - - @OneToOne( - "DataCollectionAndFieldCosts", - (dataCollectionAndFieldCosts: DataCollectionAndFieldCosts) => - dataCollectionAndFieldCosts.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "data_collection_and_field_costs", - referencedColumnName: "id", - }) - dataCollectionAndFieldCosts: DataCollectionAndFieldCosts; - - @OneToOne( - "CommunityBenefitSharingFund", - (communityBenefit: CommunityBenefitSharingFund) => - communityBenefit.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "community_benefit_sharing_fund", - referencedColumnName: "id", - }) - communityBenefit: CommunityBenefitSharingFund; - - @OneToOne( - "CarbonStandardFees", - (carbonStandardFees: CarbonStandardFees) => carbonStandardFees.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "carbon_standard_fees", - referencedColumnName: "id", - }) - carbonStandardFees: CarbonStandardFees; - - @OneToOne( - "CommunityCashFlow", - (communityCashFlow: CommunityCashFlow) => communityCashFlow.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "community_cash_flow", - referencedColumnName: "id", - }) - communityCashFlow: CommunityCashFlow; - - @OneToOne( - "EcosystemLoss", - (ecosystemLoss: EcosystemLoss) => ecosystemLoss.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "ecosystem_loss", - referencedColumnName: "id", - }) - ecosystemLoss: EcosystemLoss; - - @OneToOne( - "RestorableLand", - (restorableLand: RestorableLand) => restorableLand.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "restorable_land", - referencedColumnName: "id", - }) - restorableLand: RestorableLand; - - @OneToOne( - "EmissionFactors", - (emissionFactors: EmissionFactors) => emissionFactors.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "emission_factors", - referencedColumnName: "id", - }) - emissionFactors: EmissionFactors; - - @OneToOne( - "BaselineReassessment", - (baselineReassessment: BaselineReassessment) => - baselineReassessment.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "baseline_reassessment", - referencedColumnName: "id", - }) - baselineReassessment: BaselineReassessment; - - @OneToOne("MRV", (mrv: MRV) => mrv.baseData, { - cascade: ["insert"], - onDelete: "CASCADE", - }) - @JoinColumn({ - name: "mrv", - referencedColumnName: "id", - }) - mrv: MRV; - - @OneToOne( - "BlueCarbonProjectPlanning", - (blueCarbonProjectPlanning: BlueCarbonProjectPlanning) => - blueCarbonProjectPlanning.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "blue_carbon_project_planning", - referencedColumnName: "id", - }) - blueCarbonProjectPlanning: BlueCarbonProjectPlanning; - - @OneToOne( - "LongTermProjectOperating", - (longTermProjectOperating: LongTermProjectOperating) => - longTermProjectOperating.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "long_term_project_operating", - referencedColumnName: "id", - }) - longTermProjectOperating: LongTermProjectOperating; - - @OneToOne( - "SequestrationRate", - (sequestrationRate: SequestrationRate) => sequestrationRate.baseData, - { - cascade: ["insert"], - onDelete: "CASCADE", - }, - ) - @JoinColumn({ - name: "sequestration_rate", - referencedColumnName: "id", - }) - sequestrationRate: SequestrationRate; -} diff --git a/shared/entities/base-data.view.ts b/shared/entities/base-data.view.ts new file mode 100644 index 00000000..e5a25c55 --- /dev/null +++ b/shared/entities/base-data.view.ts @@ -0,0 +1,230 @@ +import { ViewColumn, ViewEntity } from "typeorm"; + +@ViewEntity({ + name: "base_data_view", + expression: ` +WITH country_activity_ecosystem_combinations AS ( + SELECT + c.code AS country_code, + a.activity as activity, + e.ecosystem as ecosystem + FROM + (SELECT DISTINCT code FROM countries) c + CROSS JOIN + (SELECT 'Restoration'::VARCHAR AS activity UNION ALL + SELECT 'Conservation'::VARCHAR) AS a + CROSS JOIN + (SELECT 'Mangrove'::VARCHAR AS ecosystem UNION ALL + SELECT 'Seagrass'::VARCHAR UNION ALL + SELECT 'Salt marsh'::VARCHAR) AS e +) +select + cae.country_code as country_code, + cae.ecosystem as ecosystem, + cae.activity as activity, + ps.size as project_size_ha, + fa.analysis_cost_per_project as feasibility_analysis, + cpa.planning_cost_per_project as conservation_planning_and_admin, + dcfc.field_cost_per_project as data_collection_and_field_cost, + cr.liaison_cost as community_representation, + bcpp.blue_carbon as blue_carbon_project_planning, + crights.carbon_rights_cost as establishing_carbon_rights, + fc.financing_cost_capex_percent as financing_cost, + vc.validation_cost as validation, + ilc.planting_cost_ha as implementation_labor_planting, + ilc.hybrid_cost_ha as implementation_labor_hybrid, + ilc.hydrology_cost_ha as implementation_labor_hydrology, + monitoring.monitoring_cost_per_year as monitoring, + maintenance.maintenance_cost_pc_of_impl_labor_cost as maintenance, + maintenance.maintenance_duration_years as maintenance_duration, + csf.cost_per_carbon_credit_issued as carbon_standard_fees, + cbsf.community_benefit_sharing_fund_pc_of_revenue as community_benefit_sharing_fund, + br.baseline_reassessment_cost_per_event as baseline_reassessment, + mrv.mrv_cost_per_event as MRV, + ltpo.long_term_project_operating_cost_per_year as long_term_project_operating_cost, + ee.extent as ecosystem_extent, + ee.historic_extent as ecosystem_extent_historic, + elr.ecosystem_loss_rate as ecosystem_loss_rate, + rl.restorable_land as restorable_land, + ef.emission_factor_global as tier_1_emission_factor, + ef.emission_factor_agb as emission_factor_AGB, + ef.emission_factor_soc as emission_factor_SOC, + sr.tier_1_factor as tier_1_sequestration_rate, + sr.tier_2_factor as tier_2_sequestration_rate, + ccf."cashflowType" as other_community_cash_flow +from + country_activity_ecosystem_combinations as cae +inner join + project_size ps on + ps."country_code" = cae.country_code and + ps."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR and + ps."activity"::VARCHAR = cae."activity"::VARCHAR +inner join + feasibility_analysis fa on + fa."country_code" = cae.country_code and + fa."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + conservation_planning_and_admin cpa on + cpa."country_code" = cae.country_code and + cpa."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + data_collection_and_field_costs dcfc on + dcfc."country_code" = cae.country_code and + dcfc."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + community_representation cr on + cr."country_code" = cae.country_code and + cr."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + blue_carbon_project_planning bcpp on bcpp."country_code" = cae.country_code +inner join + carbon_rights crights on crights."country_code" = cae.country_code +inner join + financing_cost fc on fc."country_code" = cae.country_code +inner join + validation_cost vc on vc."country_code" = cae.country_code +inner join + monitoring_cost monitoring on + monitoring."country_code" = cae.country_code and + monitoring."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + implementation_labor_cost ilc on + ilc."country_code" = cae.country_code and + ilc."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + maintenance maintenance on maintenance."country_code" = cae.country_code +inner join + carbon_standard_fees csf on csf."country_code" = cae.country_code +inner join + community_benefit_sharing_fund cbsf on cbsf."country_code" = cae.country_code +inner join + baseline_reassessment br on br."country_code" = cae.country_code +inner join + mrv mrv on mrv."country_code" = cae.country_code +inner join + long_term_project_operating ltpo on + ltpo."country_code" = cae.country_code and + ltpo."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + ecosystem_extent ee on + ee."country_code" = cae.country_code and + ee."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + ecosystem_loss elr on + elr."country_code" = cae.country_code and + elr."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + restorable_land rl on + rl."country_code" = cae.country_code and + rl."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + emission_factors ef on + ef."country_code" = cae.country_code and + ef."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + sequestration_rate sr on + sr."country_code" = cae.country_code and + sr."ecosystem"::VARCHAR = cae."ecosystem"::VARCHAR +inner join + community_cash_flow ccf on ccf."country_code" = cae.country_code`, +}) +export class BaseDataView { + @ViewColumn({ name: "country_code" }) + country_code: string; + + @ViewColumn({ name: "ecosystem" }) + ecosystem: string; + + @ViewColumn({ name: "activity" }) + activity: string; + + @ViewColumn({ name: "project_size_ha" }) + project_size_ha: number; + + @ViewColumn({ name: "feasibility_analysis" }) + feasibility_analysis: number; + + @ViewColumn({ name: "conservation_planning_and_admin" }) + conservation_planning_and_admin: number; + + @ViewColumn({ name: "data_collection_and_field_cost" }) + data_collection_and_field_cost: number; + + @ViewColumn({ name: "community_representation" }) + community_representation: number; + + @ViewColumn({ name: "blue_carbon_project_planning" }) + blue_carbon_project_planning: number; + + @ViewColumn({ name: "establishing_carbon_rights" }) + establishing_carbon_rights: number; + + @ViewColumn({ name: "financing_cost" }) + financing_cost: number; + + @ViewColumn({ name: "validation" }) + validation: number; + + @ViewColumn({ name: "implementation_labor_planting" }) + implementation_labor_planting: number; + + @ViewColumn({ name: "implementation_labor_hybrid" }) + implementation_labor_hybrid: number; + + @ViewColumn({ name: "implementation_labor_hydrology" }) + implementation_labor_hydrology: number; + + @ViewColumn({ name: "monitoring" }) + monitoring: number; + + @ViewColumn({ name: "maintenance" }) + maintenance: number; + + @ViewColumn({ name: "maintenance_duration" }) + maintenance_duration: number; + + @ViewColumn({ name: "carbon_standard_fees" }) + carbon_standard_fees: number; + + @ViewColumn({ name: "community_benefit_sharing_fund" }) + community_benefit_sharing_fund: number; + + @ViewColumn({ name: "baseline_reassessment" }) + baseline_reassessment: number; + + @ViewColumn({ name: "mrv" }) + mrv: number; + + @ViewColumn({ name: "long_term_project_operating_cost" }) + long_term_project_operating_cost: number; + + @ViewColumn({ name: "ecosystem_extent" }) + ecosystem_extent: number; + + @ViewColumn({ name: "ecosystem_extent_historic" }) + ecosystem_extent_historic: number; + + @ViewColumn({ name: "ecosystem_loss_rate" }) + ecosystem_loss_rate: number; + + @ViewColumn({ name: "restorable_land" }) + restorable_land: number; + + @ViewColumn({ name: "tier_1_emission_factor" }) + tier_1_emission_factor: number; + + @ViewColumn({ name: "emission_factor_agb" }) + emission_factor_agb: number; + + @ViewColumn({ name: "emission_factor_soc" }) + emission_factor_soc: number; + + @ViewColumn({ name: "tier_1_sequestration_rate" }) + tier_1_sequestration_rate: number; + + @ViewColumn({ name: "tier_2_sequestration_rate" }) + tier_2_sequestration_rate: number; + + @ViewColumn({ name: "other_community_cash_flow" }) + other_community_cash_flow: string; +} diff --git a/shared/entities/carbon-inputs/ecosystem-extent.entity.ts b/shared/entities/carbon-inputs/ecosystem-extent.entity.ts new file mode 100644 index 00000000..6404701e --- /dev/null +++ b/shared/entities/carbon-inputs/ecosystem-extent.entity.ts @@ -0,0 +1,31 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("ecosystem_extent") +@Unique(["country", "ecosystem"]) +export class EcosystemExtent extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "extent", nullable: true }) + extent: number; + + @Column("decimal", { name: "historic_extent", nullable: true }) + historicExtent: number; +} diff --git a/shared/entities/carbon-inputs/ecosystem-loss.entity.ts b/shared/entities/carbon-inputs/ecosystem-loss.entity.ts new file mode 100644 index 00000000..975a7927 --- /dev/null +++ b/shared/entities/carbon-inputs/ecosystem-loss.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("ecosystem_loss") +@Unique(["country", "ecosystem"]) +export class EcosystemLoss extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "ecosystem_loss_rate", nullable: true }) + ecosystemLossRate: number; +} diff --git a/shared/entities/carbon-inputs/emission-factors.entity.ts b/shared/entities/carbon-inputs/emission-factors.entity.ts new file mode 100644 index 00000000..6c7d0c28 --- /dev/null +++ b/shared/entities/carbon-inputs/emission-factors.entity.ts @@ -0,0 +1,74 @@ +import { + Column, + Entity, + BaseEntity, + PrimaryGeneratedColumn, + ManyToOne, + BeforeInsert, + BeforeUpdate, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +export enum EMISSION_FACTORS_TIER_TYPES { + TIER_2 = "Tier 2 - Country-specific emission factor", + TIER_1 = "Tier 1 - Global emission factor", +} + +@Entity("emission_factors") +@Unique(["country", "ecosystem"]) +export class EmissionFactors extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column({ + type: "enum", + enum: EMISSION_FACTORS_TIER_TYPES, + nullable: false, + }) + tierSelector: EMISSION_FACTORS_TIER_TYPES; + + @Column("decimal", { name: "emission_factor", nullable: true }) + emissionFactor: number; + + @Column("decimal", { name: "emission_factor_agb", nullable: true }) + AGB: number; + + @Column("decimal", { name: "emission_factor_soc", nullable: true }) + SOC: number; + + @Column("decimal", { name: "emission_factor_global", nullable: true }) + global: number; + + // TODO: the following inputs should be taken from sources table + // currently just populated at import with whatever value we have + // in this table + @Column("decimal", { name: "emission_factor_country_AGB", nullable: true }) + t2CountrySpecificAGB: number; + + @Column("decimal", { name: "emission_factor_country_SOC", nullable: true }) + t2CountrySpecificSOC: number; + + @BeforeInsert() + @BeforeUpdate() + setSequestrationRateValue() { + if (this.tierSelector === EMISSION_FACTORS_TIER_TYPES.TIER_1) { + this.emissionFactor = this.global; + this.AGB = 0; + this.SOC = 0; + } else if (this.tierSelector === EMISSION_FACTORS_TIER_TYPES.TIER_2) { + this.emissionFactor = 0; + this.AGB = this.t2CountrySpecificAGB; + this.SOC = this.t2CountrySpecificSOC; + } + } +} diff --git a/shared/entities/carbon-inputs/restorable-land.entity.ts b/shared/entities/carbon-inputs/restorable-land.entity.ts new file mode 100644 index 00000000..6609dec2 --- /dev/null +++ b/shared/entities/carbon-inputs/restorable-land.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("restorable_land") +@Unique(["country", "ecosystem"]) +export class RestorableLand extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "restorable_land", nullable: true }) + restorableLand: number; +} diff --git a/shared/entities/carbon-inputs/sequestration-rate.entity.ts b/shared/entities/carbon-inputs/sequestration-rate.entity.ts new file mode 100644 index 00000000..53198fc5 --- /dev/null +++ b/shared/entities/carbon-inputs/sequestration-rate.entity.ts @@ -0,0 +1,57 @@ +import { + Column, + Entity, + BaseEntity, + PrimaryGeneratedColumn, + ManyToOne, + BeforeInsert, + BeforeUpdate, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +export enum SEQUESTRATION_RATE_TIER_TYPES { + TIER_2 = "Tier 2 - Country-specific rate", + TIER_1 = "Tier 1 - IPCC default value", +} + +@Entity("sequestration_rate") +@Unique(["country", "ecosystem"]) +export class SequestrationRate extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column({ + type: "enum", + enum: SEQUESTRATION_RATE_TIER_TYPES, + }) + tierSelector: SEQUESTRATION_RATE_TIER_TYPES; + + @Column("decimal", { name: "tier_1_factor", nullable: true }) + tier1Factor: number; + + @Column("decimal", { name: "tier_2_factor", nullable: true }) + tier2Factor: number; + + @Column("decimal", { name: "sequestration_rate", nullable: true }) + sequestrationRate: number; + + @BeforeInsert() + @BeforeUpdate() + setSequestrationRateValue() { + if (this.tierSelector === SEQUESTRATION_RATE_TIER_TYPES.TIER_1) { + this.sequestrationRate = this.tier1Factor; + } else if (this.tierSelector === SEQUESTRATION_RATE_TIER_TYPES.TIER_2) { + this.sequestrationRate = this.tier2Factor; + } + } +} diff --git a/shared/entities/community-benefit-sharing-fund.entity.ts b/shared/entities/community-benefit-sharing-fund.entity.ts deleted file mode 100644 index 0dd00ce6..00000000 --- a/shared/entities/community-benefit-sharing-fund.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("community_benefit_sharing_fund") -export class CommunityBenefitSharingFund extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "benefit_sharing_fund_pc_of_revenue" }) - benefitSharingFund: number; - - @OneToOne(() => BaseData, (baseData) => baseData.communityBenefit) - baseData: BaseData[]; -} diff --git a/shared/entities/community-representation.entity.ts b/shared/entities/community-representation.entity.ts deleted file mode 100644 index 059eea31..00000000 --- a/shared/entities/community-representation.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("community_representation") -export class CommunityRepresentation extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "liaison_cost" }) - liaisonCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.communityRepresentation) - baseData: BaseData[]; -} diff --git a/shared/entities/conservation-and-planning-admin.entity.ts b/shared/entities/conservation-and-planning-admin.entity.ts deleted file mode 100644 index 0b8829ce..00000000 --- a/shared/entities/conservation-and-planning-admin.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("conservation_planning_and_admin") -export class ConservationPlanningAndAdmin extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "planning_cost" }) - planningCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.conservationPlanningAndAdmin) - baseData: BaseData[]; -} diff --git a/shared/entities/baseline-reassessment.entity.ts b/shared/entities/cost-inputs/baseline-reassessment.entity.ts similarity index 56% rename from shared/entities/baseline-reassessment.entity.ts rename to shared/entities/cost-inputs/baseline-reassessment.entity.ts index 167e7c3a..bf459e6e 100644 --- a/shared/entities/baseline-reassessment.entity.ts +++ b/shared/entities/cost-inputs/baseline-reassessment.entity.ts @@ -3,18 +3,22 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + Unique, + ManyToOne, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; @Entity("baseline_reassessment") +@Unique(["country"]) export class BaselineReassessment extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column("decimal", { name: "baseline_reassessment_cost_per_event" }) baselineReassessmentCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.baselineReassessment) - baseData: BaseData; } diff --git a/shared/entities/blue-carbon-project-planning.entity.ts b/shared/entities/cost-inputs/blue-carbon-project-planning.entity.ts similarity index 50% rename from shared/entities/blue-carbon-project-planning.entity.ts rename to shared/entities/cost-inputs/blue-carbon-project-planning.entity.ts index 37d92d3e..0522027c 100644 --- a/shared/entities/blue-carbon-project-planning.entity.ts +++ b/shared/entities/cost-inputs/blue-carbon-project-planning.entity.ts @@ -3,9 +3,13 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + Unique, + ManyToOne, + BeforeInsert, + BeforeUpdate, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; export enum INPUT_SELECTION { INPUT_1 = "Input 1", @@ -14,10 +18,15 @@ export enum INPUT_SELECTION { } @Entity("blue_carbon_project_planning") +@Unique(["country"]) export class BlueCarbonProjectPlanning extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column({ type: "enum", enum: INPUT_SELECTION, @@ -35,6 +44,18 @@ export class BlueCarbonProjectPlanning extends BaseEntity { @Column("decimal", { name: "input_3_cost_per_project" }) input3: number; - @OneToOne(() => BaseData, (baseData) => baseData.blueCarbonProjectPlanning) - baseData: BaseData; + @Column("decimal", { name: "blue_carbon" }) + blueCarbon: number; + + @BeforeInsert() + @BeforeUpdate() + setBlueCarbonValue() { + if (this.inputSelection === INPUT_SELECTION.INPUT_1) { + this.blueCarbon = this.input1; + } else if (this.inputSelection === INPUT_SELECTION.INPUT_2) { + this.blueCarbon = this.input2; + } else if (this.inputSelection === INPUT_SELECTION.INPUT_3) { + this.blueCarbon = this.input3; + } + } } diff --git a/shared/entities/carbon-standard-fees.entity.ts b/shared/entities/cost-inputs/carbon-standard-fees.entity.ts similarity index 55% rename from shared/entities/carbon-standard-fees.entity.ts rename to shared/entities/cost-inputs/carbon-standard-fees.entity.ts index f8f75c6f..82e181b0 100644 --- a/shared/entities/carbon-standard-fees.entity.ts +++ b/shared/entities/cost-inputs/carbon-standard-fees.entity.ts @@ -3,18 +3,22 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + ManyToOne, + Unique, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; @Entity("carbon_standard_fees") +@Unique(["country"]) export class CarbonStandardFees extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column("decimal", { name: "cost_per_carbon_credit_issued" }) carbonStandardFee: number; - - @OneToOne(() => BaseData, (baseData) => baseData.carbonStandardFees) - baseData: BaseData; } diff --git a/shared/entities/cost-inputs/community-benefit-sharing-fund.entity.ts b/shared/entities/cost-inputs/community-benefit-sharing-fund.entity.ts new file mode 100644 index 00000000..37a70ba3 --- /dev/null +++ b/shared/entities/cost-inputs/community-benefit-sharing-fund.entity.ts @@ -0,0 +1,24 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + Unique, + ManyToOne, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; + +@Entity("community_benefit_sharing_fund") +@Unique(["country"]) +export class CommunityBenefitSharingFund extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column("decimal", { name: "community_benefit_sharing_fund_pc_of_revenue" }) + communityBenefitSharingFund: number; +} diff --git a/shared/entities/community-cash-flow.entity.ts b/shared/entities/cost-inputs/community-cash-flow.entity.ts similarity index 61% rename from shared/entities/community-cash-flow.entity.ts rename to shared/entities/cost-inputs/community-cash-flow.entity.ts index f99dbfaf..5349ad92 100644 --- a/shared/entities/community-cash-flow.entity.ts +++ b/shared/entities/cost-inputs/community-cash-flow.entity.ts @@ -3,9 +3,11 @@ import { Entity, BaseEntity, PrimaryGeneratedColumn, - OneToOne, + ManyToOne, + Unique, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; export enum COMMUNITY_CASH_FLOW_TYPES { NON_DEVELOPMENT = "Non-development", @@ -13,14 +15,15 @@ export enum COMMUNITY_CASH_FLOW_TYPES { } @Entity("community_cash_flow") +@Unique(["country"]) export class CommunityCashFlow extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; - // TODO: Right now the dataset contains null values for other_community_cashflow, but not sure if this is correct + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column({ type: "enum", enum: COMMUNITY_CASH_FLOW_TYPES, nullable: true }) cashflowType: COMMUNITY_CASH_FLOW_TYPES; - - @OneToOne(() => BaseData, (baseData) => baseData.communityCashFlow) - baseData: BaseData[]; } diff --git a/shared/entities/cost-inputs/community-representation.entity.ts b/shared/entities/cost-inputs/community-representation.entity.ts new file mode 100644 index 00000000..f2c3f897 --- /dev/null +++ b/shared/entities/cost-inputs/community-representation.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + Unique, + ManyToOne, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("community_representation") +@Unique(["country", "ecosystem"]) +export class CommunityRepresentation extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "liaison_cost" }) + liaisonCost: number; +} diff --git a/shared/entities/cost-inputs/conservation-and-planning-admin.entity.ts b/shared/entities/cost-inputs/conservation-and-planning-admin.entity.ts new file mode 100644 index 00000000..02867df7 --- /dev/null +++ b/shared/entities/cost-inputs/conservation-and-planning-admin.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("conservation_planning_and_admin") +@Unique(["country", "ecosystem"]) +export class ConservationPlanningAndAdmin extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "planning_cost_per_project" }) + planningCost: number; +} diff --git a/shared/entities/cost-inputs/data-collection-and-field-costs.entity.ts b/shared/entities/cost-inputs/data-collection-and-field-costs.entity.ts new file mode 100644 index 00000000..1b23afbe --- /dev/null +++ b/shared/entities/cost-inputs/data-collection-and-field-costs.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("data_collection_and_field_costs") +@Unique(["country", "ecosystem"]) +export class DataCollectionAndFieldCosts extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "field_cost_per_project" }) + fieldCost: number; +} diff --git a/shared/entities/establishing-carbon-rights.entity.ts b/shared/entities/cost-inputs/establishing-carbon-rights.entity.ts similarity index 53% rename from shared/entities/establishing-carbon-rights.entity.ts rename to shared/entities/cost-inputs/establishing-carbon-rights.entity.ts index 89514b3b..c430df40 100644 --- a/shared/entities/establishing-carbon-rights.entity.ts +++ b/shared/entities/cost-inputs/establishing-carbon-rights.entity.ts @@ -3,18 +3,22 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + ManyToOne, + Unique, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; @Entity("carbon_rights") +@Unique(["country"]) export class CarbonRights extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column("decimal", { name: "carbon_rights_cost" }) carbonRightsCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.carbonRights) - baseData: BaseData[]; } diff --git a/shared/entities/cost-inputs/feasability-analysis.entity.ts b/shared/entities/cost-inputs/feasability-analysis.entity.ts new file mode 100644 index 00000000..3e7e6c6c --- /dev/null +++ b/shared/entities/cost-inputs/feasability-analysis.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("feasibility_analysis") +@Unique(["country", "ecosystem"]) +export class FeasibilityAnalysis extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "analysis_cost_per_project" }) + analysisCost: number; +} diff --git a/shared/entities/financing-cost.entity.ts b/shared/entities/cost-inputs/financing-cost.entity.ts similarity index 54% rename from shared/entities/financing-cost.entity.ts rename to shared/entities/cost-inputs/financing-cost.entity.ts index 6647adc1..babe28d0 100644 --- a/shared/entities/financing-cost.entity.ts +++ b/shared/entities/cost-inputs/financing-cost.entity.ts @@ -3,18 +3,22 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + ManyToOne, + Unique, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; @Entity("financing_cost") +@Unique(["country"]) export class FinancingCost extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column("decimal", { name: "financing_cost_capex_percent" }) financingCostCapexPercent: number; - - @OneToOne(() => BaseData, (baseData) => baseData.financingCost) - baseData: BaseData[]; } diff --git a/shared/entities/cost-inputs/implementation-labor-cost.entity.ts b/shared/entities/cost-inputs/implementation-labor-cost.entity.ts new file mode 100644 index 00000000..77bfc9fa --- /dev/null +++ b/shared/entities/cost-inputs/implementation-labor-cost.entity.ts @@ -0,0 +1,34 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("implementation_labor_cost") +@Unique(["country", "ecosystem"]) +export class ImplementationLaborCost extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "planting_cost_ha" }) + plantingCost: number; + + @Column("decimal", { name: "hybrid_cost_ha" }) + hybridCost: number; + + @Column("decimal", { name: "hydrology_cost_ha" }) + hydrologyCost: number; +} diff --git a/shared/entities/cost-inputs/long-term-project-operating.entity.ts b/shared/entities/cost-inputs/long-term-project-operating.entity.ts new file mode 100644 index 00000000..03028c96 --- /dev/null +++ b/shared/entities/cost-inputs/long-term-project-operating.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("long_term_project_operating") +@Unique(["country", "ecosystem"]) +export class LongTermProjectOperating extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "long_term_project_operating_cost_per_year" }) + longTermProjectOperatingCost: number; +} diff --git a/shared/entities/maintenance.entity.ts b/shared/entities/cost-inputs/maintenance.entity.ts similarity index 61% rename from shared/entities/maintenance.entity.ts rename to shared/entities/cost-inputs/maintenance.entity.ts index 14984c1e..0d9ef713 100644 --- a/shared/entities/maintenance.entity.ts +++ b/shared/entities/cost-inputs/maintenance.entity.ts @@ -3,21 +3,25 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + ManyToOne, + Unique, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; @Entity("maintenance") +@Unique(["country"]) export class Maintenance extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column("decimal", { name: "maintenance_cost_pc_of_impl_labor_cost" }) maintenanceCost: number; @Column("decimal", { name: "maintenance_duration_years" }) maintenanceDuration: number; - - @OneToOne(() => BaseData, (baseData) => baseData.maintenance) - baseData: BaseData; } diff --git a/shared/entities/cost-inputs/monitoring.entity.ts b/shared/entities/cost-inputs/monitoring.entity.ts new file mode 100644 index 00000000..df8891f9 --- /dev/null +++ b/shared/entities/cost-inputs/monitoring.entity.ts @@ -0,0 +1,28 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + ManyToOne, + Unique, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; + +@Entity("monitoring_cost") +@Unique(["country", "ecosystem"]) +export class MonitoringCost extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column("decimal", { name: "monitoring_cost_per_year" }) + monitoringCost: number; +} diff --git a/shared/entities/mrv.entity.ts b/shared/entities/cost-inputs/mrv.entity.ts similarity index 50% rename from shared/entities/mrv.entity.ts rename to shared/entities/cost-inputs/mrv.entity.ts index 9c9059f0..bc5820f5 100644 --- a/shared/entities/mrv.entity.ts +++ b/shared/entities/cost-inputs/mrv.entity.ts @@ -3,18 +3,22 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + ManyToOne, + Unique, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; @Entity("mrv") +@Unique(["country"]) export class MRV extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column("decimal", { name: "mrv_cost_per_event" }) mrvCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.mrv) - baseData: BaseData; } diff --git a/shared/entities/cost-inputs/project-size.entity.ts b/shared/entities/cost-inputs/project-size.entity.ts new file mode 100644 index 00000000..4c1a9166 --- /dev/null +++ b/shared/entities/cost-inputs/project-size.entity.ts @@ -0,0 +1,32 @@ +import { + Entity, + Column, + PrimaryGeneratedColumn, + BaseEntity, + Unique, + ManyToOne, + JoinColumn, +} from "typeorm"; +import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; +import { ACTIVITY } from "@shared/entities/activity.enum"; + +@Entity("project_size") +@Unique(["country", "ecosystem", "activity"]) +export class ProjectSize extends BaseEntity { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + + @Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" }) + ecosystem: ECOSYSTEM; + + @Column({ name: "activity", enum: ACTIVITY, type: "enum" }) + activity: ACTIVITY; + + @Column("decimal", { name: "size" }) + sizeHa: number; +} diff --git a/shared/entities/validation.entity.ts b/shared/entities/cost-inputs/validation.entity.ts similarity index 53% rename from shared/entities/validation.entity.ts rename to shared/entities/cost-inputs/validation.entity.ts index b6d88ddd..f7d5b843 100644 --- a/shared/entities/validation.entity.ts +++ b/shared/entities/cost-inputs/validation.entity.ts @@ -3,18 +3,22 @@ import { Column, PrimaryGeneratedColumn, BaseEntity, - OneToOne, + ManyToOne, + Unique, + JoinColumn, } from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; +import { Country } from "@shared/entities/country.entity"; @Entity("validation_cost") +@Unique(["country"]) export class ValidationCost extends BaseEntity { @PrimaryGeneratedColumn("uuid") id: string; + @ManyToOne(() => Country, (country) => country.code, { onDelete: "CASCADE" }) + @JoinColumn({ name: "country_code" }) + country: Country; + @Column("decimal", { name: "validation_cost" }) validationCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.validationCost) - baseData: BaseData; } diff --git a/shared/entities/data-collection-and-field-costs.entity.ts b/shared/entities/data-collection-and-field-costs.entity.ts deleted file mode 100644 index 75ecc6f5..00000000 --- a/shared/entities/data-collection-and-field-costs.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("data_collection_and_field_costs") -export class DataCollectionAndFieldCosts extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "field_cost" }) - fieldCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.dataCollectionAndFieldCosts) - baseData: BaseData[]; -} diff --git a/shared/entities/ecosystem-loss.entity.ts b/shared/entities/ecosystem-loss.entity.ts deleted file mode 100644 index c86a578f..00000000 --- a/shared/entities/ecosystem-loss.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("ecosystem_loss") -export class EcosystemLoss extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "ecosystem_loss_rate" }) - ecosystemLossRate: number; - - @OneToOne(() => BaseData, (baseData) => baseData.ecosystemLoss) - baseData: BaseData; -} diff --git a/shared/entities/ecosystem.enum.ts b/shared/entities/ecosystem.enum.ts new file mode 100644 index 00000000..00be7722 --- /dev/null +++ b/shared/entities/ecosystem.enum.ts @@ -0,0 +1,5 @@ +export enum ECOSYSTEM { + MANGROVE = "Mangrove", + SEAGRASS = "Seagrass", + SALT_MARSH = "Salt marsh", +} diff --git a/shared/entities/emission-factors.entity.ts b/shared/entities/emission-factors.entity.ts deleted file mode 100644 index ba1ce2f8..00000000 --- a/shared/entities/emission-factors.entity.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { - Column, - Entity, - BaseEntity, - PrimaryGeneratedColumn, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -export enum EMISSION_FACTORS_TIER_TYPES { - TIER_2 = "Tier 2 - Country-specific emission factor", - TIER_1 = "Tier 1 - Global emission factor", -} - -@Entity("emission_factors") -export class EmissionFactors extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column({ - type: "enum", - enum: EMISSION_FACTORS_TIER_TYPES, - nullable: false, - default: EMISSION_FACTORS_TIER_TYPES.TIER_1, - }) - tierSelector: EMISSION_FACTORS_TIER_TYPES; - - @Column("decimal", { name: "tier_1_factor" }) - tier1Factor: number; - - // TODO - // Tier2 for mangrove is taken from sources table - // Tier 2 values for other ecosystem is NA - @Column("decimal", { name: "tier_2_AGB_factor" }) - tier2AGBFactor: number; - - @Column("decimal", { name: "tier_2_SOC_factor" }) - tier2SOCFactor: number; - - @OneToOne(() => BaseData, (baseData) => baseData.emissionFactors) - baseData: BaseData[]; -} diff --git a/shared/entities/feasability-analysis.entity.ts b/shared/entities/feasability-analysis.entity.ts deleted file mode 100644 index 364d7653..00000000 --- a/shared/entities/feasability-analysis.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("feasibility_analysis") -export class FeasibilityAnalysis extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "analysis_score" }) - analysisScore: number; - - @OneToOne(() => BaseData, (baseData) => baseData.feasibilityAnalysis) - baseData: BaseData[]; -} diff --git a/shared/entities/implementation-labor.entity.ts b/shared/entities/implementation-labor.entity.ts deleted file mode 100644 index e5b816d3..00000000 --- a/shared/entities/implementation-labor.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("implementation_labor_cost") -export class ImplementationLaborCost extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "implementation_labor_cost_per_ha" }) - implementationLaborCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.implementationLaborCost) - baseData: BaseData; -} diff --git a/shared/entities/long-term-project-operating.entity.ts b/shared/entities/long-term-project-operating.entity.ts deleted file mode 100644 index b098252f..00000000 --- a/shared/entities/long-term-project-operating.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("long_term_project_operating") -export class LongTermProjectOperating extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "long_term_project_operating_cost_per_year" }) - longTermProjectOperatingCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.longTermProjectOperating) - baseData: BaseData; -} diff --git a/shared/entities/monitoring.entity.ts b/shared/entities/monitoring.entity.ts deleted file mode 100644 index f388d48d..00000000 --- a/shared/entities/monitoring.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("monitoring_cost") -export class MonitoringCost extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "monitoring_cost_per_year" }) - monitoringCost: number; - - @OneToOne(() => BaseData, (baseData) => baseData.monitoringCost) - baseData: BaseData; -} diff --git a/shared/entities/project-size.entity.ts b/shared/entities/project-size.entity.ts deleted file mode 100644 index 2427029c..00000000 --- a/shared/entities/project-size.entity.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("project_size") -export class ProjectSize extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "size_ha" }) - sizeHa: number; - - @OneToOne(() => BaseData, (baseData) => baseData.projectSize) - baseData: BaseData; - - //TODO: Additionally include unit for each type? -} diff --git a/shared/entities/projects.entity.ts b/shared/entities/projects.entity.ts index d4714868..3f999b1a 100644 --- a/shared/entities/projects.entity.ts +++ b/shared/entities/projects.entity.ts @@ -7,8 +7,9 @@ import { JoinColumn, } from "typeorm"; -import { ACTIVITY, ECOSYSTEM } from "@shared/entities/base-data.entity"; import { Country } from "@shared/entities/country.entity"; +import { ECOSYSTEM } from "./ecosystem.enum"; +import { ACTIVITY } from "./activity.enum"; export enum PROJECT_SIZE_FILTER { SMALL = "Small", diff --git a/shared/entities/restorable-land.entity.ts b/shared/entities/restorable-land.entity.ts deleted file mode 100644 index 07121a18..00000000 --- a/shared/entities/restorable-land.entity.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Entity, - Column, - PrimaryGeneratedColumn, - BaseEntity, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -@Entity("restorable_land") -export class RestorableLand extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column("decimal", { name: "restorable_land_ha" }) - restorableLand: number; - - @OneToOne(() => BaseData, (baseData) => baseData.restorableLand) - baseData: BaseData; -} diff --git a/shared/entities/sequestration-rate.entity.ts b/shared/entities/sequestration-rate.entity.ts deleted file mode 100644 index 2a198899..00000000 --- a/shared/entities/sequestration-rate.entity.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - Column, - Entity, - BaseEntity, - PrimaryGeneratedColumn, - OneToOne, -} from "typeorm"; -import { BaseData } from "@shared/entities/base-data.entity"; - -export enum SEQUESTRATION_RATE_TIER_TYPES { - TIER_2 = "Tier 2 - Country-specific rate", - TIER_1 = "Tier 1 - IPCC default value", -} - -@Entity("sequestration_rate") -export class SequestrationRate extends BaseEntity { - @PrimaryGeneratedColumn("uuid") - id: string; - - @Column({ - type: "enum", - enum: SEQUESTRATION_RATE_TIER_TYPES, - nullable: false, - default: SEQUESTRATION_RATE_TIER_TYPES.TIER_1, - }) - tierSelector: SEQUESTRATION_RATE_TIER_TYPES; - - // TODO - // Tier 1 for all ecosystem is taken from Sources >> Sequestration Rate table - @Column("decimal", { name: "tier_1_factor" }) - tier1Factor: number; - - // Tier 2 is defined for each ecosystem in this table - @Column("decimal", { name: "tier_2_factor" }) - tier2Factor: number; - - @OneToOne(() => BaseData, (baseData) => baseData.sequestrationRate) - baseData: BaseData[]; -} diff --git a/shared/lib/db-entities.ts b/shared/lib/db-entities.ts index c5718e77..ede8868f 100644 --- a/shared/lib/db-entities.ts +++ b/shared/lib/db-entities.ts @@ -1,36 +1,36 @@ -import { User } from "@shared/entities/users/user.entity"; import { ApiEventsEntity } from "@api/modules/api-events/api-events.entity"; +import { BaseDataView } from "@shared/entities/base-data.view"; +import { EcosystemExtent } from "@shared/entities/carbon-inputs/ecosystem-extent.entity"; +import { EcosystemLoss } from "@shared/entities/carbon-inputs/ecosystem-loss.entity"; +import { EmissionFactors } from "@shared/entities/carbon-inputs/emission-factors.entity"; +import { RestorableLand } from "@shared/entities/carbon-inputs/restorable-land.entity"; +import { SequestrationRate } from "@shared/entities/carbon-inputs/sequestration-rate.entity"; +import { BaselineReassessment } from "@shared/entities/cost-inputs/baseline-reassessment.entity"; +import { BlueCarbonProjectPlanning } from "@shared/entities/cost-inputs/blue-carbon-project-planning.entity"; +import { CarbonStandardFees } from "@shared/entities/cost-inputs/carbon-standard-fees.entity"; +import { CommunityBenefitSharingFund } from "@shared/entities/cost-inputs/community-benefit-sharing-fund.entity"; +import { CommunityCashFlow } from "@shared/entities/cost-inputs/community-cash-flow.entity"; +import { CommunityRepresentation } from "@shared/entities/cost-inputs/community-representation.entity"; +import { ConservationPlanningAndAdmin } from "@shared/entities/cost-inputs/conservation-and-planning-admin.entity"; +import { DataCollectionAndFieldCosts } from "@shared/entities/cost-inputs/data-collection-and-field-costs.entity"; +import { CarbonRights } from "@shared/entities/cost-inputs/establishing-carbon-rights.entity"; +import { FeasibilityAnalysis } from "@shared/entities/cost-inputs/feasability-analysis.entity"; +import { FinancingCost } from "@shared/entities/cost-inputs/financing-cost.entity"; +import { LongTermProjectOperating } from "@shared/entities/cost-inputs/long-term-project-operating.entity"; +import { Maintenance } from "@shared/entities/cost-inputs/maintenance.entity"; +import { MonitoringCost } from "@shared/entities/cost-inputs/monitoring.entity"; +import { MRV } from "@shared/entities/cost-inputs/mrv.entity"; +import { ProjectSize } from "@shared/entities/cost-inputs/project-size.entity"; +import { ValidationCost } from "@shared/entities/cost-inputs/validation.entity"; import { Country } from "@shared/entities/country.entity"; -import { BaseData } from "@shared/entities/base-data.entity"; -import { ProjectSize } from "@shared/entities/project-size.entity"; -import { FeasibilityAnalysis } from "@shared/entities/feasability-analysis.entity"; -import { ConservationPlanningAndAdmin } from "@shared/entities/conservation-and-planning-admin.entity"; -import { DataCollectionAndFieldCosts } from "@shared/entities/data-collection-and-field-costs.entity"; -import { CarbonStandardFees } from "@shared/entities/carbon-standard-fees.entity"; -import { CommunityBenefitSharingFund } from "@shared/entities/community-benefit-sharing-fund.entity"; -import { CommunityCashFlow } from "@shared/entities/community-cash-flow.entity"; -import { CommunityRepresentation } from "@shared/entities/community-representation.entity"; -import { EcosystemLoss } from "@shared/entities/ecosystem-loss.entity"; -import { CarbonRights } from "@shared/entities/establishing-carbon-rights.entity"; -import { FinancingCost } from "@shared/entities/financing-cost.entity"; -import { ImplementationLaborCost } from "@shared/entities/implementation-labor.entity"; -import { Maintenance } from "@shared/entities/maintenance.entity"; -import { MonitoringCost } from "@shared/entities/monitoring.entity"; -import { RestorableLand } from "@shared/entities/restorable-land.entity"; -import { ValidationCost } from "@shared/entities/validation.entity"; -import { BaselineReassessment } from "@shared/entities/baseline-reassessment.entity"; -import { BlueCarbonProjectPlanning } from "@shared/entities/blue-carbon-project-planning.entity"; -import { EmissionFactors } from "@shared/entities/emission-factors.entity"; -import { LongTermProjectOperating } from "@shared/entities/long-term-project-operating.entity"; -import { MRV } from "@shared/entities/mrv.entity"; -import { SequestrationRate } from "@shared/entities/sequestration-rate.entity"; +import { ImplementationLaborCost } from "@shared/entities/cost-inputs/implementation-labor-cost.entity"; import { Project } from "@shared/entities/projects.entity"; +import { User } from "@shared/entities/users/user.entity"; export const COMMON_DATABASE_ENTITIES = [ User, ApiEventsEntity, Country, - BaseData, ProjectSize, FeasibilityAnalysis, ConservationPlanningAndAdmin, @@ -39,11 +39,9 @@ export const COMMON_DATABASE_ENTITIES = [ CommunityBenefitSharingFund, CommunityCashFlow, CommunityRepresentation, - ConservationPlanningAndAdmin, EcosystemLoss, CarbonRights, FinancingCost, - ImplementationLaborCost, Maintenance, MonitoringCost, RestorableLand, @@ -55,4 +53,7 @@ export const COMMON_DATABASE_ENTITIES = [ MRV, SequestrationRate, Project, + EcosystemExtent, + BaseDataView, + ImplementationLaborCost, ]; diff --git a/shared/lib/db-helpers.ts b/shared/lib/db-helpers.ts index 12b7e5c6..1efb49c2 100644 --- a/shared/lib/db-helpers.ts +++ b/shared/lib/db-helpers.ts @@ -4,7 +4,7 @@ import { EntityTarget } from "typeorm/common/EntityTarget"; import { ObjectLiteral } from "typeorm/common/ObjectLiteral"; export async function clearTestDataFromDatabase( - dataSource: DataSource, + dataSource: DataSource ): Promise { const queryRunner = dataSource.createQueryRunner(); await queryRunner.connect(); @@ -14,25 +14,25 @@ export async function clearTestDataFromDatabase( .filter( (entityMetadata: EntityMetadata) => entityMetadata.tableType === "regular" || - entityMetadata.tableType === "junction", + entityMetadata.tableType === "junction" ) .map((entityMetadata: EntityMetadata) => entityMetadata.tableName); await Promise.all( entityTableNames.map((entityTableName: string) => - queryRunner.query(`TRUNCATE TABLE "${entityTableName}" CASCADE`), - ), + queryRunner.query(`TRUNCATE TABLE "${entityTableName}" CASCADE`) + ) ); entityTableNames.push(dataSource.metadataTableName); entityTableNames.push( - dataSource.options.migrationsTableName || "migrations", + dataSource.options.migrationsTableName || "migrations" ); entityTableNames.push("spatial_ref_sys"); const databaseTableNames: string[] = ( await dataSource.query( - `SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'`, + `SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE'` ) ).map((e: Record) => e.table_name); @@ -40,8 +40,8 @@ export async function clearTestDataFromDatabase( await Promise.all( tablesToDrop.map((tableToDrop: string) => - queryRunner.dropTable(tableToDrop), - ), + queryRunner.dropTable(tableToDrop) + ) ); await queryRunner.commitTransaction(); } catch (err) { @@ -56,7 +56,7 @@ export async function clearTestDataFromDatabase( export async function clearTablesByEntities( dataSource: DataSource, - entities: EntityTarget[], + entities: EntityTarget[] ): Promise { for (const entity of entities) { const repo = dataSource.getRepository(entity); diff --git a/shared/lib/entity-mocks.ts b/shared/lib/entity-mocks.ts index 2f71fcdf..3ddb5f2b 100644 --- a/shared/lib/entity-mocks.ts +++ b/shared/lib/entity-mocks.ts @@ -1,21 +1,18 @@ import { genSalt, hash } from "bcrypt"; import { DataSource, DeepPartial } from "typeorm"; import { User } from "@shared/entities/users/user.entity"; -import { - ACTIVITY, - BaseData, - ECOSYSTEM, -} from "@shared/entities/base-data.entity"; import { Project, PROJECT_PRICE_TYPE, PROJECT_SIZE_FILTER, } from "@shared/entities/projects.entity"; import { Country } from "@shared/entities/country.entity"; +import { ACTIVITY } from "@shared/entities/activity.enum"; +import { ECOSYSTEM } from "@shared/entities/ecosystem.enum"; export const createUser = async ( dataSource: DataSource, - additionalData?: Partial, + additionalData?: Partial ): Promise => { const salt = await genSalt(); const usedPassword = additionalData?.password ?? "12345678"; @@ -30,23 +27,9 @@ export const createUser = async ( return { ...user, password: usedPassword } as User; }; -export const createBaseData = async ( - dataSource: DataSource, - additionalData?: Partial, -): Promise => { - const baseData = new BaseData(); - baseData.ecosystem = ECOSYSTEM.MANGROVE; - baseData.countryCode = "AND"; - baseData.activity = ACTIVITY.CONSERVATION; - - return dataSource - .getRepository(BaseData) - .save({ ...baseData, ...additionalData }); -}; - export const createProject = async ( dataSource: DataSource, - additionalData?: DeepPartial, + additionalData?: DeepPartial ): Promise => { const countries = await dataSource.getRepository(Country).find(); if (!countries.length) {