diff --git a/package-lock.json b/package-lock.json index 7febf97..6e07338 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@nestjs/schematics": "^9.0.0", "@nestjs/testing": "^9.0.0", "@types/express": "^4.17.13", + "@types/geojson": "^7946.0.10", "@types/jest": "29.2.4", "@types/node": "18.11.18", "@types/supertest": "^2.0.11", @@ -2320,6 +2321,12 @@ "@types/range-parser": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.10", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", + "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", + "dev": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -10869,6 +10876,12 @@ "@types/range-parser": "*" } }, + "@types/geojson": { + "version": "7946.0.10", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", + "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", + "dev": true + }, "@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", diff --git a/package.json b/package.json index 622d5b4..8d70fc6 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "@nestjs/schematics": "^9.0.0", "@nestjs/testing": "^9.0.0", "@types/express": "^4.17.13", + "@types/geojson": "^7946.0.10", "@types/jest": "29.2.4", "@types/node": "18.11.18", "@types/supertest": "^2.0.11", diff --git a/src/modules/database/src/adapters/secondaries/prisma-repository.abstract.ts b/src/modules/database/src/adapters/secondaries/prisma-repository.abstract.ts index bf121d2..188224b 100644 --- a/src/modules/database/src/adapters/secondaries/prisma-repository.abstract.ts +++ b/src/modules/database/src/adapters/secondaries/prisma-repository.abstract.ts @@ -5,6 +5,7 @@ import { DatabaseException } from '../../exceptions/database.exception'; import { ICollection } from '../../interfaces/collection.interface'; import { IRepository } from '../../interfaces/repository.interface'; import { PrismaService } from './prisma-service'; +import { Territory } from 'src/modules/territories/domain/entities/territory'; /** * Child classes MUST redefined _model property with appropriate model name @@ -185,11 +186,22 @@ export abstract class PrismaRepository implements IRepository { } async findForPoint(point: Point): Promise> { - const strPoint = `SELECT uuid, name FROM ${this._model} WHERE ST_Intersects('POINT(${point.lon} ${point.lat})',shape) = true`; + const strPoint = `SELECT uuid, name FROM ${this._model} WHERE ST_Intersects(ST_GeomFromText('POINT(${point.lon} ${point.lat})',4326),shape) = true`; const territories: Array = await this._prisma.$queryRawUnsafe(strPoint); return Promise.resolve({ data: territories, total: territories.length, }); } + + async createTerritory(territory: Territory): Promise { + const command = `INSERT INTO ${this._model} VALUES ('bb281075-1b98-4456-89d6-c643d3044a91','${territory.name}', ST_GeomFromGeoJSON('{"type":"MultiPolygon","coordinates":${territory.shape}}'),'2023-02-07 15:58:00','2023-02-07 15:58:00')`; + const affectedRowNumber = await this._prisma.$executeRawUnsafe(command); + if (affectedRowNumber == 1) { + return this.findOne({ + name: territory.name, + }); + } + throw new DatabaseException(); + } } diff --git a/src/modules/territories/domain/dtos/update-territory.request.ts b/src/modules/territories/domain/dtos/update-territory.request.ts index 0d97070..8e6954e 100644 --- a/src/modules/territories/domain/dtos/update-territory.request.ts +++ b/src/modules/territories/domain/dtos/update-territory.request.ts @@ -1,5 +1,6 @@ import { AutoMap } from '@automapper/classes'; import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; +import { Geometry } from 'geojson'; export class UpdateTerritoryRequest { @IsString() @@ -15,5 +16,5 @@ export class UpdateTerritoryRequest { @IsString() @IsOptional() @AutoMap() - shape?: string; + shape?: Geometry; } diff --git a/src/modules/territories/domain/usecases/create-territory.usecase.ts b/src/modules/territories/domain/usecases/create-territory.usecase.ts index 0e05c2c..8258df0 100644 --- a/src/modules/territories/domain/usecases/create-territory.usecase.ts +++ b/src/modules/territories/domain/usecases/create-territory.usecase.ts @@ -25,7 +25,7 @@ export class CreateTerritoryUseCase { ); try { - const territory = await this._repository.create(entity); + const territory = await this._repository.createTerritory(entity); this._territoryMessager.publish('create', JSON.stringify(territory)); this._loggingMessager.publish( 'territory.create.info', diff --git a/src/modules/territories/tests/unit/create-territory.usecase.spec.ts b/src/modules/territories/tests/unit/create-territory.usecase.spec.ts index db86c5e..1af6563 100644 --- a/src/modules/territories/tests/unit/create-territory.usecase.spec.ts +++ b/src/modules/territories/tests/unit/create-territory.usecase.spec.ts @@ -12,7 +12,20 @@ import { TerritoryProfile } from '../../mappers/territory.profile'; const newTerritoryRequest: CreateTerritoryRequest = { name: 'Grand Est', - shape: 'grand-est-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }; const newTerritoryCommand: CreateTerritoryCommand = new CreateTerritoryCommand( newTerritoryRequest, diff --git a/src/modules/territories/tests/unit/delete-territory.usecase.spec.ts b/src/modules/territories/tests/unit/delete-territory.usecase.spec.ts index 0d8afa1..047c670 100644 --- a/src/modules/territories/tests/unit/delete-territory.usecase.spec.ts +++ b/src/modules/territories/tests/unit/delete-territory.usecase.spec.ts @@ -9,17 +9,56 @@ const mockTerritories = [ { uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', name: 'Grand Est', - shape: 'grand-est-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }, { uuid: 'bb281075-1b98-4456-89d6-c643d3044a92', name: 'Nouvelle Aquitaine', - shape: 'nouvelle-aquitaine-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }, { uuid: 'bb281075-1b98-4456-89d6-c643d3044a93', name: 'Occitanie', - shape: 'occitanie-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }, ]; diff --git a/src/modules/territories/tests/unit/find-all-territories.usecase.spec.ts b/src/modules/territories/tests/unit/find-all-territories.usecase.spec.ts index 4e4aaf4..78899f7 100644 --- a/src/modules/territories/tests/unit/find-all-territories.usecase.spec.ts +++ b/src/modules/territories/tests/unit/find-all-territories.usecase.spec.ts @@ -16,17 +16,56 @@ const mockTerritories = [ { uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', name: 'Grand Est', - shape: 'grand-est-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }, { uuid: 'bb281075-1b98-4456-89d6-c643d3044a92', name: 'Nouvelle Aquitaine', - shape: 'nouvelle-aquitaine-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }, { uuid: 'bb281075-1b98-4456-89d6-c643d3044a93', name: 'Occitanie', - shape: 'occitanie-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }, ]; diff --git a/src/modules/territories/tests/unit/find-territory-by-uuid.usecase.spec.ts b/src/modules/territories/tests/unit/find-territory-by-uuid.usecase.spec.ts index 5006fef..c944dd6 100644 --- a/src/modules/territories/tests/unit/find-territory-by-uuid.usecase.spec.ts +++ b/src/modules/territories/tests/unit/find-territory-by-uuid.usecase.spec.ts @@ -9,7 +9,20 @@ import { FindTerritoryByUuidQuery } from '../../queries/find-territory-by-uuid.q const mockTerritory = { uuid: 'bb281075-1b98-4456-89d6-c643d3044a91', name: 'Grand Est', - shape: 'grand-est-binary-shape', + shape: { + type: 'MultiPolygon', + coordinates: [ + [ + [ + [838383.2, 6570485.8], + [838483.8, 6570697.7], + [838688.1, 6571298.4], + [838809.5, 6571599.9], + [838383.2, 6570485.8], + ], + ], + ], + }, }; const mockTerritoriesRepository = {