Skip to content

Commit

Permalink
feat: TBCCT-300 BE - Update datamodel to add the Sources Entities
Browse files Browse the repository at this point in the history
  • Loading branch information
alepefe committed Feb 4, 2025
1 parent 4c63e7e commit d550f44
Show file tree
Hide file tree
Showing 23 changed files with 987 additions and 180 deletions.
4 changes: 3 additions & 1 deletion api/src/modules/import/import.repostiory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { BaseIncrease } from '@shared/entities/base-increase.entity';
import { BaseSize } from '@shared/entities/base-size.entity';
import { ModelAssumptions } from '@shared/entities/model-assumptions.entity';
import { ProjectScorecard } from '@shared/entities/project-scorecard.entity';
import { ModelComponentSource } from '@shared/entities/methodology/model-component-source.entity';

@Injectable()
export class ImportRepository {
Expand Down Expand Up @@ -99,12 +100,13 @@ export class ImportRepository {
await manager.clear(EcosystemLoss);
await manager.clear(RestorableLand);
await manager.clear(SequestrationRate);
await manager.clear(EmissionFactors);
await manager.delete(EmissionFactors, {});

// Other tables ingestion
await manager.clear(BaseSize);
await manager.clear(BaseIncrease);
await manager.clear(ModelAssumptions);
await manager.delete(ModelComponentSource, {});
// DATA WIPE ENDS

// CREATION STARTS
Expand Down
109 changes: 109 additions & 0 deletions api/test/integration/methodology/model-component-sources.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { EmissionFactors } from '@shared/entities/carbon-inputs/emission-factors.entity';
import { EmissionFactorsSource } from '@shared/entities/methodology/emission-factor-source.entity';
import { EMISSION_FACTOR_TYPE } from '@shared/entities/methodology/emission-factor.type';
import { ModelComponentSource } from '@shared/entities/methodology/model-component-source.entity';
import { TestManager } from 'api/test/utils/test-manager';
import { Repository } from 'typeorm';

describe('Model component sources', () => {
let testManager: TestManager;

beforeAll(async () => {
testManager = await TestManager.createTestManager();
await testManager.clearDatabase();
});

afterAll(async () => {
await testManager.close();
});

describe('Creation of a EmissionFactorsSource m2m relationship between a EmissionFactors and ModelComponentSource', () => {
let emissionFactorRepo: Repository<EmissionFactors>;
let modelComponentSourceRepo: Repository<ModelComponentSource>;
let emissionFactorsSourceRepo: Repository<EmissionFactorsSource>;
let emissionFactor: EmissionFactors;
let modelComponentSource: ModelComponentSource;

afterAll(async () => {
await testManager.clearDatabase();
});

beforeAll(async () => {
const { jwtToken } = await testManager.setUpTestUser();
await testManager.ingestCountries();
await testManager.ingestProjectScoreCards(jwtToken);
await testManager.ingestExcel(jwtToken);

emissionFactorRepo = testManager
.getDataSource()
.getRepository(EmissionFactors);

modelComponentSourceRepo = testManager
.getDataSource()
.getRepository(ModelComponentSource);

emissionFactorsSourceRepo = testManager
.getDataSource()
.getRepository(EmissionFactorsSource);

emissionFactor = (await emissionFactorRepo.find())[0];
modelComponentSource = await modelComponentSourceRepo.save({
name: 'Test',
reviewedAt: new Date(),
});
});

test('Check if the m2m relationship was created thourgh the intermediate table', async () => {
const emissionFactorSource = new EmissionFactorsSource();
emissionFactorSource.emissionFactor = emissionFactor;
emissionFactorSource.source = modelComponentSource;
emissionFactorSource.emissionFactorType = EMISSION_FACTOR_TYPE.SOC;

await emissionFactorsSourceRepo.save(emissionFactorSource);

const savedEmissionFactorSource = (
await emissionFactorsSourceRepo.find({
relations: ['emissionFactor', 'source'],
})
)[0];

expect(savedEmissionFactorSource).toBeDefined();
});

test("Check if the row in the intermediate table was deleted when the related row in ModelComponentSource's table was deleted", async () => {
await modelComponentSourceRepo.delete(modelComponentSource.id);

expect(
await emissionFactorsSourceRepo.find({
relations: ['emissionFactor', 'source'],
}),
).toHaveLength(0);
});

test('Check that a deletion of a row in the intermediation table (EmissionFactorsSource) doest not delete the related ModelComponentSource', async () => {
// Given
modelComponentSource = await modelComponentSourceRepo.save({
name: 'Test',
reviewedAt: new Date(),
});
const emissionFactorSource = new EmissionFactorsSource();
emissionFactorSource.emissionFactor = emissionFactor;
emissionFactorSource.source = modelComponentSource;
emissionFactorSource.emissionFactorType = EMISSION_FACTOR_TYPE.SOC;

await emissionFactorsSourceRepo.save(emissionFactorSource);

// When
await emissionFactorsSourceRepo.delete({
emissionFactor: emissionFactor,
source: modelComponentSource,
});

// Then
const expectedModelComponentSource = (
await modelComponentSourceRepo.findBy({ id: modelComponentSource.id })
)[0];
expect(expectedModelComponentSource).toBeDefined();
});
});
});
1 change: 1 addition & 0 deletions backoffice/components/atoms/selector.type.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type SelectorOption = { label: string; value: string | number };
15 changes: 15 additions & 0 deletions backoffice/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ComponentLoader } from 'adminjs';

export const componentLoader = new ComponentLoader();

export const Components = {
Dashboard: componentLoader.add('Dashboard', './dashboard'),
FileIngestion: componentLoader.add(
'FileIngestion',
'./pages/file-ingestion/page',
),
EmissionFactorSources: componentLoader.add(
'EmissionFactorSources',
'./molecules/emission-factors-sources',
),
};
70 changes: 70 additions & 0 deletions backoffice/components/molecules/emission-factors-sources.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import { BasePropertyProps, RecordJSON } from 'adminjs';
import Many2ManySources from './many-2-many-sources.js';
import { SelectorOption } from 'backoffice/components/atoms/selector.type.js';
import { EmissionFactors } from '@shared/entities/carbon-inputs/emission-factors.entity.js';
import { ModelComponentSource } from '@shared/entities/methodology/model-component-source.entity.js';
import { EmissionFactorsSource } from '@shared/entities/methodology/emission-factor-source.entity.js';

// // The import was not working, so I had to hardcode the const here
const AVAILABLE_SOURCE_TYPES = [
'SOC',
'AGB',
'global',
't2CountrySpecificAGB',
't2CountrySpecificSOC',
] as const as string[];

const computeFetchParams = (record: RecordJSON) => {
return {
emissionFactor: record.id,
};
};

const computeAddParams = (
record: RecordJSON,
typeSelection: SelectorOption,
sourceSelection: SelectorOption,
) => {
return {
emissionFactor: { id: record?.params.id } as unknown as EmissionFactors,
source: { id: sourceSelection.value } as unknown as ModelComponentSource,
emissionFactorType: typeSelection.value,
};
};

const computeDeleteParams = (
record: RecordJSON,
item: EmissionFactorsSource,
) => {
return {
emissionFactor: { id: record?.params.id } as unknown as EmissionFactors,
source: { id: item.source.id } as unknown as ModelComponentSource,
emissionFactorType: item.emissionFactorType,
};
};

const EmissionFactorSources: React.FC<BasePropertyProps> = ({
record,
property,
where,
resource,
}) => {
if (!record) return null;

return (
<Many2ManySources
record={record}
property={property}
where={where}
resource={resource}
many2manyEntityName={'EmissionFactorsSource'} // Cannot import the entity in front-end components
availableSourceTypes={AVAILABLE_SOURCE_TYPES}
computeFetchParams={computeFetchParams}
computeAddParams={computeAddParams}
computeDeleteParams={computeDeleteParams}
/>
);
};

export default EmissionFactorSources;
Loading

0 comments on commit d550f44

Please sign in to comment.