diff --git a/README.md b/README.md index 1ea22e1..298d2ea 100644 --- a/README.md +++ b/README.md @@ -14,27 +14,27 @@ A RabbitMQ instance is also required to send / receive messages when data has be ## Installation -- copy `.env.dist` to `.env` : +- copy `.env.dist` to `.env` : - ```bash - cp .env.dist .env - ``` + ```bash + cp .env.dist .env + ``` - Modify it if needed. + Modify it if needed. -- install the dependencies : +- install the dependencies : - ```bash - npm install - ``` + ```bash + npm install + ``` -- start the containers : +- start the containers : - ```bash - docker compose up -d - ``` + ```bash + docker compose up -d + ``` - The app runs automatically on port **5004**. + The app runs automatically on port **5004**. ## Database migration @@ -46,11 +46,76 @@ npm run migrate ## Usage -TBD +The app exposes the following [gRPC](https://grpc.io/) services : + +- **FindForPoint** : find all territories that include a given point (represented by its longitude and latitude) + + ```json + { + "lon": 5.493345, + "lat": 46.143376 + } + ``` + +- **FindByUuid** : find a territory by its uuid + + ```json + { + "uuid": "80126a61-d128-4f96-afdb-92e33c75a3e1" + } + ``` + +- **FindAll** : find all territories; you can use pagination with `page` (default:_1_) and `perPage` (default:_10_) + + ```json + { + "page": 1, + "perPage": 10 + } + ``` + +- **Create** : create a territory (note that uuid is optional, a uuid will be automatically attributed if it is not provided) + + ```json + { + "name": "Ain", + "shape": "[[[[ 4.7953935, 46.2200671 ], [ 4.793835, 46.2155098 ], ... [ 4.7967607, 46.2219542 ], [ 4.7953935, 46.2200671 ]]]]" + } + ``` + + Note that _shape_ **must** be a string representation of the [_coordinates_ value of a GeoJSON MultiPolygon](https://www.rfc-editor.org/rfc/rfc7946#section-3.1.7) + +- **Update** : update a territory + + ```json + { + "uuid": "80126a61-d128-4f96-afdb-92e33c75a3e1", + "name": "Ain", + "shape": "[[[[ 4.7953935, 46.2200671 ], [ 4.793835, 46.2155098 ], ... [ 4.7967607, 46.2219542 ], [ 4.7953935, 46.2200671 ]]]]" + } + ``` + + Note that _shape_ **must** be a string representation of the [_coordinates_ value of a GeoJSON MultiPolygon](https://www.rfc-editor.org/rfc/rfc7946#section-3.1.7) + +- **Delete** : delete a territory by its uuid + + ```json + { + "uuid": "80126a61-d128-4f96-afdb-92e33c75a3e1" + } + ``` ## Messages -TBD +As mentionned earlier, RabbitMQ messages are sent after these events : + +- **Create** (message : the created territory informations, without the shape) + +- **Update** (message : the updated territory informations, without the shape) + +- **Delete** (message : the uuid of the deleted territory) + +Various messages are also sent for logging purpose. ## Tests diff --git a/src/modules/territories/adapters/secondaries/territory-logging.presenter.ts b/src/modules/territories/adapters/secondaries/territory-logging.presenter.ts new file mode 100644 index 0000000..bb60d9f --- /dev/null +++ b/src/modules/territories/adapters/secondaries/territory-logging.presenter.ts @@ -0,0 +1,9 @@ +import { AutoMap } from '@automapper/classes'; + +export class TerritoryLoggingPresenter { + @AutoMap() + uuid: string; + + @AutoMap() + name: string; +} diff --git a/src/modules/territories/domain/usecases/create-territory.usecase.ts b/src/modules/territories/domain/usecases/create-territory.usecase.ts index 27dde37..ca2892f 100644 --- a/src/modules/territories/domain/usecases/create-territory.usecase.ts +++ b/src/modules/territories/domain/usecases/create-territory.usecase.ts @@ -7,6 +7,7 @@ import { CreateTerritoryCommand } from '../../commands/create-territory.command' import { TerritoryMessager } from '../../adapters/secondaries/territory.messager'; import { Territory } from '../entities/territory'; import { CreateTerritoryRequest } from '../dtos/create-territory.request'; +import { TerritoryLoggingPresenter } from '../../adapters/secondaries/territory-logging.presenter'; @CommandHandler(CreateTerritoryCommand) export class CreateTerritoryUseCase { @@ -26,10 +27,17 @@ export class CreateTerritoryUseCase { try { const territory = await this._repository.createTerritory(entity); - this._territoryMessager.publish('create', JSON.stringify(territory)); + this._territoryMessager.publish( + 'create', + JSON.stringify( + this._mapper.map(territory, Territory, TerritoryLoggingPresenter), + ), + ); this._loggingMessager.publish( 'territory.create.info', - JSON.stringify(territory), + JSON.stringify( + this._mapper.map(territory, Territory, TerritoryLoggingPresenter), + ), ); return territory; } catch (error) { diff --git a/src/modules/territories/domain/usecases/update-territory.usecase.ts b/src/modules/territories/domain/usecases/update-territory.usecase.ts index b2c509f..68f84f6 100644 --- a/src/modules/territories/domain/usecases/update-territory.usecase.ts +++ b/src/modules/territories/domain/usecases/update-territory.usecase.ts @@ -4,6 +4,7 @@ import { CommandHandler } from '@nestjs/cqrs'; import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; import { TerritoriesRepository } from '../../adapters/secondaries/territories.repository'; import { TerritoryMessager } from '../../adapters/secondaries/territory.messager'; +import { TerritoryLoggingPresenter } from '../../adapters/secondaries/territory-logging.presenter'; import { UpdateTerritoryCommand } from '../../commands/update-territory.command'; import { UpdateTerritoryRequest } from '../dtos/update-territory.request'; import { Territory } from '../entities/territory'; @@ -29,11 +30,23 @@ export class UpdateTerritoryUseCase { ); this._territoryMessager.publish( 'update', - JSON.stringify(command.updateTerritoryRequest), + JSON.stringify( + this._mapper.map( + command.updateTerritoryRequest, + UpdateTerritoryRequest, + TerritoryLoggingPresenter, + ), + ), ); this._loggingMessager.publish( 'territory.update.info', - JSON.stringify(command.updateTerritoryRequest), + JSON.stringify( + this._mapper.map( + command.updateTerritoryRequest, + UpdateTerritoryRequest, + TerritoryLoggingPresenter, + ), + ), ); return territory; } catch (error) { diff --git a/src/modules/territories/mappers/territory.profile.ts b/src/modules/territories/mappers/territory.profile.ts index cea7fa3..5a5addf 100644 --- a/src/modules/territories/mappers/territory.profile.ts +++ b/src/modules/territories/mappers/territory.profile.ts @@ -2,6 +2,7 @@ import { createMap, forMember, ignore, Mapper } from '@automapper/core'; import { AutomapperProfile, InjectMapper } from '@automapper/nestjs'; import { Injectable } from '@nestjs/common'; import { TerritoryPresenter } from '../adapters/primaries/territory.presenter'; +import { TerritoryLoggingPresenter } from '../adapters/secondaries/territory-logging.presenter'; import { CreateTerritoryRequest } from '../domain/dtos/create-territory.request'; import { UpdateTerritoryRequest } from '../domain/dtos/update-territory.request'; import { Territory } from '../domain/entities/territory'; @@ -15,6 +16,7 @@ export class TerritoryProfile extends AutomapperProfile { override get profile() { return (mapper) => { createMap(mapper, Territory, TerritoryPresenter); + createMap(mapper, Territory, TerritoryLoggingPresenter); createMap(mapper, CreateTerritoryRequest, Territory); @@ -24,6 +26,8 @@ export class TerritoryProfile extends AutomapperProfile { Territory, forMember((dest) => dest.uuid, ignore()), ); + + createMap(mapper, UpdateTerritoryRequest, TerritoryLoggingPresenter); }; } }