WIP ad creation mapping
This commit is contained in:
parent
954f26b2b3
commit
bee5fef9ff
|
@ -11,7 +11,6 @@ import { Ad } from '../../domain/entities/ad';
|
||||||
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
|
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
|
||||||
import { CreateAdCommand } from '../../commands/create-ad.command';
|
import { CreateAdCommand } from '../../commands/create-ad.command';
|
||||||
import { DatabaseException } from '../../../database/exceptions/database.exception';
|
import { DatabaseException } from '../../../database/exceptions/database.exception';
|
||||||
import { AddressDTO } from '../../domain/dtos/create.address.dto';
|
|
||||||
|
|
||||||
@UsePipes(
|
@UsePipes(
|
||||||
new RpcValidationPipe({
|
new RpcValidationPipe({
|
||||||
|
@ -43,9 +42,6 @@ export class AdController {
|
||||||
@GrpcMethod('AdsService', 'Create')
|
@GrpcMethod('AdsService', 'Create')
|
||||||
async createAd(data: CreateAdRequest): Promise<AdPresenter> {
|
async createAd(data: CreateAdRequest): Promise<AdPresenter> {
|
||||||
try {
|
try {
|
||||||
console.log('controler--------------------------------');
|
|
||||||
console.log(data);
|
|
||||||
console.log('-----------------------------------------');
|
|
||||||
const ad = await this._commandBus.execute(new CreateAdCommand(data));
|
const ad = await this._commandBus.execute(new CreateAdCommand(data));
|
||||||
return this._mapper.map(ad, Ad, AdPresenter);
|
return this._mapper.map(ad, Ad, AdPresenter);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -1,34 +1,7 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { AdRepository } from '../../../database/domain/ad-repository';
|
import { AdRepository } from '../../../database/domain/ad-repository';
|
||||||
import { Ad } from '../../domain/entities/ad';
|
import { Ad } from '../../domain/entities/ad';
|
||||||
import { DatabaseException } from '../../../database/exceptions/database.exception';
|
|
||||||
import { Prisma } from '@prisma/client';
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdsRepository extends AdRepository<Ad> {
|
export class AdsRepository extends AdRepository<Ad> {
|
||||||
protected _model = 'ad';
|
protected _model = 'ad';
|
||||||
|
|
||||||
async create(entity: Partial<Ad> | any, include?: any): Promise<Ad> {
|
|
||||||
console.log('custom ad repo ');
|
|
||||||
console.log(entity);
|
|
||||||
console.log('*****************************************');
|
|
||||||
try {
|
|
||||||
const res = await this._prisma[this._model].create({
|
|
||||||
data: entity,
|
|
||||||
include: include,
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
} catch (e) {
|
|
||||||
console.log('repo error ');
|
|
||||||
console.log(e);
|
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
|
||||||
throw new DatabaseException(
|
|
||||||
Prisma.PrismaClientKnownRequestError.name,
|
|
||||||
e.code,
|
|
||||||
e.message,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
throw new DatabaseException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import {
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
IsBoolean,
|
||||||
|
IsDate,
|
||||||
|
IsInt,
|
||||||
|
IsEnum,
|
||||||
|
ValidateNested,
|
||||||
|
IsUUID,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { Frequency } from '../types/frequency.enum';
|
||||||
|
import { AddressCreation } from './address.creation';
|
||||||
|
export class AdCreation {
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
userUuid: string;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
@AutoMap()
|
||||||
|
driver: boolean;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
@AutoMap()
|
||||||
|
passenger: boolean;
|
||||||
|
|
||||||
|
@IsEnum(Frequency)
|
||||||
|
@AutoMap()
|
||||||
|
frequency: Frequency;
|
||||||
|
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
fromDate: Date;
|
||||||
|
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
toDate: Date;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
monTime?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
tueTime?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
wedTime?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
thuTime?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
friTime?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
satTime?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
sunTime?: string;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
monMargin: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
tueMargin: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
wedMargin: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
thuMargin: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
friMargin: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
satMargin: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
sunMargin: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
seatsDriver: number;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
seatsPassenger: number;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
@AutoMap()
|
||||||
|
strict: boolean;
|
||||||
|
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
updatedAt?: Date;
|
||||||
|
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@AutoMap()
|
||||||
|
addresses: { create: AddressCreation[] };
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsInt } from 'class-validator';
|
||||||
|
|
||||||
|
export class AddressCreation {
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
position: number;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
lon: number;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
lat: number;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
houseNumber?: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
street?: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
locality: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
postalCode: string;
|
||||||
|
|
||||||
|
@AutoMap()
|
||||||
|
country: string;
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ import { Transform, Type } from 'class-transformer';
|
||||||
import { mappingKeyToFrequency } from './utils/frequency.mapping';
|
import { mappingKeyToFrequency } from './utils/frequency.mapping';
|
||||||
import { MarginDTO } from './create.margin.dto';
|
import { MarginDTO } from './create.margin.dto';
|
||||||
import { ScheduleDTO } from './create.schedule.dto';
|
import { ScheduleDTO } from './create.schedule.dto';
|
||||||
import { AddressDTO } from './create.address.dto';
|
import { AddressRequestDTO } from './create.address.request';
|
||||||
import { HasProperPassengerSeats } from './utils/has-passenger-seats.validator';
|
import { HasProperPassengerSeats } from './utils/has-passenger-seats.validator';
|
||||||
import { HasProperDriverSeats } from './utils/has-driver-seats.validator';
|
import { HasProperDriverSeats } from './utils/has-driver-seats.validator';
|
||||||
import { HasProperPositionIndexes } from './utils/address-position.validator';
|
import { HasProperPositionIndexes } from './utils/address-position.validator';
|
||||||
|
@ -27,7 +27,6 @@ export class CreateAdRequest {
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
uuid?: string;
|
uuid?: string;
|
||||||
|
|
||||||
// TODO create validation rule to verify is user exists ??
|
|
||||||
@IsUUID(4)
|
@IsUUID(4)
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
userUuid: string;
|
userUuid: string;
|
||||||
|
@ -51,6 +50,7 @@ export class CreateAdRequest {
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
frequency: Frequency;
|
frequency: Frequency;
|
||||||
|
|
||||||
|
// TODO create a proper validator
|
||||||
@ValidateIf((ad) => ad.frequency === 'PUNCTUAL')
|
@ValidateIf((ad) => ad.frequency === 'PUNCTUAL')
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
|
@ -98,9 +98,9 @@ export class CreateAdRequest {
|
||||||
strict?: boolean;
|
strict?: boolean;
|
||||||
|
|
||||||
@ArrayMinSize(2)
|
@ArrayMinSize(2)
|
||||||
@Type(() => AddressDTO)
|
@Type(() => AddressRequestDTO)
|
||||||
@HasProperPositionIndexes()
|
@HasProperPositionIndexes()
|
||||||
@ValidateNested({ each: true })
|
@ValidateNested({ each: true })
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
addresses: AddressDTO[];
|
addresses: AddressRequestDTO[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
IsUUID,
|
IsUUID,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
|
|
||||||
export class AddressDTO {
|
export class AddressRequestDTO {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsUUID(4)
|
@IsUUID(4)
|
||||||
@AutoMap()
|
@AutoMap()
|
|
@ -1,7 +1,7 @@
|
||||||
import { ValidateBy, ValidationOptions, buildMessage } from 'class-validator';
|
import { ValidateBy, ValidationOptions, buildMessage } from 'class-validator';
|
||||||
import { AddressDTO } from '../create.address.dto';
|
import { AddressRequestDTO } from '../create.address.request';
|
||||||
|
|
||||||
export function hasProperPositionIndexes(value: AddressDTO[]) {
|
export function hasProperPositionIndexes(value: AddressRequestDTO[]) {
|
||||||
if (value.every((address) => address.position === undefined)) return true;
|
if (value.every((address) => address.position === undefined)) return true;
|
||||||
else if (value.every((address) => typeof address.position === 'number')) {
|
else if (value.every((address) => typeof address.position === 'number')) {
|
||||||
value.sort((a, b) => a.position - b.position);
|
value.sort((a, b) => a.position - b.position);
|
||||||
|
@ -21,7 +21,7 @@ export function HasProperPositionIndexes(
|
||||||
name: '',
|
name: '',
|
||||||
constraints: [],
|
constraints: [],
|
||||||
validator: {
|
validator: {
|
||||||
validate: (value: AddressDTO[]): boolean =>
|
validate: (value: AddressRequestDTO[]): boolean =>
|
||||||
hasProperPositionIndexes(value),
|
hasProperPositionIndexes(value),
|
||||||
defaultMessage: buildMessage(
|
defaultMessage: buildMessage(
|
||||||
() =>
|
() =>
|
||||||
|
|
|
@ -6,15 +6,16 @@ import { Messager } from '../../adapters/secondaries/messager';
|
||||||
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
||||||
import { CreateAdCommand } from '../../commands/create-ad.command';
|
import { CreateAdCommand } from '../../commands/create-ad.command';
|
||||||
import { CreateAdRequest } from '../dtos/create-ad.request';
|
import { CreateAdRequest } from '../dtos/create-ad.request';
|
||||||
import { Ad } from '../entities/ad';
|
|
||||||
import { IProvideParams } from '../interfaces/param-provider.interface';
|
import { IProvideParams } from '../interfaces/param-provider.interface';
|
||||||
import { DefaultParams } from '../types/default-params.type';
|
import { DefaultParams } from '../types/default-params.type';
|
||||||
import { Address } from '../entities/address';
|
import { AdCreation } from '../dtos/ad.creation';
|
||||||
|
import { Ad } from '../entities/ad';
|
||||||
|
|
||||||
@CommandHandler(CreateAdCommand)
|
@CommandHandler(CreateAdCommand)
|
||||||
export class CreateAdUseCase {
|
export class CreateAdUseCase {
|
||||||
private readonly defaultParams: DefaultParams;
|
private readonly defaultParams: DefaultParams;
|
||||||
private ad: Ad;
|
private ad: AdCreation;
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _repository: AdsRepository,
|
private readonly _repository: AdsRepository,
|
||||||
private readonly _messager: Messager,
|
private readonly _messager: Messager,
|
||||||
|
@ -26,50 +27,25 @@ export class CreateAdUseCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(command: CreateAdCommand): Promise<Ad> {
|
async execute(command: CreateAdCommand): Promise<Ad> {
|
||||||
console.log('before mapping ');
|
this.ad = this._mapper.map(
|
||||||
const entity: Ad = this._mapper.map(
|
|
||||||
command.createAdRequest,
|
command.createAdRequest,
|
||||||
CreateAdRequest,
|
CreateAdRequest,
|
||||||
Ad,
|
AdCreation,
|
||||||
);
|
);
|
||||||
typeof entity.monMargin === 'number'
|
this.setDefaultSchedule();
|
||||||
? entity.monMargin
|
this.setDefaultAddressesPosition();
|
||||||
: (entity.monMargin = this.defaultParams.MON_MARGIN);
|
this.setDefaultDriverAndPassengerParameters();
|
||||||
typeof entity.tueMargin === 'number'
|
this.setDefaultDistanceMargin();
|
||||||
? entity.tueMargin
|
|
||||||
: (entity.tueMargin = this.defaultParams.TUE_MARGIN);
|
|
||||||
typeof entity.wedMargin === 'number'
|
|
||||||
? entity.wedMargin
|
|
||||||
: (entity.wedMargin = this.defaultParams.WED_MARGIN);
|
|
||||||
typeof entity.thuMargin === 'number'
|
|
||||||
? entity.thuMargin
|
|
||||||
: (entity.thuMargin = this.defaultParams.THU_MARGIN);
|
|
||||||
typeof entity.friMargin === 'number'
|
|
||||||
? entity.friMargin
|
|
||||||
: (entity.friMargin = this.defaultParams.FRI_MARGIN);
|
|
||||||
typeof entity.satMargin === 'number'
|
|
||||||
? entity.satMargin
|
|
||||||
: (entity.satMargin = this.defaultParams.SAT_MARGIN);
|
|
||||||
typeof entity.sunMargin === 'number'
|
|
||||||
? entity.sunMargin
|
|
||||||
: (entity.sunMargin = this.defaultParams.SUN_MARGIN);
|
|
||||||
typeof entity.strict === 'boolean'
|
|
||||||
? entity.strict
|
|
||||||
: (entity.strict = this.defaultParams.STRICT);
|
|
||||||
|
|
||||||
if (typeof entity.addresses[0].position === 'undefined') {
|
|
||||||
for (let i = 0; i < entity.addresses.length; i++) {
|
|
||||||
entity.addresses[i].position = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
console.log('before ***********************************');
|
console.log(this.ad);
|
||||||
console.log(entity);
|
const adCreated: Ad = await this._repository.create(this.ad);
|
||||||
console.log('******************************************');
|
this._messager.publish('ad.create', JSON.stringify(adCreated));
|
||||||
this.ad = await this._repository.create(entity);
|
this._messager.publish(
|
||||||
// this._messager.publish('ad.create', JSON.stringify(ad));
|
'logging.ad.create.info',
|
||||||
// this._messager.publish('logging.ad.create.info', JSON.stringify(ad));
|
JSON.stringify(adCreated),
|
||||||
return this.ad;
|
);
|
||||||
|
return adCreated;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
let key = 'logging.ad.create.crit';
|
let key = 'logging.ad.create.crit';
|
||||||
if (error.message.includes('Already exists')) {
|
if (error.message.includes('Already exists')) {
|
||||||
|
@ -85,107 +61,49 @@ export class CreateAdUseCase {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setDefaultSchedule(): void {
|
||||||
|
if (this.ad.monMargin === undefined)
|
||||||
|
this.ad.monMargin = this.defaultParams.MON_MARGIN;
|
||||||
|
if (this.ad.tueMargin === undefined)
|
||||||
|
this.ad.tueMargin = this.defaultParams.TUE_MARGIN;
|
||||||
|
if (this.ad.wedMargin === undefined)
|
||||||
|
this.ad.wedMargin = this.defaultParams.WED_MARGIN;
|
||||||
|
if (this.ad.thuMargin === undefined)
|
||||||
|
this.ad.thuMargin = this.defaultParams.THU_MARGIN;
|
||||||
|
if (this.ad.friMargin === undefined)
|
||||||
|
this.ad.friMargin = this.defaultParams.FRI_MARGIN;
|
||||||
|
if (this.ad.satMargin === undefined)
|
||||||
|
this.ad.satMargin = this.defaultParams.SAT_MARGIN;
|
||||||
|
if (this.ad.sunMargin === undefined)
|
||||||
|
this.ad.sunMargin = this.defaultParams.SUN_MARGIN;
|
||||||
|
}
|
||||||
|
setDefaultDistanceMargin(): void {
|
||||||
|
if (this.ad.strict === undefined)
|
||||||
|
this.ad.strict = this.defaultParams.STRICT;
|
||||||
|
}
|
||||||
|
setDefaultDriverAndPassengerParameters(): void {
|
||||||
|
if (!this.ad.driver && !this.ad.passenger) {
|
||||||
|
this.ad.driver = this.defaultParams.DRIVER;
|
||||||
|
this.ad.seatsDriver = this.defaultParams.DRIVER_SEAT;
|
||||||
|
this.ad.passenger = this.defaultParams.PASSENGER;
|
||||||
|
this.ad.seatsPassenger = this.defaultParams.PASSENGER_SEATS;
|
||||||
|
} else {
|
||||||
|
if (!this.ad.driver) {
|
||||||
|
this.ad.driver = false;
|
||||||
|
this.ad.seatsDriver = 0;
|
||||||
|
}
|
||||||
|
if (!this.ad.passenger) {
|
||||||
|
this.ad.passenger = false;
|
||||||
|
this.ad.seatsPassenger = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setDefaultAddressesPosition(): void {
|
||||||
|
if (this.ad.addresses.create[0].position === undefined) {
|
||||||
|
for (let i = 0; i < this.ad.addresses.create.length; i++) {
|
||||||
|
this.ad.addresses.create[i].position = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TransformPunctualToReccurent(): void {}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
repo error
|
|
||||||
PrismaClientValidationError:
|
|
||||||
Invalid `this._prisma[this._model].create()` invocation in
|
|
||||||
/usr/src/app/src/modules/ad/adapters/secondaries/ads.repository.ts:15:51
|
|
||||||
|
|
||||||
12 console.log(entity);
|
|
||||||
13 console.log('*****************************************');
|
|
||||||
14 try {
|
|
||||||
→ 15 const res = await this._prisma[this._model].create({
|
|
||||||
data: {
|
|
||||||
uuid: undefined,
|
|
||||||
userUuid: '113e0000-0000-4000-a000-000000000000',
|
|
||||||
driver: true,
|
|
||||||
passenger: false,
|
|
||||||
frequency: 'RECURRENT',
|
|
||||||
fromDate: new Date('2023-01-15T00:00:00.000Z'),
|
|
||||||
toDate: new Date('2023-08-01T00:00:00.000Z'),
|
|
||||||
seatsDriver: 3,
|
|
||||||
seatsPassenger: 0,
|
|
||||||
strict: false,
|
|
||||||
monMargin: 800,
|
|
||||||
tueMargin: 900,
|
|
||||||
wedMargin: 900,
|
|
||||||
thuMargin: 900,
|
|
||||||
friMargin: 900,
|
|
||||||
satMargin: 900,
|
|
||||||
sunMargin: 900,
|
|
||||||
monTime: '04:40',
|
|
||||||
tueTime: undefined,
|
|
||||||
wedTime: undefined,
|
|
||||||
thuTime: undefined,
|
|
||||||
friTime: undefined,
|
|
||||||
satTime: undefined,
|
|
||||||
sunTime: undefined,
|
|
||||||
addresses: [
|
|
||||||
{
|
|
||||||
lon: 48.68944549560547,
|
|
||||||
lat: 6.176510334014893,
|
|
||||||
houseNumber: '5',
|
|
||||||
street: 'Avenue Foch',
|
|
||||||
locality: 'Nancy',
|
|
||||||
postalCode: '54000',
|
|
||||||
country: 'France',
|
|
||||||
position: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
lon: 48.85660171508789,
|
|
||||||
lat: 2.3522000312805176,
|
|
||||||
locality: 'Paris',
|
|
||||||
postalCode: '75000',
|
|
||||||
country: 'France',
|
|
||||||
position: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
},
|
|
||||||
include: undefined
|
|
||||||
})
|
|
||||||
|
|
||||||
Argument addresses: Got invalid value
|
|
||||||
[
|
|
||||||
{
|
|
||||||
lon: 48.68944549560547,
|
|
||||||
lat: 6.176510334014893,
|
|
||||||
houseNumber: '5',
|
|
||||||
street: 'Avenue Foch',
|
|
||||||
locality: 'Nancy',
|
|
||||||
postalCode: '54000',
|
|
||||||
country: 'France',
|
|
||||||
position: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
lon: 48.85660171508789,
|
|
||||||
lat: 2.3522000312805176,
|
|
||||||
locality: 'Paris',
|
|
||||||
postalCode: '75000',
|
|
||||||
country: 'France',
|
|
||||||
position: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
on prisma.createOneAd. Provided List<Json>, expected AddressCreateNestedManyWithoutAdInput:
|
|
||||||
type AddressCreateNestedManyWithoutAdInput {
|
|
||||||
create?: AddressCreateWithoutAdInput | List<AddressCreateWithoutAdInput> | AddressUncheckedCreateWithoutAdInput | List<AddressUncheckedCreateWithoutAdInput>
|
|
||||||
connectOrCreate?: AddressCreateOrConnectWithoutAdInput | List<AddressCreateOrConnectWithoutAdInput>
|
|
||||||
createMany?: AddressCreateManyAdInputEnvelope
|
|
||||||
connect?: AddressWhereUniqueInput | List<AddressWhereUniqueInput>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
at mi.validate (/usr/src/app/node_modules/@prisma/client/runtime/library.js:149:91)
|
|
||||||
at tn.createMessage (/usr/src/app/node_modules/@prisma/client/runtime/library.js:166:1205)
|
|
||||||
at /usr/src/app/node_modules/@prisma/client/runtime/library.js:179:10962
|
|
||||||
at runInChildSpan (/usr/src/app/node_modules/@prisma/client/runtime/library.js:70:25817)
|
|
||||||
at PrismaService._executeRequest (/usr/src/app/node_modules/@prisma/client/runtime/library.js:179:10951)
|
|
||||||
at PrismaService._request (/usr/src/app/node_modules/@prisma/client/runtime/library.js:179:10484)
|
|
||||||
at AdsRepository.create (/usr/src/app/src/modules/ad/adapters/secondaries/ads.repository.ts:15:19)
|
|
||||||
at CreateAdUseCase.execute (/usr/src/app/src/modules/ad/domain/usecases/create-ad.usecase.ts:69:17)
|
|
||||||
at AdController.createAd (/usr/src/app/src/modules/ad/adapters/primaries/ad.controller.ts:49:18)
|
|
||||||
at /usr/src/app/node_modules/@nestjs/microservices/context/rpc-proxy.js:11:32
|
|
||||||
at Object.Create (/usr/src/app/node_modules/@nestjs/microservices/server/server-grpc.js:148:40) {
|
|
||||||
clientVersion: '4.13.0'
|
|
||||||
*/
|
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import { createMap, forMember, mapFrom, Mapper } from '@automapper/core';
|
import {
|
||||||
|
condition,
|
||||||
|
createMap,
|
||||||
|
forMember,
|
||||||
|
mapFrom,
|
||||||
|
Mapper,
|
||||||
|
} from '@automapper/core';
|
||||||
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Ad } from '../domain/entities/ad';
|
import { Ad } from '../domain/entities/ad';
|
||||||
import { AdPresenter } from '../adapters/primaries/ad.presenter';
|
import { AdPresenter } from '../adapters/primaries/ad.presenter';
|
||||||
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
|
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
|
||||||
import { Address } from '../domain/entities/address';
|
import { AdCreation } from '../domain/dtos/ad.creation';
|
||||||
import { AddressDTO } from '../domain/dtos/create.address.dto';
|
import { Frequency } from '@prisma/client';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdProfile extends AutomapperProfile {
|
export class AdProfile extends AutomapperProfile {
|
||||||
|
@ -15,12 +21,11 @@ export class AdProfile extends AutomapperProfile {
|
||||||
|
|
||||||
override get profile() {
|
override get profile() {
|
||||||
return (mapper) => {
|
return (mapper) => {
|
||||||
createMap(mapper, Address, AddressDTO);
|
|
||||||
createMap(mapper, Ad, AdPresenter);
|
createMap(mapper, Ad, AdPresenter);
|
||||||
createMap(
|
createMap(
|
||||||
mapper,
|
mapper,
|
||||||
CreateAdRequest,
|
CreateAdRequest,
|
||||||
Ad,
|
AdCreation,
|
||||||
forMember(
|
forMember(
|
||||||
(destination) => destination.monMargin,
|
(destination) => destination.monMargin,
|
||||||
mapFrom((source) => source.marginDurations.mon),
|
mapFrom((source) => source.marginDurations.mon),
|
||||||
|
@ -78,9 +83,17 @@ export class AdProfile extends AutomapperProfile {
|
||||||
mapFrom((source) => source.schedule.sun),
|
mapFrom((source) => source.schedule.sun),
|
||||||
),
|
),
|
||||||
forMember(
|
forMember(
|
||||||
(destination) => destination.addresses,
|
(destination) => destination.addresses.create,
|
||||||
mapFrom((source) => source.addresses),
|
mapFrom((source) => source.addresses),
|
||||||
),
|
),
|
||||||
|
//TODO use custom resolver
|
||||||
|
// forMember(
|
||||||
|
// (destination) => destination.fromDate,
|
||||||
|
// condition(
|
||||||
|
// (source) => source.frequency == Frequency.PUNCTUAL,
|
||||||
|
// source.departure,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { Mapper, createMap } from '@automapper/core';
|
||||||
|
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { AddressRequestDTO } from '../domain/dtos/create.address.request';
|
||||||
|
import { AddressCreation } from '../domain/dtos/address.creation';
|
||||||
|
@Injectable()
|
||||||
|
export class AdProfile extends AutomapperProfile {
|
||||||
|
constructor(@InjectMapper() mapper: Mapper) {
|
||||||
|
super(mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
override get profile() {
|
||||||
|
return (mapper) => {
|
||||||
|
createMap(mapper, AddressRequestDTO, AddressCreation);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,9 +9,11 @@ import { classes } from '@automapper/classes';
|
||||||
import { Frequency } from '../../domain/types/frequency.enum';
|
import { Frequency } from '../../domain/types/frequency.enum';
|
||||||
import { Ad } from '../../domain/entities/ad';
|
import { Ad } from '../../domain/entities/ad';
|
||||||
import { AdProfile } from '../../mappers/ad.profile';
|
import { AdProfile } from '../../mappers/ad.profile';
|
||||||
import { AddressDTO } from '../../domain/dtos/create.address.dto';
|
import { AddressRequestDTO } from '../../domain/dtos/create.address.request';
|
||||||
|
import { AdCreation } from '../../domain/dtos/ad.creation';
|
||||||
|
import { AddressCreation } from '../../domain/dtos/address.creation';
|
||||||
|
|
||||||
const mockAddress1: AddressDTO = {
|
const mockAddress1: AddressRequestDTO = {
|
||||||
position: 0,
|
position: 0,
|
||||||
lon: 48.68944505415954,
|
lon: 48.68944505415954,
|
||||||
lat: 6.176510296462267,
|
lat: 6.176510296462267,
|
||||||
|
@ -21,7 +23,7 @@ const mockAddress1: AddressDTO = {
|
||||||
postalCode: '54000',
|
postalCode: '54000',
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
const mockAddress2: AddressDTO = {
|
const mockAddress2: AddressRequestDTO = {
|
||||||
position: 1,
|
position: 1,
|
||||||
lon: 48.8566,
|
lon: 48.8566,
|
||||||
lat: 2.3522,
|
lat: 2.3522,
|
||||||
|
@ -29,25 +31,29 @@ const mockAddress2: AddressDTO = {
|
||||||
postalCode: '75000',
|
postalCode: '75000',
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
|
const mockAddressWithoutPos1: AddressRequestDTO = {
|
||||||
|
lon: 43.2965,
|
||||||
|
lat: 5.3698,
|
||||||
|
locality: 'Marseille',
|
||||||
|
postalCode: '13000',
|
||||||
|
country: 'France',
|
||||||
|
};
|
||||||
|
const mockAddressWithoutPos2: AddressRequestDTO = {
|
||||||
|
lon: 43.7102,
|
||||||
|
lat: 7.262,
|
||||||
|
locality: 'Marseille',
|
||||||
|
postalCode: '06000',
|
||||||
|
country: 'France',
|
||||||
|
};
|
||||||
const minimalReccurentAdREquest: CreateAdRequest = {
|
const minimalReccurentAdREquest: CreateAdRequest = {
|
||||||
userUuid: '224e0000-0000-4000-a000-000000000000',
|
userUuid: '224e0000-0000-4000-a000-000000000000',
|
||||||
driver: undefined,
|
|
||||||
passenger: undefined,
|
|
||||||
frequency: Frequency.RECURRENT,
|
frequency: Frequency.RECURRENT,
|
||||||
fromDate: new Date('01-05-2023'),
|
fromDate: new Date('01-05-2023'),
|
||||||
toDate: new Date('01-05-2024'),
|
toDate: new Date('01-05-2024'),
|
||||||
schedule: {
|
schedule: {
|
||||||
mon: '08:00',
|
mon: '08:00',
|
||||||
},
|
},
|
||||||
marginDurations: {
|
marginDurations: {},
|
||||||
mon: undefined,
|
|
||||||
tue: undefined,
|
|
||||||
wed: undefined,
|
|
||||||
thu: undefined,
|
|
||||||
fri: undefined,
|
|
||||||
sat: undefined,
|
|
||||||
sun: undefined,
|
|
||||||
},
|
|
||||||
addresses: [mockAddress1, mockAddress2],
|
addresses: [mockAddress1, mockAddress2],
|
||||||
};
|
};
|
||||||
const newAdRequest: CreateAdRequest = {
|
const newAdRequest: CreateAdRequest = {
|
||||||
|
@ -70,9 +76,26 @@ const newAdRequest: CreateAdRequest = {
|
||||||
sat: undefined,
|
sat: undefined,
|
||||||
sun: undefined,
|
sun: undefined,
|
||||||
},
|
},
|
||||||
seatsPassenger: 2,
|
seatsDriver: 2,
|
||||||
addresses: [mockAddress1, mockAddress2],
|
addresses: [mockAddress1, mockAddress2],
|
||||||
};
|
};
|
||||||
|
const newPunctualPassengerAdRequest: CreateAdRequest = {
|
||||||
|
userUuid: '113e0000-0000-4000-a000-000000000000',
|
||||||
|
passenger: true,
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
departure: new Date('05-22-2023'),
|
||||||
|
marginDurations: {
|
||||||
|
mon: undefined,
|
||||||
|
tue: undefined,
|
||||||
|
wed: undefined,
|
||||||
|
thu: undefined,
|
||||||
|
fri: undefined,
|
||||||
|
sat: undefined,
|
||||||
|
sun: undefined,
|
||||||
|
},
|
||||||
|
seatsPassenger: 1,
|
||||||
|
addresses: [mockAddressWithoutPos1, mockAddressWithoutPos2],
|
||||||
|
};
|
||||||
|
|
||||||
const mockMessager = {
|
const mockMessager = {
|
||||||
publish: jest.fn().mockImplementation(),
|
publish: jest.fn().mockImplementation(),
|
||||||
|
@ -109,7 +132,7 @@ let mockAdRepository = {
|
||||||
.mockImplementationOnce(() => {
|
.mockImplementationOnce(() => {
|
||||||
throw new Error('Already exists');
|
throw new Error('Already exists');
|
||||||
})
|
})
|
||||||
.mockImplementation(),
|
.mockImplementation((command?: CreateAdCommand) => {}),
|
||||||
};
|
};
|
||||||
describe('CreateAdUseCase', () => {
|
describe('CreateAdUseCase', () => {
|
||||||
let createAdUseCase: CreateAdUseCase;
|
let createAdUseCase: CreateAdUseCase;
|
||||||
|
@ -154,17 +177,48 @@ describe('CreateAdUseCase', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Ad parameter default setting ', () => {
|
describe('Ad parameter default setting ', () => {
|
||||||
const newAdCommand = new CreateAdCommand(minimalReccurentAdREquest);
|
beforeEach(() => {
|
||||||
|
mockAdRepository.create.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
it('should define mimimal ad as 1 passager add', async () => {
|
it('should define mimimal ad as 1 passager add', async () => {
|
||||||
const newAd: Ad = await createAdUseCase.execute(newAdCommand);
|
const newAdCommand = new CreateAdCommand(minimalReccurentAdREquest);
|
||||||
expect(mockAdRepository).toBeCalledWith({
|
await createAdUseCase.execute(newAdCommand);
|
||||||
userUuid: '113e0000-0000-4000-a000-000000000000',
|
const expectedAdCreation = {
|
||||||
driver: true,
|
userUuid: minimalReccurentAdREquest.userUuid,
|
||||||
passenger: false,
|
frequency: minimalReccurentAdREquest.frequency,
|
||||||
frequency: Frequency.RECURRENT,
|
fromDate: minimalReccurentAdREquest.fromDate,
|
||||||
fromDate: new Date('01-05-2023'),
|
toDate: minimalReccurentAdREquest.toDate,
|
||||||
toDate: new Date('20-08-2023'),
|
monTime: minimalReccurentAdREquest.schedule.mon,
|
||||||
});
|
tueTime: undefined,
|
||||||
|
wedTime: undefined,
|
||||||
|
thuTime: undefined,
|
||||||
|
friTime: undefined,
|
||||||
|
satTime: undefined,
|
||||||
|
sunTime: undefined,
|
||||||
|
monMargin: mockDefaultParamsProvider.getParams().MON_MARGIN,
|
||||||
|
tueMargin: mockDefaultParamsProvider.getParams().TUE_MARGIN,
|
||||||
|
wedMargin: mockDefaultParamsProvider.getParams().WED_MARGIN,
|
||||||
|
thuMargin: mockDefaultParamsProvider.getParams().THU_MARGIN,
|
||||||
|
friMargin: mockDefaultParamsProvider.getParams().FRI_MARGIN,
|
||||||
|
satMargin: mockDefaultParamsProvider.getParams().SAT_MARGIN,
|
||||||
|
sunMargin: mockDefaultParamsProvider.getParams().SUN_MARGIN,
|
||||||
|
driver: mockDefaultParamsProvider.getParams().DRIVER,
|
||||||
|
seatsDriver: mockDefaultParamsProvider.getParams().DRIVER_SEAT,
|
||||||
|
passenger: mockDefaultParamsProvider.getParams().PASSENGER,
|
||||||
|
seatsPassenger: mockDefaultParamsProvider.getParams().PASSENGER_SEATS,
|
||||||
|
strict: mockDefaultParamsProvider.getParams().STRICT,
|
||||||
|
addresses: {
|
||||||
|
create: minimalReccurentAdREquest.addresses as AddressCreation[],
|
||||||
|
},
|
||||||
|
createdAt: undefined,
|
||||||
|
} as AdCreation;
|
||||||
|
|
||||||
|
expect(mockAdRepository.create).toBeCalledWith(expectedAdCreation);
|
||||||
|
});
|
||||||
|
it('should create an passengerAd with addresses without position ', async () => {
|
||||||
|
const newAdCommand = new CreateAdCommand(newPunctualPassengerAdRequest);
|
||||||
|
await createAdUseCase.execute(newAdCommand);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { AddressDTO } from '../../domain/dtos/create.address.dto';
|
import { AddressRequestDTO } from '../../domain/dtos/create.address.request';
|
||||||
import { hasProperPositionIndexes } from '../../domain/dtos/utils/address-position.validator';
|
import { hasProperPositionIndexes } from '../../domain/dtos/utils/address-position.validator';
|
||||||
describe('addresses position validators', () => {
|
describe('addresses position validators', () => {
|
||||||
const mockAddress1: AddressDTO = {
|
const mockAddress1: AddressRequestDTO = {
|
||||||
lon: 48.68944505415954,
|
lon: 48.68944505415954,
|
||||||
lat: 6.176510296462267,
|
lat: 6.176510296462267,
|
||||||
houseNumber: '5',
|
houseNumber: '5',
|
||||||
|
@ -10,7 +10,7 @@ describe('addresses position validators', () => {
|
||||||
postalCode: '54000',
|
postalCode: '54000',
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
const mockAddress2: AddressDTO = {
|
const mockAddress2: AddressRequestDTO = {
|
||||||
lon: 48.8566,
|
lon: 48.8566,
|
||||||
lat: 2.3522,
|
lat: 2.3522,
|
||||||
locality: 'Paris',
|
locality: 'Paris',
|
||||||
|
@ -18,7 +18,7 @@ describe('addresses position validators', () => {
|
||||||
country: 'France',
|
country: 'France',
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockAddress3: AddressDTO = {
|
const mockAddress3: AddressRequestDTO = {
|
||||||
lon: 49.2628,
|
lon: 49.2628,
|
||||||
lat: 4.0347,
|
lat: 4.0347,
|
||||||
locality: 'Reims',
|
locality: 'Reims',
|
||||||
|
|
|
@ -80,20 +80,13 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
|
||||||
// TODO : using any is not good, but needed for nested entities
|
// TODO : using any is not good, but needed for nested entities
|
||||||
// TODO : Refactor for good clean architecture ?
|
// TODO : Refactor for good clean architecture ?
|
||||||
async create(entity: Partial<T> | any, include?: any): Promise<T> {
|
async create(entity: Partial<T> | any, include?: any): Promise<T> {
|
||||||
console.log('repo entity ');
|
|
||||||
console.log(entity);
|
|
||||||
console.log('-----------------------------------------');
|
|
||||||
try {
|
try {
|
||||||
const res = await this._prisma[this._model].create({
|
const res = await this._prisma[this._model].create({
|
||||||
data: entity,
|
data: entity,
|
||||||
include: include,
|
include: include,
|
||||||
});
|
});
|
||||||
console.log('result');
|
|
||||||
console.log(res);
|
|
||||||
return res;
|
return res;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('repo error ');
|
|
||||||
console.log(e);
|
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||||
throw new DatabaseException(
|
throw new DatabaseException(
|
||||||
Prisma.PrismaClientKnownRequestError.name,
|
Prisma.PrismaClientKnownRequestError.name,
|
||||||
|
|
Loading…
Reference in New Issue