create ad WIP, extract geography methods to dedicated module

This commit is contained in:
sbriat
2023-04-25 17:49:47 +02:00
parent ca693087d2
commit aeead7fb62
53 changed files with 824 additions and 222 deletions

View File

@@ -2,9 +2,16 @@ import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AdMessagerController } from './adapters/primaries/ad-messager.controller';
import { AdProfile } from './mappers/ad.profile';
import { CreateAdUseCase } from './domain/usecases/create-ad.usecase';
import { AdRepository } from './adapters/secondaries/ad.repository';
import { DatabaseModule } from '../database/database.module';
import { CqrsModule } from '@nestjs/cqrs';
@Module({
imports: [
DatabaseModule,
CqrsModule,
RabbitMQModule.forRootAsync(RabbitMQModule, {
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
@@ -18,9 +25,7 @@ import { AdMessagerController } from './adapters/primaries/ad-messager.controlle
adCreated: {
exchange: configService.get<string>('RMQ_EXCHANGE'),
routingKey: 'ad.created',
queue: `${configService.get<string>(
'RMQ_EXCHANGE',
)}-matcher-ad-created`,
queue: 'matcher-ad-created',
},
},
uri: configService.get<string>('RMQ_URI'),
@@ -31,7 +36,7 @@ import { AdMessagerController } from './adapters/primaries/ad-messager.controlle
}),
],
controllers: [AdMessagerController],
providers: [],
providers: [AdProfile, AdRepository, CreateAdUseCase],
exports: [],
})
export class AdModule {}

View File

@@ -1,19 +1,32 @@
import { RabbitSubscribe } from '@golevelup/nestjs-rabbitmq';
import { Controller } from '@nestjs/common';
// import { Ad } from '../../domain/entities/ad';
import { Ad } from '../../domain/entities/ad';
import { InjectMapper } from '@automapper/nestjs';
import { Mapper } from '@automapper/core';
import { CommandBus } from '@nestjs/cqrs';
import { CreateAdCommand } from '../../commands/create-ad.command';
import { AdPresenter } from './ad.presenter';
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
@Controller()
export class AdMessagerController {
constructor(
private readonly _commandBus: CommandBus,
@InjectMapper() private readonly _mapper: Mapper,
) {}
@RabbitSubscribe({
name: 'adCreated',
})
public adCreatedHandler(message: string) {
console.log(JSON.parse(message));
// try {
// const createdAd: Ad = JSON.parse(message);
// console.log(createdAd);
// } catch (e) {
// console.log('error', e);
// }
async adCreatedHandler(message: string): Promise<AdPresenter> {
try {
const createAdRequest: CreateAdRequest = JSON.parse(message);
const ad: Ad = await this._commandBus.execute(
new CreateAdCommand(createAdRequest),
);
return this._mapper.map(ad, Ad, AdPresenter);
} catch (e) {
console.log('error', e);
}
}
}

View File

@@ -0,0 +1,6 @@
import { AutoMap } from '@automapper/classes';
export class AdPresenter {
@AutoMap()
uuid: string;
}

View File

@@ -0,0 +1,79 @@
import { Injectable } from '@nestjs/common';
import { MatcherRepository } from '../../../database/src/domain/matcher-repository';
import { Ad } from '../../domain/entities/ad';
import { DatabaseException } from '../../../database/src/exceptions/database.exception';
@Injectable()
export class AdRepository extends MatcherRepository<Ad> {
protected _model = 'ad';
async createAd(ad: Partial<Ad>): Promise<Ad> {
try {
const affectedRowNumber = await this.createWithFields(
this.createFields(ad),
);
if (affectedRowNumber == 1) {
return this.findOneByUuid(ad.uuid);
}
throw new DatabaseException();
} catch (e) {
throw e;
}
}
private createFields(ad: Partial<Ad>): Partial<AdFields> {
return {
uuid: `'${ad.uuid}'`,
driver: ad.driver ? 'true' : 'false',
passenger: ad.passenger ? 'true' : 'false',
frequency: ad.frequency,
fromDate: `'${ad.fromDate}'`,
toDate: `'${ad.toDate}'`,
monTime: `'${ad.monTime}'`,
tueTime: `'${ad.tueTime}'`,
wedTime: `'${ad.wedTime}'`,
thuTime: `'${ad.thuTime}'`,
friTime: `'${ad.friTime}'`,
satTime: `'${ad.satTime}'`,
sunTime: `'${ad.sunTime}'`,
};
}
}
type AdFields = {
uuid: string;
driver: string;
passenger: string;
frequency: number;
fromDate: string;
toDate: string;
monTime: string;
tueTime: string;
wedTime: string;
thuTime: string;
friTime: string;
satTime: string;
sunTime: string;
monMargin: number;
tueMargin: number;
wedMargin: number;
thuMargin: number;
friMargin: number;
satMargin: number;
sunMargin: number;
driverDuration: number;
driverDistance: number;
passengerDuration: number;
passengerDistance: number;
originType: number;
destinationType: number;
waypoints: string;
direction: string;
fwdAzimuth: number;
backAzimuth: number;
seatsDriver: number;
seatsPassenger: number;
seatsUsed: number;
createdAt: string;
updatedAt: string;
};

View File

@@ -0,0 +1,9 @@
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
export class CreateAdCommand {
readonly createAdRequest: CreateAdRequest;
constructor(request: CreateAdRequest) {
this.createAdRequest = request;
}
}

View File

@@ -0,0 +1,116 @@
import { AutoMap } from '@automapper/classes';
import { IsBoolean, IsNotEmpty, IsNumber, IsString } from 'class-validator';
export class CreateAdRequest {
@IsString()
@IsNotEmpty()
@AutoMap()
uuid: string;
@IsBoolean()
@AutoMap()
driver: boolean;
@IsBoolean()
@AutoMap()
passenger: boolean;
@IsNumber()
@AutoMap()
frequency: number;
@IsString()
@AutoMap()
fromDate: string;
@IsString()
@AutoMap()
toDate: string;
@IsString()
@AutoMap()
monTime: string;
@IsString()
@AutoMap()
tueTime: string;
@IsString()
@AutoMap()
wedTime: string;
@IsString()
@AutoMap()
thuTime: string;
@IsString()
@AutoMap()
friTime: string;
@IsString()
@AutoMap()
satTime: string;
@IsString()
@AutoMap()
sunTime: string;
@IsNumber()
@AutoMap()
monMargin: number;
@IsNumber()
@AutoMap()
tueMargin: number;
@IsNumber()
@AutoMap()
wedMargin: number;
@IsNumber()
@AutoMap()
thuMargin: number;
@IsNumber()
@AutoMap()
friMargin: number;
@IsNumber()
@AutoMap()
satMargin: number;
@IsNumber()
@AutoMap()
sunMargin: number;
@IsNumber()
@AutoMap()
originType: number;
@IsNumber()
@AutoMap()
destinationType: number;
@AutoMap()
waypoints: [];
@IsNumber()
@AutoMap()
seatsDriver: number;
@IsNumber()
@AutoMap()
seatsPassenger: number;
@IsNumber()
@AutoMap()
seatsUsed: number;
@IsString()
@AutoMap()
createdAt: string;
@IsString()
@AutoMap()
updatedAt: string;
}

View File

@@ -4,38 +4,105 @@ export class Ad {
@AutoMap()
uuid: string;
@AutoMap()
driver: boolean;
@AutoMap()
passenger: boolean;
@AutoMap()
frequency: number;
@AutoMap()
fromDate: string;
@AutoMap()
toDate: string;
@AutoMap()
monTime: string;
@AutoMap()
tueTime: string;
@AutoMap()
wedTime: string;
@AutoMap()
thuTime: string;
@AutoMap()
friTime: string;
@AutoMap()
satTime: string;
@AutoMap()
sunTime: string;
@AutoMap()
monMargin: number;
@AutoMap()
tueMargin: number;
@AutoMap()
wedMargin: number;
@AutoMap()
thuMargin: number;
@AutoMap()
friMargin: number;
@AutoMap()
satMargin: number;
@AutoMap()
sunMargin: number;
@AutoMap()
driverDuration: number;
@AutoMap()
driverDistance: number;
@AutoMap()
passengerDuration: number;
@AutoMap()
passengerDistance: number;
@AutoMap()
originType: number;
@AutoMap()
destinationType: number;
@AutoMap()
waypoints: [];
@AutoMap()
direction: string;
@AutoMap()
fwdAzimuth: number;
@AutoMap()
backAzimuth: number;
@AutoMap()
seatsDriver: number;
@AutoMap()
seatsPassenger: number;
@AutoMap()
seatsUsed: number;
@AutoMap()
createdAt: string;
@AutoMap()
updatedAt: string;
}

View File

@@ -0,0 +1,17 @@
import { CommandHandler } from '@nestjs/cqrs';
import { CreateAdCommand } from '../../commands/create-ad.command';
import { Ad } from '../entities/ad';
import { AdRepository } from '../../adapters/secondaries/ad.repository';
@CommandHandler(CreateAdCommand)
export class CreateAdUseCase {
constructor(private readonly adRepository: AdRepository) {}
async execute(command: CreateAdCommand): Promise<Ad> {
try {
return await this.adRepository.createAd(command.createAdRequest);
} catch (error) {
throw error;
}
}
}

View File

@@ -0,0 +1,18 @@
import { createMap, Mapper } from '@automapper/core';
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
import { Injectable } from '@nestjs/common';
import { Ad } from '../domain/entities/ad';
import { AdPresenter } from '../adapters/primaries/ad.presenter';
@Injectable()
export class AdProfile extends AutomapperProfile {
constructor(@InjectMapper() mapper: Mapper) {
super(mapper);
}
override get profile() {
return (mapper: any) => {
createMap(mapper, Ad, AdPresenter);
};
}
}