diff --git a/src/modules/ad/core/application/queries/match/match.query-handler.ts b/src/modules/ad/core/application/queries/match/match.query-handler.ts index 14a8af5..33f9ac9 100644 --- a/src/modules/ad/core/application/queries/match/match.query-handler.ts +++ b/src/modules/ad/core/application/queries/match/match.query-handler.ts @@ -54,7 +54,7 @@ export class MatchQueryHandler implements IQueryHandler { maxDetourDurationRatio: this._defaultParams.MAX_DETOUR_DURATION_RATIO, }) .setDatesAndSchedule(this.datetimeTransformer); - await query.setRoutes(this.routeProvider); + await query.setRoute(this.routeProvider); let algorithm: Algorithm; switch (query.algorithmType) { diff --git a/src/modules/ad/core/application/queries/match/match.query.ts b/src/modules/ad/core/application/queries/match/match.query.ts index d899c1b..a1fb409 100644 --- a/src/modules/ad/core/application/queries/match/match.query.ts +++ b/src/modules/ad/core/application/queries/match/match.query.ts @@ -112,9 +112,10 @@ export class MatchQuery extends QueryBase { setDatesAndSchedule = ( datetimeTransformer: DateTimeTransformerPort, ): MatchQuery => { + const initialFromDate: string = this.fromDate; this.fromDate = datetimeTransformer.fromDate( { - date: this.fromDate, + date: initialFromDate, time: this.schedule[0].time, coordinates: { lon: this.waypoints[0].lon, @@ -126,7 +127,7 @@ export class MatchQuery extends QueryBase { this.toDate = datetimeTransformer.toDate( this.toDate, { - date: this.fromDate, + date: initialFromDate, time: this.schedule[0].time, coordinates: { lon: this.waypoints[0].lon, @@ -164,7 +165,7 @@ export class MatchQuery extends QueryBase { return this; }; - setRoutes = async (routeProvider: RouteProviderPort): Promise => { + setRoute = async (routeProvider: RouteProviderPort): Promise => { const roles: Role[] = []; if (this.driver) roles.push(Role.DRIVER); if (this.passenger) roles.push(Role.PASSENGER); @@ -177,7 +178,7 @@ export class MatchQuery extends QueryBase { }; } -type ScheduleItem = { +export type ScheduleItem = { day?: number; time: string; margin?: number; diff --git a/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts b/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts index 936c073..99e99f8 100644 --- a/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts +++ b/src/modules/ad/core/application/queries/match/selector/passenger-oriented.selector.ts @@ -2,22 +2,24 @@ import { Frequency, Role } from '@modules/ad/core/domain/ad.types'; import { Candidate } from '../../../types/algorithm.types'; import { Selector } from '../algorithm.abstract'; import { AdReadModel } from '@modules/ad/infrastructure/ad.repository'; +import { ScheduleItem } from '../match.query'; +import { Waypoint } from '../../../types/waypoint.type'; +import { Coordinates } from '../../../types/coordinates.type'; export class PassengerOrientedSelector extends Selector { select = async (): Promise => { const queryStringRoles: QueryStringRole[] = []; if (this.query.driver) queryStringRoles.push({ - query: this.createQueryString(Role.DRIVER), + query: this._createQueryString(Role.DRIVER), role: Role.DRIVER, }); if (this.query.passenger) queryStringRoles.push({ - query: this.createQueryString(Role.PASSENGER), + query: this._createQueryString(Role.PASSENGER), role: Role.PASSENGER, }); - console.log(queryStringRoles); return ( await Promise.all( queryStringRoles.map>( @@ -43,66 +45,251 @@ export class PassengerOrientedSelector extends Selector { .flat(); }; - private createQueryString = (role: Role): string => + private _createQueryString = (role: Role): string => [ - this.createSelect(role), - this.createFrom(), + this._createSelect(role), + this._createFrom(), 'WHERE', - this.createWhere(role), - ].join(' '); + this._createWhere(role), + ] + .join(' ') + .replace(/\s+/g, ' '); // remove duplicate spaces for easy debug ! - private createSelect = (role: Role): string => + private _createSelect = (role: Role): string => [ - `SELECT - ad.uuid,driver,passenger,frequency,public.st_astext(matcher.ad.waypoints) as waypoints, - "fromDate","toDate", - "seatsProposed","seatsRequested", - strict, - "fwdAzimuth","backAzimuth", + `SELECT \ + ad.uuid,driver,passenger,frequency,public.st_astext(ad.waypoints) as waypoints,\ + "fromDate","toDate",\ + "seatsProposed","seatsRequested",\ + strict,\ + "fwdAzimuth","backAzimuth",\ si.day,si.time,si.margin`, - role == Role.DRIVER ? this.selectAsDriver() : this.selectAsPassenger(), + role == Role.DRIVER ? this._selectAsDriver() : this._selectAsPassenger(), ].join(); - private selectAsDriver = (): string => + private _selectAsDriver = (): string => `${this.query.route?.driverDuration} as duration,${this.query.route?.driverDistance} as distance`; - private selectAsPassenger = (): string => + private _selectAsPassenger = (): string => `"driverDuration" as duration,"driverDistance" as distance`; - private createFrom = (): string => + private _createFrom = (): string => 'FROM ad LEFT JOIN schedule_item si ON ad.uuid = si."adUuid"'; - private createWhere = (role: Role): string => - [this.whereRole(role), this.whereStrict(), this.whereDate()].join(' AND '); + private _createWhere = (role: Role): string => + [ + this._whereRole(role), + this._whereStrict(), + this._whereDate(), + this._whereSchedule(role), + this._whereAzimuth(), + this._whereProportion(role), + this._whereRemoteness(role), + ] + .filter((where: string) => where != '') + .join(' AND '); - private whereRole = (role: Role): string => + private _whereRole = (role: Role): string => role == Role.PASSENGER ? 'driver=True' : 'passenger=True'; - private whereStrict = (): string => + private _whereStrict = (): string => this.query.strict ? this.query.frequency == Frequency.PUNCTUAL ? `frequency='${Frequency.PUNCTUAL}'` : `frequency='${Frequency.RECURRENT}'` : ''; - private whereDate = (): string => { - const whereDate = `( - ( - "fromDate" <= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and - "toDate" >= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}' - ) OR ( - "fromDate" >= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and - "toDate" <= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}' - ) OR ( - "fromDate" <= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and - "toDate" <= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}' - ) OR ( - "fromDate" >= '${this.query.fromDate}' and "fromDate" <= '${this.query.toDate}' and - "toDate" >= '${this.query.toDate}' and "toDate" >= '${this.query.fromDate}' - ) + private _whereDate = (): string => + `(\ + (\ + "fromDate" <= '${this.query.fromDate}' AND "fromDate" <= '${this.query.toDate}' AND\ + "toDate" >= '${this.query.toDate}' AND "toDate" >= '${this.query.fromDate}'\ + ) OR (\ + "fromDate" >= '${this.query.fromDate}' AND "fromDate" <= '${this.query.toDate}' AND\ + "toDate" <= '${this.query.toDate}' AND "toDate" >= '${this.query.fromDate}'\ + ) OR (\ + "fromDate" <= '${this.query.fromDate}' AND "fromDate" <= '${this.query.toDate}' AND\ + "toDate" <= '${this.query.toDate}' AND "toDate" >= '${this.query.fromDate}'\ + ) OR (\ + "fromDate" >= '${this.query.fromDate}' AND "fromDate" <= '${this.query.toDate}' AND\ + "toDate" >= '${this.query.toDate}' AND "toDate" >= '${this.query.fromDate}'\ + )\ )`; - return whereDate; + + private _whereSchedule = (role: Role): string => { + const schedule: string[] = []; + // we need full dates to compare times, because margins can lead to compare on previous or next day + // -first we establish a base calendar (up to a week) + const scheduleDates: Date[] = this._datesBetweenBoundaries( + this.query.fromDate, + this.query.toDate, + ); + // - then we compare each resulting day of the schedule with each day of calendar, + // adding / removing margin depending on the role + scheduleDates.map((date: Date) => { + this.query.schedule + .filter( + (scheduleItem: ScheduleItem) => date.getDay() == scheduleItem.day, + ) + .map((scheduleItem: ScheduleItem) => { + switch (role) { + case Role.PASSENGER: + schedule.push(this._wherePassengerSchedule(date, scheduleItem)); + break; + case Role.DRIVER: + schedule.push(this._whereDriverSchedule(date, scheduleItem)); + break; + } + }); + }); + if (schedule.length > 0) { + return ['(', schedule.join(' OR '), ')'].join(''); + } + return ''; }; + + private _wherePassengerSchedule = ( + date: Date, + scheduleItem: ScheduleItem, + ): string => { + let maxDepartureDatetime: Date = new Date(date); + maxDepartureDatetime.setHours(parseInt(scheduleItem.time.split(':')[0])); + maxDepartureDatetime.setMinutes(parseInt(scheduleItem.time.split(':')[1])); + maxDepartureDatetime = this._addMargin( + maxDepartureDatetime, + scheduleItem.margin as number, + ); + // we want the min departure time of the driver to be before the max departure time of the passenger + return `make_timestamp(\ + ${maxDepartureDatetime.getFullYear()},\ + ${maxDepartureDatetime.getMonth() + 1},\ + ${maxDepartureDatetime.getDate()},\ + CAST(EXTRACT(hour from time) as integer),\ + CAST(EXTRACT(minute from time) as integer),0) - interval '1 second' * margin <=\ + make_timestamp(\ + ${maxDepartureDatetime.getFullYear()},\ + ${maxDepartureDatetime.getMonth() + 1},\ + ${maxDepartureDatetime.getDate()},${maxDepartureDatetime.getHours()},${maxDepartureDatetime.getMinutes()},0)`; + }; + + private _whereDriverSchedule = ( + date: Date, + scheduleItem: ScheduleItem, + ): string => { + let minDepartureDatetime: Date = new Date(date); + minDepartureDatetime.setHours(parseInt(scheduleItem.time.split(':')[0])); + minDepartureDatetime.setMinutes(parseInt(scheduleItem.time.split(':')[1])); + minDepartureDatetime = this._addMargin( + minDepartureDatetime, + -(scheduleItem.margin as number), + ); + // we want the max departure time of the passenger to be after the min departure time of the driver + return `make_timestamp(\ + ${minDepartureDatetime.getFullYear()}, + ${minDepartureDatetime.getMonth() + 1}, + ${minDepartureDatetime.getDate()},\ + CAST(EXTRACT(hour from time) as integer),\ + CAST(EXTRACT(minute from time) as integer),0) + interval '1 second' * margin >=\ + make_timestamp(\ + ${minDepartureDatetime.getFullYear()}, + ${minDepartureDatetime.getMonth() + 1}, + ${minDepartureDatetime.getDate()},${minDepartureDatetime.getHours()},${minDepartureDatetime.getMinutes()},0)`; + }; + + private _whereAzimuth = (): string => { + if (!this.query.useAzimuth) return ''; + const { minAzimuth, maxAzimuth } = this._azimuthRange( + this.query.route?.backAzimuth as number, + this.query.azimuthMargin as number, + ); + if (minAzimuth <= maxAzimuth) + return `("fwdAzimuth" <= ${minAzimuth} OR "fwdAzimuth" >= ${maxAzimuth})`; + return `("fwdAzimuth" <= ${minAzimuth} AND "fwdAzimuth" >= ${maxAzimuth})`; + }; + + private _whereProportion = (role: Role): string => { + if (!this.query.useProportion) return ''; + switch (role) { + case Role.PASSENGER: + return `(${this.query.route?.passengerDistance}>(${this.query.proportion}*"driverDistance"))`; + case Role.DRIVER: + return `("passengerDistance">(${this.query.proportion}*${this.query.route?.driverDistance}))`; + } + }; + + private _whereRemoteness = (role: Role): string => { + this.query.waypoints.sort( + (firstWaypoint: Waypoint, secondWaypoint: Waypoint) => + firstWaypoint.position - secondWaypoint.position, + ); + switch (role) { + case Role.PASSENGER: + return `\ + public.st_distance('POINT(${this.query.waypoints[0].lon} ${ + this.query.waypoints[0].lat + })'::public.geography,direction)<\ + ${this.query.remoteness} AND \ + public.st_distance('POINT(${ + this.query.waypoints[this.query.waypoints.length - 1].lon + } ${ + this.query.waypoints[this.query.waypoints.length - 1].lat + })'::public.geography,direction)<\ + ${this.query.remoteness}`; + case Role.DRIVER: + const lineStringPoints: string[] = []; + this.query.route?.points.forEach((point: Coordinates) => + lineStringPoints.push( + `public.st_makepoint(${point.lon},${point.lat})`, + ), + ); + const lineString = [ + 'public.st_makeline( ARRAY[ ', + lineStringPoints.join(','), + '] )::public.geography', + ].join(''); + return `\ + public.st_distance( public.st_startpoint(waypoints::public.geometry), ${lineString})<\ + ${this.query.remoteness} AND \ + public.st_distance( public.st_endpoint(waypoints::public.geometry), ${lineString})<\ + ${this.query.remoteness}`; + } + }; + + private _datesBetweenBoundaries = ( + firstDate: string, + lastDate: string, + max = 7, + ): Date[] => { + const fromDate: Date = new Date(firstDate); + const toDate: Date = new Date(lastDate); + const dates: Date[] = []; + let count = 0; + for ( + let date = fromDate; + date <= toDate; + date.setDate(date.getDate() + 1) + ) { + dates.push(new Date(date)); + count++; + if (count == max) break; + } + return dates; + }; + + private _addMargin = (date: Date, marginInSeconds: number): Date => { + date.setTime(date.getTime() + marginInSeconds * 1000); + return date; + }; + + private _azimuthRange = ( + azimuth: number, + margin: number, + ): { minAzimuth: number; maxAzimuth: number } => ({ + minAzimuth: + azimuth - margin < 0 ? azimuth - margin + 360 : azimuth - margin, + maxAzimuth: + azimuth + margin > 360 ? azimuth + margin - 360 : azimuth + margin, + }); } export type QueryStringRole = { diff --git a/src/modules/ad/infrastructure/ad.repository.ts b/src/modules/ad/infrastructure/ad.repository.ts index e29cde9..c7fd343 100644 --- a/src/modules/ad/infrastructure/ad.repository.ts +++ b/src/modules/ad/infrastructure/ad.repository.ts @@ -100,10 +100,12 @@ export class AdRepository ); } - getCandidates = async (queryString: string): Promise => - this.toAdReadModels( + getCandidates = async (queryString: string): Promise => { + // console.log(queryString); + return this.toAdReadModels( (await this.prismaRaw.$queryRawUnsafe(queryString)) as UngroupedAdModel[], ); + }; private toAdReadModels = ( ungroupedAds: UngroupedAdModel[], diff --git a/src/modules/ad/infrastructure/time-converter.ts b/src/modules/ad/infrastructure/time-converter.ts index c3b955f..bb186de 100644 --- a/src/modules/ad/infrastructure/time-converter.ts +++ b/src/modules/ad/infrastructure/time-converter.ts @@ -20,7 +20,7 @@ export class TimeConverter implements TimeConverterPort { date: string, time: string, timezone: string, - dst = true, + dst = false, ): Date => new Date( new DateTime( diff --git a/src/modules/ad/interface/dtos/match.response.dto.ts b/src/modules/ad/interface/dtos/match.response.dto.ts index a69fc89..bc01e6f 100644 --- a/src/modules/ad/interface/dtos/match.response.dto.ts +++ b/src/modules/ad/interface/dtos/match.response.dto.ts @@ -1,3 +1,5 @@ -export class MatchResponseDto { +import { ResponseBase } from '@mobicoop/ddd-library'; + +export class MatchResponseDto extends ResponseBase { adId: string; } diff --git a/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts b/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts index 7d84ec5..826b5f5 100644 --- a/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts +++ b/src/modules/ad/interface/grpc-controllers/match.grpc-controller.ts @@ -1,11 +1,12 @@ import { Controller, UsePipes } from '@nestjs/common'; import { GrpcMethod, RpcException } from '@nestjs/microservices'; -import { RpcValidationPipe } from '@mobicoop/ddd-library'; +import { ResponseBase, RpcValidationPipe } from '@mobicoop/ddd-library'; import { RpcExceptionCode } from '@mobicoop/ddd-library'; import { MatchPaginatedResponseDto } from '../dtos/match.paginated.response.dto'; import { QueryBus } from '@nestjs/cqrs'; import { MatchRequestDto } from './dtos/match.request.dto'; import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query'; +import { MatchEntity } from '@modules/ad/core/domain/match.entity'; @UsePipes( new RpcValidationPipe({ @@ -20,13 +21,18 @@ export class MatchGrpcController { @GrpcMethod('MatcherService', 'Match') async match(data: MatchRequestDto): Promise { try { - const matches = await this.queryBus.execute(new MatchQuery(data)); - return { - data: matches, + const matches: MatchEntity[] = await this.queryBus.execute( + new MatchQuery(data), + ); + return new MatchPaginatedResponseDto({ + data: matches.map((match: MatchEntity) => ({ + ...new ResponseBase(match), + adId: match.getProps().adId, + })), page: 1, perPage: 5, total: matches.length, - }; + }); } catch (e) { throw new RpcException({ code: RpcExceptionCode.UNKNOWN, diff --git a/src/modules/ad/interface/grpc-controllers/matcher.proto b/src/modules/ad/interface/grpc-controllers/matcher.proto index ceeacd3..11d9a4d 100644 --- a/src/modules/ad/interface/grpc-controllers/matcher.proto +++ b/src/modules/ad/interface/grpc-controllers/matcher.proto @@ -55,6 +55,7 @@ enum AlgorithmType { message Match { string id = 1; + string adId = 2; } message Matches { diff --git a/src/modules/ad/tests/unit/core/match.query-handler.spec.ts b/src/modules/ad/tests/unit/core/match.query-handler.spec.ts index 801c3a1..8a717e8 100644 --- a/src/modules/ad/tests/unit/core/match.query-handler.spec.ts +++ b/src/modules/ad/tests/unit/core/match.query-handler.spec.ts @@ -1,10 +1,12 @@ import { AD_REPOSITORY, + AD_ROUTE_PROVIDER, INPUT_DATETIME_TRANSFORMER, PARAMS_PROVIDER, } from '@modules/ad/ad.di-tokens'; import { DateTimeTransformerPort } from '@modules/ad/core/application/ports/datetime-transformer.port'; import { DefaultParamsProviderPort } from '@modules/ad/core/application/ports/default-params-provider.port'; +import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port'; import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query'; import { MatchQueryHandler } from '@modules/ad/core/application/queries/match/match.query-handler'; import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types'; @@ -72,6 +74,10 @@ const mockInputDateTimeTransformer: DateTimeTransformerPort = { time: jest.fn(), }; +const mockRouteProvider: RouteProviderPort = { + getBasic: jest.fn(), +}; + describe('Match Query Handler', () => { let matchQueryHandler: MatchQueryHandler; @@ -91,6 +97,10 @@ describe('Match Query Handler', () => { provide: INPUT_DATETIME_TRANSFORMER, useValue: mockInputDateTimeTransformer, }, + { + provide: AD_ROUTE_PROVIDER, + useValue: mockRouteProvider, + }, ], }).compile(); diff --git a/src/modules/ad/tests/unit/core/match.query.spec.ts b/src/modules/ad/tests/unit/core/match.query.spec.ts index aea2933..651227b 100644 --- a/src/modules/ad/tests/unit/core/match.query.spec.ts +++ b/src/modules/ad/tests/unit/core/match.query.spec.ts @@ -1,5 +1,6 @@ import { DateTimeTransformerPort } from '@modules/ad/core/application/ports/datetime-transformer.port'; import { DefaultParams } from '@modules/ad/core/application/ports/default-params.type'; +import { RouteProviderPort } from '@modules/ad/core/application/ports/route-provider.port'; import { MatchQuery } from '@modules/ad/core/application/queries/match/match.query'; import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types'; import { Waypoint } from '@modules/ad/core/application/types/waypoint.type'; @@ -49,6 +50,23 @@ const mockInputDateTimeTransformer: DateTimeTransformerPort = { time: jest.fn().mockImplementation(() => '23:05'), }; +const mockRouteProvider: RouteProviderPort = { + getBasic: jest + .fn() + .mockImplementationOnce(() => ({ + driverDistance: undefined, + driverDuration: undefined, + passengerDistance: 150120, + passengerDuration: 6540, + fwdAzimuth: 276, + backAzimuth: 96, + points: [], + })) + .mockImplementationOnce(() => { + throw new Error(); + }), +}; + describe('Match Query', () => { it('should set default values', async () => { const matchQuery = new MatchQuery({ @@ -124,4 +142,40 @@ describe('Match Query', () => { expect(matchQuery.seatsProposed).toBe(3); expect(matchQuery.seatsRequested).toBe(1); }); + + it('should set route', async () => { + const matchQuery = new MatchQuery({ + frequency: Frequency.PUNCTUAL, + fromDate: '2023-08-28', + toDate: '2023-08-28', + schedule: [ + { + time: '01:05', + }, + ], + waypoints: [originWaypoint, destinationWaypoint], + }); + await matchQuery.setRoute(mockRouteProvider); + expect(matchQuery.route?.driverDistance).toBeUndefined(); + expect(matchQuery.route?.passengerDistance).toBe(150120); + }); + + it('should throw an exception if route is not found', async () => { + const matchQuery = new MatchQuery({ + driver: true, + passenger: false, + frequency: Frequency.PUNCTUAL, + fromDate: '2023-08-28', + toDate: '2023-08-28', + schedule: [ + { + time: '01:05', + }, + ], + waypoints: [originWaypoint, destinationWaypoint], + }); + await expect(matchQuery.setRoute(mockRouteProvider)).rejects.toBeInstanceOf( + Error, + ); + }); }); diff --git a/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts b/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts index 3c187f3..bd290a3 100644 --- a/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts +++ b/src/modules/ad/tests/unit/core/passenger-oriented-selector.spec.ts @@ -32,16 +32,44 @@ const matchQuery = new MatchQuery({ driver: true, passenger: true, frequency: Frequency.PUNCTUAL, - fromDate: '2023-08-28', - toDate: '2023-08-28', + fromDate: '2023-06-21', + toDate: '2023-06-21', + useAzimuth: true, + azimuthMargin: 10, + useProportion: true, + proportion: 0.3, schedule: [ { + day: 3, time: '07:05', + margin: 900, }, ], strict: false, waypoints: [originWaypoint, destinationWaypoint], }); +matchQuery.route = { + driverDistance: 150120, + driverDuration: 6540, + passengerDistance: 150120, + passengerDuration: 6540, + fwdAzimuth: 276, + backAzimuth: 96, + points: [ + { + lat: 48.689445, + lon: 6.17651, + }, + { + lat: 48.7566, + lon: 4.3522, + }, + { + lat: 48.8566, + lon: 2.3522, + }, + ], +}; const mockMatcherRepository: AdRepositoryPort = { insertExtra: jest.fn(), diff --git a/src/modules/ad/tests/unit/infrastructure/time-converter.spec.ts b/src/modules/ad/tests/unit/infrastructure/time-converter.spec.ts index df8463a..ce8ca75 100644 --- a/src/modules/ad/tests/unit/infrastructure/time-converter.spec.ts +++ b/src/modules/ad/tests/unit/infrastructure/time-converter.spec.ts @@ -60,6 +60,7 @@ describe('Time Converter', () => { parisDate, parisTime, 'Europe/Paris', + true, ); expect(utcDate.toISOString()).toBe('2023-06-22T10:00:00.000Z'); }); diff --git a/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts b/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts index 23ac483..91020a9 100644 --- a/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts +++ b/src/modules/ad/tests/unit/interface/match.grpc.controller.spec.ts @@ -1,6 +1,7 @@ import { RpcExceptionCode } from '@mobicoop/ddd-library'; import { AlgorithmType } from '@modules/ad/core/application/types/algorithm.types'; import { Frequency } from '@modules/ad/core/domain/ad.types'; +import { MatchEntity } from '@modules/ad/core/domain/match.entity'; import { MatchRequestDto } from '@modules/ad/interface/grpc-controllers/dtos/match.request.dto'; import { WaypointDto } from '@modules/ad/interface/grpc-controllers/dtos/waypoint.dto'; import { MatchGrpcController } from '@modules/ad/interface/grpc-controllers/match.grpc-controller'; @@ -49,12 +50,12 @@ const mockQueryBus = { execute: jest .fn() .mockImplementationOnce(() => [ - { - adId: 1, - }, - { - adId: 2, - }, + MatchEntity.create({ + adId: '0cc87f3b-7a27-4eff-9850-a5d642c2a0c3', + }), + MatchEntity.create({ + adId: 'e4cc156f-aaa5-4270-bf6f-82f5a230d748', + }), ]) .mockImplementationOnce(() => { throw new Error();