WIP validation pipes
This commit is contained in:
		
							parent
							
								
									1db7dc1104
								
							
						
					
					
						commit
						ad10320f5f
					
				| 
						 | 
				
			
			@ -8,6 +8,7 @@ import { AdProfile } from './mappers/ad.profile';
 | 
			
		|||
import { AdsRepository } from './adapters/secondaries/ads.repository';
 | 
			
		||||
import { Messager } from './adapters/secondaries/messager';
 | 
			
		||||
import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
 | 
			
		||||
import { CreateAdUseCase } from './domain/usecases/create-ad.usecase';
 | 
			
		||||
 | 
			
		||||
@Module({
 | 
			
		||||
  imports: [
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +30,12 @@ import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
 | 
			
		|||
    }),
 | 
			
		||||
  ],
 | 
			
		||||
  controllers: [AdController],
 | 
			
		||||
  providers: [AdProfile, AdsRepository, Messager, FindAdByUuidUseCase],
 | 
			
		||||
  providers: [
 | 
			
		||||
    AdProfile,
 | 
			
		||||
    AdsRepository,
 | 
			
		||||
    Messager,
 | 
			
		||||
    FindAdByUuidUseCase,
 | 
			
		||||
    CreateAdUseCase,
 | 
			
		||||
  ],
 | 
			
		||||
})
 | 
			
		||||
export class AdModule {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,16 @@
 | 
			
		|||
import { Mapper } from '@automapper/core';
 | 
			
		||||
import { InjectMapper } from '@automapper/nestjs';
 | 
			
		||||
import { Controller, UsePipes } from '@nestjs/common';
 | 
			
		||||
import { QueryBus } from '@nestjs/cqrs';
 | 
			
		||||
import { CommandBus, QueryBus } from '@nestjs/cqrs';
 | 
			
		||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
 | 
			
		||||
import { RpcValidationPipe } from '../../../../utils/pipes/rpc.validation-pipe';
 | 
			
		||||
import { FindAdByUuidRequest } from '../../domain/dtos/find-ad-by-uuid.request';
 | 
			
		||||
import { AdPresenter } from './ad.presenter';
 | 
			
		||||
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
 | 
			
		||||
import { Ad } from '../../domain/entities/ad';
 | 
			
		||||
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
 | 
			
		||||
import { CreateAdCommand } from '../../commands/create-ad.command';
 | 
			
		||||
import { DatabaseException } from 'src/modules/database/exceptions/database.exception';
 | 
			
		||||
 | 
			
		||||
@UsePipes(
 | 
			
		||||
  new RpcValidationPipe({
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +21,7 @@ import { Ad } from '../../domain/entities/ad';
 | 
			
		|||
@Controller()
 | 
			
		||||
export class AdController {
 | 
			
		||||
  constructor(
 | 
			
		||||
    private readonly _commandBus: CommandBus,
 | 
			
		||||
    private readonly queryBus: QueryBus,
 | 
			
		||||
    @InjectMapper() private readonly _mapper: Mapper,
 | 
			
		||||
  ) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -34,4 +38,22 @@ export class AdController {
 | 
			
		|||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @GrpcMethod('AdsService', 'Create')
 | 
			
		||||
  async createAd(data: CreateAdRequest): Promise<AdPresenter> {
 | 
			
		||||
    try {
 | 
			
		||||
      const ad = await this._commandBus.execute(new CreateAdCommand(data));
 | 
			
		||||
      return this._mapper.map(ad, Ad, AdPresenter);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      if (e instanceof DatabaseException) {
 | 
			
		||||
        if (e.message.includes('Already exists')) {
 | 
			
		||||
          throw new RpcException({
 | 
			
		||||
            code: 6,
 | 
			
		||||
            message: 'Ad already exists',
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      throw new RpcException({});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,15 +19,15 @@ message Ad {
 | 
			
		|||
  string userUuid = 2;
 | 
			
		||||
  bool driver = 3;
 | 
			
		||||
  bool passenger = 4;
 | 
			
		||||
  int32 frequency = 5;
 | 
			
		||||
  Frequency frequency = 5;
 | 
			
		||||
  string fromDate = 6;
 | 
			
		||||
  string toDate = 7;
 | 
			
		||||
  Schedule schedule = 8;
 | 
			
		||||
  MarginDurations marginDurations = 9;
 | 
			
		||||
  int32 seatsPassenger = 10;
 | 
			
		||||
  int32 seatsDriver = 11;
 | 
			
		||||
  optional int32 seatsPassenger = 10;
 | 
			
		||||
  optional int32 seatsDriver = 11;
 | 
			
		||||
  bool strict = 12;
 | 
			
		||||
  Addresses addresses = 13;
 | 
			
		||||
  repeated Address addresses = 13;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message Schedule {
 | 
			
		||||
| 
						 | 
				
			
			@ -50,10 +50,6 @@ message MarginDurations {
 | 
			
		|||
  int32 sun = 7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message Addresses {
 | 
			
		||||
  repeated Address address = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message Address {
 | 
			
		||||
  float lon = 1;
 | 
			
		||||
  float lat = 2;
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +69,11 @@ enum AddressType {
 | 
			
		|||
  OTHER = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum Frequency {
 | 
			
		||||
  PUNCTUAL = 1;
 | 
			
		||||
  RECURRENT = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message AdFilter {
 | 
			
		||||
  optional int32 page = 1;
 | 
			
		||||
  optional int32 perPage = 2;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,12 @@ import {
 | 
			
		|||
  IsBoolean,
 | 
			
		||||
  IsDate,
 | 
			
		||||
  IsInt,
 | 
			
		||||
  MinLength,
 | 
			
		||||
  ValidateIf,
 | 
			
		||||
  ArrayMinSize,
 | 
			
		||||
  IsArray,
 | 
			
		||||
  IsEnum,
 | 
			
		||||
} from 'class-validator';
 | 
			
		||||
import { FrequencyType } from '../entities/frequencyEnum';
 | 
			
		||||
import { Frequency } from '../entities/frequency.enum';
 | 
			
		||||
import { Address } from '../entities/address';
 | 
			
		||||
 | 
			
		||||
export class CreateAdRequest {
 | 
			
		||||
| 
						 | 
				
			
			@ -22,21 +24,26 @@ export class CreateAdRequest {
 | 
			
		|||
  userUuid: string;
 | 
			
		||||
 | 
			
		||||
  @ValidateIf((ad) => (ad.passenger ? false : true))
 | 
			
		||||
  @IsOptional()
 | 
			
		||||
  @IsBoolean()
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  driver?: boolean;
 | 
			
		||||
 | 
			
		||||
  @ValidateIf((ad) => (ad.driver ? false : true))
 | 
			
		||||
  @IsOptional()
 | 
			
		||||
  @IsBoolean()
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  passenger?: boolean;
 | 
			
		||||
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  frequency: FrequencyType;
 | 
			
		||||
  @IsEnum(Frequency)
 | 
			
		||||
  frequency: Frequency;
 | 
			
		||||
 | 
			
		||||
  @IsDate()
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  fromDate: Date;
 | 
			
		||||
 | 
			
		||||
  @IsDate()
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  toDate: Date;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -111,11 +118,13 @@ export class CreateAdRequest {
 | 
			
		|||
  sunMargin?: number;
 | 
			
		||||
 | 
			
		||||
  @ValidateIf((ad) => (ad.passenger ? false : true))
 | 
			
		||||
  @IsOptional()
 | 
			
		||||
  @IsInt()
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  seatsDriver?: number;
 | 
			
		||||
 | 
			
		||||
  @ValidateIf((ad) => (ad.driver ? false : true))
 | 
			
		||||
  @IsOptional()
 | 
			
		||||
  @IsInt()
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  seatsPassenger?: number;
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +139,7 @@ export class CreateAdRequest {
 | 
			
		|||
  @AutoMap()
 | 
			
		||||
  updatedAt?: Date;
 | 
			
		||||
 | 
			
		||||
  @MinLength(2)
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  @IsArray()
 | 
			
		||||
  @AutoMap(() => [Address])
 | 
			
		||||
  addresses?: Array<Address>;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ import {
 | 
			
		|||
  MinLength,
 | 
			
		||||
  ValidateIf,
 | 
			
		||||
} from 'class-validator';
 | 
			
		||||
import { FrequencyType } from '../entities/frequencyEnum';
 | 
			
		||||
import { Frequency } from './frequency.enum';
 | 
			
		||||
import { Address } from '../entities/address';
 | 
			
		||||
 | 
			
		||||
export class Ad {
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ export class Ad {
 | 
			
		|||
  passenger?: boolean;
 | 
			
		||||
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  frequency: FrequencyType;
 | 
			
		||||
  frequency: string;
 | 
			
		||||
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
  fromDate: Date;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
import { AutoMap } from '@automapper/classes';
 | 
			
		||||
import { AddressType } from './addressEnum';
 | 
			
		||||
import { AddressType } from './address.enum';
 | 
			
		||||
 | 
			
		||||
export class Address {
 | 
			
		||||
  @AutoMap()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
export enum Frequency {
 | 
			
		||||
  PUNCTUAL = 1,
 | 
			
		||||
  RECURRENT = 2,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +0,0 @@
 | 
			
		|||
export enum FrequencyType {
 | 
			
		||||
  PUNCTUAL = 'PUNCTUAL',
 | 
			
		||||
  RECURRENT = 'RECURRENT',
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
import { createMap, Mapper } from '@automapper/core';
 | 
			
		||||
import { createMap, forMember, mapFrom, 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';
 | 
			
		||||
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
 | 
			
		||||
import { Frequency } from '../domain/entities/frequency.enum';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class AdProfile extends AutomapperProfile {
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +15,17 @@ export class AdProfile extends AutomapperProfile {
 | 
			
		|||
  override get profile() {
 | 
			
		||||
    return (mapper) => {
 | 
			
		||||
      createMap(mapper, Ad, AdPresenter);
 | 
			
		||||
      createMap(mapper, CreateAdRequest, Ad);
 | 
			
		||||
      createMap(
 | 
			
		||||
        mapper,
 | 
			
		||||
        CreateAdRequest,
 | 
			
		||||
        Ad,
 | 
			
		||||
        forMember(
 | 
			
		||||
          (dest) => dest.frequency,
 | 
			
		||||
          mapFrom((source) =>
 | 
			
		||||
            source.frequency == Frequency.PUNCTUAL ? 'PUNCTUAL' : 'RECCURENT',
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,10 +5,10 @@ import { Address } from '../../domain/entities/address';
 | 
			
		|||
import { Messager } from '../../adapters/secondaries/messager';
 | 
			
		||||
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
 | 
			
		||||
import { CreateAdCommand } from '../../commands/create-ad.command';
 | 
			
		||||
import { AddressType } from '../../domain/entities/addressEnum';
 | 
			
		||||
import { AddressType } from '../../domain/entities/address.enum';
 | 
			
		||||
import { AutomapperModule } from '@automapper/nestjs';
 | 
			
		||||
import { classes } from '@automapper/classes';
 | 
			
		||||
import { FrequencyType } from '../../domain/entities/frequencyEnum';
 | 
			
		||||
import { Frequency } from '../../domain/entities/frequency.enum';
 | 
			
		||||
import { Ad } from '../../domain/entities/ad';
 | 
			
		||||
import { AdProfile } from '../../mappers/ad.profile';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ const mockAddress1: Address = {
 | 
			
		|||
  houseNumber: '5',
 | 
			
		||||
  street: 'Avenue Foch',
 | 
			
		||||
  locality: 'Nancy',
 | 
			
		||||
  postalCode: '75000',
 | 
			
		||||
  postalCode: '54000',
 | 
			
		||||
  country: 'France',
 | 
			
		||||
  type: AddressType.HOUSE_NUMBER,
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ const newAdRequest: CreateAdRequest = {
 | 
			
		|||
  userUuid: '113e0000-0000-4000-a000-000000000000',
 | 
			
		||||
  driver: true,
 | 
			
		||||
  passenger: false,
 | 
			
		||||
  frequency: FrequencyType.RECURRENT,
 | 
			
		||||
  frequency: Frequency.RECURRENT,
 | 
			
		||||
  fromDate: new Date('01-05-2023'),
 | 
			
		||||
  toDate: new Date('20-08-2023'),
 | 
			
		||||
  tueTime: new Date(''),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,6 +88,7 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
 | 
			
		|||
 | 
			
		||||
      return res;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.log(e);
 | 
			
		||||
      if (e instanceof Prisma.PrismaClientKnownRequestError) {
 | 
			
		||||
        throw new DatabaseException(
 | 
			
		||||
          Prisma.PrismaClientKnownRequestError.name,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue