Skip to content

Commit

Permalink
Add entity filters for geo-features
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeh committed Mar 7, 2024
1 parent bc53ccb commit 145b15d
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 45 deletions.
15 changes: 7 additions & 8 deletions api/src/modules/eudr-alerts/eudr.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import {
ValidationPipe,
} from '@nestjs/common';
import {
ApiExtraModels,
ApiForbiddenResponse,
ApiOkResponse,
ApiOperation,
ApiTags,
ApiUnauthorizedResponse,
refs,
} from '@nestjs/swagger';

import { ApiOkTreeResponse } from 'decorators/api-tree-response.decorator';
Expand All @@ -37,11 +35,10 @@ import { EudrService } from 'modules/eudr-alerts/eudr.service';
import { GetEUDRAlertsDto } from 'modules/eudr-alerts/dto/get-alerts.dto';
import { EUDRAlertDates } from 'modules/eudr-alerts/eudr.repositoty.interface';
import { GetEUDRFeaturesGeoJSONDto } from 'modules/geo-regions/dto/get-features-geojson.dto';
import { Feature, FeatureCollection } from 'geojson';
import {
GeoFeatureCollectionResponse,
GeoFeatureResponse,
} from '../geo-regions/dto/geo-feature-response.dto';
} from 'modules/geo-regions/dto/geo-feature-response.dto';

@ApiTags('EUDR')
@Controller('/api/v1/eudr')
Expand Down Expand Up @@ -180,7 +177,7 @@ export class EudrController {
async getGeoFeatureList(
@Query(ValidationPipe) dto: GetEUDRFeaturesGeoJSONDto,
): Promise<GeoFeatureResponse[]> {
return this.geoRegionsService.getGeoJson(dto);
return this.geoRegionsService.getGeoJson({ ...dto, eudr: true });
}

@ApiOperation({
Expand All @@ -193,8 +190,10 @@ export class EudrController {
async getGeoFeatureCollection(
@Query(ValidationPipe) dto: GetEUDRFeaturesGeoJSONDto,
): Promise<GeoFeatureCollectionResponse> {
return this.geoRegionsService.getGeoJson(
Object.assign(dto, { collection: true }),
);
return this.geoRegionsService.getGeoJson({
...dto,
eudr: true,
collection: true,
});
}
}
5 changes: 4 additions & 1 deletion api/src/modules/eudr-alerts/eudr.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ export const IEUDRAlertsRepositoryToken: symbol = Symbol(
export const EUDRDataSetToken: symbol = Symbol('EUDRDataSet');
export const EUDRCredentialsToken: symbol = Symbol('EUDRCredentials');

const { credentials, dataset } = AppConfig.get('eudr');
const { credentials, dataset } = AppConfig.get<{
credentials: string;
dataset: string;
}>('eudr');

// TODO: Use token injection and refer to the interface, right now I am having a dependencv issue
@Module({
Expand Down
23 changes: 9 additions & 14 deletions api/src/modules/geo-regions/dto/get-features-geojson.dto.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
import { ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsBoolean, IsOptional, IsUUID } from 'class-validator';

export class GetFeaturesGeoJsonDto {
@ApiPropertyOptional()
@IsOptional()
@IsUUID('4', { each: true })
geoRegionIds!: string[];
import { IsBoolean, IsOptional } from 'class-validator';
import {
CommonEUDRFiltersDTO,
CommonFiltersDto,
} from 'utils/base.query-builder';

export class GetFeaturesGeoJsonDto extends CommonFiltersDto {
@IsOptional()
@IsBoolean()
@Type(() => Boolean)
collection: boolean = false;

isEUDRRequested(): boolean {
return 'eudr' in this;
}
}

export class GetEUDRFeaturesGeoJSONDto extends GetFeaturesGeoJsonDto {
export class GetEUDRFeaturesGeoJSONDto extends CommonEUDRFiltersDTO {
@IsOptional()
@IsBoolean()
eudr: boolean = true;
@Type(() => Boolean)
collection: boolean = false;
}
24 changes: 8 additions & 16 deletions api/src/modules/geo-regions/geo-features.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ import {
GetEUDRFeaturesGeoJSONDto,
GetFeaturesGeoJsonDto,
} from 'modules/geo-regions/dto/get-features-geojson.dto';
import {
LOCATION_TYPES,
SourcingLocation,
} from 'modules/sourcing-locations/sourcing-location.entity';
import { SourcingLocation } from 'modules/sourcing-locations/sourcing-location.entity';
import { BaseQueryBuilder } from 'utils/base.query-builder';

@Injectable()
export class GeoFeaturesService extends Repository<GeoRegion> {
Expand All @@ -25,20 +23,14 @@ export class GeoFeaturesService extends Repository<GeoRegion> {
const queryBuilder: SelectQueryBuilder<GeoRegion> =
this.createQueryBuilder('gr');
queryBuilder.innerJoin(SourcingLocation, 'sl', 'sl.geoRegionId = gr.id');
if (dto.isEUDRRequested()) {
queryBuilder.where('sl.locationType = :locationType', {
locationType: LOCATION_TYPES.EUDR,
});
}
if (dto.geoRegionIds) {
queryBuilder.andWhere('gr.id IN (:...geoRegionIds)', {
geoRegionIds: dto.geoRegionIds,
});
}

const filteredQueryBuilder: SelectQueryBuilder<GeoRegion> =
BaseQueryBuilder.addFilters(queryBuilder, dto);

if (dto?.collection) {
return this.selectAsFeatureCollection(queryBuilder);
return this.selectAsFeatureCollection(filteredQueryBuilder);
}
return this.selectAsFeatures(queryBuilder);
return this.selectAsFeatures(filteredQueryBuilder);
}

private async selectAsFeatures(
Expand Down
12 changes: 12 additions & 0 deletions api/src/utils/base.query-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export class BaseQueryBuilder {
originIds: filters.originIds,
});
}
if (filters.geoRegionIds) {
queryBuilder.andWhere('sl.geoRegionId IN (:...geoRegionIds)', {
geoRegionIds: filters.geoRegionIds,
});
}
if (filters.eudr) {
queryBuilder.andWhere('sl.locationType = :eudr', {
eudr: LOCATION_TYPES.EUDR,
Expand Down Expand Up @@ -137,6 +142,8 @@ export class CommonFiltersDto {
scenarioIds?: string[];

eudr?: boolean;

geoRegionIds?: string[];
}

export class CommonEUDRFiltersDTO extends OmitType(CommonFiltersDto, [
Expand All @@ -146,4 +153,9 @@ export class CommonEUDRFiltersDTO extends OmitType(CommonFiltersDto, [
'businessUnitIds',
]) {
eudr?: boolean;

@ApiPropertyOptional({ name: 'geoRegionIds[]' })
@IsOptional()
@IsUUID('4', { each: true })
geoRegionIds?: string[];
}
3 changes: 2 additions & 1 deletion api/test/e2e/eudr/eudr-admin-region-filters.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EUDRTestManager } from './fixtures';
import { TestManager } from '../../utils/test-manager';
import { Supplier } from '../../../src/modules/suppliers/supplier.entity';

describe('Admin Regions EUDR Filters (e2e)', () => {
let testManager: EUDRTestManager;
Expand Down Expand Up @@ -43,7 +44,7 @@ describe('Admin Regions EUDR Filters (e2e)', () => {
);
await testManager.WhenIRequestEUDRAdminRegions({
'materialIds[]': [eudrMaterials[0].id],
'producerIds[]': eudrSuppliers.map((s) => s.id),
'producerIds[]': eudrSuppliers.map((s: Supplier) => s.id),
});
testManager.ThenIShouldOnlyReceiveCorrespondingAdminRegions([
eudrAdminRegions[0],
Expand Down
4 changes: 3 additions & 1 deletion api/test/e2e/eudr/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class EUDRTestManager extends TestManager {
sourcingLocations[i].materialId = materials[i].id;
await sourcingLocations[i].save();
}
return materials;
};
AndAssociatedSuppliers = async (
sourcingLocations: SourcingLocation[],
Expand All @@ -65,9 +66,10 @@ export class EUDRTestManager extends TestManager {
}
const limitLength = Math.min(suppliers.length, sourcingLocations.length);
for (let i = 0; i < limitLength; i++) {
sourcingLocations[i].materialId = suppliers[i].id;
sourcingLocations[i].producerId = suppliers[i].id;
await sourcingLocations[i].save();
}
return suppliers;
};
GivenEUDRAdminRegions = async () => {
const adminRegion = await createAdminRegion({
Expand Down
39 changes: 36 additions & 3 deletions api/test/e2e/geo-regions/fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { createGeoRegion, createSourcingLocation } from '../../entity-mocks';
import {
createAdminRegion,
createGeoRegion,
createMaterial,
createSourcingLocation,
createSupplier,
} from '../../entity-mocks';
import * as request from 'supertest';
import { GeoRegion } from '../../../src/modules/geo-regions/geo-region.entity';
import { LOCATION_TYPES } from '../../../src/modules/sourcing-locations/sourcing-location.entity';
import {
LOCATION_TYPES,
SourcingLocation,
} from '../../../src/modules/sourcing-locations/sourcing-location.entity';
import { TestManager } from '../../utils/test-manager';
import { Feature } from 'geojson';
import { SUPPLIER_TYPES } from 'modules/suppliers/supplier.entity';

export class GeoRegionsTestManager extends TestManager {
constructor(manager: TestManager) {
Expand Down Expand Up @@ -38,13 +48,33 @@ export class GeoRegionsTestManager extends TestManager {
const geoRegion2 = await createGeoRegion({
name: this.generateRandomName(),
});

const adminRegion = await createAdminRegion({ name: 'EUDR AdminRegion' });
const adminRegion2 = await createAdminRegion({
name: 'EUDR AdminRegion 2',
});

const supplier = await createSupplier({
name: 'EUDR Supplier',
});

const material = await createMaterial({ name: 'EUDR Material' });
const material2 = await createMaterial({ name: 'EUDR Material 2' });

const supplier2 = await createSupplier({ name: 'EUDR Supplier 2' });
const sourcingLocation1 = await createSourcingLocation({
geoRegionId: geoRegion.id,
locationType: LOCATION_TYPES.EUDR,
adminRegionId: adminRegion.id,
producerId: supplier.id,
materialId: material.id,
});
const sourcingLocation2 = await createSourcingLocation({
geoRegionId: geoRegion2.id,
locationType: LOCATION_TYPES.EUDR,
adminRegionId: adminRegion2.id,
producerId: supplier2.id,
materialId: material2.id,
});
return {
eudrGeoRegions: [geoRegion, geoRegion2],
Expand All @@ -63,7 +93,10 @@ export class GeoRegionsTestManager extends TestManager {
};

WhenIRequestEUDRGeoFeatureCollection = async (filters: {
'geoRegionIds[]': string[];
'geoRegionIds[]'?: string[];
'producerIds[]'?: string[];
'materialIds[]'?: string[];
'originIds[]'?: string[];
}): Promise<void> => {
this.response = await request(this.testApp.getHttpServer())
.get('/api/v1/eudr/geo-features/collection')
Expand Down
16 changes: 15 additions & 1 deletion api/test/e2e/geo-regions/geo-features.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,21 @@ describe('Admin Regions EUDR Filters (e2e)', () => {
eudrGeoRegions[0],
]);
});
test('sould only get EUDR geo-features as a FeatureCollection', async () => {
test('should only get EUDR geo-features filtered by materials, suppliers and admin regions', async () => {
const {} = await testManager.GivenRegularSourcingLocationsWithGeoRegions();
const { eudrSourcingLocations, eudrGeoRegions } =
await testManager.GivenEUDRSourcingLocationsWithGeoRegions();
await testManager.WhenIRequestEUDRGeoFeatureCollection({
'materialIds[]': [eudrSourcingLocations[0].materialId],
'producerIds[]': [eudrSourcingLocations[0].producerId as string],
'originIds[]': [eudrSourcingLocations[0].adminRegionId],
});
testManager.ThenIShouldOnlyRecieveCorrespondingGeoFeatures(
[eudrGeoRegions[0]],
true,
);
});
test('sould only get EUDR geo-features as a FeatureCollection and filtered by geo regions', async () => {
await testManager.GivenRegularSourcingLocationsWithGeoRegions();
const { eudrGeoRegions } =
await testManager.GivenEUDRSourcingLocationsWithGeoRegions();
Expand Down

0 comments on commit 145b15d

Please sign in to comment.