Files
TicketingSystem/server/prisma/schema.prisma
T
josh 28274bf7bd Add missing database indexes for FK lookups and audit queries
Type(categoryId), Item(typeId), Attachment(uploadedById), and
AuditLog(ticketId, createdAt) were missing indexes for their
primary query patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-21 20:25:40 -04:00

204 lines
5.3 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
enum Role {
ADMIN
AGENT
USER
}
enum TicketStatus {
OPEN
IN_PROGRESS
RESOLVED
CLOSED
}
model User {
id String @id @default(cuid())
username String @unique
email String @unique
passwordHash String
displayName String
role Role @default(AGENT)
apiKey String? @unique
notificationPrefs Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
assignedTickets Ticket[] @relation("AssignedTickets")
createdTickets Ticket[] @relation("CreatedTickets")
comments Comment[]
auditLogs AuditLog[]
attachments Attachment[]
notifications Notification[]
savedViews SavedView[]
}
model Category {
id String @id @default(cuid())
name String @unique
types Type[]
tickets Ticket[]
}
model Type {
id String @id @default(cuid())
name String
categoryId String
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
items Item[]
tickets Ticket[]
@@unique([categoryId, name])
@@index([categoryId])
}
model Item {
id String @id @default(cuid())
name String
typeId String
type Type @relation(fields: [typeId], references: [id], onDelete: Cascade)
tickets Ticket[]
@@unique([typeId, name])
@@index([typeId])
}
model Ticket {
id String @id @default(cuid())
displayId String @unique @default(dbgenerated("concat('V', (floor(random() * 900000000) + 100000000)::bigint::text)"))
title String
overview String
severity Int
status TicketStatus @default(OPEN)
categoryId String
typeId String
itemId String
assigneeId String?
createdById String
resolvedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Managed by post-push.sql — trigger keeps it in sync; queried only via raw SQL.
searchVector Unsupported("tsvector")?
category Category @relation(fields: [categoryId], references: [id])
type Type @relation(fields: [typeId], references: [id])
item Item @relation(fields: [itemId], references: [id])
assignee User? @relation("AssignedTickets", fields: [assigneeId], references: [id])
createdBy User @relation("CreatedTickets", fields: [createdById], references: [id])
comments Comment[]
auditLogs AuditLog[]
attachments Attachment[]
notifications Notification[]
@@index([status])
@@index([severity])
@@index([assigneeId])
@@index([createdById])
@@index([createdAt])
}
model Comment {
id String @id @default(cuid())
body String
ticketId String
authorId String
createdAt DateTime @default(now())
// Managed by post-push.sql — trigger keeps it in sync; queried only via raw SQL.
searchVector Unsupported("tsvector")?
ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade)
author User @relation(fields: [authorId], references: [id])
attachments Attachment[]
notifications Notification[]
@@index([ticketId])
}
model Attachment {
id String @id @default(cuid())
filename String
mimetype String
size Int
storagePath String
ticketId String?
commentId String?
uploadedById String
createdAt DateTime @default(now())
ticket Ticket? @relation(fields: [ticketId], references: [id], onDelete: Cascade)
comment Comment? @relation(fields: [commentId], references: [id], onDelete: Cascade)
uploadedBy User @relation(fields: [uploadedById], references: [id])
@@index([ticketId])
@@index([commentId])
@@index([uploadedById])
}
model Webhook {
id String @id @default(cuid())
name String
url String
events String[]
secret String
active Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Notification {
id String @id @default(cuid())
userId String
kind String
ticketId String?
commentId String?
data Json?
readAt DateTime?
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
ticket Ticket? @relation(fields: [ticketId], references: [id], onDelete: Cascade)
comment Comment? @relation(fields: [commentId], references: [id], onDelete: Cascade)
@@index([userId, readAt])
@@index([userId, createdAt])
}
model SavedView {
id String @id @default(cuid())
userId String
name String
filters Json
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([userId, name])
}
model AuditLog {
id String @id @default(cuid())
ticketId String
userId String
action String
detail String?
createdAt DateTime @default(now())
ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id])
@@index([ticketId, createdAt])
}