309 lines
7.9 KiB
Plaintext
309 lines
7.9 KiB
Plaintext
// Prisma Schema für Aufgabenplaner
|
|
// Dokumentation: https://pris.ly/d/prisma-schema
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// Benutzerrollen im System
|
|
enum Role {
|
|
BEARBEITER
|
|
PFLEGER
|
|
VORGESETZTER
|
|
ADMIN
|
|
}
|
|
|
|
// Aufgaben-Status
|
|
enum TaskStatus {
|
|
UNERLEDIGT
|
|
IN_BEARBEITUNG
|
|
ERLEDIGT
|
|
}
|
|
|
|
// Benutzer-Modell
|
|
model User {
|
|
id String @id @default(cuid())
|
|
email String @unique
|
|
name String
|
|
password String
|
|
role Role @default(BEARBEITER)
|
|
active Boolean @default(true)
|
|
sessionVersion Int @default(1)
|
|
mustChangePassword Boolean @default(false)
|
|
oidcSubject String? @unique
|
|
memberships UserGroup[]
|
|
roles UserRole[]
|
|
tokens ActionToken[]
|
|
notifications Notification[]
|
|
filters SavedFilter[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// Relations: Aufgaben die der Benutzer erstellt hat
|
|
createdTasks Task[] @relation("TaskCreator")
|
|
|
|
// Relations: Aufgaben die dem Benutzer zugewiesen sind
|
|
assignedTasks Task[] @relation("TaskAssignee")
|
|
|
|
// Relations: Kommentare des Benutzers
|
|
comments Comment[]
|
|
}
|
|
|
|
// Aufgaben-Modell
|
|
model Task {
|
|
id String @id @default(cuid())
|
|
wo String
|
|
was String @db.Text
|
|
bisWann DateTime
|
|
status TaskStatus @default(UNERLEDIGT)
|
|
beauftragtAm DateTime?
|
|
firmaBeauftragt String?
|
|
version Int @default(1)
|
|
priority Int @default(2)
|
|
tags String[] @default([])
|
|
project String @default("")
|
|
archivedAt DateTime?
|
|
completedAt DateTime?
|
|
owningGroupId String @default("legacy")
|
|
owningGroup Group @relation(fields: [owningGroupId], references: [id])
|
|
parentId String?
|
|
parent Task? @relation("Subtasks", fields: [parentId], references: [id], onDelete: SetNull)
|
|
children Task[] @relation("Subtasks")
|
|
checklist Json @default("[]")
|
|
recurrenceDays Int?
|
|
recurrenceSourceId String? @unique
|
|
dependencies TaskDependency[] @relation("Dependent")
|
|
dependents TaskDependency[] @relation("Dependency")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
// Relations: Ersteller der Aufgabe
|
|
creatorId String
|
|
creator User @relation("TaskCreator", fields: [creatorId], references: [id])
|
|
|
|
// Relations: Zugewiesener Bearbeiter
|
|
assigneeId String?
|
|
assignee User? @relation("TaskAssignee", fields: [assigneeId], references: [id])
|
|
|
|
// Relations: Kommentare zur Aufgabe
|
|
comments Comment[]
|
|
|
|
// Relations: Dateien der Aufgabe
|
|
files File[]
|
|
|
|
@@index([status])
|
|
@@index([bisWann])
|
|
@@index([assigneeId])
|
|
@@index([creatorId])
|
|
@@index([owningGroupId, archivedAt, bisWann, id])
|
|
@@index([assigneeId, archivedAt, bisWann, id])
|
|
}
|
|
|
|
// Kommentar-Modell
|
|
model Comment {
|
|
id String @id @default(cuid())
|
|
content String @db.Text
|
|
createdAt DateTime @default(now())
|
|
|
|
// Relations: Zugehörige Aufgabe
|
|
taskId String
|
|
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
|
|
|
|
// Relations: Autor des Kommentars
|
|
authorId String
|
|
author User @relation(fields: [authorId], references: [id])
|
|
|
|
@@index([taskId])
|
|
}
|
|
|
|
// Datei-Modell
|
|
model File {
|
|
id String @id @default(cuid())
|
|
name String
|
|
path String
|
|
mimeType String
|
|
uploaderId String?
|
|
size Int
|
|
createdAt DateTime @default(now())
|
|
|
|
// Relations: Zugehörige Aufgabe
|
|
taskId String
|
|
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([taskId])
|
|
}
|
|
|
|
enum Scope {
|
|
ASSIGNED
|
|
GROUP
|
|
GLOBAL
|
|
}
|
|
|
|
model Group {
|
|
id String @id @default(cuid())
|
|
name String @unique
|
|
active Boolean @default(true)
|
|
members UserGroup[]
|
|
roles GroupRole[]
|
|
tasks Task[]
|
|
}
|
|
|
|
model UserGroup {
|
|
userId String
|
|
groupId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([userId, groupId])
|
|
}
|
|
|
|
model AccessRole {
|
|
id String @id @default(cuid())
|
|
name String @unique
|
|
protected Boolean @default(false)
|
|
permissions RolePermission[]
|
|
users UserRole[]
|
|
groups GroupRole[]
|
|
}
|
|
|
|
model Permission {
|
|
key String @id
|
|
roles RolePermission[]
|
|
}
|
|
|
|
model RolePermission {
|
|
roleId String
|
|
permissionKey String
|
|
role AccessRole @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
permission Permission @relation(fields: [permissionKey], references: [key], onDelete: Cascade)
|
|
|
|
@@id([roleId, permissionKey])
|
|
}
|
|
|
|
model UserRole {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
roleId String
|
|
scope Scope
|
|
targetGroupId String @default("")
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
role AccessRole @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([userId, roleId, scope, targetGroupId])
|
|
}
|
|
|
|
model GroupRole {
|
|
groupId String
|
|
roleId String
|
|
scope Scope
|
|
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
|
role AccessRole @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([groupId, roleId, scope])
|
|
}
|
|
|
|
model AuditEvent {
|
|
id String @id @default(cuid())
|
|
actorId String
|
|
action String
|
|
targetId String
|
|
taskId String?
|
|
data Json @default("{}")
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([taskId, createdAt])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
model ActionToken {
|
|
hash String @id
|
|
userId String
|
|
purpose String
|
|
expiresAt DateTime
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model RateLimit {
|
|
key String @id
|
|
count Int
|
|
expiresAt DateTime
|
|
}
|
|
|
|
model Notification {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
taskId String
|
|
key String @unique
|
|
text String
|
|
read Boolean @default(false)
|
|
emailed Boolean @default(false)
|
|
createdAt DateTime @default(now())
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId, createdAt])
|
|
}
|
|
|
|
model SavedFilter {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
name String
|
|
query Json
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model TaskTemplate {
|
|
id String @id @default(cuid())
|
|
name String
|
|
ownerId String
|
|
data Json
|
|
}
|
|
|
|
model TaskDependency {
|
|
taskId String
|
|
dependsOnId String
|
|
task Task @relation("Dependent", fields: [taskId], references: [id], onDelete: Cascade)
|
|
dependsOn Task @relation("Dependency", fields: [dependsOnId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([taskId, dependsOnId])
|
|
}
|
|
|
|
model CleanupJob {
|
|
id String @id @default(cuid())
|
|
storageKey String
|
|
attempts Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
model Webhook {
|
|
id String @id @default(cuid())
|
|
name String
|
|
url String
|
|
secret String
|
|
active Boolean @default(true)
|
|
}
|
|
|
|
model WebhookDelivery {
|
|
id String @id @default(cuid())
|
|
webhookId String
|
|
eventId String
|
|
attempts Int @default(0)
|
|
deliveredAt DateTime?
|
|
nextAttemptAt DateTime @default(now())
|
|
|
|
@@unique([webhookId, eventId])
|
|
}
|
|
|
|
model ApiToken {
|
|
hash String @id
|
|
userId String
|
|
name String
|
|
permissions String[]
|
|
expiresAt DateTime
|
|
createdAt DateTime @default(now())
|
|
}
|