update initial migration

This commit is contained in:
sbriat 2023-05-04 10:05:23 +02:00
parent 706ea81b9f
commit be529c111a
12 changed files with 222 additions and 50 deletions

View File

@ -58,3 +58,6 @@ CREATE INDEX "ad_fromDate_idx" ON "ad"("fromDate");
-- CreateIndex
CREATE INDEX "ad_toDate_idx" ON "ad"("toDate");
-- AddForeignKey
ALTER TABLE "address" ADD CONSTRAINT "address_adUuid_fkey" FOREIGN KEY ("adUuid") REFERENCES "ad"("uuid") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -11,20 +11,20 @@ datasource db {
}
model Ad {
uuid String @id @default(uuid()) @db.Uuid
userUuid String @db.Uuid
uuid String @id @default(uuid()) @db.Uuid
userUuid String @db.Uuid
driver Boolean
passenger Boolean
frequency Int
fromDate DateTime @db.Date
toDate DateTime @db.Date
monTime DateTime @db.Timestamptz()
tueTime DateTime @db.Timestamptz()
wedTime DateTime @db.Timestamptz()
thuTime DateTime @db.Timestamptz()
friTime DateTime @db.Timestamptz()
satTime DateTime @db.Timestamptz()
sunTime DateTime @db.Timestamptz()
fromDate DateTime @db.Date
toDate DateTime @db.Date
monTime DateTime @db.Timestamptz()
tueTime DateTime @db.Timestamptz()
wedTime DateTime @db.Timestamptz()
thuTime DateTime @db.Timestamptz()
friTime DateTime @db.Timestamptz()
satTime DateTime @db.Timestamptz()
sunTime DateTime @db.Timestamptz()
monMargin Int
tueMargin Int
wedMargin Int
@ -32,10 +32,11 @@ model Ad {
friMargin Int
satMargin Int
sunMargin Int
seatsDriver Int @db.SmallInt
seatsPassenger Int @db.SmallInt
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
seatsDriver Int @db.SmallInt
seatsPassenger Int @db.SmallInt
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
addresses Address[]
@@index([driver])
@@index([passenger])
@ -57,6 +58,7 @@ model Address {
type Int @db.SmallInt
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
Ad Ad @relation(fields: [adUuid], references: [uuid])
@@map("address")
}

View File

@ -1,14 +1,14 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ConfigurationModule } from './modules/configuration/configuration.module';
// import { HealthModule } from './modules/health/health.module';
import { HealthModule } from './modules/health/health.module';
import { AdModule } from './modules/ad/ad.module';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
ConfigurationModule,
// HealthModule,
HealthModule,
AdModule,
],
controllers: [],

View File

@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { AdRepository } from '../../../database/src/domain/ad-repository';
import { AdRepository } from '../../../database/domain/ad-repository';
import { Ad } from '../../domain/entities/ad';
@Injectable()

View File

@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { PrismaClientKnownRequestError } from '@prisma/client/runtime';
import { Prisma } from '@prisma/client';
import { DatabaseException } from '../../exceptions/database.exception';
import { ICollection } from '../../interfaces/collection.interface';
import { IRepository } from '../../interfaces/repository.interface';
@ -45,9 +45,9 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
return entity;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
PrismaClientKnownRequestError.name,
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
@ -66,8 +66,11 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
return entity;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
throw new DatabaseException(PrismaClientKnownRequestError.name, e.code);
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
Prisma.PrismaClientKnownRequestError.name,
e.code,
);
} else {
throw new DatabaseException();
}
@ -85,9 +88,9 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
return res;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
PrismaClientKnownRequestError.name,
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
@ -105,9 +108,9 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
});
return updatedEntity;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
PrismaClientKnownRequestError.name,
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
@ -131,9 +134,9 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
return updatedEntity;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
PrismaClientKnownRequestError.name,
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
@ -151,9 +154,9 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
return entity;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
PrismaClientKnownRequestError.name,
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
@ -171,9 +174,63 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
return entity;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
PrismaClientKnownRequestError.name,
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async findAllByQuery(
include: string[],
where: string[],
): Promise<ICollection<T>> {
const query = `SELECT ${include.join(',')} FROM ${
this._model
} WHERE ${where.join(' AND ')}`;
const data: T[] = await this._prisma.$queryRawUnsafe(query);
return Promise.resolve({
data,
total: data.length,
});
}
async createWithFields(fields: object): Promise<number> {
try {
const command = `INSERT INTO ${this._model} ("${Object.keys(fields).join(
'","',
)}") VALUES (${Object.values(fields).join(',')})`;
return await this._prisma.$executeRawUnsafe(command);
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
} else {
throw new DatabaseException();
}
}
}
async updateWithFields(uuid: string, entity: object): Promise<number> {
entity['"updatedAt"'] = `to_timestamp(${Date.now()} / 1000.0)`;
const values = Object.keys(entity).map((key) => `${key} = ${entity[key]}`);
try {
const command = `UPDATE ${this._model} SET ${values.join(
', ',
)} WHERE uuid = '${uuid}'`;
return await this._prisma.$executeRawUnsafe(command);
} catch (e) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);
@ -188,9 +245,9 @@ export abstract class PrismaRepository<T> implements IRepository<T> {
await this._prisma.$queryRaw`SELECT 1`;
return true;
} catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
if (e instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseException(
PrismaClientKnownRequestError.name,
Prisma.PrismaClientKnownRequestError.name,
e.code,
e.message,
);

View File

@ -1,6 +1,6 @@
import { Module } from '@nestjs/common';
import { PrismaService } from './src/adapters/secondaries/prisma-service';
import { AdRepository } from './src/domain/ad-repository';
import { PrismaService } from './adapters/secondaries/prisma-service';
import { AdRepository } from './domain/ad-repository';
@Module({
providers: [PrismaService, AdRepository],

View File

@ -1,9 +1,9 @@
import { Injectable } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { PrismaService } from '../../src/adapters/secondaries/prisma-service';
import { PrismaRepository } from '../../src/adapters/secondaries/prisma-repository.abstract';
import { DatabaseException } from '../../src/exceptions/database.exception';
import { PrismaClientKnownRequestError } from '@prisma/client/runtime';
import { PrismaService } from '../../adapters/secondaries/prisma-service';
import { PrismaRepository } from '../../adapters/secondaries/prisma-repository.abstract';
import { DatabaseException } from '../../exceptions/database.exception';
import { Prisma } from '@prisma/client';
class FakeEntity {
uuid?: string;
@ -57,10 +57,40 @@ const mockPrismaService = {
return Promise.resolve([fakeEntities, fakeEntities.length]);
}),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
$queryRawUnsafe: jest.fn().mockImplementation((query?: string) => {
return Promise.resolve(fakeEntities);
}),
$executeRawUnsafe: jest
.fn()
.mockResolvedValueOnce(fakeEntityCreated)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((fields: object) => {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((fields: object) => {
throw new Error('an unknown error');
})
.mockResolvedValueOnce(fakeEntityCreated)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((fields: object) => {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((fields: object) => {
throw new Error('an unknown error');
}),
$queryRaw: jest
.fn()
.mockImplementationOnce(() => {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
@ -69,7 +99,7 @@ const mockPrismaService = {
return true;
})
.mockImplementation(() => {
throw new PrismaClientKnownRequestError('Database unavailable', {
throw new Prisma.PrismaClientKnownRequestError('Database unavailable', {
code: 'code',
clientVersion: 'version',
});
@ -80,7 +110,7 @@ const mockPrismaService = {
.mockResolvedValueOnce(fakeEntityCreated)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((params?: any) => {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
@ -109,7 +139,7 @@ const mockPrismaService = {
}
if (!entity && params?.where?.uuid == 'unknown') {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
@ -131,7 +161,7 @@ const mockPrismaService = {
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((params?: any) => {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
@ -145,14 +175,14 @@ const mockPrismaService = {
.fn()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((params?: any) => {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((params?: any) => {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
@ -182,7 +212,7 @@ const mockPrismaService = {
.fn()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((params?: any) => {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
@ -206,7 +236,7 @@ const mockPrismaService = {
.fn()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.mockImplementationOnce((params?: any) => {
throw new PrismaClientKnownRequestError('unknown request', {
throw new Prisma.PrismaClientKnownRequestError('unknown request', {
code: 'code',
clientVersion: 'version',
});
@ -440,6 +470,86 @@ describe('PrismaRepository', () => {
});
});
describe('findAllByquery', () => {
it('should return an array of entities', async () => {
const entities = await fakeRepository.findAllByQuery(
['uuid', 'name'],
['name is not null'],
);
expect(entities).toStrictEqual({
data: fakeEntities,
total: fakeEntities.length,
});
});
});
describe('createWithFields', () => {
it('should create an entity', async () => {
jest.spyOn(prisma, '$queryRawUnsafe');
const newEntity = await fakeRepository.createWithFields({
uuid: '804319b3-a09b-4491-9f82-7976bfce0aff',
name: 'my-name',
});
expect(newEntity).toBe(fakeEntityCreated);
expect(prisma.$queryRawUnsafe).toHaveBeenCalledTimes(1);
});
it('should throw a DatabaseException for client error', async () => {
await expect(
fakeRepository.createWithFields({
uuid: '804319b3-a09b-4491-9f82-7976bfce0aff',
name: 'my-name',
}),
).rejects.toBeInstanceOf(DatabaseException);
});
it('should throw a DatabaseException if uuid is not found', async () => {
await expect(
fakeRepository.createWithFields({
name: 'my-name',
}),
).rejects.toBeInstanceOf(DatabaseException);
});
});
describe('updateWithFields', () => {
it('should update an entity', async () => {
jest.spyOn(prisma, '$queryRawUnsafe');
const updatedEntity = await fakeRepository.updateWithFields(
'804319b3-a09b-4491-9f82-7976bfce0aff',
{
name: 'my-name',
},
);
expect(updatedEntity).toBe(fakeEntityCreated);
expect(prisma.$queryRawUnsafe).toHaveBeenCalledTimes(1);
});
it('should throw a DatabaseException for client error', async () => {
await expect(
fakeRepository.updateWithFields(
'804319b3-a09b-4491-9f82-7976bfce0aff',
{
name: 'my-name',
},
),
).rejects.toBeInstanceOf(DatabaseException);
});
it('should throw a DatabaseException if uuid is not found', async () => {
await expect(
fakeRepository.updateWithFields(
'804319b3-a09b-4491-9f82-7976bfce0aff',
{
name: 'my-name',
},
),
).rejects.toBeInstanceOf(DatabaseException);
});
});
describe('healthCheck', () => {
it('should throw a DatabaseException for client error', async () => {
await expect(fakeRepository.healthCheck()).rejects.toBeInstanceOf(