feat: integrate Prisma for database management
This commit is contained in:
2
.env.example
Normal file
2
.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
DATABASE_URL="postgres://user:secret123@postgres:5432/db"
|
||||
PORT=3000
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -54,3 +54,5 @@ pids
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
/generated/prisma
|
||||
|
||||
944
package-lock.json
generated
944
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,8 @@
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/mapped-types": "*",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@prisma/client": "^7.4.1",
|
||||
"dotenv": "^17.3.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
@@ -43,6 +45,7 @@
|
||||
"globals": "^16.0.0",
|
||||
"jest": "^30.0.0",
|
||||
"prettier": "^3.4.2",
|
||||
"prisma": "^7.4.1",
|
||||
"source-map-support": "^0.5.21",
|
||||
"supertest": "^7.0.0",
|
||||
"ts-jest": "^29.2.5",
|
||||
|
||||
14
prisma.config.ts
Normal file
14
prisma.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// This file was generated by Prisma, and assumes you have installed the following:
|
||||
// npm install --save-dev prisma dotenv
|
||||
import "dotenv/config";
|
||||
import { defineConfig } from "prisma/config";
|
||||
|
||||
export default defineConfig({
|
||||
schema: "prisma/schema.prisma",
|
||||
migrations: {
|
||||
path: "prisma/migrations",
|
||||
},
|
||||
datasource: {
|
||||
url: process.env["DATABASE_URL"],
|
||||
},
|
||||
});
|
||||
229
prisma/migrations/20260226161313_init/migration.sql
Normal file
229
prisma/migrations/20260226161313_init/migration.sql
Normal file
@@ -0,0 +1,229 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "categories" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"name" VARCHAR(100) NOT NULL,
|
||||
"description" TEXT,
|
||||
|
||||
CONSTRAINT "categories_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "roles" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"name" VARCHAR(50) NOT NULL,
|
||||
"description" TEXT,
|
||||
|
||||
CONSTRAINT "roles_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "users" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"external_uid" VARCHAR(255) NOT NULL,
|
||||
"role_id" BIGINT NOT NULL,
|
||||
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "tickets" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"title" VARCHAR(255) NOT NULL,
|
||||
"description" TEXT,
|
||||
"status" VARCHAR(30) NOT NULL,
|
||||
"priority" VARCHAR(30),
|
||||
"category_id" BIGINT,
|
||||
"created_by_user_id" BIGINT NOT NULL,
|
||||
"assigned_to_user_id" BIGINT,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"closed_at" TIMESTAMPTZ,
|
||||
"ticket_number" VARCHAR(30) NOT NULL,
|
||||
|
||||
CONSTRAINT "tickets_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ticket_messages" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"ticket_id" BIGINT NOT NULL,
|
||||
"author_id" BIGINT NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"is_internal" BOOLEAN NOT NULL DEFAULT false,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ticket_messages_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ticket_attachments" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"ticket_id" BIGINT NOT NULL,
|
||||
"message_id" BIGINT,
|
||||
"uploaded_by" BIGINT NOT NULL,
|
||||
"file_name" VARCHAR(255),
|
||||
"file_url" TEXT NOT NULL,
|
||||
"file_size" BIGINT,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ticket_attachments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ticket_invitations" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"ticket_id" BIGINT NOT NULL,
|
||||
"inviter_id" BIGINT NOT NULL,
|
||||
"invitee_id" BIGINT NOT NULL,
|
||||
"status" VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
"message" TEXT,
|
||||
"created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"responded_at" TIMESTAMPTZ,
|
||||
|
||||
CONSTRAINT "ticket_invitations_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ticket_participants" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"ticket_id" BIGINT NOT NULL,
|
||||
"user_id" BIGINT NOT NULL,
|
||||
"added_by" BIGINT NOT NULL,
|
||||
"added_via" VARCHAR(20) NOT NULL,
|
||||
"can_edit" BOOLEAN NOT NULL DEFAULT false,
|
||||
"can_comment" BOOLEAN NOT NULL DEFAULT true,
|
||||
"joined_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ticket_participants_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ticket_status_history" (
|
||||
"id" BIGSERIAL NOT NULL,
|
||||
"ticket_id" BIGINT NOT NULL,
|
||||
"old_status" VARCHAR(30),
|
||||
"new_status" VARCHAR(30) NOT NULL,
|
||||
"changed_by" BIGINT NOT NULL,
|
||||
"changed_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ticket_status_history_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "categories_name_key" ON "categories"("name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "roles_name_key" ON "roles"("name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_external_uid_key" ON "users"("external_uid");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_users_external_uid" ON "users"("external_uid");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "tickets_ticket_number_key" ON "tickets"("ticket_number");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_tickets_assigned_to" ON "tickets"("assigned_to_user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_tickets_created_at" ON "tickets"("created_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_tickets_created_by" ON "tickets"("created_by_user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_tickets_status" ON "tickets"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_tickets_ticket_number" ON "tickets"("ticket_number");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_messages_ticket_id" ON "ticket_messages"("ticket_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_invitations_created_at" ON "ticket_invitations"("created_at");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_invitations_invitee_id" ON "ticket_invitations"("invitee_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_invitations_inviter_id" ON "ticket_invitations"("inviter_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_invitations_status" ON "ticket_invitations"("status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_invitations_ticket_id" ON "ticket_invitations"("ticket_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ticket_invitations_ticket_id_invitee_id_status_key" ON "ticket_invitations"("ticket_id", "invitee_id", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_participants_added_by" ON "ticket_participants"("added_by");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_participants_ticket_id" ON "ticket_participants"("ticket_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_participants_user_id" ON "ticket_participants"("user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ticket_participants_ticket_id_user_id_key" ON "ticket_participants"("ticket_id", "user_id");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "idx_history_ticket_id" ON "ticket_status_history"("ticket_id");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "users" ADD CONSTRAINT "users_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "roles"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "tickets" ADD CONSTRAINT "tickets_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "categories"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "tickets" ADD CONSTRAINT "tickets_created_by_user_id_fkey" FOREIGN KEY ("created_by_user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "tickets" ADD CONSTRAINT "tickets_assigned_to_user_id_fkey" FOREIGN KEY ("assigned_to_user_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_messages" ADD CONSTRAINT "ticket_messages_ticket_id_fkey" FOREIGN KEY ("ticket_id") REFERENCES "tickets"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_messages" ADD CONSTRAINT "ticket_messages_author_id_fkey" FOREIGN KEY ("author_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_attachments" ADD CONSTRAINT "ticket_attachments_ticket_id_fkey" FOREIGN KEY ("ticket_id") REFERENCES "tickets"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_attachments" ADD CONSTRAINT "ticket_attachments_message_id_fkey" FOREIGN KEY ("message_id") REFERENCES "ticket_messages"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_attachments" ADD CONSTRAINT "ticket_attachments_uploaded_by_fkey" FOREIGN KEY ("uploaded_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_invitations" ADD CONSTRAINT "ticket_invitations_ticket_id_fkey" FOREIGN KEY ("ticket_id") REFERENCES "tickets"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_invitations" ADD CONSTRAINT "ticket_invitations_inviter_id_fkey" FOREIGN KEY ("inviter_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_invitations" ADD CONSTRAINT "ticket_invitations_invitee_id_fkey" FOREIGN KEY ("invitee_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_participants" ADD CONSTRAINT "ticket_participants_ticket_id_fkey" FOREIGN KEY ("ticket_id") REFERENCES "tickets"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_participants" ADD CONSTRAINT "ticket_participants_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_participants" ADD CONSTRAINT "ticket_participants_added_by_fkey" FOREIGN KEY ("added_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_status_history" ADD CONSTRAINT "ticket_status_history_ticket_id_fkey" FOREIGN KEY ("ticket_id") REFERENCES "tickets"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ticket_status_history" ADD CONSTRAINT "ticket_status_history_changed_by_fkey" FOREIGN KEY ("changed_by") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
3
prisma/migrations/migration_lock.toml
Normal file
3
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 (e.g., Git)
|
||||
provider = "postgresql"
|
||||
184
prisma/schema.prisma
Normal file
184
prisma/schema.prisma
Normal file
@@ -0,0 +1,184 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
model Category {
|
||||
id BigInt @id @default(autoincrement())
|
||||
name String @unique @db.VarChar(100)
|
||||
description String?
|
||||
|
||||
tickets Ticket[]
|
||||
|
||||
@@map("categories")
|
||||
}
|
||||
|
||||
model Role {
|
||||
id BigInt @id @default(autoincrement())
|
||||
name String @unique @db.VarChar(50)
|
||||
description String?
|
||||
|
||||
users User[]
|
||||
|
||||
@@map("roles")
|
||||
}
|
||||
|
||||
model User {
|
||||
id BigInt @id @default(autoincrement())
|
||||
external_uid String @unique @db.VarChar(255)
|
||||
role_id BigInt
|
||||
is_active Boolean @default(true)
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
role Role @relation(fields: [role_id], references: [id])
|
||||
tickets_created Ticket[] @relation("CreatedBy")
|
||||
tickets_assigned Ticket[] @relation("AssignedTo")
|
||||
messages TicketMessage[]
|
||||
attachments_uploaded TicketAttachment[]
|
||||
invitations_sent TicketInvitation[] @relation("Inviter")
|
||||
invitations_received TicketInvitation[] @relation("Invitee")
|
||||
participants TicketParticipant[] @relation("Participant")
|
||||
participants_added TicketParticipant[] @relation("AddedBy")
|
||||
status_history_changed TicketStatusHistory[]
|
||||
|
||||
@@index([external_uid], name: "idx_users_external_uid")
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model Ticket {
|
||||
id BigInt @id @default(autoincrement())
|
||||
title String @db.VarChar(255)
|
||||
description String?
|
||||
status String @db.VarChar(30)
|
||||
priority String? @db.VarChar(30)
|
||||
category_id BigInt?
|
||||
created_by_user_id BigInt
|
||||
assigned_to_user_id BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
updated_at DateTime @default(now()) @db.Timestamptz
|
||||
closed_at DateTime? @db.Timestamptz
|
||||
/// Número de ticket legible para usuarios y APIs públicas (formato: TCK-YYYY-NNNNN). Este identificador se usa en lugar del ID interno en todas las comunicaciones externas.
|
||||
ticket_number String @unique @db.VarChar(30)
|
||||
|
||||
category Category? @relation(fields: [category_id], references: [id])
|
||||
created_by User @relation("CreatedBy", fields: [created_by_user_id], references: [id])
|
||||
assigned_to User? @relation("AssignedTo", fields: [assigned_to_user_id], references: [id])
|
||||
messages TicketMessage[]
|
||||
attachments TicketAttachment[]
|
||||
invitations TicketInvitation[]
|
||||
participants TicketParticipant[]
|
||||
status_history TicketStatusHistory[]
|
||||
|
||||
@@index([assigned_to_user_id], name: "idx_tickets_assigned_to")
|
||||
@@index([created_at], name: "idx_tickets_created_at")
|
||||
@@index([created_by_user_id], name: "idx_tickets_created_by")
|
||||
@@index([status], name: "idx_tickets_status")
|
||||
@@index([ticket_number], name: "idx_tickets_ticket_number")
|
||||
@@map("tickets")
|
||||
}
|
||||
|
||||
model TicketMessage {
|
||||
id BigInt @id @default(autoincrement())
|
||||
ticket_id BigInt
|
||||
author_id BigInt
|
||||
message String
|
||||
is_internal Boolean @default(false)
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
ticket Ticket @relation(fields: [ticket_id], references: [id], onDelete: Cascade)
|
||||
author User @relation(fields: [author_id], references: [id])
|
||||
attachments TicketAttachment[]
|
||||
|
||||
@@index([ticket_id], name: "idx_messages_ticket_id")
|
||||
@@map("ticket_messages")
|
||||
}
|
||||
|
||||
model TicketAttachment {
|
||||
id BigInt @id @default(autoincrement())
|
||||
ticket_id BigInt
|
||||
message_id BigInt?
|
||||
uploaded_by BigInt
|
||||
file_name String? @db.VarChar(255)
|
||||
file_url String
|
||||
file_size BigInt?
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
ticket Ticket @relation(fields: [ticket_id], references: [id], onDelete: Cascade)
|
||||
message TicketMessage? @relation(fields: [message_id], references: [id])
|
||||
uploader User @relation(fields: [uploaded_by], references: [id])
|
||||
|
||||
@@map("ticket_attachments")
|
||||
}
|
||||
|
||||
/// Invitaciones pendientes, aceptadas o rechazadas para unirse a un ticket
|
||||
model TicketInvitation {
|
||||
id BigInt @id @default(autoincrement())
|
||||
ticket_id BigInt
|
||||
inviter_id BigInt
|
||||
invitee_id BigInt
|
||||
/// Estado de la invitación: pending, accepted, rejected, cancelled
|
||||
status String @default("pending") @db.VarChar(20)
|
||||
message String?
|
||||
created_at DateTime @default(now()) @db.Timestamptz
|
||||
responded_at DateTime? @db.Timestamptz
|
||||
|
||||
ticket Ticket @relation(fields: [ticket_id], references: [id], onDelete: Cascade)
|
||||
inviter User @relation("Inviter", fields: [inviter_id], references: [id])
|
||||
invitee User @relation("Invitee", fields: [invitee_id], references: [id])
|
||||
|
||||
@@unique([ticket_id, invitee_id, status], name: "unique_pending_invitation")
|
||||
@@index([created_at], name: "idx_invitations_created_at")
|
||||
@@index([invitee_id], name: "idx_invitations_invitee_id")
|
||||
@@index([inviter_id], name: "idx_invitations_inviter_id")
|
||||
@@index([status], name: "idx_invitations_status")
|
||||
@@index([ticket_id], name: "idx_invitations_ticket_id")
|
||||
@@map("ticket_invitations")
|
||||
}
|
||||
|
||||
/// Usuarios que tienen acceso a un ticket específico
|
||||
model TicketParticipant {
|
||||
id BigInt @id @default(autoincrement())
|
||||
ticket_id BigInt
|
||||
user_id BigInt
|
||||
added_by BigInt
|
||||
/// Método de adición: creator, invitation, direct_add, assignment, staff_access
|
||||
added_via String @db.VarChar(20)
|
||||
can_edit Boolean @default(false)
|
||||
can_comment Boolean @default(true)
|
||||
joined_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
ticket Ticket @relation(fields: [ticket_id], references: [id], onDelete: Cascade)
|
||||
user User @relation("Participant", fields: [user_id], references: [id])
|
||||
added_by_user User @relation("AddedBy", fields: [added_by], references: [id])
|
||||
|
||||
@@unique([ticket_id, user_id])
|
||||
@@index([added_by], name: "idx_participants_added_by")
|
||||
@@index([ticket_id], name: "idx_participants_ticket_id")
|
||||
@@index([user_id], name: "idx_participants_user_id")
|
||||
@@map("ticket_participants")
|
||||
}
|
||||
|
||||
model TicketStatusHistory {
|
||||
id BigInt @id @default(autoincrement())
|
||||
ticket_id BigInt
|
||||
old_status String? @db.VarChar(30)
|
||||
new_status String @db.VarChar(30)
|
||||
changed_by BigInt
|
||||
changed_at DateTime @default(now()) @db.Timestamptz
|
||||
|
||||
ticket Ticket @relation(fields: [ticket_id], references: [id], onDelete: Cascade)
|
||||
changed_by_user User @relation(fields: [changed_by], references: [id])
|
||||
|
||||
@@index([ticket_id], name: "idx_history_ticket_id")
|
||||
@@map("ticket_status_history")
|
||||
}
|
||||
@@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { CategoriesModule } from './categories/categories.module';
|
||||
import { PrismaModule } from './prisma/prisma.module';
|
||||
|
||||
@Module({
|
||||
imports: [CategoriesModule],
|
||||
imports: [PrismaModule, CategoriesModule],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
|
||||
@@ -3,6 +3,6 @@ import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(process.env.PORT ?? 3020);
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
}
|
||||
bootstrap();
|
||||
|
||||
9
src/prisma/prisma.module.ts
Normal file
9
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 {}
|
||||
9
src/prisma/prisma.service.ts
Normal file
9
src/prisma/prisma.service.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { PrismaClient } from 'generated/prisma/client';
|
||||
|
||||
@Injectable()
|
||||
export class PrismaService extends PrismaClient implements OnModuleInit {
|
||||
async onModuleInit() {
|
||||
await this.$connect();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user