feat: add Prisma ORM to backend with spaces migration and PrismaService
This commit is contained in:
parent
71a4c63926
commit
08eddc1d9a
@ -6,7 +6,9 @@
|
||||
"build": "nest build",
|
||||
"start": "nest start",
|
||||
"start:dev": "nest start --watch",
|
||||
"start:prod": "node dist/main"
|
||||
"start:prod": "node dist/main",
|
||||
"db:migrate": "prisma migrate deploy",
|
||||
"db:generate": "prisma generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
@ -14,6 +16,7 @@
|
||||
"@nestjs/jwt": "^10.0.0",
|
||||
"@nestjs/passport": "^10.0.0",
|
||||
"@nestjs/platform-express": "^10.0.0",
|
||||
"@prisma/client": "^5.0.0",
|
||||
"passport": "^0.7.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
@ -24,6 +27,7 @@
|
||||
"@nestjs/schematics": "^10.0.0",
|
||||
"@types/node": "^20.0.0",
|
||||
"@types/passport-jwt": "^4.0.0",
|
||||
"prisma": "^5.0.0",
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
17
backend/prisma/migrations/20260615000000_init/migration.sql
Normal file
17
backend/prisma/migrations/20260615000000_init/migration.sql
Normal file
@ -0,0 +1,17 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "reservas" (
|
||||
"id" TEXT NOT NULL,
|
||||
"resourceId" TEXT NOT NULL,
|
||||
"resourceName" TEXT NOT NULL,
|
||||
"date" TEXT NOT NULL,
|
||||
"startTime" TEXT NOT NULL,
|
||||
"endTime" TEXT NOT NULL,
|
||||
"author" TEXT NOT NULL,
|
||||
"notes" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "reservas_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "reservas_resourceName_date_startTime_key" ON "reservas"("resourceName", "date", "startTime");
|
||||
3
backend/prisma/migrations/migration_lock.toml
Normal file
3
backend/prisma/migrations/migration_lock.toml
Normal file
@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "postgresql"
|
||||
23
backend/prisma/schema.prisma
Normal file
23
backend/prisma/schema.prisma
Normal file
@ -0,0 +1,23 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model Reserva {
|
||||
id String @id @default(cuid())
|
||||
resourceId String
|
||||
resourceName String
|
||||
date String // "YYYY-MM-DD"
|
||||
startTime String // "HH:mm"
|
||||
endTime String // "HH:mm"
|
||||
author String
|
||||
notes String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([resourceName, date, startTime])
|
||||
@@map("reservas")
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PrismaModule } from './prisma/prisma.module';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { CmsModule } from './cms/cms.module';
|
||||
import { DirectoryModule } from './directory/directory.module';
|
||||
@ -8,6 +9,7 @@ import { TicketingModule } from './ticketing/ticketing.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
AuthModule,
|
||||
CmsModule,
|
||||
DirectoryModule,
|
||||
@ -17,3 +19,4 @@ import { TicketingModule } from './ticketing/ticketing.module';
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
|
||||
9
backend/src/prisma/prisma.module.ts
Normal file
9
backend/src/prisma/prisma.module.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Global, Module } from '@nestjs/common';
|
||||
import { PrismaService } from './prisma.service';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
providers: [PrismaService],
|
||||
exports: [PrismaService],
|
||||
})
|
||||
export class PrismaModule {}
|
||||
16
backend/src/prisma/prisma.service.ts
Normal file
16
backend/src/prisma/prisma.service.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
@Injectable()
|
||||
export class PrismaService
|
||||
extends PrismaClient
|
||||
implements OnModuleInit, OnModuleDestroy
|
||||
{
|
||||
async onModuleInit() {
|
||||
await this.$connect();
|
||||
}
|
||||
|
||||
async onModuleDestroy() {
|
||||
await this.$disconnect();
|
||||
}
|
||||
}
|
||||
@ -19,7 +19,7 @@ export class SpacesController {
|
||||
* Devuelve todas las reservas (opcionalmente filtradas por fecha)
|
||||
*/
|
||||
@Get()
|
||||
findAll(@Query('date') date?: string) {
|
||||
async findAll(@Query('date') date?: string) {
|
||||
return this.spacesService.findAll(date);
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ export class SpacesController {
|
||||
* Crea una nueva reserva
|
||||
*/
|
||||
@Post()
|
||||
create(@Body() dto: CreateReservaDto) {
|
||||
async create(@Body() dto: CreateReservaDto) {
|
||||
return this.spacesService.create(dto);
|
||||
}
|
||||
|
||||
@ -37,8 +37,8 @@ export class SpacesController {
|
||||
* Elimina una reserva por ID
|
||||
*/
|
||||
@Delete(':id')
|
||||
delete(@Param('id') id: string) {
|
||||
this.spacesService.delete(id);
|
||||
async delete(@Param('id') id: string) {
|
||||
await this.spacesService.delete(id);
|
||||
return { message: 'Reserva eliminada correctamente.' };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { SpacesController } from './spaces.controller';
|
||||
import { SpacesService } from './spaces.service';
|
||||
|
||||
@Module({})
|
||||
@Module({
|
||||
controllers: [SpacesController],
|
||||
providers: [SpacesService],
|
||||
})
|
||||
export class SpacesModule {}
|
||||
|
||||
@ -1,26 +1,28 @@
|
||||
import { Injectable, ConflictException } from '@nestjs/common';
|
||||
import { CreateReservaDto, Reserva } from './reserva.dto';
|
||||
import { Injectable, ConflictException, NotFoundException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { CreateReservaDto } from './reserva.dto';
|
||||
|
||||
@Injectable()
|
||||
export class SpacesService {
|
||||
private reservas: Reserva[] = [];
|
||||
private idCounter = 1;
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
findAll(date?: string): Reserva[] {
|
||||
if (date) {
|
||||
return this.reservas.filter((r) => r.date === date);
|
||||
}
|
||||
return this.reservas;
|
||||
async findAll(date?: string) {
|
||||
return this.prisma.reserva.findMany({
|
||||
where: date ? { date } : undefined,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
}
|
||||
|
||||
create(dto: CreateReservaDto): Reserva {
|
||||
// Verificar conflicto: mismo recurso, mismo día, mismo horario de inicio
|
||||
const conflict = this.reservas.find(
|
||||
(r) =>
|
||||
r.resourceName === dto.resourceName &&
|
||||
r.date === dto.date &&
|
||||
r.startTime === dto.startTime,
|
||||
);
|
||||
async create(dto: CreateReservaDto) {
|
||||
const conflict = await this.prisma.reserva.findUnique({
|
||||
where: {
|
||||
resourceName_date_startTime: {
|
||||
resourceName: dto.resourceName,
|
||||
date: dto.date,
|
||||
startTime: dto.startTime,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (conflict) {
|
||||
throw new ConflictException(
|
||||
@ -28,17 +30,16 @@ export class SpacesService {
|
||||
);
|
||||
}
|
||||
|
||||
const newReserva: Reserva = {
|
||||
...dto,
|
||||
id: String(this.idCounter++),
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
this.reservas.unshift(newReserva);
|
||||
return newReserva;
|
||||
return this.prisma.reserva.create({ data: dto });
|
||||
}
|
||||
|
||||
delete(id: string): void {
|
||||
this.reservas = this.reservas.filter((r) => r.id !== id);
|
||||
async delete(id: string): Promise<void> {
|
||||
const reserva = await this.prisma.reserva.findUnique({ where: { id } });
|
||||
|
||||
if (!reserva) {
|
||||
throw new NotFoundException(`Reserva con id "${id}" no encontrada.`);
|
||||
}
|
||||
|
||||
await this.prisma.reserva.delete({ where: { id } });
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user