diff --git a/api/src/modules/import/dtos/excel-projects.dto.ts b/api/src/modules/import/dtos/excel-projects.dto.ts index 7ec6dc1a..0420af2e 100644 --- a/api/src/modules/import/dtos/excel-projects.dto.ts +++ b/api/src/modules/import/dtos/excel-projects.dto.ts @@ -18,8 +18,7 @@ export type ExcelProjects = { abatement_potential: number; total_cost_npv: number; total_cost: number; - // TODO: This column has dissapeared from the excel sheet - '$/tCO2e (NPV)': number; + cost_per_tco2e_npv: number; cost_per_tco2e: number; initial_price_assumption: string; price_type: PROJECT_PRICE_TYPE; diff --git a/api/test/integration/custom-projects/custom-projects-setup.spec.ts b/api/test/integration/custom-projects/custom-projects-setup.spec.ts index 9dd3852e..9feb9b9b 100644 --- a/api/test/integration/custom-projects/custom-projects-setup.spec.ts +++ b/api/test/integration/custom-projects/custom-projects-setup.spec.ts @@ -65,11 +65,11 @@ describe('Create Custom Projects - Setup', () => { expect(response.body.data).toMatchObject({ feasibilityAnalysis: 50000, - conservationPlanningAndAdmin: 166766.66666666666, - dataCollectionAndFieldCost: 26666.666666666668, - communityRepresentation: 67633.33333333333, + conservationPlanningAndAdmin: 166766.666666667, + dataCollectionAndFieldCost: 26666.6666666667, + communityRepresentation: 67633.3333333333, blueCarbonProjectPlanning: 100000, - establishingCarbonRights: 46666.666666666664, + establishingCarbonRights: 46666.6666666667, financingCost: 0.05, validation: 50000, implementationLabor: 0, diff --git a/client/src/app/(overview)/constants.ts b/client/src/app/(overview)/constants.ts index cb0cd0ee..1b75b436 100644 --- a/client/src/app/(overview)/constants.ts +++ b/client/src/app/(overview)/constants.ts @@ -11,7 +11,7 @@ export const FILTER_KEYS = [ "countryCode", "ecosystem", "activity", - "activitySubtype", + "restorationActivity", "costRange", "abatementPotentialRange", ] as const; diff --git a/client/src/app/(overview)/store.ts b/client/src/app/(overview)/store.ts index a87e2a5e..0d7fe945 100644 --- a/client/src/app/(overview)/store.ts +++ b/client/src/app/(overview)/store.ts @@ -12,3 +12,11 @@ export const popupAtom = atom<{ lngLat: MapMouseEvent["lngLat"]; features: MapMouseEvent["features"]; } | null>(null); + +export const projectDetailsAtom = atom<{ + isOpen: boolean; + projectName: string; +}>({ + isOpen: false, + projectName: "", +}); diff --git a/client/src/app/(overview)/url-store.ts b/client/src/app/(overview)/url-store.ts index 44e6207e..7deef6d9 100644 --- a/client/src/app/(overview)/url-store.ts +++ b/client/src/app/(overview)/url-store.ts @@ -44,7 +44,7 @@ export const INITIAL_FILTERS_STATE: z.infer = { countryCode: "", ecosystem: [], activity: [], - activitySubtype: [], + restorationActivity: [], costRange: INITIAL_COST_RANGE[COST_TYPE_SELECTOR.NPV], abatementPotentialRange: INITIAL_ABATEMENT_POTENTIAL_RANGE, }; diff --git a/client/src/components/ui/bar-chart/index.tsx b/client/src/components/ui/bar-chart/index.tsx new file mode 100644 index 00000000..972983e6 --- /dev/null +++ b/client/src/components/ui/bar-chart/index.tsx @@ -0,0 +1,71 @@ +import { toCompactAmount } from "@/lib/format"; + +interface BarChartProps { + total: number; + segments: { + value: number; + label: string; + colorClass: string; + }[]; + orientation?: "horizontal" | "vertical"; +} + +const BarChart = ({ + total, + segments, + orientation = "horizontal", +}: BarChartProps) => { + const getSize = (value: number) => { + const percentage = (value / total) * 100; + return `${Math.max(percentage, 0)}%`; + }; + + if (orientation === "horizontal") { + return ( +
+
+ {segments.map((segment, index) => ( +
+
+
+ ${toCompactAmount(segment.value)} +
+
+
+ ))} +
+
+ ); + } + + return ( +
+
+ {segments.map((segment, index) => ( +
+
+
+ ${toCompactAmount(segment.value)} +
+
+
+ ))} +
+
+ ); +}; + +export default BarChart; diff --git a/client/src/containers/overview/filters/index.tsx b/client/src/containers/overview/filters/index.tsx index 7b7e65e0..a8e4b436 100644 --- a/client/src/containers/overview/filters/index.tsx +++ b/client/src/containers/overview/filters/index.tsx @@ -57,7 +57,7 @@ export default function ProjectsFilters() { countryCode: INITIAL_FILTERS_STATE.countryCode, ecosystem: INITIAL_FILTERS_STATE.ecosystem, activities: INITIAL_FILTERS_STATE.activity, - activitySubtype: INITIAL_FILTERS_STATE.activitySubtype, + restorationActivity: INITIAL_FILTERS_STATE.restorationActivity, abatementPotentialRange: INITIAL_FILTERS_STATE.abatementPotentialRange, costRange: INITIAL_FILTERS_STATE.costRange, })); @@ -113,13 +113,13 @@ export default function ProjectsFilters() { const handleSubActivityChange = async ( isChecked: CheckedState, - subActivity: (typeof filters.activitySubtype)[number], + subActivity: (typeof filters.restorationActivity)[number], ) => { await setFilters((prev) => ({ ...prev, - activitySubtype: isChecked - ? [...prev.activitySubtype, subActivity] - : prev.activitySubtype.filter((e) => e !== subActivity), + restorationActivity: isChecked + ? [...prev.restorationActivity, subActivity] + : prev.restorationActivity.filter((e) => e !== subActivity), })); }; @@ -279,7 +279,7 @@ export default function ProjectsFilters() { { diff --git a/client/src/containers/overview/project-details/index.tsx b/client/src/containers/overview/project-details/index.tsx new file mode 100644 index 00000000..7c0cf318 --- /dev/null +++ b/client/src/containers/overview/project-details/index.tsx @@ -0,0 +1,489 @@ +import Link from "next/link"; + +import { useAtom } from "jotai"; +import { ChevronUp, ChevronDown, Plus, NotebookPen } from "lucide-react"; + +import { + renderCurrency, + formatCurrency, + renderAbatementCurrency, +} from "@/lib/format"; + +import { projectDetailsAtom } from "@/app/(overview)/store"; + +import ParametersProjects from "@/containers/overview/project-details/parameters"; + +import BarChart from "@/components/ui/bar-chart"; +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { + Dialog, + DialogContent, + DialogClose, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Label } from "@/components/ui/label"; +import { + Sheet, + SheetContent, + SheetHeader, + SheetTitle, +} from "@/components/ui/sheet"; + +const CreateProjectDetails = () => ( + + + + + + + + Create a Custom Project + + + By creating a custom project you will generate a customizable version + where you can edit all parameters to fit your specific needs. + + + + + + + + + +); + +//////// ScoreIndicator component //////// +interface ScoreIndicatorProps { + score: "High" | "Medium" | "Low"; + className?: string; +} + +const ScoreIndicator = ({ score, className = "" }: ScoreIndicatorProps) => { + const bgColorClass = { + High: "bg-high", + Medium: "bg-medium", + Low: "bg-low", + }[score]; + + return ( +
+ {score} +
+ ); +}; + +//////// Legend component //////// +const Legend = ({ + name, + textColor, + bgColor, +}: { + name: string; + textColor: string; + bgColor: string; +}) => { + return ( +
+
+
+ {name} +
+
+ ); +}; + +// Mock data - to be replaced with API data later +const projectData = { + name: "Australian Mangrove Conservation", + size: "Small", + carbonPricingType: "Market (30$)", + cost: "NPV", + totalCost: 38023789, + capEx: 1500000, + opEx: 36500000, + leftover: 4106132, + totalRevenue: 40600000, + opExRevenue: 36500000, + abatement: 962991, + overallScore: "Medium", + scorecard: [ + { name: "Economic feasibility", rating: "High" }, + { name: "Legal feasibility", rating: "Low" }, + { name: "Implementation risk", rating: "High" }, + { name: "Social feasibility", rating: "Medium" }, + { name: "Security risk", rating: "Medium" }, + { name: "Value for money", rating: "Low" }, + { name: "Overall", rating: "Medium" }, + ], + costEstimates: [ + { + name: "Capital expenditure", + value: 1514218, + items: [ + { name: "Feasibility analysis", value: 70000 }, + { name: "Conservation planning and admin", value: 629559 }, + { name: "Data collection and field costs", value: 76963 }, + { name: "Community representation", value: 286112 }, + { name: "Blue carbon project planning", value: 111125 }, + { name: "Establishing carbon rights", value: 296010 }, + { name: "Validation", value: 44450 }, + { name: "Implementation labor", value: 0 }, + ], + }, + { + name: "Operating expenditure", + value: 36509571, + items: [ + { name: "Monitoring and Maintenance", value: 402322 }, + { name: "Community benefit sharing fund", value: 34523347 }, + { name: "Carbon standard fees", value: 227875 }, + { name: "Baseline reassessment", value: 75812 }, + { name: "MRV", value: 223062 }, + ], + }, + { name: "Total cost", value: 38023789 }, + ], +}; + +export default function ProjectDetails() { + const [projectDetails, setProjectDetails] = useAtom(projectDetailsAtom); + + const handleOpenDetails = (open: boolean) => + setProjectDetails({ ...projectDetails, isOpen: open }); + + return ( + + + +
+
+ + +
+
+ {projectDetails.projectName} +
+
+ +
+ +
+
+ +
+
+
+ +
+
+ Refers to the summary of Capital Expenditure and Operating + Expenditure +
+
+
+
+
+
+ + {renderCurrency(projectData.totalCost)} + +
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+ Refers to the summary of Capital Expenditure and Operating + Expenditure +
+
+
+
+
+
+ + {renderCurrency(projectData.totalCost)} + +
+
+ + +
+
+
+ +
+
+
+
+ +
+ +
+
+ +
+ + {renderAbatementCurrency(projectData.abatement)} + +
+
+

Estimation of total CO2 expected during the project.

+
+
+ + +
+
+ +
+
+
+ + {projectData.overallScore} + +
+
+
+ + +
+
+ +
+
+ + +
+
+
+ {projectData.scorecard.map((item, index) => ( + <> + {index === 0 &&
} +
+
{item.name}
+ +
+ {projectData.scorecard.length !== index + 1 && ( +
+ )} + + ))} +
+
+ + +
+
+ +
+
+ + +
+
+
+ {projectData.costEstimates.map((estimate) => ( +
+
+
+ {estimate.name} +
+
+ + {formatCurrency(estimate.value)} + +
+
+ {estimate.items?.map((item) => ( +
+
+ {item.name} +
+
+ + {formatCurrency(item.value)} + +
+
+ ))} +
+ ))} +
+
+
+ +
+
+
+ Values considered for a{" "} + small project (40 ha). +
+
For more detailed analysis, create a custom project.
+
+
+ +
+
+
+
+ ); +} diff --git a/client/src/containers/overview/project-details/parameters/index.tsx b/client/src/containers/overview/project-details/parameters/index.tsx new file mode 100644 index 00000000..afd78739 --- /dev/null +++ b/client/src/containers/overview/project-details/parameters/index.tsx @@ -0,0 +1,122 @@ +import { + PROJECT_SIZE_FILTER, + COST_TYPE_SELECTOR, + PROJECT_PRICE_TYPE, +} from "@shared/entities/projects.entity"; +import { atom, useAtom } from "jotai"; +import { z } from "zod"; + +import { FILTER_KEYS } from "@/app/(overview)/constants"; +import { filtersSchema } from "@/app/(overview)/url-store"; + +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +const INITIAL_FILTERS_STATE: Partial> = { + projectSizeFilter: PROJECT_SIZE_FILTER.MEDIUM, + priceType: PROJECT_PRICE_TYPE.OPEN_BREAK_EVEN_PRICE, + costRangeSelector: COST_TYPE_SELECTOR.NPV, +}; + +const filtersAtom = atom(INITIAL_FILTERS_STATE); + +export const PROJECT_PARAMETERS = [ + { + key: FILTER_KEYS[1], + label: "Project size", + className: "w-[125px]", + options: [ + { + label: PROJECT_SIZE_FILTER.SMALL, + value: PROJECT_SIZE_FILTER.SMALL, + }, + { + label: PROJECT_SIZE_FILTER.MEDIUM, + value: PROJECT_SIZE_FILTER.MEDIUM, + }, + { + label: PROJECT_SIZE_FILTER.LARGE, + value: PROJECT_SIZE_FILTER.LARGE, + }, + ], + }, + { + key: FILTER_KEYS[2], + label: "Carbon pricing type", + className: "w-[195px]", + options: [ + { + label: PROJECT_PRICE_TYPE.MARKET_PRICE, + value: PROJECT_PRICE_TYPE.MARKET_PRICE, + }, + { + label: PROJECT_PRICE_TYPE.OPEN_BREAK_EVEN_PRICE, + value: PROJECT_PRICE_TYPE.OPEN_BREAK_EVEN_PRICE, + }, + ], + }, + { + key: FILTER_KEYS[3], + label: "Cost", + className: "w-[85px]", + options: [ + { + label: COST_TYPE_SELECTOR.TOTAL, + value: COST_TYPE_SELECTOR.TOTAL, + }, + { + label: COST_TYPE_SELECTOR.NPV, + value: COST_TYPE_SELECTOR.NPV, + }, + ], + }, +] as const; + +function useFilters() { + return useAtom(filtersAtom); +} + +export default function ParametersProjects() { + const [filters, setFilters] = useFilters(); + + const handleParameters = ( + v: string, + parameter: keyof Omit, "keyword">, + ) => { + setFilters((prev) => ({ ...prev, [parameter]: v })); + }; + + return ( +
+ {PROJECT_PARAMETERS.map((parameter) => ( +
+ + +
+ ))} +
+ ); +} diff --git a/client/src/containers/overview/table/view/overview/index.tsx b/client/src/containers/overview/table/view/overview/index.tsx index 2207b0c2..3d41b2d6 100644 --- a/client/src/containers/overview/table/view/overview/index.tsx +++ b/client/src/containers/overview/table/view/overview/index.tsx @@ -12,6 +12,7 @@ import { SortingState, useReactTable, } from "@tanstack/react-table"; +import { useAtom } from "jotai"; import { ChevronsUpDownIcon } from "lucide-react"; import { z } from "zod"; @@ -19,12 +20,10 @@ import { client } from "@/lib/query-client"; import { queryKeys } from "@/lib/query-keys"; import { cn } from "@/lib/utils"; +import { projectDetailsAtom } from "@/app/(overview)/store"; import { useGlobalFilters, useTableView } from "@/app/(overview)/url-store"; -import TablePagination, { - PAGINATION_SIZE_OPTIONS, -} from "@/components/ui/table-pagination"; - +import ProjectDetails from "@/containers/overview/project-details"; import { filtersToQueryParams, NO_DATA, @@ -42,10 +41,14 @@ import { TableHeader, TableRow, } from "@/components/ui/table"; +import TablePagination, { + PAGINATION_SIZE_OPTIONS, +} from "@/components/ui/table-pagination"; export function OverviewTable() { const [tableView] = useTableView(); const [filters] = useGlobalFilters(); + const [, setProjectDetails] = useAtom(projectDetailsAtom); const [sorting, setSorting] = useState([ { id: "projectName", @@ -107,6 +110,7 @@ export function OverviewTable() { return ( <> + {table.getHeaderGroups().map((headerGroup) => ( @@ -154,8 +158,15 @@ export function OverviewTable() { {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( { + setProjectDetails({ + isOpen: true, + projectName: row.original.projectName ?? "", + }); + }} > {row.getVisibleCells().map((cell) => ( diff --git a/client/src/lib/format.tsx b/client/src/lib/format.tsx index 35bee11b..ed7046eb 100644 --- a/client/src/lib/format.tsx +++ b/client/src/lib/format.tsx @@ -21,6 +21,23 @@ export const formatNumber = ( }).format(value); }; +export const renderAbatementCurrency = ( + value: number, + options: Intl.NumberFormatOptions = {}, +) => { + let formatted = formatCurrency(value, options); + formatted = formatted.replace(/\.\d+/, ""); + const [, amount] = formatted.match(/^(\D*)(.+)$/)!.slice(1); + return ( + <> + + tCO2e/yr   + + {amount} + + ); +}; + export function renderCurrency( value: number, options: Intl.NumberFormatOptions = {}, @@ -37,3 +54,17 @@ export function renderCurrency( ); } + +/** + * Converts a large numeric value into a compact format with an "M" suffix + * representing millions. + * + * @param {number} value - The numeric value to be converted. + * @returns {string} - The formatted string representing the value in millions with one decimal place. + * + * @example + * toCompactAmount(38023789); // Returns "38.0M" + */ +export const toCompactAmount = (value: number) => { + return `${(value / 1_000_000).toFixed(1)}M`; +}; diff --git a/client/tailwind.config.ts b/client/tailwind.config.ts index 198e19e5..b48f26ad 100644 --- a/client/tailwind.config.ts +++ b/client/tailwind.config.ts @@ -89,6 +89,16 @@ const config: Config = { "mint-green": { 200: "#70C69B" }, + "wheat": { + 200: "#EEE0BD" + }, + "yellow": { + 500: "#EACD3F" + }, + "high": "#B9CCA3", + "medium": "#F5EBB8", + "low": "#F7BA93", + "deep-ocean": "#132A47" }, borderRadius: { lg: "var(--radius)", diff --git a/data/excel/data_ingestion_WIP.xlsm b/data/excel/data_ingestion_WIP.xlsm index a8b6871b..ecb591b1 100644 Binary files a/data/excel/data_ingestion_WIP.xlsm and b/data/excel/data_ingestion_WIP.xlsm differ diff --git a/data/notebooks/High_level_overview.ipynb b/data/notebooks/High_level_overview.ipynb index a79fab76..f0a457ce 100644 --- a/data/notebooks/High_level_overview.ipynb +++ b/data/notebooks/High_level_overview.ipynb @@ -2,14 +2,14 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# import libraries\n", "import sys\n", "\n", - "sys.path.append(\"../src/bcc_model/\")\n", + "sys.path.append(\"./src/bcc_model/\")\n", "\n", "import itertools\n", "import math\n", @@ -22,7 +22,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -76,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -302,7 +302,7 @@ "[5 rows x 36 columns]" ] }, - "execution_count": 3, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -310,7 +310,7 @@ "source": [ "# 1. Import master table, base size table and base increase table\n", "# with information for the project calculations\n", - "data_path = \"../../raw_data/data_ingestion.xlsm\"\n", + "data_path = \"./raw_data/data_ingestion.xlsm\"\n", "\n", "# Open the excel file - tab 'master_table'\n", "master_table = pd.read_excel(data_path, sheet_name=\"master_table\")\n", @@ -326,7 +326,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -365,7 +365,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -469,7 +469,7 @@ "4 100 Market price " ] }, - "execution_count": 5, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -520,7 +520,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -584,7 +584,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -700,7 +700,7 @@ "4 100 Opex breakeven USA North America " ] }, - "execution_count": 7, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -719,7 +719,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -841,7 +841,7 @@ "4 100 Opex breakeven USA North America 500.0 " ] }, - "execution_count": 8, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -861,7 +861,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -996,7 +996,7 @@ "24 United StatesMangroveRestoration100 " ] }, - "execution_count": 9, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -1017,7 +1017,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -1802,6 +1802,7 @@ " \"opex\",\n", " \"abatement_potential\",\n", " \"cost_per_tco2e\",\n", + " \"cost_per_tco2e_npv\",\n", " \"feasibility_analysis_npv\",\n", " \"feasibility_analysis\",\n", " \"conservation_planning_npv\",\n", @@ -1991,6 +1992,12 @@ " round(cost_per_tCO2e) if not math.isnan(cost_per_tCO2e) else 0\n", " )\n", "\n", + " # Safely handle NaN in cost_per_tCO2e NPV\n", + " cost_per_tCO2e_npv = cost_calculator.cost_per_tCO2e # noqa: N816\n", + " df_combinations.loc[index, \"cost_per_tco2e\"] = (\n", + " round(cost_per_tCO2e) if not math.isnan(cost_per_tCO2e) else 0\n", + " )\n", + "\n", " # Add total revenue, total revenue NPV, and credits issued\n", " df_combinations.loc[index, \"total_revenue\"] = (\n", " summary.get(\"Total revenue (non-discounted)\", 0).replace(\"$\", \"\").replace(\",\", \"\")\n", @@ -2011,7 +2018,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -2181,7 +2188,7 @@ " \n", " \n", "
\n", - "

5 rows × 57 columns

\n", + "

5 rows × 58 columns

\n", "" ], "text/plain": [ @@ -2220,10 +2227,10 @@ "18 290522 994000 353284 \n", "24 2264746 994000 2753998 \n", "\n", - "[5 rows x 57 columns]" + "[5 rows x 58 columns]" ] }, - "execution_count": 12, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -2232,6 +2239,47 @@ "df_combinations.head()" ] }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Index(['country', 'ecosystem', 'activity', 'activity_type',\n", + " 'project_size_filter', 'project_size', 'price_type', 'country_code',\n", + " 'continent', 'base_size', 'project_name', 'total_cost_npv',\n", + " 'total_cost', 'capex_npv', 'capex', 'opex_npv', 'opex',\n", + " 'abatement_potential', 'cost_per_tco2e', 'cost_per_tco2e_npv',\n", + " 'feasibility_analysis_npv', 'feasibility_analysis',\n", + " 'conservation_planning_npv', 'conservation_planning',\n", + " 'data_collection_npv', 'data_collection',\n", + " 'community_representation_npv', 'community_representation',\n", + " 'blue_carbon_project_planning_npv', 'blue_carbon_project_planning',\n", + " 'establishing_carbon_rights_npv', 'establishing_carbon_rights',\n", + " 'validation_npv', 'validation', 'implementation_labor_npv',\n", + " 'implementation_labor', 'monitoring_maintenance_npv',\n", + " 'monitoring_maintenance', 'community_benefit_npv', 'community_benefit',\n", + " 'carbon_standard_fees_npv', 'carbon_standard_fees',\n", + " 'baseline_reassessment_npv', 'baseline_reassessment', 'mrv_npv', 'mrv',\n", + " 'long_term_project_operating_npv', 'long_term_project_operating',\n", + " 'initial_price_assumption', 'leftover_after_opex',\n", + " 'leftover_after_opex_npv', 'total_revenue', 'total_revenu_npv',\n", + " 'credits_issued', 'monitoring_npv', 'maintenance_npv', 'monitoring',\n", + " 'maintenance'],\n", + " dtype='object')" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_combinations.columns" + ] + }, { "cell_type": "code", "execution_count": 13, diff --git a/shared/entities/projects.entity.ts b/shared/entities/projects.entity.ts index b9031dbc..0d352176 100644 --- a/shared/entities/projects.entity.ts +++ b/shared/entities/projects.entity.ts @@ -18,7 +18,7 @@ export enum PROJECT_SIZE_FILTER { } export enum PROJECT_PRICE_TYPE { - OPEN_BREAK_EVEN_PRICE = "Opex breakeven price", + OPEN_BREAK_EVEN_PRICE = "Opex breakeven", MARKET_PRICE = "Market price", }