feat: integrate Prisma for database management

This commit is contained in:
2026-02-26 13:14:09 -03:00
parent 2f29430b28
commit e60752743f
12 changed files with 1390 additions and 14 deletions

184
prisma/schema.prisma Normal file
View 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")
}