Skip to content

Commit

Permalink
Add active material and indicator checks to maps
Browse files Browse the repository at this point in the history
  • Loading branch information
yulia-bel authored and alexeh committed Feb 15, 2023
1 parent 5c4d111 commit be9ecd5
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 4 deletions.
24 changes: 24 additions & 0 deletions api/src/modules/h3-data/h3-data.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
GetScenarioVsScenarioImpactMapDto,
} from 'modules/h3-data/dto/get-impact-map.dto';
import { H3DataMapService } from 'modules/h3-data/h3-data-map.service';
import { MaterialsService } from 'modules/materials/materials.service';
import { IndicatorsService } from 'modules/indicators/indicators.service';

@Controller('/api/v1/h3')
@ApiTags(H3Data.name)
Expand All @@ -29,6 +31,8 @@ export class H3DataController {
constructor(
protected readonly h3DataService: H3DataService,
protected readonly h3DataMapService: H3DataMapService,
protected readonly materialsService: MaterialsService,
protected readonly indicatorService: IndicatorsService,
) {}

@ApiOperation({ description: 'Retrieve H3 data providing its name' })
Expand Down Expand Up @@ -100,6 +104,9 @@ export class H3DataController {
queryParams: GetMaterialH3ByResolutionDto,
): Promise<H3MapResponse> {
const { materialId, resolution, year } = queryParams;

await this.materialsService.checkActiveMaterials([materialId]);

return await this.h3DataMapService.getMaterialMapByResolutionAndYear(
materialId,
resolution,
Expand All @@ -121,6 +128,13 @@ export class H3DataController {
async getImpactMap(
@Query(ValidationPipe) getImpactMapDto: GetImpactMapDto,
): Promise<H3MapResponse> {
await this.indicatorService.checkActiveIndicatorsForCalculations([
getImpactMapDto.indicatorId,
]);
if (getImpactMapDto.materialIds)
await this.materialsService.checkActiveMaterials(
getImpactMapDto.materialIds,
);
return this.h3DataMapService.getImpactMapByResolution(getImpactMapDto);
}

Expand All @@ -139,6 +153,11 @@ export class H3DataController {
async getImpactActualVsScenarioComparisonMap(
@Query(ValidationPipe) dto: GetActualVsScenarioImpactMapDto,
): Promise<H3MapResponse> {
await this.indicatorService.checkActiveIndicatorsForCalculations([
dto.indicatorId,
]);
if (dto.materialIds)
await this.materialsService.checkActiveMaterials(dto.materialIds);
return this.h3DataMapService.getImpactMapByResolution(dto);
}

Expand All @@ -157,6 +176,11 @@ export class H3DataController {
async getImpactScenarioVsScenarioComparisonMap(
@Query(ValidationPipe) dto: GetScenarioVsScenarioImpactMapDto,
): Promise<H3MapResponse> {
await this.indicatorService.checkActiveIndicatorsForCalculations([
dto.indicatorId,
]);
if (dto.materialIds)
await this.materialsService.checkActiveMaterials(dto.materialIds);
return this.h3DataMapService.getImpactMapByResolution(dto);
}
}
6 changes: 6 additions & 0 deletions api/src/modules/h3-data/h3-data.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import { SuppliersModule } from 'modules/suppliers/suppliers.module';
import { BusinessUnitsModule } from 'modules/business-units/business-units.module';
import { H3DataMapService } from 'modules/h3-data/h3-data-map.service';
import { H3DataRepository } from 'modules/h3-data/h3-data.repository';
import { MaterialsService } from 'modules/materials/materials.service';
import { SourcingLocationsModule } from 'modules/sourcing-locations/sourcing-locations.module';
import { IndicatorsService } from 'modules/indicators/indicators.service';

@Module({
imports: [
Expand All @@ -24,13 +27,16 @@ import { H3DataRepository } from 'modules/h3-data/h3-data.repository';
AdminRegionsModule,
SuppliersModule,
BusinessUnitsModule,
SourcingLocationsModule,
],
controllers: [H3DataController],
providers: [
H3DataService,
H3DataMapService,
H3DataYearsService,
H3DataRepository,
MaterialsService,
IndicatorsService,
],
exports: [H3DataService, H3DataYearsService],
})
Expand Down
14 changes: 14 additions & 0 deletions api/src/modules/impact/impact.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { ActualVsScenarioImpactService } from 'modules/impact/comparison/actual-
import { SetScenarioIdsInterceptor } from 'modules/impact/set-scenario-ids.interceptor';
import { ScenarioVsScenarioImpactService } from 'modules/impact/comparison/scenario-vs-scenario.service';
import { ScenarioVsScenarioPaginatedImpactTable } from 'modules/impact/dto/response-scenario-scenario.dto';
import { IndicatorsService } from 'modules/indicators/indicators.service';
import { MaterialsService } from 'modules/materials/materials.service';

@Controller('/api/v1/impact')
Expand All @@ -41,6 +42,7 @@ export class ImpactController {
private readonly impactService: ImpactService,
private readonly actualVsScenarioImpactService: ActualVsScenarioImpactService,
private readonly scenarioVsScenarioService: ScenarioVsScenarioImpactService,
private readonly indicatorService: IndicatorsService,
private readonly materialsService: MaterialsService,
) {}

Expand All @@ -57,6 +59,9 @@ export class ImpactController {
@ProcessFetchSpecification() fetchSpecification: FetchSpecification,
@Query(ValidationPipe) impactTableDto: GetImpactTableDto,
): Promise<PaginatedImpactTable> {
await this.indicatorService.checkActiveIndicatorsForCalculations(
impactTableDto.indicatorIds,
);
/* Here we are validating received materialIds to be active, without validating recursively possible descendants,
since the Material Ids come from existing impact data (materials present in Sourcing Locations) and existing descendants
will be active per default */
Expand Down Expand Up @@ -84,6 +89,9 @@ export class ImpactController {
@Query(ValidationPipe)
scenarioVsScenarioImpactTableDto: GetScenarioVsScenarioImpactTableDto,
): Promise<ScenarioVsScenarioPaginatedImpactTable> {
await this.indicatorService.checkActiveIndicatorsForCalculations(
scenarioVsScenarioImpactTableDto.indicatorIds,
);
/* Here we are validating received materialIds to be active, without validating recursively possible descendants,
since the Material Ids come from existing impact data (materials present in Sourcing Locations) and existing descendants
will be active per default */
Expand Down Expand Up @@ -112,6 +120,9 @@ export class ImpactController {
@Query(ValidationPipe)
actualVsScenarioImpactTableDto: GetActualVsScenarioImpactTableDto,
): Promise<PaginatedImpactTable> {
await this.indicatorService.checkActiveIndicatorsForCalculations(
actualVsScenarioImpactTableDto.indicatorIds,
);
/* Here we are validating received materialIds to be active, without validating recursively possible descendants,
since the Material Ids come from existing impact data (materials present in Sourcing Locations) and existing descendants
will be active per default */
Expand Down Expand Up @@ -139,6 +150,9 @@ export class ImpactController {
async getRankedImpactTable(
@Query(ValidationPipe) rankedImpactTableDto: GetRankedImpactTableDto,
): Promise<ImpactTable> {
await this.indicatorService.checkActiveIndicatorsForCalculations(
rankedImpactTableDto.indicatorIds,
);
/* Here we are validating received materialIds to be active, without validating recursively possible descendants,
since the Material Ids come from existing impact data (materials present in Sourcing Locations) and existing descendants
will be active per default */
Expand Down
2 changes: 1 addition & 1 deletion api/src/modules/impact/impact.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { SuppliersModule } from 'modules/suppliers/suppliers.module';
import { MaterialsModule } from 'modules/materials/materials.module';
import { ActualVsScenarioImpactService } from 'modules/impact/comparison/actual-vs-scenario.service';
import { ScenarioVsScenarioImpactService } from 'modules/impact/comparison/scenario-vs-scenario.service';
import { MaterialsService } from '../materials/materials.service';
import { MaterialsService } from 'modules/materials/materials.service';
import { SourcingLocationsModule } from 'modules/sourcing-locations/sourcing-locations.module';
import { IndicatorsService } from 'modules/indicators/indicators.service';

Expand Down
102 changes: 102 additions & 0 deletions api/test/e2e/h3-data/h3-impact-map.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,108 @@ describe('H3 Data Module (e2e) - Impact map', () => {
).toBeTruthy();
});
});

describe('Active materials and indicator validations', () => {
test('When I query impact map for inactive material, then I should get a proper error message', async () => {
const response = await request(testApplication.getHttpServer())
.get(`/api/v1/h3/map/impact`)
.set('Authorization', `Bearer ${jwtToken}`)
.query({
indicatorId: impactMapMockData.indicatorId,
'materialIds[]': [impactMapMockData.inactiveMaterialId],
year: 2020,
resolution: 6,
});
expect(response.body.errors[0].meta.rawError.response.message).toEqual(
'Following Requested Materials are not activated: Inactive Material',
);
});

test('When I query impact map for inactive indicator, then I should get a proper error message', async () => {
const response = await request(testApplication.getHttpServer())
.get(`/api/v1/h3/map/impact`)
.set('Authorization', `Bearer ${jwtToken}`)
.query({
indicatorId: impactMapMockData.inactiveIndicatorId,
'materialIds[]': [impactMapMockData.materialOneId],
year: 2020,
resolution: 6,
});
expect(response.body.errors[0].meta.rawError.response.message).toEqual(
'Requested Indicators are not activated: Inactive Indicator',
);
});

test('When I query Actual vs Scenario comparison map for inactive material, then I should get a proper error message', async () => {
const response = await request(testApplication.getHttpServer())
.get(`/api/v1/h3/map/impact/compare/actual/vs/scenario`)
.set('Authorization', `Bearer ${jwtToken}`)
.query({
indicatorId: impactMapMockData.indicatorId,
'materialIds[]': [impactMapMockData.inactiveMaterialId],
year: 2020,
resolution: 6,
comparedScenarioId: impactMapMockData.scenarioId,
relative: false,
});
expect(response.body.errors[0].meta.rawError.response.message).toEqual(
'Following Requested Materials are not activated: Inactive Material',
);
});

test('When I query Actual vs Scenario comparison map for inactive indicator, then I should get a proper error message', async () => {
const response = await request(testApplication.getHttpServer())
.get(`/api/v1/h3/map/impact/compare/actual/vs/scenario`)
.set('Authorization', `Bearer ${jwtToken}`)
.query({
indicatorId: impactMapMockData.inactiveIndicatorId,
'materialIds[]': [impactMapMockData.materialOneId],
year: 2020,
resolution: 6,
comparedScenarioId: impactMapMockData.scenarioId,
relative: false,
});
expect(response.body.errors[0].meta.rawError.response.message).toEqual(
'Requested Indicators are not activated: Inactive Indicator',
);
});

test('When I query Scenario vs Scenario comparison map for inactive material, then I should get a proper error message', async () => {
const response = await request(testApplication.getHttpServer())
.get(`/api/v1/h3/map/impact/compare/scenario/vs/scenario`)
.set('Authorization', `Bearer ${jwtToken}`)
.query({
indicatorId: impactMapMockData.indicatorId,
'materialIds[]': [impactMapMockData.inactiveMaterialId],
year: 2020,
resolution: 6,
baseScenarioId: impactMapMockData.scenarioId,
comparedScenarioId: impactMapMockData.scenarioTwoId,
relative: false,
});
expect(response.body.errors[0].meta.rawError.response.message).toEqual(
'Following Requested Materials are not activated: Inactive Material',
);
});

test('When I query Scenario vs Scenario comparison map for inactive indicator, then I should get a proper error message', async () => {
const response = await request(testApplication.getHttpServer())
.get(`/api/v1/h3/map/impact/compare/scenario/vs/scenario`)
.set('Authorization', `Bearer ${jwtToken}`)
.query({
indicatorId: impactMapMockData.inactiveIndicatorId,
'materialIds[]': [impactMapMockData.materialOneId],
year: 2020,
resolution: 6,
baseScenarioId: impactMapMockData.scenarioId,
comparedScenarioId: impactMapMockData.scenarioTwoId,
relative: false,
});
expect(response.body.errors[0].meta.rawError.response.message).toEqual(
'Requested Indicators are not activated: Inactive Indicator',
);
});
});
});

/**
Expand Down
21 changes: 20 additions & 1 deletion api/test/e2e/h3-data/h3-material-map.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as request from 'supertest';
import { H3DataRepository } from 'modules/h3-data/h3-data.repository';
import { h3DataMock, dropH3DataMock } from './mocks/h3-data.mock';
import { dropH3DataMock, h3DataMock } from './mocks/h3-data.mock';
import { createMaterial, createMaterialToH3 } from '../../entity-mocks';
import { MaterialRepository } from 'modules/materials/material.repository';
import { MATERIAL_TO_H3_TYPE } from 'modules/materials/material-to-h3.entity';
Expand All @@ -12,6 +12,10 @@ import ApplicationManager, {
} from '../../utils/application-manager';
import { DataSource } from 'typeorm';
import { clearTestDataFromDatabase } from '../../utils/database-test-helper';
import {
Material,
MATERIALS_STATUS,
} from '../../../src/modules/materials/material.entity';

/**
* Tests for the H3DataModule.
Expand Down Expand Up @@ -75,6 +79,21 @@ describe('H3 Data Module (e2e) - Material map', () => {
);
});

test('When I query inactive material H3 data, then I should get a proper error message', async () => {
const material: Material = await createMaterial({
status: MATERIALS_STATUS.INACTIVE,
name: 'Inactive Material',
});
const response = await request(testApplication.getHttpServer())
.get(
`/api/v1/h3/map/material?materialId=${material.id}&resolution=6&year=2020`,
)
.set('Authorization', `Bearer ${jwtToken}`);
expect(response.body.errors[0].meta.rawError.response.message).toEqual(
'Following Requested Materials are not activated: Inactive Material',
);
});

test('When I query a material H3 data but it has no year value, then I should get a proper error message', async () => {
const material = await createMaterial({ name: 'Material with no H3' });
const response = await request(testApplication.getHttpServer())
Expand Down
23 changes: 21 additions & 2 deletions api/test/e2e/h3-data/mocks/h3-impact-map.mock.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Unit } from 'modules/units/unit.entity';
import { UnitConversion } from 'modules/unit-conversions/unit-conversion.entity';
import { Indicator } from 'modules/indicators/indicator.entity';
import {
Indicator,
INDICATOR_STATUS,
} from 'modules/indicators/indicator.entity';
import { h3DataMock } from './h3-data.mock';
import { Material } from 'modules/materials/material.entity';
import { Material, MATERIALS_STATUS } from 'modules/materials/material.entity';
import {
createAdminRegion,
createGeoRegion,
Expand Down Expand Up @@ -40,6 +43,7 @@ import { DataSource } from 'typeorm';

export interface ImpactMapMockData {
indicatorId: string;
inactiveIndicatorId: string;
unitId: string;
adminRegionOneId: string;
adminRegionTwoId: string;
Expand All @@ -49,6 +53,7 @@ export interface ImpactMapMockData {
t1SupplierTwoId: string;
producerOneId: string;
producerTwoId: string;
inactiveMaterialId: string;
materialOneId: string;
materialTwoId: string;
harvestH3DataOneId: string;
Expand Down Expand Up @@ -79,6 +84,13 @@ export const createImpactMapMockData = async (
indicator.nameCode = 'UWU_T';
await indicator.save();

const inactiveIndicator: Indicator = new Indicator();
inactiveIndicator.name = 'Inactive Indicator';
inactiveIndicator.unit = unit;
inactiveIndicator.status = INDICATOR_STATUS.INACTIVE;
inactiveIndicator.nameCode = 'INA_IN';
await inactiveIndicator.save();

const harvestH3Data = await h3DataMock(dataSource, {
h3TableName: 'harvestTable',
h3ColumnName: 'harvestColumn',
Expand All @@ -99,6 +111,11 @@ export const createImpactMapMockData = async (

tablesToDrop.push(productionH3Data.h3tableName);

const inactiveMaterial: Material = await createMaterial({
name: 'Inactive Material',
status: MATERIALS_STATUS.INACTIVE,
});

const materialOne: Material = await createMaterial({
name: 'MaterialOne',
});
Expand Down Expand Up @@ -452,6 +469,7 @@ export const createImpactMapMockData = async (

return {
indicatorId: indicator.id,
inactiveIndicatorId: inactiveIndicator.id,
unitId: unit.id,
geoRegionOneId: geoRegionOne.id,
geoRegionTwoId: geoRegionTwo.id,
Expand All @@ -461,6 +479,7 @@ export const createImpactMapMockData = async (
t1SupplierTwoId: t1SupplierTwo.id,
producerOneId: producerSupplierOne.id,
producerTwoId: producerSupplierTwo.id,
inactiveMaterialId: inactiveMaterial.id,
materialOneId: materialOne.id,
materialTwoId: materialTwo.id,
harvestH3DataOneId: harvestH3Data.id,
Expand Down

0 comments on commit be9ecd5

Please sign in to comment.