Merge branch 'createAD' into 'main'
feat : ad creation to the service See merge request v3/service/ad!3
This commit is contained in:
commit
954962d072
13
.env.dist
13
.env.dist
|
@ -15,3 +15,16 @@ RMQ_EXCHANGE=mobicoop
|
||||||
REDIS_HOST=v3-redis
|
REDIS_HOST=v3-redis
|
||||||
REDIS_PASSWORD=redis
|
REDIS_PASSWORD=redis
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
# DEFAULT CARPOOL DEPARTURE MARGIN (in seconds)
|
||||||
|
DEPARTURE_MARGIN=900
|
||||||
|
|
||||||
|
# DEFAULT ROLE
|
||||||
|
ROLE=passenger
|
||||||
|
|
||||||
|
# SEATS PROVIDED AS DRIVER / REQUESTED AS PASSENGER
|
||||||
|
SEATS_PROVIDED=3
|
||||||
|
SEATS_REQUESTED=1
|
||||||
|
|
||||||
|
# ACCEPT ONLY SAME FREQUENCY REQUESTS
|
||||||
|
STRICT_FREQUENCY=false
|
|
@ -0,0 +1,8 @@
|
||||||
|
# SERVICE
|
||||||
|
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"
|
|
@ -26,6 +26,7 @@
|
||||||
"@prisma/client": "^4.13.0",
|
"@prisma/client": "^4.13.0",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
|
"dotenv-cli": "^7.2.1",
|
||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.2.0"
|
"rxjs": "^7.2.0"
|
||||||
|
@ -3841,7 +3842,6 @@
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"path-key": "^3.1.0",
|
"path-key": "^3.1.0",
|
||||||
"shebang-command": "^2.0.0",
|
"shebang-command": "^2.0.0",
|
||||||
|
@ -4003,6 +4003,20 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dotenv-cli": {
|
||||||
|
"version": "7.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.2.1.tgz",
|
||||||
|
"integrity": "sha512-ODHbGTskqRtXAzZapDPvgNuDVQApu4oKX8lZW7Y0+9hKA6le1ZJlyRS687oU9FXjOVEDU/VFV6zI125HzhM1UQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"cross-spawn": "^7.0.3",
|
||||||
|
"dotenv": "^16.0.0",
|
||||||
|
"dotenv-expand": "^10.0.0",
|
||||||
|
"minimist": "^1.2.6"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"dotenv": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dotenv-expand": {
|
"node_modules/dotenv-expand": {
|
||||||
"version": "10.0.0",
|
"version": "10.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz",
|
||||||
|
@ -5354,8 +5368,7 @@
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"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": {
|
"node_modules/istanbul-lib-coverage": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
|
@ -6798,7 +6811,6 @@
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
|
@ -7657,7 +7669,6 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"shebang-regex": "^3.0.0"
|
"shebang-regex": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
@ -7669,7 +7680,6 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
|
@ -8626,7 +8636,6 @@
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,13 +19,16 @@
|
||||||
"pretty": "./node_modules/.bin/prettier --write .",
|
"pretty": "./node_modules/.bin/prettier --write .",
|
||||||
"test": "npm run migrate:test && dotenv -e .env.test jest",
|
"test": "npm run migrate:test && dotenv -e .env.test jest",
|
||||||
"test:unit": "jest --testPathPattern 'tests/unit/' --verbose",
|
"test:unit": "jest --testPathPattern 'tests/unit/' --verbose",
|
||||||
|
"test:unit:watch": "jest --testPathPattern 'tests/unit/' --verbose --watch",
|
||||||
"test:unit:ci": "jest --testPathPattern 'tests/unit/' --coverage",
|
"test:unit:ci": "jest --testPathPattern 'tests/unit/' --coverage",
|
||||||
"test:integration": "npm run migrate:test && dotenv -e .env.test -- jest --testPathPattern 'tests/integration/' --verbose",
|
"test:integration": "npm run migrate:test && dotenv -e .env.test -- jest --testPathPattern 'tests/integration/' --verbose",
|
||||||
|
"test:integration:watch": "npm run migrate:test && dotenv -e .env.test -- jest --testPathPattern 'tests/integration/' --verbose --watch",
|
||||||
"test:integration:ci": "npm run migrate:test:ci && dotenv -e ci/.env.ci -- jest --testPathPattern 'tests/integration/'",
|
"test:integration:ci": "npm run migrate:test:ci && dotenv -e ci/.env.ci -- jest --testPathPattern 'tests/integration/'",
|
||||||
"test:cov": "jest --testPathPattern 'tests/unit/' --coverage",
|
"test:cov": "jest --testPathPattern 'tests/unit/' --coverage",
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||||
"generate": "docker exec v3-ad-api sh -c 'npx prisma generate'",
|
"generate": "docker exec v3-ad-api sh -c 'npx prisma generate'",
|
||||||
"migrate": "docker exec v3-ad-api sh -c 'npx prisma migrate dev'",
|
"migrate": "docker exec v3-ad-api sh -c 'npx prisma migrate dev'",
|
||||||
|
"migrate:init": "docker exec v3-ad-api sh -c 'npx prisma migrate dev --name init'",
|
||||||
"migrate:test": "dotenv -e .env.test -- npx prisma migrate deploy",
|
"migrate:test": "dotenv -e .env.test -- npx prisma migrate deploy",
|
||||||
"migrate:test:ci": "dotenv -e ci/.env.ci -- npx prisma migrate deploy",
|
"migrate:test:ci": "dotenv -e ci/.env.ci -- npx prisma migrate deploy",
|
||||||
"migrate:deploy": "npx prisma migrate deploy"
|
"migrate:deploy": "npx prisma migrate deploy"
|
||||||
|
@ -48,6 +51,7 @@
|
||||||
"@prisma/client": "^4.13.0",
|
"@prisma/client": "^4.13.0",
|
||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"class-validator": "^0.14.0",
|
"class-validator": "^0.14.0",
|
||||||
|
"dotenv-cli": "^7.2.1",
|
||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rxjs": "^7.2.0"
|
"rxjs": "^7.2.0"
|
||||||
|
@ -100,6 +104,7 @@
|
||||||
"**/*.(t|j)s"
|
"**/*.(t|j)s"
|
||||||
],
|
],
|
||||||
"coveragePathIgnorePatterns": [
|
"coveragePathIgnorePatterns": [
|
||||||
|
".validator.ts",
|
||||||
".controller.ts",
|
".controller.ts",
|
||||||
".module.ts",
|
".module.ts",
|
||||||
".request.ts",
|
".request.ts",
|
||||||
|
|
|
@ -1,34 +1,32 @@
|
||||||
-- CreateEnum
|
-- CreateEnum
|
||||||
CREATE TYPE "Frequency" AS ENUM ('PUNCTUAL', 'RECURRENT');
|
CREATE TYPE "Frequency" AS ENUM ('PUNCTUAL', 'RECURRENT');
|
||||||
|
|
||||||
-- CreateEnum
|
|
||||||
CREATE TYPE "AddressType" AS ENUM ('HOUSE_NUMBER', 'STREET_ADDRESS', 'LOCALITY', 'VENUE', 'OTHER');
|
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "ad" (
|
CREATE TABLE "ad" (
|
||||||
"uuid" UUID NOT NULL,
|
"uuid" UUID NOT NULL,
|
||||||
"userUuid" UUID NOT NULL,
|
"userUuid" UUID NOT NULL,
|
||||||
"driver" BOOLEAN,
|
"driver" BOOLEAN NOT NULL,
|
||||||
"passenger" BOOLEAN,
|
"passenger" BOOLEAN NOT NULL,
|
||||||
"frequency" "Frequency" NOT NULL DEFAULT 'RECURRENT',
|
"frequency" "Frequency" NOT NULL,
|
||||||
"fromDate" DATE NOT NULL,
|
"fromDate" DATE NOT NULL,
|
||||||
"toDate" DATE,
|
"toDate" DATE NOT NULL,
|
||||||
"monTime" TIMESTAMPTZ,
|
"monTime" TEXT,
|
||||||
"tueTime" TIMESTAMPTZ,
|
"tueTime" TEXT,
|
||||||
"wedTime" TIMESTAMPTZ,
|
"wedTime" TEXT,
|
||||||
"thuTime" TIMESTAMPTZ,
|
"thuTime" TEXT,
|
||||||
"friTime" TIMESTAMPTZ,
|
"friTime" TEXT,
|
||||||
"satTime" TIMESTAMPTZ,
|
"satTime" TEXT,
|
||||||
"sunTime" TIMESTAMPTZ,
|
"sunTime" TEXT,
|
||||||
"monMargin" INTEGER,
|
"monMargin" INTEGER NOT NULL,
|
||||||
"tueMargin" INTEGER,
|
"tueMargin" INTEGER NOT NULL,
|
||||||
"wedMargin" INTEGER,
|
"wedMargin" INTEGER NOT NULL,
|
||||||
"thuMargin" INTEGER,
|
"thuMargin" INTEGER NOT NULL,
|
||||||
"friMargin" INTEGER,
|
"friMargin" INTEGER NOT NULL,
|
||||||
"satMargin" INTEGER,
|
"satMargin" INTEGER NOT NULL,
|
||||||
"sunMargin" INTEGER,
|
"sunMargin" INTEGER NOT NULL,
|
||||||
"seatsDriver" SMALLINT,
|
"seatsDriver" SMALLINT NOT NULL,
|
||||||
"seatsPassenger" SMALLINT,
|
"seatsPassenger" SMALLINT NOT NULL,
|
||||||
|
"strict" BOOLEAN NOT NULL,
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
@ -42,29 +40,17 @@ CREATE TABLE "address" (
|
||||||
"position" SMALLINT NOT NULL,
|
"position" SMALLINT NOT NULL,
|
||||||
"lon" DOUBLE PRECISION NOT NULL,
|
"lon" DOUBLE PRECISION NOT NULL,
|
||||||
"lat" DOUBLE PRECISION NOT NULL,
|
"lat" DOUBLE PRECISION NOT NULL,
|
||||||
|
"name" TEXT,
|
||||||
"houseNumber" TEXT,
|
"houseNumber" TEXT,
|
||||||
"street" TEXT,
|
"street" TEXT,
|
||||||
"locality" TEXT,
|
"locality" TEXT,
|
||||||
"postalCode" TEXT,
|
"postalCode" TEXT,
|
||||||
"country" TEXT,
|
"country" TEXT NOT NULL,
|
||||||
"type" "AddressType" DEFAULT 'OTHER',
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
CONSTRAINT "address_pkey" PRIMARY KEY ("uuid")
|
CONSTRAINT "address_pkey" PRIMARY KEY ("uuid")
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "ad_driver_idx" ON "ad"("driver");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "ad_passenger_idx" ON "ad"("passenger");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "ad_fromDate_idx" ON "ad"("fromDate");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "ad_toDate_idx" ON "ad"("toDate");
|
|
||||||
|
|
||||||
-- AddForeignKey
|
-- AddForeignKey
|
||||||
ALTER TABLE "address" ADD CONSTRAINT "address_adUuid_fkey" FOREIGN KEY ("adUuid") REFERENCES "ad"("uuid") ON DELETE CASCADE ON UPDATE CASCADE;
|
ALTER TABLE "address" ADD CONSTRAINT "address_adUuid_fkey" FOREIGN KEY ("adUuid") REFERENCES "ad"("uuid") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -13,35 +13,32 @@ datasource db {
|
||||||
model Ad {
|
model Ad {
|
||||||
uuid String @id @default(uuid()) @db.Uuid
|
uuid String @id @default(uuid()) @db.Uuid
|
||||||
userUuid String @db.Uuid
|
userUuid String @db.Uuid
|
||||||
driver Boolean?
|
driver Boolean
|
||||||
passenger Boolean?
|
passenger Boolean
|
||||||
frequency Frequency @default(RECURRENT)
|
frequency Frequency
|
||||||
fromDate DateTime @db.Date
|
fromDate DateTime @db.Date
|
||||||
toDate DateTime? @db.Date
|
toDate DateTime @db.Date
|
||||||
monTime DateTime? @db.Timestamptz()
|
monTime String?
|
||||||
tueTime DateTime? @db.Timestamptz()
|
tueTime String?
|
||||||
wedTime DateTime? @db.Timestamptz()
|
wedTime String?
|
||||||
thuTime DateTime? @db.Timestamptz()
|
thuTime String?
|
||||||
friTime DateTime? @db.Timestamptz()
|
friTime String?
|
||||||
satTime DateTime? @db.Timestamptz()
|
satTime String?
|
||||||
sunTime DateTime? @db.Timestamptz()
|
sunTime String?
|
||||||
monMargin Int?
|
monMargin Int
|
||||||
tueMargin Int?
|
tueMargin Int
|
||||||
wedMargin Int?
|
wedMargin Int
|
||||||
thuMargin Int?
|
thuMargin Int
|
||||||
friMargin Int?
|
friMargin Int
|
||||||
satMargin Int?
|
satMargin Int
|
||||||
sunMargin Int?
|
sunMargin Int
|
||||||
seatsDriver Int? @db.SmallInt
|
seatsDriver Int @db.SmallInt
|
||||||
seatsPassenger Int? @db.SmallInt
|
seatsPassenger Int @db.SmallInt
|
||||||
|
strict Boolean
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @default(now()) @updatedAt
|
updatedAt DateTime @default(now()) @updatedAt
|
||||||
addresses Address[]
|
addresses Address[]
|
||||||
|
|
||||||
@@index([driver])
|
|
||||||
@@index([passenger])
|
|
||||||
@@index([fromDate])
|
|
||||||
@@index([toDate])
|
|
||||||
@@map("ad")
|
@@map("ad")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,12 +48,12 @@ model Address {
|
||||||
position Int @db.SmallInt
|
position Int @db.SmallInt
|
||||||
lon Float
|
lon Float
|
||||||
lat Float
|
lat Float
|
||||||
|
name String?
|
||||||
houseNumber String?
|
houseNumber String?
|
||||||
street String?
|
street String?
|
||||||
locality String?
|
locality String?
|
||||||
postalCode String?
|
postalCode String?
|
||||||
country String?
|
country String
|
||||||
type AddressType? @default(OTHER)
|
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @default(now()) @updatedAt
|
updatedAt DateTime @default(now()) @updatedAt
|
||||||
Ad Ad @relation(fields: [adUuid], references: [uuid], onDelete: Cascade)
|
Ad Ad @relation(fields: [adUuid], references: [uuid], onDelete: Cascade)
|
||||||
|
@ -68,11 +65,3 @@ enum Frequency {
|
||||||
PUNCTUAL
|
PUNCTUAL
|
||||||
RECURRENT
|
RECURRENT
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AddressType {
|
|
||||||
HOUSE_NUMBER
|
|
||||||
STREET_ADDRESS
|
|
||||||
LOCALITY
|
|
||||||
VENUE
|
|
||||||
OTHER
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ import { AdProfile } from './mappers/ad.profile';
|
||||||
import { AdsRepository } from './adapters/secondaries/ads.repository';
|
import { AdsRepository } from './adapters/secondaries/ads.repository';
|
||||||
import { Messager } from './adapters/secondaries/messager';
|
import { Messager } from './adapters/secondaries/messager';
|
||||||
import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
|
import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
|
||||||
|
import { CreateAdUseCase } from './domain/usecases/create-ad.usecase';
|
||||||
|
import { DefaultParamsProvider } from './adapters/secondaries/default-params.provider';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -29,6 +31,16 @@ import { FindAdByUuidUseCase } from './domain/usecases/find-ad-by-uuid.usecase';
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
controllers: [AdController],
|
controllers: [AdController],
|
||||||
providers: [AdProfile, AdsRepository, Messager, FindAdByUuidUseCase],
|
providers: [
|
||||||
|
AdProfile,
|
||||||
|
AdsRepository,
|
||||||
|
Messager,
|
||||||
|
FindAdByUuidUseCase,
|
||||||
|
CreateAdUseCase,
|
||||||
|
{
|
||||||
|
provide: 'ParamsProvider',
|
||||||
|
useClass: DefaultParamsProvider,
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class AdModule {}
|
export class AdModule {}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import { Mapper } from '@automapper/core';
|
import { Mapper } from '@automapper/core';
|
||||||
import { InjectMapper } from '@automapper/nestjs';
|
import { InjectMapper } from '@automapper/nestjs';
|
||||||
import { Controller, UsePipes } from '@nestjs/common';
|
import { Controller, UsePipes } from '@nestjs/common';
|
||||||
import { QueryBus } from '@nestjs/cqrs';
|
import { CommandBus, QueryBus } from '@nestjs/cqrs';
|
||||||
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
import { GrpcMethod, RpcException } from '@nestjs/microservices';
|
||||||
import { RpcValidationPipe } from '../../../../utils/pipes/rpc.validation-pipe';
|
import { RpcValidationPipe } from '../../../../utils/pipes/rpc.validation-pipe';
|
||||||
import { FindAdByUuidRequest } from '../../domain/dtos/find-ad-by-uuid.request';
|
import { FindAdByUuidRequest } from '../../domain/dtos/find-ad-by-uuid.request';
|
||||||
import { AdPresenter } from './ad.presenter';
|
import { AdPresenter } from './ad.presenter';
|
||||||
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
|
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
|
||||||
import { Ad } from '../../domain/entities/ad';
|
import { Ad } from '../../domain/entities/ad';
|
||||||
|
import { CreateAdRequest } from '../../domain/dtos/create-ad.request';
|
||||||
|
import { CreateAdCommand } from '../../commands/create-ad.command';
|
||||||
|
import { DatabaseException } from '../../../database/exceptions/database.exception';
|
||||||
|
|
||||||
@UsePipes(
|
@UsePipes(
|
||||||
new RpcValidationPipe({
|
new RpcValidationPipe({
|
||||||
|
@ -18,6 +21,7 @@ import { Ad } from '../../domain/entities/ad';
|
||||||
@Controller()
|
@Controller()
|
||||||
export class AdController {
|
export class AdController {
|
||||||
constructor(
|
constructor(
|
||||||
|
private readonly _commandBus: CommandBus,
|
||||||
private readonly queryBus: QueryBus,
|
private readonly queryBus: QueryBus,
|
||||||
@InjectMapper() private readonly _mapper: Mapper,
|
@InjectMapper() private readonly _mapper: Mapper,
|
||||||
) {}
|
) {}
|
||||||
|
@ -25,7 +29,6 @@ export class AdController {
|
||||||
@GrpcMethod('AdsService', 'FindOneByUuid')
|
@GrpcMethod('AdsService', 'FindOneByUuid')
|
||||||
async findOnebyUuid(data: FindAdByUuidRequest): Promise<AdPresenter> {
|
async findOnebyUuid(data: FindAdByUuidRequest): Promise<AdPresenter> {
|
||||||
try {
|
try {
|
||||||
console.log('ici');
|
|
||||||
const ad = await this.queryBus.execute(new FindAdByUuidQuery(data));
|
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) {
|
} catch (e) {
|
||||||
|
@ -35,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({});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ package ad;
|
||||||
service AdsService {
|
service AdsService {
|
||||||
rpc FindOneByUuid(AdByUuid) returns (Ad);
|
rpc FindOneByUuid(AdByUuid) returns (Ad);
|
||||||
rpc FindAll(AdFilter) returns (Ads);
|
rpc FindAll(AdFilter) returns (Ads);
|
||||||
rpc Create(Ad) returns (Ad);
|
rpc Create(Ad) returns (AdByUuid);
|
||||||
rpc Update(Ad) returns (Ad);
|
rpc Update(Ad) returns (Ad);
|
||||||
rpc Delete(AdByUuid) returns (Empty);
|
rpc Delete(AdByUuid) returns (Empty);
|
||||||
}
|
}
|
||||||
|
@ -19,25 +19,26 @@ message Ad {
|
||||||
string userUuid = 2;
|
string userUuid = 2;
|
||||||
bool driver = 3;
|
bool driver = 3;
|
||||||
bool passenger = 4;
|
bool passenger = 4;
|
||||||
int32 frequency = 5;
|
Frequency frequency = 5;
|
||||||
string fromDate = 6;
|
optional string departure = 6;
|
||||||
string toDate = 7;
|
string fromDate = 7;
|
||||||
Schedule schedule = 8;
|
string toDate = 8;
|
||||||
MarginDurations marginDurations = 9;
|
Schedule schedule = 9;
|
||||||
int32 seatsPassenger = 10;
|
MarginDurations marginDurations = 10;
|
||||||
int32 seatsDriver = 11;
|
int32 seatsPassenger = 11;
|
||||||
bool strict = 12;
|
int32 seatsDriver = 12;
|
||||||
Addresses addresses = 13;
|
bool strict = 13;
|
||||||
|
repeated Address addresses = 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Schedule {
|
message Schedule {
|
||||||
string mon = 1;
|
optional string mon = 1;
|
||||||
string tue = 2;
|
optional string tue = 2;
|
||||||
string wed = 3;
|
optional string wed = 3;
|
||||||
string thu = 4;
|
optional string thu = 4;
|
||||||
string fri = 5;
|
optional string fri = 5;
|
||||||
string sat = 6;
|
optional string sat = 6;
|
||||||
string sun = 7;
|
optional string sun = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MarginDurations {
|
message MarginDurations {
|
||||||
|
@ -50,32 +51,28 @@ message MarginDurations {
|
||||||
int32 sun = 7;
|
int32 sun = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Addresses {
|
|
||||||
repeated Address address = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Address {
|
message Address {
|
||||||
float lon = 1;
|
string uuid = 1;
|
||||||
float lat = 2;
|
int32 position = 2;
|
||||||
string houseNumber = 3;
|
float lon = 3;
|
||||||
string street = 4;
|
float lat = 4;
|
||||||
string locality = 5;
|
optional string name = 5;
|
||||||
string postalCode = 6;
|
optional string houseNumber = 6;
|
||||||
string country = 7;
|
optional string street = 7;
|
||||||
AddressType type = 8;
|
optional string locality = 8;
|
||||||
|
optional string postalCode = 9;
|
||||||
|
string country = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AddressType {
|
|
||||||
HOUSE_NUMBER = 1;
|
enum Frequency {
|
||||||
STREET_ADDRESS = 2;
|
PUNCTUAL = 1;
|
||||||
LOCALITY = 3;
|
RECURRENT = 2;
|
||||||
VENUE = 4;
|
|
||||||
OTHER = 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message AdFilter {
|
message AdFilter {
|
||||||
optional int32 page = 1;
|
int32 page = 1;
|
||||||
optional int32 perPage = 2;
|
int32 perPage = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Ads {
|
message Ads {
|
||||||
|
|
|
@ -1,7 +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';
|
||||||
|
//TODO : properly implement mutate operation to prisma
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdsRepository extends AdRepository<Ad> {
|
export class AdsRepository extends AdRepository<Ad> {
|
||||||
protected _model = 'ad';
|
protected _model = 'ad';
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { DefaultParams } from '../../domain/types/default-params.type';
|
||||||
|
import { IProvideParams } from '../../domain/interfaces/param-provider.interface';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DefaultParamsProvider implements IProvideParams {
|
||||||
|
constructor(private readonly configService: ConfigService) {}
|
||||||
|
getParams = (): DefaultParams => {
|
||||||
|
return {
|
||||||
|
MON_MARGIN: parseInt(this.configService.get('DEPARTURE_MARGIN')),
|
||||||
|
TUE_MARGIN: parseInt(this.configService.get('DEPARTURE_MARGIN')),
|
||||||
|
WED_MARGIN: parseInt(this.configService.get('DEPARTURE_MARGIN')),
|
||||||
|
THU_MARGIN: parseInt(this.configService.get('DEPARTURE_MARGIN')),
|
||||||
|
FRI_MARGIN: parseInt(this.configService.get('DEPARTURE_MARGIN')),
|
||||||
|
SAT_MARGIN: parseInt(this.configService.get('DEPARTURE_MARGIN')),
|
||||||
|
SUN_MARGIN: parseInt(this.configService.get('DEPARTURE_MARGIN')),
|
||||||
|
DRIVER: this.configService.get('ROLE') == 'driver' ? true : false,
|
||||||
|
SEATS_PROVIDED: parseInt(this.configService.get('SEATS_PROVIDED')),
|
||||||
|
PASSENGER: this.configService.get('ROLE') == 'passenger' ? true : false,
|
||||||
|
SEATS_REQUESTED: parseInt(this.configService.get('SEATS_REQUESTED')),
|
||||||
|
STRICT: false,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { CreateAdRequest } from '../domain/dtos/create-ad.request';
|
||||||
|
|
||||||
|
export class CreateAdCommand {
|
||||||
|
readonly createAdRequest: CreateAdRequest;
|
||||||
|
|
||||||
|
constructor(request: CreateAdRequest) {
|
||||||
|
this.createAdRequest = request;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import {
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
IsBoolean,
|
||||||
|
IsDate,
|
||||||
|
IsInt,
|
||||||
|
IsEnum,
|
||||||
|
ValidateNested,
|
||||||
|
IsUUID,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { Frequency } from '../types/frequency.enum';
|
||||||
|
import { Address } from '../entities/address';
|
||||||
|
|
||||||
|
export class AdCreation {
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@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: Address[] };
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import {
|
||||||
|
IsOptional,
|
||||||
|
IsBoolean,
|
||||||
|
IsDate,
|
||||||
|
IsInt,
|
||||||
|
IsEnum,
|
||||||
|
ValidateNested,
|
||||||
|
ArrayMinSize,
|
||||||
|
IsUUID,
|
||||||
|
} 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 { 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';
|
||||||
|
import { HasProperPositionIndexes } from './validators/decorators/address-position.validator';
|
||||||
|
|
||||||
|
export class CreateAdRequest {
|
||||||
|
@IsOptional()
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
uuid?: string;
|
||||||
|
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
userUuid: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
@AutoMap()
|
||||||
|
driver?: boolean;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
@AutoMap()
|
||||||
|
passenger?: boolean;
|
||||||
|
|
||||||
|
@Transform(({ value }) => mappingKeyToFrequency(value), {
|
||||||
|
toClassOnly: true,
|
||||||
|
})
|
||||||
|
@IsEnum(Frequency)
|
||||||
|
@AutoMap()
|
||||||
|
frequency: Frequency;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsPunctualOrRecurrent()
|
||||||
|
@Type(() => Date)
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
departure?: Date;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsPunctualOrRecurrent()
|
||||||
|
@Type(() => Date)
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
fromDate?: Date;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsPunctualOrRecurrent()
|
||||||
|
@Type(() => Date)
|
||||||
|
@IsDate()
|
||||||
|
@AutoMap()
|
||||||
|
toDate?: Date;
|
||||||
|
|
||||||
|
@Type(() => ScheduleDTO)
|
||||||
|
@IsPunctualOrRecurrent()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@AutoMap()
|
||||||
|
schedule: ScheduleDTO = {};
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => MarginDTO)
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@AutoMap()
|
||||||
|
marginDurations?: MarginDTO;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@HasProperDriverSeats()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
seatsDriver?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@HasProperPassengerSeats()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
seatsPassenger?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
@AutoMap()
|
||||||
|
strict?: boolean;
|
||||||
|
|
||||||
|
@ArrayMinSize(2)
|
||||||
|
@Type(() => AddressRequestDTO)
|
||||||
|
@HasProperPositionIndexes()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@AutoMap()
|
||||||
|
addresses: AddressRequestDTO[];
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import {
|
||||||
|
IsInt,
|
||||||
|
IsLatitude,
|
||||||
|
IsLongitude,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
IsUUID,
|
||||||
|
} from 'class-validator';
|
||||||
|
|
||||||
|
export class AddressRequestDTO {
|
||||||
|
@IsOptional()
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
uuid?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
adUuid?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
position?: number;
|
||||||
|
|
||||||
|
@IsLongitude()
|
||||||
|
@AutoMap()
|
||||||
|
lon: number;
|
||||||
|
|
||||||
|
@IsLatitude()
|
||||||
|
@AutoMap()
|
||||||
|
lat: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@AutoMap()
|
||||||
|
name?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
houseNumber?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
street?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
locality?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
postalCode?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@AutoMap()
|
||||||
|
country: string;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsInt, IsOptional } from 'class-validator';
|
||||||
|
|
||||||
|
export class MarginDTO {
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
mon?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
tue?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
wed?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
thu?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
fri?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
sat?: number;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@AutoMap()
|
||||||
|
sun?: number;
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsOptional, IsMilitaryTime } from 'class-validator';
|
||||||
|
|
||||||
|
export class ScheduleDTO {
|
||||||
|
@IsOptional()
|
||||||
|
@IsMilitaryTime()
|
||||||
|
@AutoMap()
|
||||||
|
mon?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsMilitaryTime()
|
||||||
|
@AutoMap()
|
||||||
|
tue?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsMilitaryTime()
|
||||||
|
@AutoMap()
|
||||||
|
wed?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsMilitaryTime()
|
||||||
|
@AutoMap()
|
||||||
|
thu?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsMilitaryTime()
|
||||||
|
@AutoMap()
|
||||||
|
fri?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsMilitaryTime()
|
||||||
|
@AutoMap()
|
||||||
|
sat?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsMilitaryTime()
|
||||||
|
@AutoMap()
|
||||||
|
sun?: string;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { AddressRequestDTO } from '../create.address.request';
|
||||||
|
|
||||||
|
export function hasProperPositionIndexes(value: AddressRequestDTO[]) {
|
||||||
|
if (value.every((address) => address.position === undefined)) return true;
|
||||||
|
else 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;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { ValidateBy, ValidationOptions, buildMessage } from 'class-validator';
|
||||||
|
import { AddressRequestDTO } from '../../create.address.request';
|
||||||
|
import { hasProperPositionIndexes } from '../address-position';
|
||||||
|
|
||||||
|
export function HasProperPositionIndexes(
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
): PropertyDecorator {
|
||||||
|
return ValidateBy(
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
constraints: [],
|
||||||
|
validator: {
|
||||||
|
validate: (value: AddressRequestDTO[]): boolean =>
|
||||||
|
hasProperPositionIndexes(value),
|
||||||
|
|
||||||
|
defaultMessage: buildMessage(
|
||||||
|
() =>
|
||||||
|
`indexes position incorrect, please provide a complete list of indexes or ordened list of adresses from start to end of journey`,
|
||||||
|
validationOptions,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validationOptions,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {
|
||||||
|
ValidateBy,
|
||||||
|
ValidationArguments,
|
||||||
|
ValidationOptions,
|
||||||
|
buildMessage,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { hasProperDriverSeats } from '../has-driver-seats';
|
||||||
|
|
||||||
|
export function HasProperDriverSeats(
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
): PropertyDecorator {
|
||||||
|
return ValidateBy(
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
constraints: [],
|
||||||
|
validator: {
|
||||||
|
validate: (value: any, args: ValidationArguments): boolean =>
|
||||||
|
hasProperDriverSeats(args),
|
||||||
|
defaultMessage: buildMessage(
|
||||||
|
() => `driver and driver seats are not correct`,
|
||||||
|
validationOptions,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validationOptions,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {
|
||||||
|
ValidateBy,
|
||||||
|
ValidationArguments,
|
||||||
|
ValidationOptions,
|
||||||
|
buildMessage,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { hasProperPassengerSeats } from '../has-passenger-seats';
|
||||||
|
|
||||||
|
export function HasProperPassengerSeats(
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
): PropertyDecorator {
|
||||||
|
return ValidateBy(
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
constraints: [],
|
||||||
|
validator: {
|
||||||
|
validate: (value, args: ValidationArguments): boolean =>
|
||||||
|
hasProperPassengerSeats(args),
|
||||||
|
defaultMessage: buildMessage(
|
||||||
|
() => `passenger and passenger seats are not correct`,
|
||||||
|
validationOptions,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validationOptions,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import {
|
||||||
|
ValidateBy,
|
||||||
|
ValidationArguments,
|
||||||
|
ValidationOptions,
|
||||||
|
buildMessage,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { isPunctualOrRecurrent } from '../is-punctual-or-recurrent';
|
||||||
|
|
||||||
|
export function IsPunctualOrRecurrent(
|
||||||
|
validationOptions?: ValidationOptions,
|
||||||
|
): PropertyDecorator {
|
||||||
|
return ValidateBy(
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
constraints: [],
|
||||||
|
validator: {
|
||||||
|
validate: (value, args: ValidationArguments): boolean =>
|
||||||
|
isPunctualOrRecurrent(args),
|
||||||
|
defaultMessage: buildMessage(
|
||||||
|
() =>
|
||||||
|
`the departure, from date, to date and schedule must be properly set on reccurent or punctual ad `,
|
||||||
|
validationOptions,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
validationOptions,
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { Frequency } from '../../types/frequency.enum';
|
||||||
|
export const mappingKeyToFrequency = (index: number): Frequency => {
|
||||||
|
if (index == 1) return Frequency.PUNCTUAL;
|
||||||
|
if (index == 2) return Frequency.RECURRENT;
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { ValidationArguments } from 'class-validator';
|
||||||
|
|
||||||
|
export function hasProperDriverSeats(args: ValidationArguments) {
|
||||||
|
if (
|
||||||
|
args.object['driver'] === true &&
|
||||||
|
typeof args.object['seatsDriver'] === 'number'
|
||||||
|
)
|
||||||
|
return args.object['seatsDriver'] > 0;
|
||||||
|
if (
|
||||||
|
(args.object['driver'] === false ||
|
||||||
|
args.object['driver'] === null ||
|
||||||
|
args.object['driver'] === undefined) &&
|
||||||
|
(args.object['seatsDriver'] === 0 ||
|
||||||
|
args.object['seatsDriver'] === null ||
|
||||||
|
args.object['seatsDriver'] === undefined)
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { ValidationArguments } from 'class-validator';
|
||||||
|
|
||||||
|
export function hasProperPassengerSeats(args: ValidationArguments) {
|
||||||
|
if (
|
||||||
|
args.object['passenger'] === true &&
|
||||||
|
typeof args.object['seatsPassenger'] === 'number'
|
||||||
|
)
|
||||||
|
return args.object['seatsPassenger'] > 0;
|
||||||
|
else if (
|
||||||
|
(args.object['passenger'] === false ||
|
||||||
|
args.object['passenger'] === null ||
|
||||||
|
args.object['passenger'] === undefined) &&
|
||||||
|
(args.object['seatsPassenger'] === 0 ||
|
||||||
|
args.object['seatsPassenger'] === null ||
|
||||||
|
args.object['seatsPassenger'] === undefined)
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
else return false;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isPunctualOrRecurrent = (args: ValidationArguments): boolean => {
|
||||||
|
return isPunctual(args) || isRecurrent(args);
|
||||||
|
};
|
|
@ -1,6 +1,131 @@
|
||||||
import { AutoMap } from '@automapper/classes';
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import {
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
IsBoolean,
|
||||||
|
IsDate,
|
||||||
|
IsInt,
|
||||||
|
IsEnum,
|
||||||
|
ValidateNested,
|
||||||
|
ArrayMinSize,
|
||||||
|
IsUUID,
|
||||||
|
} from 'class-validator';
|
||||||
|
import { Address } from '../entities/address';
|
||||||
|
import { Frequency } from '../types/frequency.enum';
|
||||||
export class Ad {
|
export class Ad {
|
||||||
|
@IsUUID(4)
|
||||||
@AutoMap()
|
@AutoMap()
|
||||||
uuid: string;
|
uuid: string;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
@ArrayMinSize(2)
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@AutoMap(() => [Address])
|
||||||
|
addresses: Address[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { AutoMap } from '@automapper/classes';
|
||||||
|
import { IsInt, IsUUID } from 'class-validator';
|
||||||
|
|
||||||
|
export class Address {
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
uuid: string;
|
||||||
|
|
||||||
|
@IsUUID(4)
|
||||||
|
@AutoMap()
|
||||||
|
adUuid: string;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { DefaultParams } from '../types/default-params.type';
|
||||||
|
export interface IProvideParams {
|
||||||
|
getParams(): DefaultParams;
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
export type DefaultParams = {
|
||||||
|
MON_MARGIN: number;
|
||||||
|
TUE_MARGIN: number;
|
||||||
|
WED_MARGIN: number;
|
||||||
|
THU_MARGIN: number;
|
||||||
|
FRI_MARGIN: number;
|
||||||
|
SAT_MARGIN: number;
|
||||||
|
SUN_MARGIN: number;
|
||||||
|
DRIVER: boolean;
|
||||||
|
SEATS_PROVIDED: number;
|
||||||
|
PASSENGER: boolean;
|
||||||
|
SEATS_REQUESTED: number;
|
||||||
|
STRICT: boolean;
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum Frequency {
|
||||||
|
PUNCTUAL = 'PUNCTUAL',
|
||||||
|
RECURRENT = 'RECURRENT',
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
import { Mapper } from '@automapper/core';
|
||||||
|
import { InjectMapper } from '@automapper/nestjs';
|
||||||
|
import { Inject } from '@nestjs/common';
|
||||||
|
import { CommandHandler } from '@nestjs/cqrs';
|
||||||
|
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';
|
||||||
|
import { Ad } from '../entities/ad';
|
||||||
|
|
||||||
|
@CommandHandler(CreateAdCommand)
|
||||||
|
export class CreateAdUseCase {
|
||||||
|
private readonly defaultParams: DefaultParams;
|
||||||
|
private ad: AdCreation;
|
||||||
|
constructor(
|
||||||
|
private readonly _repository: AdsRepository,
|
||||||
|
private readonly _messager: Messager,
|
||||||
|
@InjectMapper() private readonly _mapper: Mapper,
|
||||||
|
@Inject('ParamsProvider')
|
||||||
|
private readonly defaultParamsProvider: IProvideParams,
|
||||||
|
) {
|
||||||
|
this.defaultParams = defaultParamsProvider.getParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute(command: CreateAdCommand): Promise<Ad> {
|
||||||
|
this.ad = this._mapper.map(
|
||||||
|
command.createAdRequest,
|
||||||
|
CreateAdRequest,
|
||||||
|
AdCreation,
|
||||||
|
);
|
||||||
|
this.setDefaultSchedule();
|
||||||
|
this.setDefaultAddressesPosition();
|
||||||
|
this.setDefaultDriverAndPassengerParameters();
|
||||||
|
this.setDefaultDistanceMargin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
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),
|
||||||
|
);
|
||||||
|
return adCreated;
|
||||||
|
} catch (error) {
|
||||||
|
let key = 'logging.ad.create.crit';
|
||||||
|
if (error.message.includes('Already exists')) {
|
||||||
|
key = 'logging.ad.create.warning';
|
||||||
|
}
|
||||||
|
this._messager.publish(
|
||||||
|
key,
|
||||||
|
JSON.stringify({
|
||||||
|
command,
|
||||||
|
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.SEATS_PROVIDED;
|
||||||
|
this.ad.passenger = this.defaultParams.PASSENGER;
|
||||||
|
this.ad.seatsPassenger = this.defaultParams.SEATS_REQUESTED;
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,139 @@
|
||||||
import { createMap, Mapper } from '@automapper/core';
|
import { 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 { AdCreation } from '../domain/dtos/ad.creation';
|
||||||
|
import { RecurrentNormaliser } from '../domain/entities/recurrent-normaliser';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdProfile extends AutomapperProfile {
|
export class AdProfile extends AutomapperProfile {
|
||||||
|
recurrentNormaliser = new RecurrentNormaliser();
|
||||||
constructor(@InjectMapper() mapper: Mapper) {
|
constructor(@InjectMapper() mapper: Mapper) {
|
||||||
super(mapper);
|
super(mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
override get profile() {
|
override get profile() {
|
||||||
return (mapper) => {
|
return (mapper) => {
|
||||||
createMap(mapper, Ad, AdPresenter);
|
createMap(mapper, Ad, AdPresenter);
|
||||||
|
createMap(
|
||||||
|
mapper,
|
||||||
|
CreateAdRequest,
|
||||||
|
AdCreation,
|
||||||
|
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.monMargin,
|
||||||
|
mapFrom((source) => source.marginDurations.mon),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.tueMargin,
|
||||||
|
mapFrom((source) => source.marginDurations.tue),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.wedMargin,
|
||||||
|
mapFrom((source) => source.marginDurations.wed),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.thuMargin,
|
||||||
|
mapFrom((source) => source.marginDurations.thu),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.friMargin,
|
||||||
|
mapFrom((source) => source.marginDurations.fri),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.satMargin,
|
||||||
|
mapFrom((source) => source.marginDurations.sat),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.sunMargin,
|
||||||
|
mapFrom((source) => source.marginDurations.sun),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.monTime,
|
||||||
|
mapFrom((source) => source.schedule.mon),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.tueTime,
|
||||||
|
mapFrom((source) => source.schedule.tue),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.wedTime,
|
||||||
|
mapFrom((source) => source.schedule.wed),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.thuTime,
|
||||||
|
mapFrom((source) => source.schedule.thu),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.friTime,
|
||||||
|
mapFrom((source) => source.schedule.fri),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.satTime,
|
||||||
|
mapFrom((source) => source.schedule.sat),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.sunTime,
|
||||||
|
mapFrom((source) => source.schedule.sun),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.addresses.create,
|
||||||
|
mapFrom((source) => source.addresses),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.fromDate,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.fromDateResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.toDate,
|
||||||
|
mapFrom((source) => this.recurrentNormaliser.toDateResolver(source)),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.monTime,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.scheduleMonResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.tueTime,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.scheduleTueResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.wedTime,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.scheduleWedResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.thuTime,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.scheduleThuResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.friTime,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.scheduleFriResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.satTime,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.scheduleSatResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
forMember(
|
||||||
|
(destination) => destination.sunTime,
|
||||||
|
mapFrom((source) =>
|
||||||
|
this.recurrentNormaliser.scheduleSunResolver(source),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
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 { Address } from '../domain/entities/address';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AdProfile extends AutomapperProfile {
|
||||||
|
constructor(@InjectMapper() mapper: Mapper) {
|
||||||
|
super(mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
override get profile() {
|
||||||
|
return (mapper) => {
|
||||||
|
createMap(mapper, AddressRequestDTO, Address);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,468 @@
|
||||||
|
import { Test } from '@nestjs/testing';
|
||||||
|
import { PrismaService } from '../../../database/adapters/secondaries/prisma-service';
|
||||||
|
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
||||||
|
import { DatabaseModule } from '../../../database/database.module';
|
||||||
|
import { Frequency } from '../../domain/types/frequency.enum';
|
||||||
|
import { AdCreation } from '../../domain/dtos/ad.creation';
|
||||||
|
import { Address } from '../../domain/entities/address';
|
||||||
|
|
||||||
|
describe('Ad Repository', () => {
|
||||||
|
let prismaService: PrismaService;
|
||||||
|
let adsRepository: AdsRepository;
|
||||||
|
|
||||||
|
const executeInsertCommand = async (table: string, object: any) => {
|
||||||
|
const command = `INSERT INTO ${table} ("${Object.keys(object).join(
|
||||||
|
'","',
|
||||||
|
)}") VALUES (${Object.values(object).join(',')})`;
|
||||||
|
|
||||||
|
await prismaService.$executeRawUnsafe(command);
|
||||||
|
};
|
||||||
|
const getSeed = (index: number, uuid: string): string => {
|
||||||
|
return `'${uuid.slice(0, -2)}${index.toString(16).padStart(2, '0')}'`;
|
||||||
|
};
|
||||||
|
const baseUuid = {
|
||||||
|
uuid: 'be459a29-7a41-4c0b-b371-abe90bfb6f00',
|
||||||
|
};
|
||||||
|
const baseAdress0Uuid = {
|
||||||
|
uuid: 'bad5e786-3b15-4e51-a8fc-926fa9327ff1',
|
||||||
|
};
|
||||||
|
const baseAdress1Uuid = {
|
||||||
|
uuid: '4d200eb6-7389-487f-a1ca-dbc0e40381c9',
|
||||||
|
};
|
||||||
|
const baseUserUuid = {
|
||||||
|
userUuid: "'113e0000-0000-4000-a000-000000000000'",
|
||||||
|
};
|
||||||
|
const driverAd = {
|
||||||
|
driver: 'true',
|
||||||
|
passenger: 'false',
|
||||||
|
seatsDriver: 3,
|
||||||
|
seatsPassenger: 0,
|
||||||
|
strict: 'false',
|
||||||
|
};
|
||||||
|
const passengerAd = {
|
||||||
|
driver: 'false',
|
||||||
|
passenger: 'true',
|
||||||
|
seatsDriver: 0,
|
||||||
|
seatsPassenger: 1,
|
||||||
|
strict: 'false',
|
||||||
|
};
|
||||||
|
const driverAndPassengerAd = {
|
||||||
|
driver: 'true',
|
||||||
|
passenger: 'true',
|
||||||
|
seatsDriver: 3,
|
||||||
|
seatsPassenger: 1,
|
||||||
|
strict: 'false',
|
||||||
|
};
|
||||||
|
const punctualAd = {
|
||||||
|
frequency: `'PUNCTUAL'`,
|
||||||
|
fromDate: `'2023-01-01'`,
|
||||||
|
toDate: `'2023-01-01'`,
|
||||||
|
monTime: 'NULL',
|
||||||
|
tueTime: 'NULL',
|
||||||
|
wedTime: 'NULL',
|
||||||
|
thuTime: 'NULL',
|
||||||
|
friTime: 'NULL',
|
||||||
|
satTime: 'NULL',
|
||||||
|
sunTime: `'07:00'`,
|
||||||
|
monMargin: 900,
|
||||||
|
tueMargin: 900,
|
||||||
|
wedMargin: 900,
|
||||||
|
thuMargin: 900,
|
||||||
|
friMargin: 900,
|
||||||
|
satMargin: 900,
|
||||||
|
sunMargin: 900,
|
||||||
|
};
|
||||||
|
const recurrentAd = {
|
||||||
|
frequency: `'RECURRENT'`,
|
||||||
|
fromDate: `'2023-01-01'`,
|
||||||
|
toDate: `'2023-12-31'`,
|
||||||
|
monTime: `'07:00'`,
|
||||||
|
tueTime: `'07:00'`,
|
||||||
|
wedTime: `'07:00'`,
|
||||||
|
thuTime: `'07:00'`,
|
||||||
|
friTime: `'07:00'`,
|
||||||
|
satTime: 'NULL',
|
||||||
|
sunTime: 'NULL',
|
||||||
|
monMargin: 900,
|
||||||
|
tueMargin: 900,
|
||||||
|
wedMargin: 900,
|
||||||
|
thuMargin: 900,
|
||||||
|
friMargin: 900,
|
||||||
|
satMargin: 900,
|
||||||
|
sunMargin: 900,
|
||||||
|
};
|
||||||
|
|
||||||
|
const address0 = {
|
||||||
|
position: 0,
|
||||||
|
lon: 43.7102,
|
||||||
|
lat: 7.262,
|
||||||
|
locality: "'Nice'",
|
||||||
|
postalCode: "'06000'",
|
||||||
|
country: "'France'",
|
||||||
|
};
|
||||||
|
const address1 = {
|
||||||
|
position: 1,
|
||||||
|
lon: 43.2965,
|
||||||
|
lat: 5.3698,
|
||||||
|
locality: "'Marseille'",
|
||||||
|
postalCode: "'13000'",
|
||||||
|
country: "'France'",
|
||||||
|
};
|
||||||
|
const createPunctualDriverAds = async (nbToCreate = 10) => {
|
||||||
|
const adToCreate = {
|
||||||
|
...baseUuid,
|
||||||
|
...baseUserUuid,
|
||||||
|
...driverAd,
|
||||||
|
...punctualAd,
|
||||||
|
};
|
||||||
|
for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
await executeInsertCommand('ad', adToCreate);
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address0,
|
||||||
|
});
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const createRecurrentDriverAds = async (nbToCreate = 10) => {
|
||||||
|
const adToCreate = {
|
||||||
|
...baseUuid,
|
||||||
|
...baseUserUuid,
|
||||||
|
...driverAd,
|
||||||
|
...punctualAd,
|
||||||
|
};
|
||||||
|
for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
await executeInsertCommand('ad', adToCreate);
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address0,
|
||||||
|
});
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createPunctualPassengerAds = async (nbToCreate = 10) => {
|
||||||
|
const adToCreate = {
|
||||||
|
...baseUuid,
|
||||||
|
...baseUserUuid,
|
||||||
|
...passengerAd,
|
||||||
|
...punctualAd,
|
||||||
|
};
|
||||||
|
for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
await executeInsertCommand('ad', adToCreate);
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address0,
|
||||||
|
});
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createRecurrentPassengerAds = async (nbToCreate = 10) => {
|
||||||
|
const adToCreate = {
|
||||||
|
...baseUuid,
|
||||||
|
...baseUserUuid,
|
||||||
|
...passengerAd,
|
||||||
|
...recurrentAd,
|
||||||
|
};
|
||||||
|
for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
await executeInsertCommand('ad', adToCreate);
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address0,
|
||||||
|
});
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createPunctualDriverPassengerAds = async (nbToCreate = 10) => {
|
||||||
|
const adToCreate = {
|
||||||
|
...baseUuid,
|
||||||
|
...baseUserUuid,
|
||||||
|
...driverAndPassengerAd,
|
||||||
|
...punctualAd,
|
||||||
|
};
|
||||||
|
for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
await executeInsertCommand('ad', adToCreate);
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address0,
|
||||||
|
});
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createRecurrentDriverPassengerAds = async (nbToCreate = 10) => {
|
||||||
|
const adToCreate = {
|
||||||
|
...baseUuid,
|
||||||
|
...baseUserUuid,
|
||||||
|
...driverAndPassengerAd,
|
||||||
|
...recurrentAd,
|
||||||
|
};
|
||||||
|
for (let i = 0; i < nbToCreate; i++) {
|
||||||
|
adToCreate.uuid = getSeed(i, baseUuid.uuid);
|
||||||
|
await executeInsertCommand('ad', adToCreate);
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress0Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address0,
|
||||||
|
});
|
||||||
|
await executeInsertCommand('address', {
|
||||||
|
uuid: getSeed(i, baseAdress1Uuid.uuid),
|
||||||
|
adUuid: adToCreate.uuid,
|
||||||
|
...address1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module = await Test.createTestingModule({
|
||||||
|
imports: [DatabaseModule],
|
||||||
|
providers: [PrismaService, AdsRepository],
|
||||||
|
}).compile();
|
||||||
|
prismaService = module.get<PrismaService>(PrismaService);
|
||||||
|
adsRepository = module.get<AdsRepository>(AdsRepository);
|
||||||
|
});
|
||||||
|
afterAll(async () => {
|
||||||
|
await prismaService.$disconnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await prismaService.ad.deleteMany();
|
||||||
|
});
|
||||||
|
describe('findAll', () => {
|
||||||
|
it('should return an empty data array', async () => {
|
||||||
|
const res = await adsRepository.findAll();
|
||||||
|
expect(res).toEqual({
|
||||||
|
data: [],
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('drivers', () => {
|
||||||
|
it('should return a data array with 8 punctual driver ads', async () => {
|
||||||
|
await createPunctualDriverAds(8);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(8);
|
||||||
|
expect(ads.total).toBe(8);
|
||||||
|
expect(ads.data[0].driver).toBeTruthy();
|
||||||
|
expect(ads.data[0].passenger).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array limited to 10 punctual driver ads', async () => {
|
||||||
|
await createPunctualDriverAds(20);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(10);
|
||||||
|
expect(ads.total).toBe(20);
|
||||||
|
expect(ads.data[1].driver).toBeTruthy();
|
||||||
|
expect(ads.data[1].passenger).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array with 8 recurrent driver ads', async () => {
|
||||||
|
await createRecurrentDriverAds(8);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(8);
|
||||||
|
expect(ads.total).toBe(8);
|
||||||
|
expect(ads.data[2].driver).toBeTruthy();
|
||||||
|
expect(ads.data[2].passenger).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array limited to 10 recurrent driver ads', async () => {
|
||||||
|
await createRecurrentDriverAds(20);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(10);
|
||||||
|
expect(ads.total).toBe(20);
|
||||||
|
expect(ads.data[3].driver).toBeTruthy();
|
||||||
|
expect(ads.data[3].passenger).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('passengers', () => {
|
||||||
|
it('should return a data array with 7 punctual passenger ads', async () => {
|
||||||
|
await createPunctualPassengerAds(7);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(7);
|
||||||
|
expect(ads.total).toBe(7);
|
||||||
|
expect(ads.data[0].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[0].driver).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array limited to 10 punctual passenger ads', async () => {
|
||||||
|
await createPunctualPassengerAds(15);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(10);
|
||||||
|
expect(ads.total).toBe(15);
|
||||||
|
expect(ads.data[1].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[1].driver).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array with 7 recurrent passenger ads', async () => {
|
||||||
|
await createRecurrentPassengerAds(7);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(7);
|
||||||
|
expect(ads.total).toBe(7);
|
||||||
|
expect(ads.data[2].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[2].driver).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array limited to 10 recurrent passenger ads', async () => {
|
||||||
|
await createRecurrentPassengerAds(15);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(10);
|
||||||
|
expect(ads.total).toBe(15);
|
||||||
|
expect(ads.data[3].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[3].driver).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('drivers and passengers', () => {
|
||||||
|
it('should return a data array with 6 punctual driver and passenger ads', async () => {
|
||||||
|
await createPunctualDriverPassengerAds(6);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(6);
|
||||||
|
expect(ads.total).toBe(6);
|
||||||
|
expect(ads.data[0].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[0].driver).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array limited to 10 punctual driver and passenger ads', async () => {
|
||||||
|
await createPunctualDriverPassengerAds(16);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(10);
|
||||||
|
expect(ads.total).toBe(16);
|
||||||
|
expect(ads.data[1].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[1].driver).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array with 6 recurrent driver and passenger ads', async () => {
|
||||||
|
await createRecurrentDriverPassengerAds(6);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(6);
|
||||||
|
expect(ads.total).toBe(6);
|
||||||
|
expect(ads.data[2].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[2].driver).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a data array limited to 10 recurrent driver and passenger ads', async () => {
|
||||||
|
await createRecurrentDriverPassengerAds(16);
|
||||||
|
const ads = await adsRepository.findAll();
|
||||||
|
expect(ads.data.length).toBe(10);
|
||||||
|
expect(ads.total).toBe(16);
|
||||||
|
expect(ads.data[3].passenger).toBeTruthy();
|
||||||
|
expect(ads.data[3].driver).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('findOneByUuid', () => {
|
||||||
|
it('should return an ad', async () => {
|
||||||
|
await createPunctualDriverAds(1);
|
||||||
|
const ad = await adsRepository.findOneByUuid(baseUuid.uuid);
|
||||||
|
|
||||||
|
expect(ad.uuid).toBe(baseUuid.uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null', async () => {
|
||||||
|
const ad = await adsRepository.findOneByUuid(
|
||||||
|
'544572be-11fb-4244-8235-587221fc9104',
|
||||||
|
);
|
||||||
|
expect(ad).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('create', () => {
|
||||||
|
it('should create an punctual ad', async () => {
|
||||||
|
const beforeCount = await prismaService.ad.count();
|
||||||
|
const adToCreate: AdCreation = new AdCreation();
|
||||||
|
|
||||||
|
adToCreate.uuid = 'be459a29-7a41-4c0b-b371-abe90bfb6f00';
|
||||||
|
adToCreate.userUuid = '4e52b54d-a729-4dbd-9283-f84a11bb2200';
|
||||||
|
adToCreate.driver = true;
|
||||||
|
adToCreate.passenger = false;
|
||||||
|
adToCreate.frequency = Frequency.PUNCTUAL;
|
||||||
|
adToCreate.fromDate = new Date('05-22-2023 09:36');
|
||||||
|
adToCreate.toDate = new Date('05-22-2023 09:36');
|
||||||
|
adToCreate.monTime = '09:36';
|
||||||
|
adToCreate.monMargin = 900;
|
||||||
|
adToCreate.tueMargin = 900;
|
||||||
|
adToCreate.wedMargin = 900;
|
||||||
|
adToCreate.thuMargin = 900;
|
||||||
|
adToCreate.friMargin = 900;
|
||||||
|
adToCreate.satMargin = 900;
|
||||||
|
adToCreate.sunMargin = 900;
|
||||||
|
adToCreate.seatsDriver = 3;
|
||||||
|
adToCreate.seatsPassenger = 0;
|
||||||
|
adToCreate.strict = false;
|
||||||
|
adToCreate.addresses = {
|
||||||
|
create: [address0 as Address, address1 as Address],
|
||||||
|
};
|
||||||
|
const ad = await adsRepository.create(adToCreate);
|
||||||
|
|
||||||
|
const afterCount = await prismaService.ad.count();
|
||||||
|
|
||||||
|
expect(afterCount - beforeCount).toBe(1);
|
||||||
|
expect(ad.uuid).toBe('be459a29-7a41-4c0b-b371-abe90bfb6f00');
|
||||||
|
});
|
||||||
|
it('should create an recurrent ad', async () => {
|
||||||
|
const beforeCount = await prismaService.ad.count();
|
||||||
|
const adToCreate: AdCreation = new AdCreation();
|
||||||
|
|
||||||
|
adToCreate.uuid = '137a26fa-4b38-48ba-aecf-1a75f6b20f3d';
|
||||||
|
adToCreate.userUuid = '4e52b54d-a729-4dbd-9283-f84a11bb2200';
|
||||||
|
adToCreate.driver = true;
|
||||||
|
adToCreate.passenger = false;
|
||||||
|
adToCreate.frequency = Frequency.RECURRENT;
|
||||||
|
adToCreate.fromDate = new Date('01-15-2023 ');
|
||||||
|
adToCreate.toDate = new Date('10-31-2023');
|
||||||
|
adToCreate.monTime = '07:30';
|
||||||
|
adToCreate.friTime = '07:45';
|
||||||
|
adToCreate.thuTime = '08:00';
|
||||||
|
adToCreate.monMargin = 900;
|
||||||
|
adToCreate.tueMargin = 900;
|
||||||
|
adToCreate.wedMargin = 900;
|
||||||
|
adToCreate.thuMargin = 900;
|
||||||
|
adToCreate.friMargin = 900;
|
||||||
|
adToCreate.satMargin = 900;
|
||||||
|
adToCreate.sunMargin = 900;
|
||||||
|
adToCreate.seatsDriver = 2;
|
||||||
|
adToCreate.seatsPassenger = 0;
|
||||||
|
adToCreate.strict = false;
|
||||||
|
adToCreate.addresses = {
|
||||||
|
create: [address0 as Address, address1 as Address],
|
||||||
|
};
|
||||||
|
const ad = await adsRepository.create(adToCreate);
|
||||||
|
|
||||||
|
const afterCount = await prismaService.ad.count();
|
||||||
|
|
||||||
|
expect(afterCount - beforeCount).toBe(1);
|
||||||
|
expect(ad.uuid).toBe('137a26fa-4b38-48ba-aecf-1a75f6b20f3d');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { DefaultParamsProvider } from '../../../../adapters/secondaries/default-params.provider';
|
||||||
|
import { DefaultParams } from '../../../../domain/types/default-params.type';
|
||||||
|
|
||||||
|
const mockConfigService = {
|
||||||
|
get: jest.fn().mockImplementation(() => 'some_default_value'),
|
||||||
|
};
|
||||||
|
//TODO complete coverage
|
||||||
|
describe('DefaultParamsProvider', () => {
|
||||||
|
let defaultParamsProvider: DefaultParamsProvider;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [],
|
||||||
|
providers: [
|
||||||
|
DefaultParamsProvider,
|
||||||
|
{
|
||||||
|
provide: ConfigService,
|
||||||
|
useValue: mockConfigService,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
defaultParamsProvider = module.get<DefaultParamsProvider>(
|
||||||
|
DefaultParamsProvider,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(defaultParamsProvider).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide default params', async () => {
|
||||||
|
const params: DefaultParams = defaultParamsProvider.getParams();
|
||||||
|
expect(params.SUN_MARGIN).toBeNaN();
|
||||||
|
expect(params.PASSENGER).toBe(false);
|
||||||
|
expect(params.DRIVER).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { Messager } from '../../adapters/secondaries/messager';
|
import { Messager } from '../../../../adapters/secondaries/messager';
|
||||||
|
|
||||||
const mockAmqpConnection = {
|
const mockAmqpConnection = {
|
||||||
publish: jest.fn().mockImplementation(),
|
publish: jest.fn().mockImplementation(),
|
|
@ -0,0 +1,256 @@
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { CreateAdUseCase } from '../../../domain/usecases/create-ad.usecase';
|
||||||
|
import { CreateAdRequest } from '../../../domain/dtos/create-ad.request';
|
||||||
|
import { Messager } from '../../../adapters/secondaries/messager';
|
||||||
|
import { AdsRepository } from '../../../adapters/secondaries/ads.repository';
|
||||||
|
import { CreateAdCommand } from '../../../commands/create-ad.command';
|
||||||
|
import { AutomapperModule } from '@automapper/nestjs';
|
||||||
|
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 { AdCreation } from '../../../domain/dtos/ad.creation';
|
||||||
|
import { Address } from 'src/modules/ad/domain/entities/address';
|
||||||
|
|
||||||
|
const mockAddress1: AddressRequestDTO = {
|
||||||
|
position: 0,
|
||||||
|
lon: 48.68944505415954,
|
||||||
|
lat: 6.176510296462267,
|
||||||
|
houseNumber: '5',
|
||||||
|
street: 'Avenue Foch',
|
||||||
|
locality: 'Nancy',
|
||||||
|
postalCode: '54000',
|
||||||
|
country: 'France',
|
||||||
|
};
|
||||||
|
const mockAddress2: AddressRequestDTO = {
|
||||||
|
position: 1,
|
||||||
|
lon: 48.8566,
|
||||||
|
lat: 2.3522,
|
||||||
|
locality: 'Paris',
|
||||||
|
postalCode: '75000',
|
||||||
|
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: 'Nice',
|
||||||
|
postalCode: '06000',
|
||||||
|
country: 'France',
|
||||||
|
};
|
||||||
|
const minimalRecurrentAdREquest: CreateAdRequest = {
|
||||||
|
userUuid: '224e0000-0000-4000-a000-000000000000',
|
||||||
|
frequency: Frequency.RECURRENT,
|
||||||
|
fromDate: new Date('01-05-2023'),
|
||||||
|
toDate: new Date('01-05-2024'),
|
||||||
|
schedule: {
|
||||||
|
mon: '08:00',
|
||||||
|
},
|
||||||
|
marginDurations: {},
|
||||||
|
addresses: [mockAddress1, mockAddress2],
|
||||||
|
};
|
||||||
|
const newAdRequest: CreateAdRequest = {
|
||||||
|
userUuid: '113e0000-0000-4000-a000-000000000000',
|
||||||
|
driver: true,
|
||||||
|
passenger: false,
|
||||||
|
frequency: Frequency.RECURRENT,
|
||||||
|
fromDate: new Date('01-05-2023'),
|
||||||
|
toDate: new Date('20-08-2023'),
|
||||||
|
schedule: {
|
||||||
|
tue: '08:00',
|
||||||
|
wed: '08:30',
|
||||||
|
},
|
||||||
|
marginDurations: {
|
||||||
|
mon: undefined,
|
||||||
|
tue: undefined,
|
||||||
|
wed: undefined,
|
||||||
|
thu: undefined,
|
||||||
|
fri: undefined,
|
||||||
|
sat: undefined,
|
||||||
|
sun: undefined,
|
||||||
|
},
|
||||||
|
seatsDriver: 2,
|
||||||
|
addresses: [mockAddress1, mockAddress2],
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockMessager = {
|
||||||
|
publish: jest.fn().mockImplementation(),
|
||||||
|
};
|
||||||
|
const mockDefaultParamsProvider = {
|
||||||
|
getParams: () => {
|
||||||
|
return {
|
||||||
|
MON_MARGIN: 900,
|
||||||
|
TUE_MARGIN: 900,
|
||||||
|
WED_MARGIN: 900,
|
||||||
|
THU_MARGIN: 900,
|
||||||
|
FRI_MARGIN: 900,
|
||||||
|
SAT_MARGIN: 900,
|
||||||
|
SUN_MARGIN: 900,
|
||||||
|
DRIVER: false,
|
||||||
|
SEATS_PROVIDED: 0,
|
||||||
|
PASSENGER: true,
|
||||||
|
SEATS_REQUESTED: 1,
|
||||||
|
STRICT: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mockAdRepository = {
|
||||||
|
create: jest
|
||||||
|
.fn()
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
.mockImplementationOnce((command?: CreateAdCommand) => {
|
||||||
|
return Promise.resolve({
|
||||||
|
...newAdRequest,
|
||||||
|
uuid: 'ad000000-0000-4000-a000-000000000000',
|
||||||
|
createdAt: new Date('01-05-2023'),
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.mockImplementationOnce(() => {
|
||||||
|
throw new Error('Already exists');
|
||||||
|
})
|
||||||
|
.mockImplementation(),
|
||||||
|
};
|
||||||
|
describe('CreateAdUseCase', () => {
|
||||||
|
let createAdUseCase: CreateAdUseCase;
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AutomapperModule.forRoot({ strategyInitializer: classes() })],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: AdsRepository,
|
||||||
|
useValue: mockAdRepository,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: Messager,
|
||||||
|
useValue: mockMessager,
|
||||||
|
},
|
||||||
|
CreateAdUseCase,
|
||||||
|
AdProfile,
|
||||||
|
{
|
||||||
|
provide: 'ParamsProvider',
|
||||||
|
useValue: mockDefaultParamsProvider,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
createAdUseCase = module.get<CreateAdUseCase>(CreateAdUseCase);
|
||||||
|
});
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(createAdUseCase).toBeDefined();
|
||||||
|
});
|
||||||
|
describe('execution', () => {
|
||||||
|
const newAdCommand = new CreateAdCommand(newAdRequest);
|
||||||
|
it('should create an new ad', async () => {
|
||||||
|
const newAd: Ad = await createAdUseCase.execute(newAdCommand);
|
||||||
|
expect(newAd.userUuid).toBe(newAdRequest.userUuid);
|
||||||
|
expect(newAd.uuid).toBeDefined();
|
||||||
|
});
|
||||||
|
it('should throw an error if the ad already exists', async () => {
|
||||||
|
await expect(
|
||||||
|
createAdUseCase.execute(newAdCommand),
|
||||||
|
).rejects.toBeInstanceOf(Error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Ad parameter default setting ', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockAdRepository.create.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should define mimimal ad as 1 passager add', async () => {
|
||||||
|
const newAdCommand = new CreateAdCommand(minimalRecurrentAdREquest);
|
||||||
|
await createAdUseCase.execute(newAdCommand);
|
||||||
|
const expectedAdCreation = {
|
||||||
|
userUuid: minimalRecurrentAdREquest.userUuid,
|
||||||
|
frequency: minimalRecurrentAdREquest.frequency,
|
||||||
|
fromDate: minimalRecurrentAdREquest.fromDate,
|
||||||
|
toDate: minimalRecurrentAdREquest.toDate,
|
||||||
|
monTime: minimalRecurrentAdREquest.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().SEATS_PROVIDED,
|
||||||
|
passenger: mockDefaultParamsProvider.getParams().PASSENGER,
|
||||||
|
seatsPassenger: mockDefaultParamsProvider.getParams().SEATS_REQUESTED,
|
||||||
|
strict: mockDefaultParamsProvider.getParams().STRICT,
|
||||||
|
addresses: {
|
||||||
|
create: minimalRecurrentAdREquest.addresses as Address[],
|
||||||
|
},
|
||||||
|
createdAt: undefined,
|
||||||
|
} as AdCreation;
|
||||||
|
|
||||||
|
expect(mockAdRepository.create).toBeCalledWith(expectedAdCreation);
|
||||||
|
});
|
||||||
|
it('should create an passengerAd with addresses without position ', async () => {
|
||||||
|
const newPunctualPassengerAdRequest: CreateAdRequest = {
|
||||||
|
userUuid: '113e0000-0000-4000-a000-000000000000',
|
||||||
|
passenger: true,
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
departure: new Date('05-22-2023 09:36'),
|
||||||
|
|
||||||
|
marginDurations: {
|
||||||
|
mon: undefined,
|
||||||
|
tue: undefined,
|
||||||
|
wed: undefined,
|
||||||
|
thu: undefined,
|
||||||
|
fri: undefined,
|
||||||
|
sat: undefined,
|
||||||
|
sun: undefined,
|
||||||
|
},
|
||||||
|
seatsPassenger: 1,
|
||||||
|
addresses: [mockAddressWithoutPos1, mockAddressWithoutPos2],
|
||||||
|
schedule: {},
|
||||||
|
};
|
||||||
|
const newAdCommand = new CreateAdCommand(newPunctualPassengerAdRequest);
|
||||||
|
await createAdUseCase.execute(newAdCommand);
|
||||||
|
const expectedAdCreation = {
|
||||||
|
userUuid: newPunctualPassengerAdRequest.userUuid,
|
||||||
|
frequency: newPunctualPassengerAdRequest.frequency,
|
||||||
|
fromDate: newPunctualPassengerAdRequest.departure,
|
||||||
|
toDate: newPunctualPassengerAdRequest.departure,
|
||||||
|
monTime: '09:36',
|
||||||
|
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: false,
|
||||||
|
seatsDriver: 0,
|
||||||
|
passenger: newPunctualPassengerAdRequest.passenger,
|
||||||
|
seatsPassenger: newPunctualPassengerAdRequest.seatsPassenger,
|
||||||
|
strict: mockDefaultParamsProvider.getParams().STRICT,
|
||||||
|
addresses: {
|
||||||
|
create: newPunctualPassengerAdRequest.addresses as Address[],
|
||||||
|
},
|
||||||
|
createdAt: undefined,
|
||||||
|
} as AdCreation;
|
||||||
|
expect(mockAdRepository.create).toBeCalledWith(expectedAdCreation);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,10 +1,10 @@
|
||||||
import { NotFoundException } from '@nestjs/common';
|
import { NotFoundException } from '@nestjs/common';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { Messager } from '../../adapters/secondaries/messager';
|
import { Messager } from '../../../adapters/secondaries/messager';
|
||||||
import { FindAdByUuidQuery } from '../../queries/find-ad-by-uuid.query';
|
import { FindAdByUuidQuery } from '../../../queries/find-ad-by-uuid.query';
|
||||||
import { AdsRepository } from '../../adapters/secondaries/ads.repository';
|
import { AdsRepository } from '../../../adapters/secondaries/ads.repository';
|
||||||
import { FindAdByUuidUseCase } from '../../domain/usecases/find-ad-by-uuid.usecase';
|
import { FindAdByUuidUseCase } from '../../../domain/usecases/find-ad-by-uuid.usecase';
|
||||||
import { FindAdByUuidRequest } from '../../domain/dtos/find-ad-by-uuid.request';
|
import { FindAdByUuidRequest } from '../../../domain/dtos/find-ad-by-uuid.request';
|
||||||
|
|
||||||
const mockAd = {
|
const mockAd = {
|
||||||
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
uuid: 'bb281075-1b98-4456-89d6-c643d3044a91',
|
||||||
|
@ -18,7 +18,7 @@ const mockAdRepository = {
|
||||||
return Promise.resolve(mockAd);
|
return Promise.resolve(mockAd);
|
||||||
})
|
})
|
||||||
.mockImplementation(() => {
|
.mockImplementation(() => {
|
||||||
return Promise.resolve(undefined);
|
return Promise.resolve(null);
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { mappingKeyToFrequency } 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);
|
||||||
|
});
|
||||||
|
it('should return recurent', () => {
|
||||||
|
expect(mappingKeyToFrequency(2)).toBe(Frequency.RECURRENT);
|
||||||
|
});
|
||||||
|
it('should return undefined', () => {
|
||||||
|
expect(mappingKeyToFrequency(0)).toBeUndefined();
|
||||||
|
expect(mappingKeyToFrequency(3)).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { hasProperDriverSeats } from '../../../domain/dtos/validators/has-driver-seats';
|
||||||
|
|
||||||
|
describe('driver and/or driver seats validator', () => {
|
||||||
|
it('should validate if driver and drivers seats is not provided ', () => {
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: undefined },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: false },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: null },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
it('should not validate if driver is set to true but not the related seats is not provided or 0', () => {
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: true },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: true, seatsDriver: 0 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: true, seatsDriver: undefined },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: true, seatsDriver: null },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
it('should not validate if driver seats are provided but driver is not set or set to false ', () => {
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: false, seatsDriver: 1 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: undefined, seatsDriver: 1 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperDriverSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { driver: null, seatsDriver: 1 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { hasProperPassengerSeats } from '../../../domain/dtos/validators/has-passenger-seats';
|
||||||
|
|
||||||
|
describe('driver and/or passenger seats validator', () => {
|
||||||
|
it('should validate if passenger and passengers seats is not provided ', () => {
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: undefined },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: false },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: null },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
});
|
||||||
|
it('should not validate if passenger is set to true but not the related seats is not provided or 0', () => {
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: true },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: true, seatsPassenger: 0 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: true, seatsPassenger: undefined },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: true, seatsPassenger: null },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
it('should not validate if passenger seats are provided but passenger is not set or set to false ', () => {
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: false, seatsPassenger: 1 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: undefined, seatsPassenger: 1 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
expect(
|
||||||
|
hasProperPassengerSeats({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: { passenger: null, seatsPassenger: 1 },
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { AddressRequestDTO } from '../../../domain/dtos/create.address.request';
|
||||||
|
import { hasProperPositionIndexes } from '../../../domain/dtos/validators/address-position';
|
||||||
|
describe('addresses position validators', () => {
|
||||||
|
const mockAddress1: AddressRequestDTO = {
|
||||||
|
lon: 48.68944505415954,
|
||||||
|
lat: 6.176510296462267,
|
||||||
|
houseNumber: '5',
|
||||||
|
street: 'Avenue Foch',
|
||||||
|
locality: 'Nancy',
|
||||||
|
postalCode: '54000',
|
||||||
|
country: 'France',
|
||||||
|
};
|
||||||
|
const mockAddress2: AddressRequestDTO = {
|
||||||
|
lon: 48.8566,
|
||||||
|
lat: 2.3522,
|
||||||
|
locality: 'Paris',
|
||||||
|
postalCode: '75000',
|
||||||
|
country: 'France',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockAddress3: AddressRequestDTO = {
|
||||||
|
lon: 49.2628,
|
||||||
|
lat: 4.0347,
|
||||||
|
locality: 'Reims',
|
||||||
|
postalCode: '51454',
|
||||||
|
country: 'France',
|
||||||
|
};
|
||||||
|
it('should validate if none of position is definded ', () => {
|
||||||
|
expect(
|
||||||
|
hasProperPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
it('should throw an error if position are partialy defined ', () => {
|
||||||
|
mockAddress1.position = 0;
|
||||||
|
expect(
|
||||||
|
hasProperPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('should throw an error if position are partialy defined ', () => {
|
||||||
|
mockAddress1.position = 0;
|
||||||
|
mockAddress2.position = null;
|
||||||
|
mockAddress3.position = undefined;
|
||||||
|
expect(
|
||||||
|
hasProperPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if positions are not incremented ', () => {
|
||||||
|
mockAddress1.position = 0;
|
||||||
|
mockAddress2.position = 1;
|
||||||
|
mockAddress3.position = 1;
|
||||||
|
expect(
|
||||||
|
hasProperPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('should validate if all positions are defined and incremented', () => {
|
||||||
|
mockAddress1.position = 0;
|
||||||
|
mockAddress2.position = 1;
|
||||||
|
mockAddress3.position = 2;
|
||||||
|
expect(
|
||||||
|
hasProperPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||||
|
).toBeTruthy();
|
||||||
|
mockAddress1.position = 10;
|
||||||
|
mockAddress2.position = 0;
|
||||||
|
mockAddress3.position = 3;
|
||||||
|
expect(
|
||||||
|
hasProperPositionIndexes([mockAddress1, mockAddress2, mockAddress3]),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,113 @@
|
||||||
|
import { isPunctualOrRecurrent } from '../../../domain/dtos/validators/is-punctual-or-recurrent';
|
||||||
|
import { Frequency } from '../../../domain/types/frequency.enum';
|
||||||
|
|
||||||
|
describe('punctual or reccurent validators', () => {
|
||||||
|
describe('punctual case ', () => {
|
||||||
|
describe('valid cases', () => {
|
||||||
|
it('should validate with valid departure and empty schedule ', () => {
|
||||||
|
expect(
|
||||||
|
isPunctualOrRecurrent({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: {
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
departure: new Date('01-02-2023'),
|
||||||
|
schedule: {},
|
||||||
|
},
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('invalid cases ', () => {
|
||||||
|
it('should not validate with invalid departure and empty schedule and margin', () => {
|
||||||
|
expect(
|
||||||
|
isPunctualOrRecurrent({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: {
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
fromDate: new Date('20-10-2023'),
|
||||||
|
toDate: new Date('30-10-2023'),
|
||||||
|
},
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('should not validate with no empty schedule', () => {
|
||||||
|
expect(
|
||||||
|
isPunctualOrRecurrent({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: {
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
departure: new Date('01-02-2023'),
|
||||||
|
schedule: {
|
||||||
|
mon: '08:30',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('reccurent case ', () => {
|
||||||
|
describe('valid cases', () => {
|
||||||
|
it('should validate with valid from date, to date and non empty schedule ', () => {
|
||||||
|
expect(
|
||||||
|
isPunctualOrRecurrent({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: {
|
||||||
|
frequency: Frequency.RECURRENT,
|
||||||
|
fromDate: new Date('01-15-2023'),
|
||||||
|
toDate: new Date('06-30-2023'),
|
||||||
|
schedule: {
|
||||||
|
mon: '08:30',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('invalid cases ', () => {
|
||||||
|
it('should not validate with empty schedule ', () => {
|
||||||
|
expect(
|
||||||
|
isPunctualOrRecurrent({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: {
|
||||||
|
frequency: Frequency.RECURRENT,
|
||||||
|
fromDate: new Date('01-15-2023'),
|
||||||
|
toDate: new Date('06-30-2023'),
|
||||||
|
schedule: {},
|
||||||
|
},
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
it('should not validate with invalid from date to date and empty schedule and margin', () => {
|
||||||
|
expect(
|
||||||
|
isPunctualOrRecurrent({
|
||||||
|
value: undefined,
|
||||||
|
constraints: [],
|
||||||
|
targetName: '',
|
||||||
|
object: {
|
||||||
|
frequency: Frequency.RECURRENT,
|
||||||
|
departure: new Date('20-10-2023'),
|
||||||
|
toDate: new Date('30-10-2023'),
|
||||||
|
},
|
||||||
|
property: '',
|
||||||
|
}),
|
||||||
|
).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,92 @@
|
||||||
|
import { CreateAdRequest } from '../../../domain/dtos/create-ad.request';
|
||||||
|
import { ScheduleDTO } from '../../../domain/dtos/create.schedule.dto';
|
||||||
|
import { RecurrentNormaliser } from '../../../domain/entities/recurrent-normaliser';
|
||||||
|
import { Frequency } from '../../../domain/types/frequency.enum';
|
||||||
|
describe('recurrent normalizer transformer for punctual ad ', () => {
|
||||||
|
const recurrentNormaliser = new RecurrentNormaliser();
|
||||||
|
it('should transform punctual ad into recurrent ad ', () => {
|
||||||
|
const punctualAd: CreateAdRequest = {
|
||||||
|
userUuid: '',
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
departure: new Date('05-03-2023 12:39:39 '),
|
||||||
|
schedule: {} as ScheduleDTO,
|
||||||
|
addresses: [],
|
||||||
|
};
|
||||||
|
expect(recurrentNormaliser.fromDateResolver(punctualAd)).toBe(
|
||||||
|
punctualAd.departure,
|
||||||
|
);
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
it('should leave recurrent ad as is', () => {
|
||||||
|
const recurrentAd: CreateAdRequest = {
|
||||||
|
userUuid: '',
|
||||||
|
frequency: Frequency.RECURRENT,
|
||||||
|
schedule: {
|
||||||
|
mon: '08:30',
|
||||||
|
tue: '08:30',
|
||||||
|
wed: '09:00',
|
||||||
|
fri: '09:00',
|
||||||
|
},
|
||||||
|
addresses: [],
|
||||||
|
};
|
||||||
|
expect(recurrentNormaliser.fromDateResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.departure,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.toDateResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.departure,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.scheduleMonResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.schedule.mon,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.scheduleTueResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.schedule.tue,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.scheduleWedResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.schedule.wed,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.scheduleThuResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.schedule.thu,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.scheduleFriResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.schedule.fri,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.scheduleSatResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.schedule.sat,
|
||||||
|
);
|
||||||
|
expect(recurrentNormaliser.scheduleSunResolver(recurrentAd)).toBe(
|
||||||
|
recurrentAd.schedule.sun,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('should pass for each day of the week of a deprarture ', () => {
|
||||||
|
const punctualAd: CreateAdRequest = {
|
||||||
|
userUuid: '',
|
||||||
|
frequency: Frequency.PUNCTUAL,
|
||||||
|
departure: undefined,
|
||||||
|
schedule: {} as ScheduleDTO,
|
||||||
|
addresses: [],
|
||||||
|
};
|
||||||
|
punctualAd.departure = new Date('05-01-2023 ');
|
||||||
|
expect(recurrentNormaliser.scheduleMonResolver(punctualAd)).toBe('00:00');
|
||||||
|
punctualAd.departure = new Date('05-02-2023 06:32:45');
|
||||||
|
expect(recurrentNormaliser.scheduleTueResolver(punctualAd)).toBe('06:32');
|
||||||
|
punctualAd.departure = new Date('05-03-2023 10:21');
|
||||||
|
expect(recurrentNormaliser.scheduleWedResolver(punctualAd)).toBe('10:21');
|
||||||
|
punctualAd.departure = new Date('05-04-2023 11:06:00');
|
||||||
|
expect(recurrentNormaliser.scheduleThuResolver(punctualAd)).toBe('11:06');
|
||||||
|
punctualAd.departure = new Date('05-05-2023 05:20');
|
||||||
|
expect(recurrentNormaliser.scheduleFriResolver(punctualAd)).toBe('05:20');
|
||||||
|
punctualAd.departure = new Date('05-06-2023');
|
||||||
|
expect(recurrentNormaliser.scheduleSatResolver(punctualAd)).toBe('00:00');
|
||||||
|
punctualAd.departure = new Date('05-07-2023');
|
||||||
|
expect(recurrentNormaliser.scheduleSunResolver(punctualAd)).toBe('00:00');
|
||||||
|
});
|
||||||
|
});
|
|
@ -85,7 +85,6 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
|
||||||
data: entity,
|
data: entity,
|
||||||
include: include,
|
include: include,
|
||||||
});
|
});
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
if (e instanceof Prisma.PrismaClientKnownRequestError) {
|
||||||
|
|
Loading…
Reference in New Issue