Skip to content

Commit

Permalink
add project entity and backoffice resource
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeh committed Oct 26, 2024
1 parent c8f7cd2 commit 7805842
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 0 deletions.
2 changes: 2 additions & 0 deletions admin/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ 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/users/projects.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 = [
Expand Down Expand Up @@ -54,6 +55,7 @@ export const ADMINJS_ENTITIES = [
LongTermProjectOperating,
MRV,
SequestrationRate,
Project,
];

export const dataSource = new DataSource({
Expand Down
3 changes: 3 additions & 0 deletions admin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { MRVResource } from "./resources/mrv/mrv.resource.js";
import { BlueCarbonProjectPlanningResource } from "./resources/blue-carbon-project-planning/blue-carbon-project-planning.resource.js";
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";

AdminJS.registerAdapter({
Database: AdminJSTypeorm.Database,
Expand Down Expand Up @@ -77,6 +78,7 @@ const start = async () => {
BlueCarbonProjectPlanningResource,
LongTermProjectOperatingResource,
SequestrationRateResource,
ProjectsResource,
{
resource: Country,
name: "Country",
Expand All @@ -93,6 +95,7 @@ const start = async () => {
labels: {
User: "Users",
Country: "Countries",
Project: "Projects",
},
},
},
Expand Down
82 changes: 82 additions & 0 deletions admin/resources/projects/projects.resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
ActionContext,
ActionRequest,
ActionResponse,
BaseRecord,
ResourceWithOptions,
} from "adminjs";
import { dataSource } from "../../datasource.js";
import { COMMON_RESOURCE_LIST_PROPERTIES } from "../common/common.resources.js";
import { Project } from "@shared/entities/users/projects.entity.js";
import { Country } from "@shared/entities/country.entity.js";

export const ProjectsResource: ResourceWithOptions = {
resource: Project,
options: {
properties: COMMON_RESOURCE_LIST_PROPERTIES,
listProperties: [
"projectName",
"projectSize",
"abatementPotential",
"totalCostNPV",
"costPerTCO2eNPV",
"initialPriceAssumption",
"activitySubtype",
"projectSizeFilter",
"priceType",
],
sort: {
sortBy: "projectName",
direction: "asc",
},
navigation: {
name: "Data Management",
icon: "Database",
},
actions: {
list: {
after: async (
request: ActionRequest,
response: ActionResponse,
context: ActionContext,
) => {
const { records } = context;
const projectDataRepo = dataSource.getRepository(Project);
const queryBuilder = projectDataRepo
.createQueryBuilder("project")
.leftJoin(Country, "country", "project.countryCode = country.code")
.select("project.id", "id")
.addSelect("project.projectName", "projectName")
.addSelect("project.ecosystem", "ecosystem")
.addSelect("project.activity", "activity")
.addSelect("project.activitySubtype", "activitySubtype")
.addSelect("country.name", "countryName")
.addSelect("project.projectSize", "projectSize")
.addSelect("project.abatementPotential", "abatementPotential")
.addSelect("project.totalCostNPV", "totalCostNPV")
.addSelect("project.costPerTCO2eNPV", "costPerTCO2eNPV")
.addSelect(
"project.initialPriceAssumption",
"initialPriceAssumption",
);

if (records?.length) {
queryBuilder.andWhere("projectDataImport.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;
}),
};
},
},
},
},
};
85 changes: 85 additions & 0 deletions shared/entities/users/projects.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import {
Column,
Entity,
PrimaryGeneratedColumn,
BaseEntity,
ManyToOne,
JoinColumn,
} from "typeorm";
import { Country } from "@shared/entities/country.entity";
import { ACTIVITY, ECOSYSTEM } from "@shared/entities/base-data.entity";

export enum PROJECT_SIZE_FILTER {
SMALL = "Small",
MEDIUM = "Medium",
LARGE = "Large",
}

export enum PROJECT_PRICE_TYPE {
OPEN_BREAK_EVEN_PRICE = "Open Break Even Price",
MARKET_PRICE = "Market Price",
}

@Entity("projects")
export class Project extends BaseEntity {
@PrimaryGeneratedColumn("uuid")
id: string;

@Column({ name: "project_name", type: "varchar", length: 255 })
projectName: string;

@Column({ name: "country_code", length: 3, nullable: true, type: "char" })
countryCode: string;

// Unidirectional relation
@ManyToOne(() => Country)
@JoinColumn({ name: "country_code" })
country: Country;

@Column({ name: "ecosystem", enum: ECOSYSTEM, type: "enum" })
ecosystem: ECOSYSTEM;

@Column({ name: "activity", enum: ACTIVITY, type: "enum" })
activity: ACTIVITY;

// TODO: We need to make this a somehow enum, as a subactivity of restoration, that can be null for conservation, and can represent all restoration activities
@Column({
name: "activity_subtype",
type: "varchar",
length: 255,
nullable: true,
})
activitySubtype: string;

@Column({ name: "project_size", type: "decimal" })
projectSize: number;

// TODO: We could potentially remove this column from the database and excel, and have a threshold to filter by
@Column({
name: "project_size_filter",
type: "enum",
enum: PROJECT_SIZE_FILTER,
})
projectSizeFilter: string;

@Column({ name: "abatement_potential", type: "decimal" })
abatementPotential: number;

@Column({ name: "total_cost_npv", type: "decimal" })
totalCostNPV: number;

@Column({ name: "total_cost", type: "decimal" })
totalCost: number;

@Column({ name: "cost_per_tco2e_npv", type: "decimal" })
costPerTCO2eNPV: number;

@Column({ name: "cost_per_tco2e", type: "decimal" })
costPerTCO2e: number;

@Column({ name: "initial_price_assumption", type: "varchar", length: 255 })
initialPriceAssumption: string;

@Column({ name: "price_type", enum: PROJECT_PRICE_TYPE, type: "enum" })
priceType: PROJECT_PRICE_TYPE;
}
2 changes: 2 additions & 0 deletions shared/lib/db-entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ 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 { Project } from "@shared/entities/users/projects.entity";

export const COMMON_DATABASE_ENTITIES = [
User,
Expand Down Expand Up @@ -53,4 +54,5 @@ export const COMMON_DATABASE_ENTITIES = [
LongTermProjectOperating,
MRV,
SequestrationRate,
Project,
];

0 comments on commit 7805842

Please sign in to comment.