From 8ab1ddbebc4901aa158c8e111a7df51507bb8987 Mon Sep 17 00:00:00 2001 From: sbriat Date: Tue, 11 Apr 2023 10:13:15 +0200 Subject: [PATCH] use interfaces for requests --- package.json | 1 + .../adapters/primaries/matcher.controller.ts | 6 +-- .../secondaries/default-params.provider.ts | 16 ++++++++ .../adapters/secondaries/message-broker.ts | 2 +- .../matcher/adapters/secondaries/messager.ts | 4 +- .../matcher/domain/dtos/match.request.ts | 13 +++++-- src/modules/matcher/domain/entities/person.ts | 10 ++--- src/modules/matcher/domain/entities/time.ts | 31 +++++++++------ .../interfaces/default-params.interface.ts | 5 +++ .../interfaces/person-request.interface.ts | 3 ++ .../interfaces/role-request.interface.ts | 4 ++ .../interfaces/time-request.interface.ts | 7 ++++ src/modules/matcher/matcher.module.ts | 9 ++++- src/modules/matcher/queries/match.query.ts | 27 ++++--------- .../unit/default-params.provider.spec.ts | 38 +++++++++++++++++++ .../matcher/tests/unit/match.usecase.spec.ts | 12 +++++- 16 files changed, 141 insertions(+), 47 deletions(-) create mode 100644 src/modules/matcher/adapters/secondaries/default-params.provider.ts create mode 100644 src/modules/matcher/domain/interfaces/default-params.interface.ts create mode 100644 src/modules/matcher/domain/interfaces/person-request.interface.ts create mode 100644 src/modules/matcher/domain/interfaces/role-request.interface.ts create mode 100644 src/modules/matcher/domain/interfaces/time-request.interface.ts create mode 100644 src/modules/matcher/tests/unit/default-params.provider.spec.ts diff --git a/package.json b/package.json index 5919315..7df44c8 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ ".controller.ts", ".module.ts", ".request.ts", + ".presenter.ts", "main.ts" ], "rootDir": "src", diff --git a/src/modules/matcher/adapters/primaries/matcher.controller.ts b/src/modules/matcher/adapters/primaries/matcher.controller.ts index 1a837a9..7e001d5 100644 --- a/src/modules/matcher/adapters/primaries/matcher.controller.ts +++ b/src/modules/matcher/adapters/primaries/matcher.controller.ts @@ -9,7 +9,7 @@ import { ICollection } from 'src/modules/database/src/interfaces/collection.inte import { Match } from '../../domain/entities/match'; import { MatchQuery } from '../../queries/match.query'; import { MatchPresenter } from '../secondaries/match.presenter'; -import { ConfigService } from '@nestjs/config'; +import { DefaultParamsProvider } from '../secondaries/default-params.provider'; @UsePipes( new RpcValidationPipe({ @@ -21,7 +21,7 @@ import { ConfigService } from '@nestjs/config'; export class MatcherController { constructor( private readonly _queryBus: QueryBus, - private readonly _configService: ConfigService, + private readonly _defaultParamsProvider: DefaultParamsProvider, @InjectMapper() private readonly _mapper: Mapper, ) {} @@ -29,7 +29,7 @@ export class MatcherController { async match(data: MatchRequest): Promise> { try { const matchCollection = await this._queryBus.execute( - new MatchQuery(data, this._configService), + new MatchQuery(data, this._defaultParamsProvider.getParams()), ); return Promise.resolve({ data: matchCollection.data.map((match: Match) => diff --git a/src/modules/matcher/adapters/secondaries/default-params.provider.ts b/src/modules/matcher/adapters/secondaries/default-params.provider.ts new file mode 100644 index 0000000..d113c4a --- /dev/null +++ b/src/modules/matcher/adapters/secondaries/default-params.provider.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { IDefaultParams } from '../../domain/interfaces/default-params.interface'; + +@Injectable() +export class DefaultParamsProvider { + constructor(private readonly configService: ConfigService) {} + + getParams(): IDefaultParams { + return { + DEFAULT_IDENTIFIER: this.configService.get('DEFAULT_IDENTIFIER'), + MARGIN_DURATION: this.configService.get('MARGIN_DURATION'), + VALIDITY_DURATION: this.configService.get('VALIDITY_DURATION'), + }; + } +} diff --git a/src/modules/matcher/adapters/secondaries/message-broker.ts b/src/modules/matcher/adapters/secondaries/message-broker.ts index 594aa43..7b4f4df 100644 --- a/src/modules/matcher/adapters/secondaries/message-broker.ts +++ b/src/modules/matcher/adapters/secondaries/message-broker.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; @Injectable() -export abstract class IMessageBroker { +export abstract class MessageBroker { exchange: string; constructor(exchange: string) { diff --git a/src/modules/matcher/adapters/secondaries/messager.ts b/src/modules/matcher/adapters/secondaries/messager.ts index 0725261..e808bcf 100644 --- a/src/modules/matcher/adapters/secondaries/messager.ts +++ b/src/modules/matcher/adapters/secondaries/messager.ts @@ -1,10 +1,10 @@ import { AmqpConnection } from '@golevelup/nestjs-rabbitmq'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { IMessageBroker } from './message-broker'; +import { MessageBroker } from './message-broker'; @Injectable() -export class Messager extends IMessageBroker { +export class Messager extends MessageBroker { constructor( private readonly _amqpConnection: AmqpConnection, configService: ConfigService, diff --git a/src/modules/matcher/domain/dtos/match.request.ts b/src/modules/matcher/domain/dtos/match.request.ts index bbdd274..3052a7e 100644 --- a/src/modules/matcher/domain/dtos/match.request.ts +++ b/src/modules/matcher/domain/dtos/match.request.ts @@ -14,8 +14,13 @@ import { Point } from '../entities/point.type'; import { Schedule } from './schedule.type'; import { MarginDurations } from './margin-durations.type'; import { Algorithm } from './algorithm.enum'; +import { IRequestTime } from '../interfaces/time-request.interface'; +import { IRequestRole } from '../interfaces/role-request.interface'; +import { IRequestPerson } from '../interfaces/person-request.interface'; -export class MatchRequest { +export class MatchRequest + implements IRequestTime, IRequestRole, IRequestPerson +{ @IsArray() @AutoMap() waypoints: Array; @@ -23,12 +28,12 @@ export class MatchRequest { @IsOptional() @IsString() @AutoMap() - departure: number; + departure: string; @IsOptional() - @IsInt() + @IsString() @AutoMap() - fromDate: number; + fromDate: string; @IsOptional() @AutoMap() diff --git a/src/modules/matcher/domain/entities/person.ts b/src/modules/matcher/domain/entities/person.ts index 37b2add..40349f1 100644 --- a/src/modules/matcher/domain/entities/person.ts +++ b/src/modules/matcher/domain/entities/person.ts @@ -1,25 +1,25 @@ -import { MatchRequest } from '../dtos/match.request'; +import { IRequestPerson } from '../interfaces/person-request.interface'; export class Person { - _matchRequest: MatchRequest; + _personRequest: IRequestPerson; _defaultIdentifier: number; _defaultMarginDuration: number; identifier: number; marginDurations: Array; constructor( - matchRequest: MatchRequest, + personRequest: IRequestPerson, defaultIdentifier: number, defaultMarginDuration: number, ) { - this._matchRequest = matchRequest; + this._personRequest = personRequest; this._defaultIdentifier = defaultIdentifier; this._defaultMarginDuration = defaultMarginDuration; } init() { this.setIdentifier( - this._matchRequest.identifier ?? this._defaultIdentifier, + this._personRequest.identifier ?? this._defaultIdentifier, ); this.setMarginDurations([ this._defaultMarginDuration, diff --git a/src/modules/matcher/domain/entities/time.ts b/src/modules/matcher/domain/entities/time.ts index 36ae203..f29c5e0 100644 --- a/src/modules/matcher/domain/entities/time.ts +++ b/src/modules/matcher/domain/entities/time.ts @@ -1,9 +1,9 @@ import { MatcherException } from '../../exceptions/matcher.exception'; -import { MatchRequest } from '../dtos/match.request'; +import { IRequestTime } from '../interfaces/time-request.interface'; import { TimingFrequency } from './timing'; export class Time { - _matchRequest: MatchRequest; + _timeRequest: IRequestTime; _defaultMarginDuration: number; _defaultValidityDuration: number; frequency: TimingFrequency; @@ -13,35 +13,44 @@ export class Time { marginDurations: Array; constructor( - matchRequest: MatchRequest, + timeRequest: IRequestTime, defaultMarginDuration: number, defaultValidityDuration: number, ) { - this._matchRequest = matchRequest; + this._timeRequest = timeRequest; this._defaultMarginDuration = defaultMarginDuration; this._defaultValidityDuration = defaultValidityDuration; } init() { + this._validateBaseDate(); this._validatePunctualDate(); this._validateRecurrentDate(); + console.log(this.fromDate); + } + + _validateBaseDate() { + if (!this._timeRequest.departure && !this._timeRequest.fromDate) { + throw new MatcherException(3, 'departure or fromDate is required'); + } } _validatePunctualDate() { - if (!this._matchRequest.departure && !this._matchRequest.fromDate) { - throw new MatcherException(3, 'departure or fromDate is Required'); - } - if (this._matchRequest.departure) { - this.fromDate = new Date(this._matchRequest.departure); + if (this._timeRequest.departure) { + this.fromDate = new Date(this._timeRequest.departure); if (!this._isDate(this.fromDate)) { throw new MatcherException(3, 'Wrong departure date'); } - console.log(this.fromDate); } } _validateRecurrentDate() { - console.log('validate recurrent date'); + if (this._timeRequest.fromDate) { + this.fromDate = new Date(this._timeRequest.fromDate); + if (!this._isDate(this.fromDate)) { + throw new MatcherException(3, 'Wrong fromDate'); + } + } } _isDate(date: Date) { diff --git a/src/modules/matcher/domain/interfaces/default-params.interface.ts b/src/modules/matcher/domain/interfaces/default-params.interface.ts new file mode 100644 index 0000000..e5d5f2d --- /dev/null +++ b/src/modules/matcher/domain/interfaces/default-params.interface.ts @@ -0,0 +1,5 @@ +export interface IDefaultParams { + DEFAULT_IDENTIFIER: number; + MARGIN_DURATION: number; + VALIDITY_DURATION: number; +} diff --git a/src/modules/matcher/domain/interfaces/person-request.interface.ts b/src/modules/matcher/domain/interfaces/person-request.interface.ts new file mode 100644 index 0000000..75211f7 --- /dev/null +++ b/src/modules/matcher/domain/interfaces/person-request.interface.ts @@ -0,0 +1,3 @@ +export interface IRequestPerson { + identifier: number; +} diff --git a/src/modules/matcher/domain/interfaces/role-request.interface.ts b/src/modules/matcher/domain/interfaces/role-request.interface.ts new file mode 100644 index 0000000..cc124b8 --- /dev/null +++ b/src/modules/matcher/domain/interfaces/role-request.interface.ts @@ -0,0 +1,4 @@ +export interface IRequestRole { + driver: boolean; + passenger: boolean; +} diff --git a/src/modules/matcher/domain/interfaces/time-request.interface.ts b/src/modules/matcher/domain/interfaces/time-request.interface.ts new file mode 100644 index 0000000..44ee14e --- /dev/null +++ b/src/modules/matcher/domain/interfaces/time-request.interface.ts @@ -0,0 +1,7 @@ +import { Schedule } from '../dtos/schedule.type'; + +export interface IRequestTime { + departure: string; + fromDate: string; + schedule: Schedule; +} diff --git a/src/modules/matcher/matcher.module.ts b/src/modules/matcher/matcher.module.ts index ef74b38..2bb67a3 100644 --- a/src/modules/matcher/matcher.module.ts +++ b/src/modules/matcher/matcher.module.ts @@ -11,6 +11,7 @@ import { Messager } from './adapters/secondaries/messager'; import { CacheModule } from '@nestjs/cache-manager'; import { RedisClientOptions } from '@liaoliaots/nestjs-redis'; import { redisStore } from 'cache-manager-ioredis-yet'; +import { DefaultParamsProvider } from './adapters/secondaries/default-params.provider'; @Module({ imports: [ @@ -44,7 +45,13 @@ import { redisStore } from 'cache-manager-ioredis-yet'; }), ], controllers: [MatcherController], - providers: [MatchProfile, AdRepository, Messager, MatchUseCase], + providers: [ + MatchProfile, + AdRepository, + Messager, + DefaultParamsProvider, + MatchUseCase, + ], exports: [], }) export class MatcherModule {} diff --git a/src/modules/matcher/queries/match.query.ts b/src/modules/matcher/queries/match.query.ts index 4d26d19..e957080 100644 --- a/src/modules/matcher/queries/match.query.ts +++ b/src/modules/matcher/queries/match.query.ts @@ -1,4 +1,3 @@ -import { ConfigService } from '@nestjs/config'; import { MatchRequest } from '../domain/dtos/match.request'; import { Geography } from '../domain/entities/geography'; import { Person } from '../domain/entities/person'; @@ -6,11 +5,11 @@ import { Requirement } from '../domain/entities/requirement'; import { Role } from '../domain/entities/role.enum'; import { Settings } from '../domain/entities/settings'; import { Time } from '../domain/entities/time'; -import { MatcherException } from '../exceptions/matcher.exception'; +import { IDefaultParams } from '../domain/interfaces/default-params.interface'; export class MatchQuery { private readonly _matchRequest: MatchRequest; - private readonly _configService: ConfigService; + private readonly _defaultParams: IDefaultParams; person: Person; exclusions: Array; time: Time; @@ -19,10 +18,9 @@ export class MatchQuery { requirement: Requirement; settings: Settings; - constructor(matchRequest: MatchRequest, configService: ConfigService) { + constructor(matchRequest: MatchRequest, defaultParams: IDefaultParams) { this._matchRequest = matchRequest; - this._configService = configService; - this._validate(); + this._defaultParams = defaultParams; this._initialize(); this._setPerson(); this._setExclusions(); @@ -31,15 +29,6 @@ export class MatchQuery { // console.log(this); } - _validate() { - if (!this._matchRequest.departure) { - if (!this._matchRequest.fromDate) - throw new MatcherException(3, 'departure or fromDate is Required'); - if (!this._matchRequest.schedule) - throw new MatcherException(3, 'schedule is Required'); - } - } - _initialize() { if ( this._matchRequest.driver === undefined && @@ -54,8 +43,8 @@ export class MatchQuery { _setPerson() { this.person = new Person( this._matchRequest, - this._configService.get('DEFAULT_IDENTIFIER'), - this._configService.get('MARGIN_DURATION'), + this._defaultParams.DEFAULT_IDENTIFIER, + this._defaultParams.MARGIN_DURATION, ); this.person.init(); } @@ -77,8 +66,8 @@ export class MatchQuery { _setTime() { this.time = new Time( this._matchRequest, - this._configService.get('MARGIN_DURATION'), - this._configService.get('VALIDITY_DURATION'), + this._defaultParams.MARGIN_DURATION, + this._defaultParams.VALIDITY_DURATION, ); this.time.init(); } diff --git a/src/modules/matcher/tests/unit/default-params.provider.spec.ts b/src/modules/matcher/tests/unit/default-params.provider.spec.ts new file mode 100644 index 0000000..49cf3ca --- /dev/null +++ b/src/modules/matcher/tests/unit/default-params.provider.spec.ts @@ -0,0 +1,38 @@ +import { ConfigService } from '@nestjs/config'; +import { Test, TestingModule } from '@nestjs/testing'; +import { DefaultParamsProvider } from '../../adapters/secondaries/default-params.provider'; +import { IDefaultParams } from '../../domain/interfaces/default-params.interface'; + +const mockConfigService = { + get: jest.fn().mockImplementationOnce(() => 99), +}; + +describe('DefaultParamsProvider', () => { + let defaultParamsProvider: DefaultParamsProvider; + + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + imports: [], + providers: [ + DefaultParamsProvider, + { + provide: ConfigService, + useValue: mockConfigService, + }, + ], + }).compile(); + + defaultParamsProvider = module.get( + DefaultParamsProvider, + ); + }); + + it('should be defined', () => { + expect(defaultParamsProvider).toBeDefined(); + }); + + it('should provide default params', async () => { + const params: IDefaultParams = defaultParamsProvider.getParams(); + expect(params.DEFAULT_IDENTIFIER).toBe(99); + }); +}); diff --git a/src/modules/matcher/tests/unit/match.usecase.spec.ts b/src/modules/matcher/tests/unit/match.usecase.spec.ts index b0b304f..3fa3f92 100644 --- a/src/modules/matcher/tests/unit/match.usecase.spec.ts +++ b/src/modules/matcher/tests/unit/match.usecase.spec.ts @@ -6,6 +6,7 @@ import { MatchQuery } from '../../queries/match.query'; import { AdRepository } from '../../adapters/secondaries/ad.repository'; import { AutomapperModule } from '@automapper/nestjs'; import { classes } from '@automapper/classes'; +import { IDefaultParams } from '../../domain/interfaces/default-params.interface'; const mockAdRepository = {}; @@ -13,6 +14,12 @@ const mockMessager = { publish: jest.fn().mockImplementation(), }; +const defaultParams: IDefaultParams = { + DEFAULT_IDENTIFIER: 0, + MARGIN_DURATION: 900, + VALIDITY_DURATION: 365, +}; + describe('MatchUseCase', () => { let matchUseCase: MatchUseCase; @@ -52,7 +59,10 @@ describe('MatchUseCase', () => { lon: 3.045432, }, ]; - const matches = await matchUseCase.execute(new MatchQuery(matchRequest)); + matchRequest.departure = '2023-04-01 12:23:00'; + const matches = await matchUseCase.execute( + new MatchQuery(matchRequest, defaultParams), + ); expect(matches.total).toBe(1); }); });