move route compute to create service as entity creation is not async

This commit is contained in:
sbriat
2023-08-22 16:14:36 +02:00
parent 4762c844e1
commit ac8e459e90
27 changed files with 403 additions and 94 deletions

View File

@@ -0,0 +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 {
get(data: GetRouteRequestDto): Promise<RouteResponseDto>;
}

View File

@@ -9,6 +9,5 @@ export type Route = {
fwdAzimuth: number;
backAzimuth: number;
distanceAzimuth: number;
points: Coordinates[];
spacetimePoints: SpacetimePoint[];
points: Coordinates[] | SpacetimePoint[];
};

View File

@@ -60,9 +60,7 @@ export class RouteEntity extends AggregateRoot<RouteProps> {
? driverRoute.distanceAzimuth
: passengerRoute.distanceAzimuth,
waypoints: create.waypoints,
spacetimePoints: driverRoute
? driverRoute.spacetimePoints
: passengerRoute.spacetimePoints,
points: driverRoute ? driverRoute.points : passengerRoute.points,
};
return new RouteEntity({
id: v4(),

View File

@@ -1,5 +1,6 @@
import { GeorouterPort } from '../application/ports/georouter.port';
import { GeorouterSettings } from '../application/types/georouter-settings.type';
import { CoordinatesProps } from './value-objects/coordinates.value-object';
import { SpacetimePointProps } from './value-objects/spacetime-point.value-object';
import { WaypointProps } from './value-objects/waypoint.value-object';
@@ -13,7 +14,7 @@ export interface RouteProps {
backAzimuth: number;
distanceAzimuth: number;
waypoints: WaypointProps[];
spacetimePoints: SpacetimePointProps[];
points: SpacetimePointProps[] | CoordinatesProps[];
}
// Properties that are needed for a Route creation
@@ -31,8 +32,7 @@ export type Direction = {
fwdAzimuth: number;
backAzimuth: number;
distanceAzimuth: number;
points: Point[];
spacetimePoints: SpacetimePoint[];
points: SpacetimePoint[] | Point[];
};
export type Path = {

View File

@@ -0,0 +1,31 @@
import {
ArgumentOutOfRangeException,
ValueObject,
} from '@mobicoop/ddd-library';
/** Note:
* Value Objects with multiple properties can contain
* other Value Objects inside if needed.
* */
export interface CoordinatesProps {
lon: number;
lat: number;
}
export class Coordinates extends ValueObject<CoordinatesProps> {
get lon(): number {
return this.props.lon;
}
get lat(): number {
return this.props.lat;
}
protected validate(props: CoordinatesProps): void {
if (props.lon > 180 || props.lon < -180)
throw new ArgumentOutOfRangeException('lon must be between -180 and 180');
if (props.lat > 90 || props.lat < -90)
throw new ArgumentOutOfRangeException('lat must be between -90 and 90');
}
}

View File

@@ -3,7 +3,7 @@ import { CqrsModule } from '@nestjs/cqrs';
import { DIRECTION_ENCODER, PARAMS_PROVIDER } from './geography.di-tokens';
import { DefaultParamsProvider } from './infrastructure/default-params-provider';
import { PostgresDirectionEncoder } from './infrastructure/postgres-direction-encoder';
import { GetRouteController } from './interface/controllers/get-route.controller';
import { GetBasicRouteController } from './interface/controllers/get-basic-route.controller';
const adapters: Provider[] = [
{
@@ -14,12 +14,12 @@ const adapters: Provider[] = [
provide: DIRECTION_ENCODER,
useClass: PostgresDirectionEncoder,
},
GetRouteController,
GetBasicRouteController,
];
@Module({
imports: [CqrsModule],
providers: [...adapters],
exports: [DIRECTION_ENCODER, GetRouteController],
exports: [DIRECTION_ENCODER, GetBasicRouteController],
})
export class GeographyModule {}

View File

@@ -1,9 +1,7 @@
import { GeorouterSettings } from '@modules/geography/core/application/types/georouter-settings.type';
import { Waypoint } from '@modules/geography/core/application/types/waypoint.type';
import { Role } from '@modules/geography/core/domain/route.types';
export class GetRouteRequestDto {
export type GetRouteRequestDto = {
roles: Role[];
waypoints: Waypoint[];
georouterSettings: GeorouterSettings;
}
};

View File

@@ -4,10 +4,11 @@ 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 { Injectable } from '@nestjs/common';
import { Controller } from '@nestjs/common';
import { GetBasicRouteControllerPort } from '@modules/geography/core/application/ports/get-basic-route-controller.port';
@Injectable()
export class GetRouteController {
@Controller()
export class GetBasicRouteController implements GetBasicRouteControllerPort {
constructor(
private readonly queryBus: QueryBus,
private readonly mapper: RouteMapper,
@@ -15,7 +16,11 @@ export class GetRouteController {
async get(data: GetRouteRequestDto): Promise<RouteResponseDto> {
const route: RouteEntity = await this.queryBus.execute(
new GetRouteQuery(data.roles, data.waypoints, data.georouterSettings),
new GetRouteQuery(data.roles, data.waypoints, {
detailedDistance: false,
detailedDuration: false,
points: true,
}),
);
return this.mapper.toResponse(route);
}

View File

@@ -1,3 +1,4 @@
import { Coordinates } from '@modules/geography/core/application/types/coordinates.type';
import { SpacetimePoint } from '@modules/geography/core/application/types/spacetime-point.type';
export class RouteResponseDto {
@@ -8,5 +9,5 @@ export class RouteResponseDto {
fwdAzimuth: number;
backAzimuth: number;
distanceAzimuth: number;
spacetimePoints: SpacetimePoint[];
points: SpacetimePoint[] | Coordinates[];
}

View File

@@ -33,7 +33,7 @@ export class RouteMapper
response.fwdAzimuth = entity.getProps().fwdAzimuth;
response.backAzimuth = entity.getProps().backAzimuth;
response.distanceAzimuth = entity.getProps().distanceAzimuth;
response.spacetimePoints = entity.getProps().spacetimePoints;
response.points = entity.getProps().points;
return response;
};
}

View File

@@ -0,0 +1,49 @@
import { ArgumentOutOfRangeException } from '@mobicoop/ddd-library';
import { Coordinates } from '@modules/geography/core/domain/value-objects/coordinates.value-object';
describe('Waypoint value object', () => {
it('should create a waypoint value object', () => {
const coordinatesVO = new Coordinates({
lon: 48.689445,
lat: 6.17651,
});
expect(coordinatesVO.lon).toBe(48.689445);
expect(coordinatesVO.lat).toBe(6.17651);
});
it('should throw an exception if longitude is invalid', () => {
try {
new Coordinates({
lon: 348.689445,
lat: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
new Coordinates({
lon: -348.689445,
lat: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
});
it('should throw an exception if latitude is invalid', () => {
try {
new Coordinates({
lon: 48.689445,
lat: 96.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
new Coordinates({
lon: 48.689445,
lat: -96.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
});
});

View File

@@ -46,7 +46,7 @@ describe('Waypoint value object', () => {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
});
it('should throw an exception if longitude is invalid', () => {
it('should throw an exception if latitude is invalid', () => {
try {
new Waypoint({
position: 0,

View File

@@ -1,5 +1,5 @@
import { Role } from '@modules/geography/core/domain/route.types';
import { GetRouteController } from '@modules/geography/interface/controllers/get-route.controller';
import { GetBasicRouteController } from '@modules/geography/interface/controllers/get-basic-route.controller';
import { RouteMapper } from '@modules/geography/route.mapper';
import { QueryBus } from '@nestjs/cqrs';
import { Test, TestingModule } from '@nestjs/testing';
@@ -14,8 +14,8 @@ const mockRouteMapper = {
toResponse: jest.fn(),
};
describe('Get Route Controller', () => {
let getRouteController: GetRouteController;
describe('Get Basic Route Controller', () => {
let getBasicRouteController: GetBasicRouteController;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
@@ -28,11 +28,13 @@ describe('Get Route Controller', () => {
provide: RouteMapper,
useValue: mockRouteMapper,
},
GetRouteController,
GetBasicRouteController,
],
}).compile();
getRouteController = module.get<GetRouteController>(GetRouteController);
getBasicRouteController = module.get<GetBasicRouteController>(
GetBasicRouteController,
);
});
afterEach(async () => {
@@ -40,12 +42,12 @@ describe('Get Route Controller', () => {
});
it('should be defined', () => {
expect(getRouteController).toBeDefined();
expect(getBasicRouteController).toBeDefined();
});
it('should get a route', async () => {
jest.spyOn(mockQueryBus, 'execute');
await getRouteController.get({
await getBasicRouteController.get({
roles: [Role.DRIVER],
waypoints: [
{
@@ -59,11 +61,6 @@ describe('Get Route Controller', () => {
lat: 2.3522,
},
],
georouterSettings: {
points: true,
detailedDistance: false,
detailedDuration: false,
},
});
expect(mockQueryBus.execute).toHaveBeenCalledTimes(1);
});

View File

@@ -38,7 +38,7 @@ describe('Route Mapper', () => {
fwdAzimuth: 283,
backAzimuth: 93,
distanceAzimuth: 19840,
spacetimePoints: [],
points: [],
waypoints: [
{
position: 0,