diff --git a/.env.test b/.env.test index bd695a5..84fce77 100644 --- a/.env.test +++ b/.env.test @@ -3,6 +3,5 @@ SERVICE_URL=0.0.0.0 SERVICE_PORT=5006 SERVICE_CONFIGURATION_DOMAIN=AD - # PRISMA DATABASE_URL="postgresql://mobicoop:mobicoop@localhost:5432/mobicoop-test?schema=ad" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index be8ee32..c8197ed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,7 @@ test: - docker-compose -f docker-compose.ci.tools.yml -p ad-tools --env-file ci/.env.ci up -d - sh ci/wait-up.sh - docker-compose -f docker-compose.ci.service.yml -p ad-service --env-file ci/.env.ci up -d - # - docker exec -t v3-ad-api sh -c "npm run test:integration:ci" + - docker exec -t v3-ad-api sh -c "npm run test:integration:ci" coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/ rules: - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_MESSAGE =~ /--check/ || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' diff --git a/package-lock.json b/package-lock.json index 67a5d8c..ba693c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,6 @@ "@prisma/client": "^4.13.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", - "dotenv-cli": "^7.2.1", "ioredis": "^5.3.2", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0" @@ -41,6 +40,7 @@ "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", + "dotenv-cli": "^7.2.1", "eslint": "^8.0.1", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", @@ -3842,6 +3842,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4007,6 +4008,7 @@ "version": "7.2.1", "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.2.1.tgz", "integrity": "sha512-ODHbGTskqRtXAzZapDPvgNuDVQApu4oKX8lZW7Y0+9hKA6le1ZJlyRS687oU9FXjOVEDU/VFV6zI125HzhM1UQ==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "dotenv": "^16.0.0", @@ -5368,7 +5370,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -6811,6 +6814,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -7669,6 +7673,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -7680,6 +7685,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -8636,6 +8642,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, diff --git a/package.json b/package.json index 94127d3..36dee54 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,6 @@ "@prisma/client": "^4.13.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", - "dotenv-cli": "^7.2.1", "ioredis": "^5.3.2", "reflect-metadata": "^0.1.13", "rxjs": "^7.2.0" @@ -66,6 +65,7 @@ "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", + "dotenv-cli": "^7.2.1", "eslint": "^8.0.1", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 28064d3..c6dbca0 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -2,7 +2,8 @@ // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" + binaryTargets = ["linux-musl", "debian-openssl-3.0.x"] } datasource db { diff --git a/src/modules/ad/adapters/primaries/ad.controller.ts b/src/modules/ad/adapters/primaries/ad.controller.ts index f0ce22d..b3aa278 100644 --- a/src/modules/ad/adapters/primaries/ad.controller.ts +++ b/src/modules/ad/adapters/primaries/ad.controller.ts @@ -21,16 +21,16 @@ import { DatabaseException } from '../../../database/exceptions/database.excepti @Controller() export class AdController { constructor( - private readonly _commandBus: CommandBus, + private readonly commandBus: CommandBus, private readonly queryBus: QueryBus, - @InjectMapper() private readonly _mapper: Mapper, + @InjectMapper() private readonly mapper: Mapper, ) {} @GrpcMethod('AdsService', 'FindOneByUuid') async findOnebyUuid(data: FindAdByUuidRequest): Promise { try { const ad = await this.queryBus.execute(new FindAdByUuidQuery(data)); - return this._mapper.map(ad, Ad, AdPresenter); + return this.mapper.map(ad, Ad, AdPresenter); } catch (e) { throw new RpcException({ code: e.code, @@ -42,8 +42,8 @@ export class AdController { @GrpcMethod('AdsService', 'Create') async createAd(data: CreateAdRequest): Promise { try { - const ad = await this._commandBus.execute(new CreateAdCommand(data)); - return this._mapper.map(ad, Ad, AdPresenter); + 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')) { diff --git a/src/modules/ad/adapters/secondaries/messager.ts b/src/modules/ad/adapters/secondaries/messager.ts index 0ee32e3..8e584cf 100644 --- a/src/modules/ad/adapters/secondaries/messager.ts +++ b/src/modules/ad/adapters/secondaries/messager.ts @@ -6,13 +6,13 @@ import { IMessageBroker } from '../../domain/interfaces/message-broker'; @Injectable() export class Messager extends IMessageBroker { constructor( - private readonly _amqpConnection: AmqpConnection, + private readonly amqpConnection: AmqpConnection, configService: ConfigService, ) { super(configService.get('RMQ_EXCHANGE')); } publish(routingKey: string, message: string): void { - this._amqpConnection.publish(this.exchange, routingKey, message); + this.amqpConnection.publish(this.exchange, routingKey, message); } } diff --git a/src/modules/ad/domain/dtos/create.address.request.ts b/src/modules/ad/domain/dtos/address.dto.ts similarity index 95% rename from src/modules/ad/domain/dtos/create.address.request.ts rename to src/modules/ad/domain/dtos/address.dto.ts index 59d6e8f..17a7b79 100644 --- a/src/modules/ad/domain/dtos/create.address.request.ts +++ b/src/modules/ad/domain/dtos/address.dto.ts @@ -8,7 +8,7 @@ import { IsUUID, } from 'class-validator'; -export class AddressRequestDTO { +export class AddressDTO { @IsOptional() @IsUUID(4) @AutoMap() diff --git a/src/modules/ad/domain/dtos/create-ad.request.ts b/src/modules/ad/domain/dtos/create-ad.request.ts index 0075948..864507a 100644 --- a/src/modules/ad/domain/dtos/create-ad.request.ts +++ b/src/modules/ad/domain/dtos/create-ad.request.ts @@ -11,10 +11,10 @@ import { } from 'class-validator'; import { Frequency } from '../types/frequency.enum'; import { Transform, Type } from 'class-transformer'; -import { mappingKeyToFrequency } from './validators/frequency.mapping'; -import { MarginDTO } from './create.margin.dto'; -import { ScheduleDTO } from './create.schedule.dto'; -import { AddressRequestDTO } from './create.address.request'; +import { intToFrequency } from './validators/frequency.mapping'; +import { MarginDTO } from './margin.dto'; +import { ScheduleDTO } from './schedule.dto'; +import { AddressDTO } from './address.dto'; import { IsPunctualOrRecurrent } from './validators/decorators/is-punctual-or-recurrent.validator'; import { HasProperDriverSeats } from './validators/decorators/has-driver-seats.validator'; import { HasProperPassengerSeats } from './validators/decorators/has-passenger-seats.validator'; @@ -40,7 +40,7 @@ export class CreateAdRequest { @AutoMap() passenger?: boolean; - @Transform(({ value }) => mappingKeyToFrequency(value), { + @Transform(({ value }) => intToFrequency(value), { toClassOnly: true, }) @IsEnum(Frequency) @@ -98,9 +98,9 @@ export class CreateAdRequest { strict?: boolean; @ArrayMinSize(2) - @Type(() => AddressRequestDTO) + @Type(() => AddressDTO) @HasProperPositionIndexes() @ValidateNested({ each: true }) @AutoMap() - addresses: AddressRequestDTO[]; + addresses: AddressDTO[]; } diff --git a/src/modules/ad/domain/dtos/create.margin.dto.ts b/src/modules/ad/domain/dtos/margin.dto.ts similarity index 100% rename from src/modules/ad/domain/dtos/create.margin.dto.ts rename to src/modules/ad/domain/dtos/margin.dto.ts diff --git a/src/modules/ad/domain/dtos/create.schedule.dto.ts b/src/modules/ad/domain/dtos/schedule.dto.ts similarity index 100% rename from src/modules/ad/domain/dtos/create.schedule.dto.ts rename to src/modules/ad/domain/dtos/schedule.dto.ts diff --git a/src/modules/ad/domain/dtos/validators/address-position.ts b/src/modules/ad/domain/dtos/validators/address-position.ts index bbf8551..fe0cb0c 100644 --- a/src/modules/ad/domain/dtos/validators/address-position.ts +++ b/src/modules/ad/domain/dtos/validators/address-position.ts @@ -1,8 +1,8 @@ -import { AddressRequestDTO } from '../create.address.request'; +import { AddressDTO } from '../address.dto'; -export function hasProperPositionIndexes(value: AddressRequestDTO[]) { +export const hasProperPositionIndexes = (value: AddressDTO[]): boolean => { if (value.every((address) => address.position === undefined)) return true; - else if (value.every((address) => typeof address.position === 'number')) { + if (value.every((address) => typeof address.position === 'number')) { value.sort((a, b) => a.position - b.position); for (let i = 1; i < value.length; i++) { if (value[i - 1].position >= value[i].position) return false; @@ -10,4 +10,4 @@ export function hasProperPositionIndexes(value: AddressRequestDTO[]) { return true; } return false; -} +}; diff --git a/src/modules/ad/domain/dtos/validators/decorators/address-position.validator.ts b/src/modules/ad/domain/dtos/validators/decorators/address-position.validator.ts index 5ac8e5a..a21283e 100644 --- a/src/modules/ad/domain/dtos/validators/decorators/address-position.validator.ts +++ b/src/modules/ad/domain/dtos/validators/decorators/address-position.validator.ts @@ -1,16 +1,16 @@ import { ValidateBy, ValidationOptions, buildMessage } from 'class-validator'; -import { AddressRequestDTO } from '../../create.address.request'; +import { AddressDTO } from '../../address.dto'; import { hasProperPositionIndexes } from '../address-position'; -export function HasProperPositionIndexes( +export const HasProperPositionIndexes = ( validationOptions?: ValidationOptions, -): PropertyDecorator { - return ValidateBy( +): PropertyDecorator => + ValidateBy( { name: '', constraints: [], validator: { - validate: (value: AddressRequestDTO[]): boolean => + validate: (value: AddressDTO[]): boolean => hasProperPositionIndexes(value), defaultMessage: buildMessage( @@ -22,4 +22,3 @@ export function HasProperPositionIndexes( }, validationOptions, ); -} diff --git a/src/modules/ad/domain/dtos/validators/decorators/has-driver-seats.validator.ts b/src/modules/ad/domain/dtos/validators/decorators/has-driver-seats.validator.ts index fc12011..d1ba793 100644 --- a/src/modules/ad/domain/dtos/validators/decorators/has-driver-seats.validator.ts +++ b/src/modules/ad/domain/dtos/validators/decorators/has-driver-seats.validator.ts @@ -6,10 +6,10 @@ import { } from 'class-validator'; import { hasProperDriverSeats } from '../has-driver-seats'; -export function HasProperDriverSeats( +export const HasProperDriverSeats = ( validationOptions?: ValidationOptions, -): PropertyDecorator { - return ValidateBy( +): PropertyDecorator => + ValidateBy( { name: '', constraints: [], @@ -24,4 +24,3 @@ export function HasProperDriverSeats( }, validationOptions, ); -} diff --git a/src/modules/ad/domain/dtos/validators/decorators/has-passenger-seats.validator.ts b/src/modules/ad/domain/dtos/validators/decorators/has-passenger-seats.validator.ts index 82d4240..26dc5de 100644 --- a/src/modules/ad/domain/dtos/validators/decorators/has-passenger-seats.validator.ts +++ b/src/modules/ad/domain/dtos/validators/decorators/has-passenger-seats.validator.ts @@ -6,10 +6,10 @@ import { } from 'class-validator'; import { hasProperPassengerSeats } from '../has-passenger-seats'; -export function HasProperPassengerSeats( +export const HasProperPassengerSeats = ( validationOptions?: ValidationOptions, -): PropertyDecorator { - return ValidateBy( +): PropertyDecorator => + ValidateBy( { name: '', constraints: [], @@ -24,4 +24,3 @@ export function HasProperPassengerSeats( }, validationOptions, ); -} diff --git a/src/modules/ad/domain/dtos/validators/decorators/is-punctual-or-recurrent.validator.ts b/src/modules/ad/domain/dtos/validators/decorators/is-punctual-or-recurrent.validator.ts index d18a1a6..b9375b2 100644 --- a/src/modules/ad/domain/dtos/validators/decorators/is-punctual-or-recurrent.validator.ts +++ b/src/modules/ad/domain/dtos/validators/decorators/is-punctual-or-recurrent.validator.ts @@ -6,10 +6,10 @@ import { } from 'class-validator'; import { isPunctualOrRecurrent } from '../is-punctual-or-recurrent'; -export function IsPunctualOrRecurrent( +export const IsPunctualOrRecurrent = ( validationOptions?: ValidationOptions, -): PropertyDecorator { - return ValidateBy( +): PropertyDecorator => + ValidateBy( { name: '', constraints: [], @@ -18,11 +18,10 @@ export function IsPunctualOrRecurrent( isPunctualOrRecurrent(args), defaultMessage: buildMessage( () => - `the departure, from date, to date and schedule must be properly set on reccurent or punctual ad `, + `the departure, from date, to date and schedule must be properly set on reccurent or punctual ad`, validationOptions, ), }, }, validationOptions, ); -} diff --git a/src/modules/ad/domain/dtos/validators/frequency.mapping.ts b/src/modules/ad/domain/dtos/validators/frequency.mapping.ts index 3164960..030fa34 100644 --- a/src/modules/ad/domain/dtos/validators/frequency.mapping.ts +++ b/src/modules/ad/domain/dtos/validators/frequency.mapping.ts @@ -1,5 +1,6 @@ import { Frequency } from '../../types/frequency.enum'; -export const mappingKeyToFrequency = (index: number): Frequency => { + +export const intToFrequency = (index: number): Frequency => { if (index == 1) return Frequency.PUNCTUAL; if (index == 2) return Frequency.RECURRENT; return undefined; diff --git a/src/modules/ad/domain/dtos/validators/has-driver-seats.ts b/src/modules/ad/domain/dtos/validators/has-driver-seats.ts index aaef9c8..fb34229 100644 --- a/src/modules/ad/domain/dtos/validators/has-driver-seats.ts +++ b/src/modules/ad/domain/dtos/validators/has-driver-seats.ts @@ -1,6 +1,6 @@ import { ValidationArguments } from 'class-validator'; -export function hasProperDriverSeats(args: ValidationArguments) { +export const hasProperDriverSeats = (args: ValidationArguments): boolean => { if ( args.object['driver'] === true && typeof args.object['seatsDriver'] === 'number' @@ -16,4 +16,4 @@ export function hasProperDriverSeats(args: ValidationArguments) { ) return true; return false; -} +}; diff --git a/src/modules/ad/domain/dtos/validators/has-passenger-seats.ts b/src/modules/ad/domain/dtos/validators/has-passenger-seats.ts index 46b1dad..f96eeb9 100644 --- a/src/modules/ad/domain/dtos/validators/has-passenger-seats.ts +++ b/src/modules/ad/domain/dtos/validators/has-passenger-seats.ts @@ -1,12 +1,12 @@ import { ValidationArguments } from 'class-validator'; -export function hasProperPassengerSeats(args: ValidationArguments) { +export const hasProperPassengerSeats = (args: ValidationArguments): boolean => { if ( args.object['passenger'] === true && typeof args.object['seatsPassenger'] === 'number' ) return args.object['seatsPassenger'] > 0; - else if ( + if ( (args.object['passenger'] === false || args.object['passenger'] === null || args.object['passenger'] === undefined) && @@ -15,5 +15,5 @@ export function hasProperPassengerSeats(args: ValidationArguments) { args.object['seatsPassenger'] === undefined) ) return true; - else return false; -} + return false; +}; diff --git a/src/modules/ad/domain/dtos/validators/is-punctual-or-recurrent.ts b/src/modules/ad/domain/dtos/validators/is-punctual-or-recurrent.ts index 70bfef3..39124c5 100644 --- a/src/modules/ad/domain/dtos/validators/is-punctual-or-recurrent.ts +++ b/src/modules/ad/domain/dtos/validators/is-punctual-or-recurrent.ts @@ -1,27 +1,16 @@ import { ValidationArguments } from 'class-validator'; import { Frequency } from '../../types/frequency.enum'; -function isPunctual(args: ValidationArguments): boolean { - if ( - args.object['frequency'] === Frequency.PUNCTUAL && - args.object['departure'] instanceof Date && - !Object.keys(args.object['schedule']).length - ) - return true; - return false; -} +const isPunctual = (args: ValidationArguments): boolean => + args.object['frequency'] === Frequency.PUNCTUAL && + args.object['departure'] instanceof Date && + !Object.keys(args.object['schedule']).length; -function isRecurrent(args: ValidationArguments): boolean { - if ( - args.object['frequency'] === Frequency.RECURRENT && - args.object['fromDate'] instanceof Date && - args.object['toDate'] instanceof Date && - Object.keys(args.object['schedule']).length - ) - return true; - return false; -} +const isRecurrent = (args: ValidationArguments): boolean => + args.object['frequency'] === Frequency.RECURRENT && + args.object['fromDate'] instanceof Date && + args.object['toDate'] instanceof Date && + Object.keys(args.object['schedule']).length > 0; -export const isPunctualOrRecurrent = (args: ValidationArguments): boolean => { - return isPunctual(args) || isRecurrent(args); -}; +export const isPunctualOrRecurrent = (args: ValidationArguments): boolean => + isPunctual(args) || isRecurrent(args); diff --git a/src/modules/ad/domain/entities/ad.ts b/src/modules/ad/domain/entities/ad.ts index 865070d..d46e204 100644 --- a/src/modules/ad/domain/entities/ad.ts +++ b/src/modules/ad/domain/entities/ad.ts @@ -12,6 +12,7 @@ import { } from 'class-validator'; import { Address } from '../entities/address'; import { Frequency } from '../types/frequency.enum'; + export class Ad { @IsUUID(4) @AutoMap() diff --git a/src/modules/ad/domain/entities/frequency.normaliser.ts b/src/modules/ad/domain/entities/frequency.normaliser.ts new file mode 100644 index 0000000..95e8ebd --- /dev/null +++ b/src/modules/ad/domain/entities/frequency.normaliser.ts @@ -0,0 +1,35 @@ +import { CreateAdRequest } from '../dtos/create-ad.request'; +import { Day } from '../types/day.enum'; + +import { Frequency } from '../types/frequency.enum'; + +export class FrequencyNormaliser { + fromDateResolver(createAdRequest: CreateAdRequest): Date { + if (createAdRequest.frequency === Frequency.PUNCTUAL) + return createAdRequest.departure; + return createAdRequest.fromDate; + } + toDateResolver(createAdRequest: CreateAdRequest): Date { + if (createAdRequest.frequency === Frequency.PUNCTUAL) + return createAdRequest.departure; + return createAdRequest.toDate; + } + scheduleResolver = ( + createAdRequest: CreateAdRequest, + day: number, + ): string => { + if ( + Object.keys(createAdRequest.schedule).length === 0 && + createAdRequest.frequency == Frequency.PUNCTUAL && + createAdRequest.departure.getDay() === day + ) + return `${createAdRequest.departure + .getHours() + .toString() + .padStart(2, '0')}:${createAdRequest.departure + .getMinutes() + .toString() + .padStart(2, '0')}`; + return createAdRequest.schedule[Day[day]]; + }; +} diff --git a/src/modules/ad/domain/entities/recurrent-normaliser.ts b/src/modules/ad/domain/entities/recurrent-normaliser.ts deleted file mode 100644 index f51dfd3..0000000 --- a/src/modules/ad/domain/entities/recurrent-normaliser.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { CreateAdRequest } from '../dtos/create-ad.request'; - -import { Frequency } from '../types/frequency.enum'; - -export class RecurrentNormaliser { - fromDateResolver(createAdRequest: CreateAdRequest): Date { - if (createAdRequest.frequency === Frequency.PUNCTUAL) - return createAdRequest.departure; - return createAdRequest.fromDate; - } - toDateResolver(createAdRequest: CreateAdRequest): Date { - if (createAdRequest.frequency === Frequency.PUNCTUAL) - return createAdRequest.departure; - return createAdRequest.toDate; - } - scheduleSunResolver(createAdRequest: CreateAdRequest): string { - if ( - Object.keys(createAdRequest.schedule).length === 0 && - createAdRequest.frequency == Frequency.PUNCTUAL && - createAdRequest.departure.getDay() === 0 - ) - return `${('0' + createAdRequest.departure.getHours()).slice(-2)}:${( - '0' + createAdRequest.departure.getMinutes() - ).slice(-2)}`; - return createAdRequest.schedule.sun; - } - scheduleMonResolver(createAdRequest: CreateAdRequest): string { - if ( - Object.keys(createAdRequest.schedule).length === 0 && - createAdRequest.frequency == Frequency.PUNCTUAL && - createAdRequest.departure.getDay() === 1 - ) { - return `${('0' + createAdRequest.departure.getHours()).slice(-2)}:${( - '0' + createAdRequest.departure.getMinutes() - ).slice(-2)}`; - } - - return createAdRequest.schedule.mon; - } - scheduleTueResolver(createAdRequest: CreateAdRequest): string { - if ( - Object.keys(createAdRequest.schedule).length === 0 && - createAdRequest.frequency == Frequency.PUNCTUAL && - createAdRequest.departure.getDay() === 2 - ) - return `${('0' + createAdRequest.departure.getHours()).slice(-2)}:${( - '0' + createAdRequest.departure.getMinutes() - ).slice(-2)}`; - return createAdRequest.schedule.tue; - } - scheduleWedResolver(createAdRequest: CreateAdRequest): string { - if ( - Object.keys(createAdRequest.schedule).length === 0 && - createAdRequest.frequency == Frequency.PUNCTUAL && - createAdRequest.departure.getDay() === 3 - ) - return `${('0' + createAdRequest.departure.getHours()).slice(-2)}:${( - '0' + createAdRequest.departure.getMinutes() - ).slice(-2)}`; - return createAdRequest.schedule.wed; - } - scheduleThuResolver(createAdRequest: CreateAdRequest): string { - if ( - Object.keys(createAdRequest.schedule).length === 0 && - createAdRequest.frequency == Frequency.PUNCTUAL && - createAdRequest.departure.getDay() === 4 - ) - return `${('0' + createAdRequest.departure.getHours()).slice(-2)}:${( - '0' + createAdRequest.departure.getMinutes() - ).slice(-2)}`; - return createAdRequest.schedule.thu; - } - scheduleFriResolver(createAdRequest: CreateAdRequest): string { - if ( - Object.keys(createAdRequest.schedule).length === 0 && - createAdRequest.frequency == Frequency.PUNCTUAL && - createAdRequest.departure.getDay() === 5 - ) - return `${('0' + createAdRequest.departure.getHours()).slice(-2)}:${( - '0' + createAdRequest.departure.getMinutes() - ).slice(-2)}`; - return createAdRequest.schedule.fri; - } - scheduleSatResolver(createAdRequest: CreateAdRequest): string { - if ( - Object.keys(createAdRequest.schedule).length === 0 && - createAdRequest.frequency == Frequency.PUNCTUAL && - createAdRequest.departure.getDay() === 6 - ) - return `${('0' + createAdRequest.departure.getHours()).slice(-2)}:${( - '0' + createAdRequest.departure.getMinutes() - ).slice(-2)}`; - return createAdRequest.schedule.sat; - } -} diff --git a/src/modules/ad/domain/types/day.enum.ts b/src/modules/ad/domain/types/day.enum.ts new file mode 100644 index 0000000..5a7f7f3 --- /dev/null +++ b/src/modules/ad/domain/types/day.enum.ts @@ -0,0 +1,9 @@ +export enum Day { + sun = 0, + mon, + tue, + wed, + thu, + fri, + sat, +} diff --git a/src/modules/ad/domain/usecases/create-ad.usecase.ts b/src/modules/ad/domain/usecases/create-ad.usecase.ts index b5731da..ea30327 100644 --- a/src/modules/ad/domain/usecases/create-ad.usecase.ts +++ b/src/modules/ad/domain/usecases/create-ad.usecase.ts @@ -6,7 +6,6 @@ import { Messager } from '../../adapters/secondaries/messager'; import { AdsRepository } from '../../adapters/secondaries/ads.repository'; import { CreateAdCommand } from '../../commands/create-ad.command'; import { CreateAdRequest } from '../dtos/create-ad.request'; - import { IProvideParams } from '../interfaces/param-provider.interface'; import { DefaultParams } from '../types/default-params.type'; import { AdCreation } from '../dtos/ad.creation'; @@ -17,9 +16,9 @@ export class CreateAdUseCase { private readonly defaultParams: DefaultParams; private ad: AdCreation; constructor( - private readonly _repository: AdsRepository, - private readonly _messager: Messager, - @InjectMapper() private readonly _mapper: Mapper, + private readonly repository: AdsRepository, + private readonly messager: Messager, + @InjectMapper() private readonly mapper: Mapper, @Inject('ParamsProvider') private readonly defaultParamsProvider: IProvideParams, ) { @@ -27,7 +26,7 @@ export class CreateAdUseCase { } async execute(command: CreateAdCommand): Promise { - this.ad = this._mapper.map( + this.ad = this.mapper.map( command.createAdRequest, CreateAdRequest, AdCreation, @@ -35,12 +34,12 @@ export class CreateAdUseCase { this.setDefaultSchedule(); this.setDefaultAddressesPosition(); this.setDefaultDriverAndPassengerParameters(); - this.setDefaultDistanceMargin(); + this.setDefaultStrict(); try { - const adCreated: Ad = await this._repository.create(this.ad); - this._messager.publish('ad.create', JSON.stringify(adCreated)); - this._messager.publish( + const adCreated: Ad = await this.repository.create(this.ad); + this.messager.publish('ad.create', JSON.stringify(adCreated)); + this.messager.publish( 'logging.ad.create.info', JSON.stringify(adCreated), ); @@ -50,7 +49,7 @@ export class CreateAdUseCase { if (error.message.includes('Already exists')) { key = 'logging.ad.create.warning'; } - this._messager.publish( + this.messager.publish( key, JSON.stringify({ command, @@ -60,7 +59,8 @@ export class CreateAdUseCase { throw error; } } - setDefaultSchedule(): void { + + private setDefaultSchedule = (): void => { if (this.ad.monMargin === undefined) this.ad.monMargin = this.defaultParams.MON_MARGIN; if (this.ad.tueMargin === undefined) @@ -75,12 +75,14 @@ export class CreateAdUseCase { this.ad.satMargin = this.defaultParams.SAT_MARGIN; if (this.ad.sunMargin === undefined) this.ad.sunMargin = this.defaultParams.SUN_MARGIN; - } - setDefaultDistanceMargin(): void { + }; + + private setDefaultStrict = (): void => { if (this.ad.strict === undefined) this.ad.strict = this.defaultParams.STRICT; - } - setDefaultDriverAndPassengerParameters(): void { + }; + + private setDefaultDriverAndPassengerParameters = (): void => { if (!this.ad.driver && !this.ad.passenger) { this.ad.driver = this.defaultParams.DRIVER; this.ad.seatsDriver = this.defaultParams.SEATS_PROVIDED; @@ -96,12 +98,13 @@ export class CreateAdUseCase { this.ad.seatsPassenger = 0; } } - } - setDefaultAddressesPosition(): void { + }; + + private 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; } } - } + }; } diff --git a/src/modules/ad/mappers/ad.profile.ts b/src/modules/ad/mappers/ad.profile.ts index c4de6e4..96a2f2b 100644 --- a/src/modules/ad/mappers/ad.profile.ts +++ b/src/modules/ad/mappers/ad.profile.ts @@ -5,11 +5,12 @@ import { Ad } from '../domain/entities/ad'; import { AdPresenter } from '../adapters/primaries/ad.presenter'; import { CreateAdRequest } from '../domain/dtos/create-ad.request'; import { AdCreation } from '../domain/dtos/ad.creation'; -import { RecurrentNormaliser } from '../domain/entities/recurrent-normaliser'; +import { FrequencyNormaliser } from '../domain/entities/frequency.normaliser'; +import { Day } from '../domain/types/day.enum'; @Injectable() export class AdProfile extends AutomapperProfile { - recurrentNormaliser = new RecurrentNormaliser(); + frequencyNormaliser = new FrequencyNormaliser(); constructor(@InjectMapper() mapper: Mapper) { super(mapper); } @@ -84,53 +85,53 @@ export class AdProfile extends AutomapperProfile { forMember( (destination) => destination.fromDate, mapFrom((source) => - this.recurrentNormaliser.fromDateResolver(source), + this.frequencyNormaliser.fromDateResolver(source), ), ), forMember( (destination) => destination.toDate, - mapFrom((source) => this.recurrentNormaliser.toDateResolver(source)), + mapFrom((source) => this.frequencyNormaliser.toDateResolver(source)), ), forMember( (destination) => destination.monTime, mapFrom((source) => - this.recurrentNormaliser.scheduleMonResolver(source), + this.frequencyNormaliser.scheduleResolver(source, Day.mon), ), ), forMember( (destination) => destination.tueTime, mapFrom((source) => - this.recurrentNormaliser.scheduleTueResolver(source), + this.frequencyNormaliser.scheduleResolver(source, Day.tue), ), ), forMember( (destination) => destination.wedTime, mapFrom((source) => - this.recurrentNormaliser.scheduleWedResolver(source), + this.frequencyNormaliser.scheduleResolver(source, Day.wed), ), ), forMember( (destination) => destination.thuTime, mapFrom((source) => - this.recurrentNormaliser.scheduleThuResolver(source), + this.frequencyNormaliser.scheduleResolver(source, Day.thu), ), ), forMember( (destination) => destination.friTime, mapFrom((source) => - this.recurrentNormaliser.scheduleFriResolver(source), + this.frequencyNormaliser.scheduleResolver(source, Day.fri), ), ), forMember( (destination) => destination.satTime, mapFrom((source) => - this.recurrentNormaliser.scheduleSatResolver(source), + this.frequencyNormaliser.scheduleResolver(source, Day.sat), ), ), forMember( (destination) => destination.sunTime, mapFrom((source) => - this.recurrentNormaliser.scheduleSunResolver(source), + this.frequencyNormaliser.scheduleResolver(source, Day.sun), ), ), ); diff --git a/src/modules/ad/mappers/address.profile.ts b/src/modules/ad/mappers/address.profile.ts index 12def6e..09fa720 100644 --- a/src/modules/ad/mappers/address.profile.ts +++ b/src/modules/ad/mappers/address.profile.ts @@ -1,7 +1,7 @@ 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 { AddressDTO } from '../domain/dtos/address.dto'; import { Address } from '../domain/entities/address'; @Injectable() @@ -12,7 +12,7 @@ export class AdProfile extends AutomapperProfile { override get profile() { return (mapper) => { - createMap(mapper, AddressRequestDTO, Address); + createMap(mapper, AddressDTO, Address); }; } } diff --git a/src/modules/ad/tests/unit/domain/create-ad.usecase.spec.ts b/src/modules/ad/tests/unit/domain/create-ad.usecase.spec.ts index 83c994a..0e31ee6 100644 --- a/src/modules/ad/tests/unit/domain/create-ad.usecase.spec.ts +++ b/src/modules/ad/tests/unit/domain/create-ad.usecase.spec.ts @@ -9,11 +9,11 @@ import { classes } from '@automapper/classes'; import { Frequency } from '../../../domain/types/frequency.enum'; import { Ad } from '../../../domain/entities/ad'; import { AdProfile } from '../../../mappers/ad.profile'; -import { AddressRequestDTO } from '../../../domain/dtos/create.address.request'; +import { AddressDTO } from '../../../domain/dtos/address.dto'; import { AdCreation } from '../../../domain/dtos/ad.creation'; import { Address } from 'src/modules/ad/domain/entities/address'; -const mockAddress1: AddressRequestDTO = { +const mockAddress1: AddressDTO = { position: 0, lon: 48.68944505415954, lat: 6.176510296462267, @@ -23,7 +23,7 @@ const mockAddress1: AddressRequestDTO = { postalCode: '54000', country: 'France', }; -const mockAddress2: AddressRequestDTO = { +const mockAddress2: AddressDTO = { position: 1, lon: 48.8566, lat: 2.3522, @@ -31,14 +31,14 @@ const mockAddress2: AddressRequestDTO = { postalCode: '75000', country: 'France', }; -const mockAddressWithoutPos1: AddressRequestDTO = { +const mockAddressWithoutPos1: AddressDTO = { lon: 43.2965, lat: 5.3698, locality: 'Marseille', postalCode: '13000', country: 'France', }; -const mockAddressWithoutPos2: AddressRequestDTO = { +const mockAddressWithoutPos2: AddressDTO = { lon: 43.7102, lat: 7.262, locality: 'Nice', diff --git a/src/modules/ad/tests/unit/domain/frequency.mapping.spec.ts b/src/modules/ad/tests/unit/domain/frequency.mapping.spec.ts index ef5a72b..0df3372 100644 --- a/src/modules/ad/tests/unit/domain/frequency.mapping.spec.ts +++ b/src/modules/ad/tests/unit/domain/frequency.mapping.spec.ts @@ -1,15 +1,15 @@ -import { mappingKeyToFrequency } from '../../../domain/dtos/validators/frequency.mapping'; +import { intToFrequency } from '../../../domain/dtos/validators/frequency.mapping'; import { Frequency } from '../../../domain/types/frequency.enum'; describe('frequency mapping function ', () => { it('should return punctual', () => { - expect(mappingKeyToFrequency(1)).toBe(Frequency.PUNCTUAL); + expect(intToFrequency(1)).toBe(Frequency.PUNCTUAL); }); it('should return recurent', () => { - expect(mappingKeyToFrequency(2)).toBe(Frequency.RECURRENT); + expect(intToFrequency(2)).toBe(Frequency.RECURRENT); }); it('should return undefined', () => { - expect(mappingKeyToFrequency(0)).toBeUndefined(); - expect(mappingKeyToFrequency(3)).toBeUndefined(); + expect(intToFrequency(0)).toBeUndefined(); + expect(intToFrequency(3)).toBeUndefined(); }); }); diff --git a/src/modules/ad/tests/unit/domain/has-proper-addresses-indexes.spec.ts b/src/modules/ad/tests/unit/domain/has-proper-addresses-indexes.spec.ts index 6785548..4a84a5e 100644 --- a/src/modules/ad/tests/unit/domain/has-proper-addresses-indexes.spec.ts +++ b/src/modules/ad/tests/unit/domain/has-proper-addresses-indexes.spec.ts @@ -1,7 +1,7 @@ -import { AddressRequestDTO } from '../../../domain/dtos/create.address.request'; +import { AddressDTO } from '../../../domain/dtos/address.dto'; import { hasProperPositionIndexes } from '../../../domain/dtos/validators/address-position'; describe('addresses position validators', () => { - const mockAddress1: AddressRequestDTO = { + const mockAddress1: AddressDTO = { lon: 48.68944505415954, lat: 6.176510296462267, houseNumber: '5', @@ -10,7 +10,7 @@ describe('addresses position validators', () => { postalCode: '54000', country: 'France', }; - const mockAddress2: AddressRequestDTO = { + const mockAddress2: AddressDTO = { lon: 48.8566, lat: 2.3522, locality: 'Paris', @@ -18,7 +18,7 @@ describe('addresses position validators', () => { country: 'France', }; - const mockAddress3: AddressRequestDTO = { + const mockAddress3: AddressDTO = { lon: 49.2628, lat: 4.0347, locality: 'Reims', diff --git a/src/modules/ad/tests/unit/domain/recurrent-normaliser.spec.ts b/src/modules/ad/tests/unit/domain/recurrent-normaliser.spec.ts index f9cc3f0..a411b2b 100644 --- a/src/modules/ad/tests/unit/domain/recurrent-normaliser.spec.ts +++ b/src/modules/ad/tests/unit/domain/recurrent-normaliser.spec.ts @@ -1,9 +1,11 @@ +import { Day } from '../../../domain/types/day.enum'; import { CreateAdRequest } from '../../../domain/dtos/create-ad.request'; -import { ScheduleDTO } from '../../../domain/dtos/create.schedule.dto'; -import { RecurrentNormaliser } from '../../../domain/entities/recurrent-normaliser'; +import { ScheduleDTO } from '../../../domain/dtos/schedule.dto'; +import { FrequencyNormaliser } from '../../../domain/entities/frequency.normaliser'; import { Frequency } from '../../../domain/types/frequency.enum'; + describe('recurrent normalizer transformer for punctual ad ', () => { - const recurrentNormaliser = new RecurrentNormaliser(); + const recurrentNormaliser = new FrequencyNormaliser(); it('should transform punctual ad into recurrent ad ', () => { const punctualAd: CreateAdRequest = { userUuid: '', @@ -18,13 +20,27 @@ describe('recurrent normalizer transformer for punctual ad ', () => { expect(recurrentNormaliser.toDateResolver(punctualAd)).toBe( punctualAd.departure, ); - expect(recurrentNormaliser.scheduleMonResolver(punctualAd)).toBeUndefined(); - expect(recurrentNormaliser.scheduleTueResolver(punctualAd)).toBeUndefined(); - expect(recurrentNormaliser.scheduleWedResolver(punctualAd)).toBe('12:39'); - expect(recurrentNormaliser.scheduleThuResolver(punctualAd)).toBeUndefined(); - expect(recurrentNormaliser.scheduleFriResolver(punctualAd)).toBeUndefined(); - expect(recurrentNormaliser.scheduleSatResolver(punctualAd)).toBeUndefined(); - expect(recurrentNormaliser.scheduleSunResolver(punctualAd)).toBeUndefined(); + expect( + recurrentNormaliser.scheduleResolver(punctualAd, Day.mon), + ).toBeUndefined(); + expect( + recurrentNormaliser.scheduleResolver(punctualAd, Day.tue), + ).toBeUndefined(); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.wed)).toBe( + '12:39', + ); + expect( + recurrentNormaliser.scheduleResolver(punctualAd, Day.thu), + ).toBeUndefined(); + expect( + recurrentNormaliser.scheduleResolver(punctualAd, Day.fri), + ).toBeUndefined(); + expect( + recurrentNormaliser.scheduleResolver(punctualAd, Day.sat), + ).toBeUndefined(); + expect( + recurrentNormaliser.scheduleResolver(punctualAd, Day.sun), + ).toBeUndefined(); }); it('should leave recurrent ad as is', () => { const recurrentAd: CreateAdRequest = { @@ -44,25 +60,25 @@ describe('recurrent normalizer transformer for punctual ad ', () => { expect(recurrentNormaliser.toDateResolver(recurrentAd)).toBe( recurrentAd.departure, ); - expect(recurrentNormaliser.scheduleMonResolver(recurrentAd)).toBe( + expect(recurrentNormaliser.scheduleResolver(recurrentAd, Day.mon)).toBe( recurrentAd.schedule.mon, ); - expect(recurrentNormaliser.scheduleTueResolver(recurrentAd)).toBe( + expect(recurrentNormaliser.scheduleResolver(recurrentAd, Day.tue)).toBe( recurrentAd.schedule.tue, ); - expect(recurrentNormaliser.scheduleWedResolver(recurrentAd)).toBe( + expect(recurrentNormaliser.scheduleResolver(recurrentAd, Day.wed)).toBe( recurrentAd.schedule.wed, ); - expect(recurrentNormaliser.scheduleThuResolver(recurrentAd)).toBe( + expect(recurrentNormaliser.scheduleResolver(recurrentAd, Day.thu)).toBe( recurrentAd.schedule.thu, ); - expect(recurrentNormaliser.scheduleFriResolver(recurrentAd)).toBe( + expect(recurrentNormaliser.scheduleResolver(recurrentAd, Day.fri)).toBe( recurrentAd.schedule.fri, ); - expect(recurrentNormaliser.scheduleSatResolver(recurrentAd)).toBe( + expect(recurrentNormaliser.scheduleResolver(recurrentAd, Day.sat)).toBe( recurrentAd.schedule.sat, ); - expect(recurrentNormaliser.scheduleSunResolver(recurrentAd)).toBe( + expect(recurrentNormaliser.scheduleResolver(recurrentAd, Day.sun)).toBe( recurrentAd.schedule.sun, ); }); @@ -75,18 +91,32 @@ describe('recurrent normalizer transformer for punctual ad ', () => { addresses: [], }; punctualAd.departure = new Date('05-01-2023 '); - expect(recurrentNormaliser.scheduleMonResolver(punctualAd)).toBe('00:00'); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.mon)).toBe( + '00:00', + ); punctualAd.departure = new Date('05-02-2023 06:32:45'); - expect(recurrentNormaliser.scheduleTueResolver(punctualAd)).toBe('06:32'); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.tue)).toBe( + '06:32', + ); punctualAd.departure = new Date('05-03-2023 10:21'); - expect(recurrentNormaliser.scheduleWedResolver(punctualAd)).toBe('10:21'); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.wed)).toBe( + '10:21', + ); punctualAd.departure = new Date('05-04-2023 11:06:00'); - expect(recurrentNormaliser.scheduleThuResolver(punctualAd)).toBe('11:06'); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.thu)).toBe( + '11:06', + ); punctualAd.departure = new Date('05-05-2023 05:20'); - expect(recurrentNormaliser.scheduleFriResolver(punctualAd)).toBe('05:20'); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.fri)).toBe( + '05:20', + ); punctualAd.departure = new Date('05-06-2023'); - expect(recurrentNormaliser.scheduleSatResolver(punctualAd)).toBe('00:00'); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.sat)).toBe( + '00:00', + ); punctualAd.departure = new Date('05-07-2023'); - expect(recurrentNormaliser.scheduleSunResolver(punctualAd)).toBe('00:00'); + expect(recurrentNormaliser.scheduleResolver(punctualAd, Day.sun)).toBe( + '00:00', + ); }); });