diff --git a/src/modules/ad/ad.di-tokens.ts b/src/modules/ad/ad.di-tokens.ts index 4a69ae2..87c11ec 100644 --- a/src/modules/ad/ad.di-tokens.ts +++ b/src/modules/ad/ad.di-tokens.ts @@ -4,6 +4,9 @@ export const AD_MESSAGE_PUBLISHER = Symbol('AD_MESSAGE_PUBLISHER'); export const AD_GET_BASIC_ROUTE_CONTROLLER = Symbol( 'AD_GET_BASIC_ROUTE_CONTROLLER', ); +export const AD_GET_DETAILED_ROUTE_CONTROLLER = Symbol( + 'AD_GET_DETAILED_ROUTE_CONTROLLER', +); export const AD_ROUTE_PROVIDER = Symbol('AD_ROUTE_PROVIDER'); export const PARAMS_PROVIDER = Symbol('PARAMS_PROVIDER'); export const TIMEZONE_FINDER = Symbol('TIMEZONE_FINDER'); diff --git a/src/modules/ad/ad.module.ts b/src/modules/ad/ad.module.ts index 90610bd..bebd374 100644 --- a/src/modules/ad/ad.module.ts +++ b/src/modules/ad/ad.module.ts @@ -10,6 +10,7 @@ import { TIMEZONE_FINDER, TIME_CONVERTER, INPUT_DATETIME_TRANSFORMER, + AD_GET_DETAILED_ROUTE_CONTROLLER, } from './ad.di-tokens'; import { MessageBrokerPublisher } from '@mobicoop/message-broker-module'; import { AdRepository } from './infrastructure/ad.repository'; @@ -27,6 +28,7 @@ import { DefaultParamsProvider } from './infrastructure/default-params-provider' import { TimezoneFinder } from './infrastructure/timezone-finder'; import { TimeConverter } from './infrastructure/time-converter'; import { InputDateTimeTransformer } from './infrastructure/input-datetime-transformer'; +import { GetDetailedRouteController } from '@modules/geography/interface/controllers/get-detailed-route.controller'; const grpcControllers = [MatchGrpcController]; @@ -67,6 +69,10 @@ const adapters: Provider[] = [ provide: AD_GET_BASIC_ROUTE_CONTROLLER, useClass: GetBasicRouteController, }, + { + provide: AD_GET_DETAILED_ROUTE_CONTROLLER, + useClass: GetDetailedRouteController, + }, { provide: PARAMS_PROVIDER, useClass: DefaultParamsProvider, diff --git a/src/modules/ad/core/application/ports/route-provider.port.ts b/src/modules/ad/core/application/ports/route-provider.port.ts index b016365..ca06709 100644 --- a/src/modules/ad/core/application/ports/route-provider.port.ts +++ b/src/modules/ad/core/application/ports/route-provider.port.ts @@ -3,7 +3,17 @@ import { Point } from '../types/point.type'; export interface RouteProviderPort { /** - * Get a basic route with points and overall duration / distance + * Get a basic route : + * - simple points (coordinates only) + * - overall duration + * - overall distance */ getBasic(waypoints: Point[]): Promise; + /** + * Get a detailed route : + * - detailed points (coordinates and time / distance to reach the point) + * - overall duration + * - overall distance + */ + getDetailed(waypoints: Point[]): Promise; } diff --git a/src/modules/ad/core/application/queries/match/completer/route.completer.ts b/src/modules/ad/core/application/queries/match/completer/route.completer.ts index 2f516ec..c8e61a9 100644 --- a/src/modules/ad/core/application/queries/match/completer/route.completer.ts +++ b/src/modules/ad/core/application/queries/match/completer/route.completer.ts @@ -15,12 +15,31 @@ export class RouteCompleter extends Completer { ): Promise => { await Promise.all( candidates.map(async (candidate: CandidateEntity) => { - const candidateRoute = await this.query.routeProvider.getBasic( - (candidate.getProps().carpoolSteps as WayStep[]).map( - (wayStep: WayStep) => wayStep.point, - ), - ); - candidate.setMetrics(candidateRoute.distance, candidateRoute.duration); + switch (this.type) { + case RouteCompleterType.BASIC: + const basicCandidateRoute = await this.query.routeProvider.getBasic( + (candidate.getProps().carpoolSteps as WayStep[]).map( + (wayStep: WayStep) => wayStep.point, + ), + ); + candidate.setMetrics( + basicCandidateRoute.distance, + basicCandidateRoute.duration, + ); + break; + case RouteCompleterType.DETAILED: + const detailedCandidateRoute = + await this.query.routeProvider.getBasic( + (candidate.getProps().carpoolSteps as WayStep[]).map( + (wayStep: WayStep) => wayStep.point, + ), + ); + candidate.setMetrics( + detailedCandidateRoute.distance, + detailedCandidateRoute.duration, + ); + break; + } return candidate; }), ); diff --git a/src/modules/ad/infrastructure/route-provider.ts b/src/modules/ad/infrastructure/route-provider.ts index b32317b..dac1d05 100644 --- a/src/modules/ad/infrastructure/route-provider.ts +++ b/src/modules/ad/infrastructure/route-provider.ts @@ -1,6 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { RouteProviderPort } from '../core/application/ports/route-provider.port'; -import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; +import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port'; import { AD_GET_BASIC_ROUTE_CONTROLLER } from '../ad.di-tokens'; import { Point, Route } from '@modules/geography/core/domain/route.types'; @@ -8,11 +8,16 @@ import { Point, Route } from '@modules/geography/core/domain/route.types'; export class RouteProvider implements RouteProviderPort { constructor( @Inject(AD_GET_BASIC_ROUTE_CONTROLLER) - private readonly getBasicRouteController: GetBasicRouteControllerPort, + private readonly getBasicRouteController: GetRouteControllerPort, ) {} getBasic = async (waypoints: Point[]): Promise => await this.getBasicRouteController.get({ waypoints, }); + + getDetailed = async (waypoints: Point[]): Promise => + await this.getBasicRouteController.get({ + waypoints, + }); } diff --git a/src/modules/ad/tests/unit/core/create-ad.service.spec.ts b/src/modules/ad/tests/unit/core/create-ad.service.spec.ts index 4198e68..220bd18 100644 --- a/src/modules/ad/tests/unit/core/create-ad.service.spec.ts +++ b/src/modules/ad/tests/unit/core/create-ad.service.spec.ts @@ -93,6 +93,7 @@ const mockRouteProvider: RouteProviderPort = { }, ], })), + getDetailed: jest.fn(), }; describe('create-ad.service', () => { 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 c96bd3b..9fd930d 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 @@ -92,6 +92,7 @@ const mockRouteProvider: RouteProviderPort = { distanceAzimuth: 336544, points: [], })), + getDetailed: jest.fn(), }; describe('Match Query Handler', () => { 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 8c0c580..14f7415 100644 --- a/src/modules/ad/tests/unit/core/match.query.spec.ts +++ b/src/modules/ad/tests/unit/core/match.query.spec.ts @@ -104,6 +104,7 @@ const mockRouteProvider: RouteProviderPort = { .mockImplementationOnce(() => { throw new Error(); }), + getDetailed: jest.fn(), }; describe('Match Query', () => { diff --git a/src/modules/ad/tests/unit/core/passenger-oriented-algorithm.spec.ts b/src/modules/ad/tests/unit/core/passenger-oriented-algorithm.spec.ts index 705a9a3..4e9748e 100644 --- a/src/modules/ad/tests/unit/core/passenger-oriented-algorithm.spec.ts +++ b/src/modules/ad/tests/unit/core/passenger-oriented-algorithm.spec.ts @@ -46,6 +46,7 @@ const matchQuery = new MatchQuery( duration: 6500, distance: 89745, })), + getDetailed: jest.fn(), }, ); diff --git a/src/modules/ad/tests/unit/core/passenger-oriented-carpool-path-completer.spec.ts b/src/modules/ad/tests/unit/core/passenger-oriented-carpool-path-completer.spec.ts index fdf5a0f..b1235e3 100644 --- a/src/modules/ad/tests/unit/core/passenger-oriented-carpool-path-completer.spec.ts +++ b/src/modules/ad/tests/unit/core/passenger-oriented-carpool-path-completer.spec.ts @@ -42,6 +42,7 @@ const matchQuery = new MatchQuery( }, { getBasic: jest.fn(), + getDetailed: jest.fn(), }, ); diff --git a/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts b/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts index 394717a..331183c 100644 --- a/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts +++ b/src/modules/ad/tests/unit/core/passenger-oriented-geo-filter.spec.ts @@ -42,6 +42,7 @@ const matchQuery = new MatchQuery( }, { getBasic: jest.fn(), + getDetailed: jest.fn(), }, ); 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 0972a6f..c3be07e 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 @@ -49,6 +49,7 @@ const matchQuery = new MatchQuery( }, { getBasic: jest.fn(), + getDetailed: jest.fn(), }, ); matchQuery.driverRoute = { diff --git a/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts b/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts index 064349c..8c68cf7 100644 --- a/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts +++ b/src/modules/ad/tests/unit/infrastructure/ad.repository.spec.ts @@ -75,6 +75,7 @@ const mockDirectionEncoder: DirectionEncoderPort = { const mockRouteProvider: RouteProviderPort = { getBasic: jest.fn(), + getDetailed: jest.fn(), }; const mockPrismaService = { diff --git a/src/modules/ad/tests/unit/infrastructure/route-provider.spec.ts b/src/modules/ad/tests/unit/infrastructure/route-provider.spec.ts index 82113c8..641d5b3 100644 --- a/src/modules/ad/tests/unit/infrastructure/route-provider.spec.ts +++ b/src/modules/ad/tests/unit/infrastructure/route-provider.spec.ts @@ -1,7 +1,7 @@ import { AD_GET_BASIC_ROUTE_CONTROLLER } from '@modules/ad/ad.di-tokens'; import { Point } from '@modules/ad/core/application/types/point.type'; import { RouteProvider } from '@modules/ad/infrastructure/route-provider'; -import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; +import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port'; import { Route } from '@modules/geography/core/domain/route.types'; import { Test, TestingModule } from '@nestjs/testing'; @@ -14,7 +14,7 @@ const destinationPoint: Point = { lon: 2.3522, }; -const mockGetBasicRouteController: GetBasicRouteControllerPort = { +const mockGetBasicRouteController: GetRouteControllerPort = { get: jest.fn().mockImplementationOnce(() => ({ distance: 350101, duration: 14422, @@ -59,7 +59,7 @@ describe('Route provider', () => { expect(routeProvider).toBeDefined(); }); - it('should provide a route', async () => { + it('should provide a basic route', async () => { const route: Route = await routeProvider.getBasic([ originPoint, destinationPoint, 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 cf614ed..6f75433 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 @@ -66,6 +66,7 @@ const mockQueryBus = { const mockRouteProvider: RouteProviderPort = { getBasic: jest.fn(), + getDetailed: jest.fn(), }; describe('Match Grpc Controller', () => { diff --git a/src/modules/geography/core/application/ports/get-basic-route-controller.port.ts b/src/modules/geography/core/application/ports/get-route-controller.port.ts similarity index 84% rename from src/modules/geography/core/application/ports/get-basic-route-controller.port.ts rename to src/modules/geography/core/application/ports/get-route-controller.port.ts index a1f0bd4..0217143 100644 --- a/src/modules/geography/core/application/ports/get-basic-route-controller.port.ts +++ b/src/modules/geography/core/application/ports/get-route-controller.port.ts @@ -1,6 +1,6 @@ import { GetRouteRequestDto } from '@modules/geography/interface/controllers/dtos/get-route.request.dto'; import { RouteResponseDto } from '@modules/geography/interface/dtos/route.response.dto'; -export interface GetBasicRouteControllerPort { +export interface GetRouteControllerPort { get(data: GetRouteRequestDto): Promise; } diff --git a/src/modules/geography/core/application/queries/get-route/get-route.query.ts b/src/modules/geography/core/application/queries/get-route/get-route.query.ts index 2eecbc0..56e33d6 100644 --- a/src/modules/geography/core/application/queries/get-route/get-route.query.ts +++ b/src/modules/geography/core/application/queries/get-route/get-route.query.ts @@ -6,7 +6,14 @@ export class GetRouteQuery extends QueryBase { readonly waypoints: Point[]; readonly georouterSettings: GeorouterSettings; - constructor(waypoints: Point[], georouterSettings: GeorouterSettings) { + constructor( + waypoints: Point[], + georouterSettings: GeorouterSettings = { + detailedDistance: false, + detailedDuration: false, + points: true, + }, + ) { super(); this.waypoints = waypoints; this.georouterSettings = georouterSettings; diff --git a/src/modules/geography/interface/controllers/get-basic-route.controller.ts b/src/modules/geography/interface/controllers/get-basic-route.controller.ts index 3c14b10..b28b88e 100644 --- a/src/modules/geography/interface/controllers/get-basic-route.controller.ts +++ b/src/modules/geography/interface/controllers/get-basic-route.controller.ts @@ -5,10 +5,10 @@ import { RouteEntity } from '@modules/geography/core/domain/route.entity'; import { GetRouteQuery } from '@modules/geography/core/application/queries/get-route/get-route.query'; import { RouteMapper } from '@modules/geography/route.mapper'; import { Controller } from '@nestjs/common'; -import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port'; +import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port'; @Controller() -export class GetBasicRouteController implements GetBasicRouteControllerPort { +export class GetBasicRouteController implements GetRouteControllerPort { constructor( private readonly queryBus: QueryBus, private readonly mapper: RouteMapper, @@ -16,11 +16,7 @@ export class GetBasicRouteController implements GetBasicRouteControllerPort { async get(data: GetRouteRequestDto): Promise { const route: RouteEntity = await this.queryBus.execute( - new GetRouteQuery(data.waypoints, { - detailedDistance: false, - detailedDuration: false, - points: true, - }), + new GetRouteQuery(data.waypoints), ); return this.mapper.toResponse(route); } diff --git a/src/modules/geography/interface/controllers/get-detailed-route.controller.ts b/src/modules/geography/interface/controllers/get-detailed-route.controller.ts new file mode 100644 index 0000000..34cf693 --- /dev/null +++ b/src/modules/geography/interface/controllers/get-detailed-route.controller.ts @@ -0,0 +1,27 @@ +import { QueryBus } from '@nestjs/cqrs'; +import { RouteResponseDto } from '../dtos/route.response.dto'; +import { GetRouteRequestDto } from './dtos/get-route.request.dto'; +import { RouteEntity } from '@modules/geography/core/domain/route.entity'; +import { GetRouteQuery } from '@modules/geography/core/application/queries/get-route/get-route.query'; +import { RouteMapper } from '@modules/geography/route.mapper'; +import { Controller } from '@nestjs/common'; +import { GetRouteControllerPort } from '@modules/geography/core/application/ports/get-route-controller.port'; + +@Controller() +export class GetDetailedRouteController implements GetRouteControllerPort { + constructor( + private readonly queryBus: QueryBus, + private readonly mapper: RouteMapper, + ) {} + + async get(data: GetRouteRequestDto): Promise { + const route: RouteEntity = await this.queryBus.execute( + new GetRouteQuery(data.waypoints, { + detailedDistance: true, + detailedDuration: true, + points: true, + }), + ); + return this.mapper.toResponse(route); + } +}