mirror of
https://gitlab.com/mobicoop/v3/service/matcher.git
synced 2026-01-01 16:02:40 +00:00
create ad, WIP
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
import { Frequency } from '../types/frequency.enum';
|
||||
import { Coordinates } from '../../../geography/domain/entities/coordinates';
|
||||
import { Type } from 'class-transformer';
|
||||
import { HasTruthyWith } from './has-truthy-with.validator';
|
||||
|
||||
export class CreateAdRequest {
|
||||
@IsString()
|
||||
@@ -26,6 +27,9 @@ export class CreateAdRequest {
|
||||
@AutoMap()
|
||||
userUuid: string;
|
||||
|
||||
@HasTruthyWith('passenger', {
|
||||
message: 'A role (driver or passenger) must be set to true',
|
||||
})
|
||||
@IsBoolean()
|
||||
@AutoMap()
|
||||
driver: boolean;
|
||||
@@ -117,27 +121,6 @@ export class CreateAdRequest {
|
||||
@AutoMap(() => [Coordinates])
|
||||
waypoints: Coordinates[];
|
||||
|
||||
@AutoMap()
|
||||
driverDuration?: number;
|
||||
|
||||
@AutoMap()
|
||||
driverDistance?: number;
|
||||
|
||||
@AutoMap()
|
||||
passengerDuration?: number;
|
||||
|
||||
@AutoMap()
|
||||
passengerDistance?: number;
|
||||
|
||||
@AutoMap()
|
||||
direction: string;
|
||||
|
||||
@AutoMap()
|
||||
fwdAzimuth: number;
|
||||
|
||||
@AutoMap()
|
||||
backAzimuth: number;
|
||||
|
||||
@IsNumber()
|
||||
@AutoMap()
|
||||
seatsDriver: number;
|
||||
@@ -154,6 +137,4 @@ export class CreateAdRequest {
|
||||
@IsBoolean()
|
||||
@AutoMap()
|
||||
strict: boolean;
|
||||
|
||||
timezone?: string;
|
||||
}
|
||||
|
||||
32
src/modules/ad/domain/dtos/has-truthy-with.validator.ts
Normal file
32
src/modules/ad/domain/dtos/has-truthy-with.validator.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
registerDecorator,
|
||||
ValidationOptions,
|
||||
ValidationArguments,
|
||||
} from 'class-validator';
|
||||
|
||||
export function HasTruthyWith(
|
||||
property: string,
|
||||
validationOptions?: ValidationOptions,
|
||||
) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
return function (object: Object, propertyName: string) {
|
||||
registerDecorator({
|
||||
name: 'hasTruthyWith',
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
constraints: [property],
|
||||
options: validationOptions,
|
||||
validator: {
|
||||
validate(value: any, args: ValidationArguments) {
|
||||
const [relatedPropertyName] = args.constraints;
|
||||
const relatedValue = (args.object as any)[relatedPropertyName];
|
||||
return (
|
||||
typeof value === 'boolean' &&
|
||||
typeof relatedValue === 'boolean' &&
|
||||
(value || relatedValue)
|
||||
); // you can return a Promise<boolean> here as well, if you want to make async validation
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Ad } from './ad';
|
||||
|
||||
export class AdCompleter {
|
||||
complete = async (ad: Ad): Promise<Ad> => {
|
||||
return ad;
|
||||
};
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import { AutoMap } from '@automapper/classes';
|
||||
import { Coordinates } from '../../../geography/domain/entities/coordinates';
|
||||
import { Frequency } from '../types/frequency.enum';
|
||||
|
||||
export class Ad {
|
||||
@AutoMap()
|
||||
uuid: string;
|
||||
|
||||
@AutoMap()
|
||||
userUuid: string;
|
||||
|
||||
@AutoMap()
|
||||
driver: boolean;
|
||||
|
||||
@@ -75,8 +77,8 @@ export class Ad {
|
||||
@AutoMap()
|
||||
passengerDistance?: number;
|
||||
|
||||
@AutoMap(() => [Coordinates])
|
||||
waypoints: Coordinates[];
|
||||
@AutoMap()
|
||||
waypoints: string;
|
||||
|
||||
@AutoMap()
|
||||
direction: string;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Role } from '../types/role.enum';
|
||||
import { IGeorouter } from '../../../geography/domain/interfaces/georouter.interface';
|
||||
import { Path } from '../../../geography/domain/types/path.type';
|
||||
import { Timezoner } from '../../../geography/domain/types/timezoner';
|
||||
import { GeorouterSettings } from '../../../geography/domain/types/georouter-settings.type';
|
||||
|
||||
export class Geography {
|
||||
private points: Coordinates[];
|
||||
@@ -23,6 +24,7 @@ export class Geography {
|
||||
createRoutes = async (
|
||||
roles: Role[],
|
||||
georouter: IGeorouter,
|
||||
settings: GeorouterSettings,
|
||||
): Promise<void> => {
|
||||
const paths: Path[] = [];
|
||||
if (roles.includes(Role.DRIVER) && roles.includes(Role.PASSENGER)) {
|
||||
@@ -57,11 +59,7 @@ export class Geography {
|
||||
};
|
||||
paths.push(passengerPath);
|
||||
}
|
||||
const routes = await georouter.route(paths, {
|
||||
withDistance: false,
|
||||
withPoints: false,
|
||||
withTime: false,
|
||||
});
|
||||
const routes = await georouter.route(paths, settings);
|
||||
if (routes.some((route) => route.key == RouteKey.COMMON)) {
|
||||
this.driverRoute = routes.find(
|
||||
(route) => route.key == RouteKey.COMMON,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { DefaultParams } from '../types/default-params.type';
|
||||
|
||||
export interface IProvideParams {
|
||||
getParams(): DefaultParams;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
export type IDefaultParams = {
|
||||
export type DefaultParams = {
|
||||
DEFAULT_TIMEZONE: string;
|
||||
GEOROUTER_TYPE: string;
|
||||
GEOROUTER_URL: string;
|
||||
|
||||
@@ -5,35 +5,125 @@ import { AdRepository } from '../../adapters/secondaries/ad.repository';
|
||||
import { InjectMapper } from '@automapper/nestjs';
|
||||
import { Mapper } from '@automapper/core';
|
||||
import { CreateAdRequest } from '../dtos/create-ad.request';
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { IProvideParams } from '../interfaces/params-provider.interface';
|
||||
import { ICreateGeorouter } from '../../../geography/domain/interfaces/georouter-creator.interface';
|
||||
import { IFindTimezone } from '../../../geography/domain/interfaces/timezone-finder.interface';
|
||||
import { IGeorouter } from '../../../geography/domain/interfaces/georouter.interface';
|
||||
import { DefaultParams } from '../types/default-params.type';
|
||||
import { Role } from '../types/role.enum';
|
||||
import { Geography } from '../entities/geography';
|
||||
import { IEncodeDirection } from '../../../geography/domain/interfaces/direction-encoder.interface';
|
||||
import { TimeConverter } from '../entities/time-converter';
|
||||
|
||||
@CommandHandler(CreateAdCommand)
|
||||
export class CreateAdUseCase {
|
||||
private readonly georouter: IGeorouter;
|
||||
private readonly defaultParams: DefaultParams;
|
||||
private timezone: string;
|
||||
private roles: Role[];
|
||||
private geography: Geography;
|
||||
private ad: Ad;
|
||||
|
||||
constructor(
|
||||
@InjectMapper() private readonly mapper: Mapper,
|
||||
private readonly adRepository: AdRepository,
|
||||
) {}
|
||||
@Inject('ParamsProvider')
|
||||
private readonly defaultParamsProvider: IProvideParams,
|
||||
@Inject('GeorouterCreator')
|
||||
private readonly georouterCreator: ICreateGeorouter,
|
||||
@Inject('TimezoneFinder')
|
||||
private readonly timezoneFinder: IFindTimezone,
|
||||
@Inject('DirectionEncoder')
|
||||
private readonly directionEncoder: IEncodeDirection,
|
||||
) {
|
||||
this.defaultParams = defaultParamsProvider.getParams();
|
||||
this.timezone = this.defaultParams.DEFAULT_TIMEZONE;
|
||||
this.georouter = georouterCreator.create(
|
||||
this.defaultParams.GEOROUTER_TYPE,
|
||||
this.defaultParams.GEOROUTER_URL,
|
||||
);
|
||||
}
|
||||
|
||||
async execute(command: CreateAdCommand): Promise<Ad> {
|
||||
try {
|
||||
const adToCreate: Ad = this.mapper.map(
|
||||
command.createAdRequest,
|
||||
CreateAdRequest,
|
||||
Ad,
|
||||
this.ad = this.mapper.map(command.createAdRequest, CreateAdRequest, Ad);
|
||||
this.setRoles(command.createAdRequest);
|
||||
this.setGeography(command.createAdRequest);
|
||||
await this.geography.createRoutes(this.roles, this.georouter, {
|
||||
withDistance: false,
|
||||
withPoints: true,
|
||||
withTime: false,
|
||||
});
|
||||
this.ad.driverDistance = this.geography.driverRoute?.distance;
|
||||
this.ad.driverDuration = this.geography.driverRoute?.duration;
|
||||
this.ad.passengerDistance = this.geography.passengerRoute?.distance;
|
||||
this.ad.passengerDuration = this.geography.passengerRoute?.duration;
|
||||
this.ad.fwdAzimuth = this.geography.driverRoute
|
||||
? this.geography.driverRoute.fwdAzimuth
|
||||
: this.geography.passengerRoute.fwdAzimuth;
|
||||
this.ad.backAzimuth = this.geography.driverRoute
|
||||
? this.geography.driverRoute.backAzimuth
|
||||
: this.geography.passengerRoute.backAzimuth;
|
||||
this.ad.waypoints = this.directionEncoder.encode(
|
||||
command.createAdRequest.waypoints,
|
||||
);
|
||||
adToCreate.driverDistance = command.geography.driverRoute?.distance;
|
||||
adToCreate.driverDuration = command.geography.driverRoute?.duration;
|
||||
adToCreate.passengerDistance = command.geography.passengerRoute?.distance;
|
||||
adToCreate.passengerDuration = command.geography.passengerRoute?.duration;
|
||||
adToCreate.fwdAzimuth = command.geography.driverRoute
|
||||
? command.geography.driverRoute.fwdAzimuth
|
||||
: command.geography.passengerRoute.fwdAzimuth;
|
||||
adToCreate.backAzimuth = command.geography.driverRoute
|
||||
? command.geography.driverRoute.backAzimuth
|
||||
: command.geography.passengerRoute.backAzimuth;
|
||||
return adToCreate;
|
||||
// return await this.adRepository.createAd(adToCreate);
|
||||
this.ad.direction = this.geography.driverRoute
|
||||
? this.directionEncoder.encode(this.geography.driverRoute.points)
|
||||
: undefined;
|
||||
this.ad.monTime = TimeConverter.toUtcDatetime(
|
||||
this.ad.fromDate,
|
||||
command.createAdRequest.monTime,
|
||||
this.timezone,
|
||||
);
|
||||
this.ad.tueTime = TimeConverter.toUtcDatetime(
|
||||
this.ad.fromDate,
|
||||
command.createAdRequest.tueTime,
|
||||
this.timezone,
|
||||
);
|
||||
this.ad.wedTime = TimeConverter.toUtcDatetime(
|
||||
this.ad.fromDate,
|
||||
command.createAdRequest.wedTime,
|
||||
this.timezone,
|
||||
);
|
||||
this.ad.thuTime = TimeConverter.toUtcDatetime(
|
||||
this.ad.fromDate,
|
||||
command.createAdRequest.thuTime,
|
||||
this.timezone,
|
||||
);
|
||||
this.ad.friTime = TimeConverter.toUtcDatetime(
|
||||
this.ad.fromDate,
|
||||
command.createAdRequest.friTime,
|
||||
this.timezone,
|
||||
);
|
||||
this.ad.satTime = TimeConverter.toUtcDatetime(
|
||||
this.ad.fromDate,
|
||||
command.createAdRequest.satTime,
|
||||
this.timezone,
|
||||
);
|
||||
this.ad.sunTime = TimeConverter.toUtcDatetime(
|
||||
this.ad.fromDate,
|
||||
command.createAdRequest.sunTime,
|
||||
this.timezone,
|
||||
);
|
||||
return await this.adRepository.createAd(this.ad);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private setRoles = (createAdRequest: CreateAdRequest): void => {
|
||||
this.roles = [];
|
||||
if (createAdRequest.driver) this.roles.push(Role.DRIVER);
|
||||
if (createAdRequest.passenger) this.roles.push(Role.PASSENGER);
|
||||
};
|
||||
|
||||
private setGeography = (createAdRequest: CreateAdRequest): void => {
|
||||
this.geography = new Geography(createAdRequest.waypoints, {
|
||||
timezone: this.defaultParams.DEFAULT_TIMEZONE,
|
||||
finder: this.timezoneFinder,
|
||||
});
|
||||
if (this.geography.timezones.length > 0)
|
||||
this.timezone = this.geography.timezones[0];
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user