Initial commit: Lageplan v1.0 - Next.js 15.5, React 19
This commit is contained in:
414
prisma/schema.prisma
Normal file
414
prisma/schema.prisma
Normal file
@@ -0,0 +1,414 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum Role {
|
||||
SERVER_ADMIN
|
||||
TENANT_ADMIN
|
||||
OPERATOR
|
||||
VIEWER
|
||||
}
|
||||
|
||||
enum IconType {
|
||||
STANDARD
|
||||
RETTUNG
|
||||
GEFAHRSTOFF
|
||||
FEUER
|
||||
WASSER
|
||||
FAHRZEUG
|
||||
}
|
||||
|
||||
enum ItemKind {
|
||||
SYMBOL
|
||||
LINE
|
||||
POLYGON
|
||||
RECTANGLE
|
||||
CIRCLE
|
||||
ARROW
|
||||
TEXT
|
||||
}
|
||||
|
||||
enum SubscriptionPlan {
|
||||
FREE
|
||||
PRO
|
||||
}
|
||||
|
||||
enum DictionaryScope {
|
||||
GLOBAL
|
||||
TENANT
|
||||
}
|
||||
|
||||
enum SubscriptionStatus {
|
||||
ACTIVE
|
||||
TRIAL
|
||||
SUSPENDED
|
||||
EXPIRED
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
model Tenant {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
isActive Boolean @default(true)
|
||||
contactEmail String?
|
||||
contactPhone String?
|
||||
address String?
|
||||
|
||||
logoUrl String?
|
||||
logoFileKey String?
|
||||
|
||||
// Subscription
|
||||
plan SubscriptionPlan @default(FREE)
|
||||
subscriptionStatus SubscriptionStatus @default(ACTIVE)
|
||||
trialEndsAt DateTime?
|
||||
subscriptionEndsAt DateTime?
|
||||
maxUsers Int @default(5)
|
||||
maxProjects Int @default(10)
|
||||
notes String?
|
||||
hiddenIconIds String[] @default([])
|
||||
journalSuggestions String[] @default([])
|
||||
|
||||
// Privacy consent
|
||||
privacyAccepted Boolean @default(false)
|
||||
privacyAcceptedAt DateTime?
|
||||
adminAccessAccepted Boolean @default(false)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
memberships TenantMembership[]
|
||||
projects Project[]
|
||||
hoseTypes HoseType[]
|
||||
checkTemplates JournalCheckTemplate[]
|
||||
iconCategories IconCategory[]
|
||||
iconAssets IconAsset[]
|
||||
upgradeRequests UpgradeRequest[]
|
||||
dictionaryEntries DictionaryEntry[]
|
||||
rapports Rapport[]
|
||||
|
||||
@@map("tenants")
|
||||
}
|
||||
|
||||
// ─── System Settings (Key-Value, encrypted for secrets) ──────
|
||||
|
||||
model SystemSetting {
|
||||
id String @id @default(uuid())
|
||||
key String @unique
|
||||
value String
|
||||
isSecret Boolean @default(false)
|
||||
category String @default("general")
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@map("system_settings")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
email String @unique
|
||||
password String
|
||||
name String
|
||||
role Role @default(OPERATOR)
|
||||
emailVerified Boolean @default(true)
|
||||
emailVerificationToken String? @unique
|
||||
resetToken String? @unique
|
||||
resetTokenExpiry DateTime?
|
||||
lastLoginAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
memberships TenantMembership[]
|
||||
projects Project[]
|
||||
iconAssets IconAsset[]
|
||||
upgradeRequests UpgradeRequest[]
|
||||
rapports Rapport[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model TenantMembership {
|
||||
id String @id @default(uuid())
|
||||
role Role @default(OPERATOR)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
tenantId String
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, tenantId])
|
||||
@@map("tenant_memberships")
|
||||
}
|
||||
|
||||
model Project {
|
||||
id String @id @default(uuid())
|
||||
einsatzNr String?
|
||||
title String
|
||||
location String?
|
||||
description String?
|
||||
einsatzleiter String?
|
||||
journalfuehrer String?
|
||||
mapCenter Json @default("{\"lng\": 8.5417, \"lat\": 47.3769}")
|
||||
mapZoom Float @default(15)
|
||||
isLocked Boolean @default(false)
|
||||
|
||||
// Live editing lock (session-based for same-account multi-device)
|
||||
editingById String?
|
||||
editingUserName String?
|
||||
editingSessionId String?
|
||||
editingStartedAt DateTime?
|
||||
editingHeartbeat DateTime?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
ownerId String?
|
||||
owner User? @relation(fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
tenantId String?
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)
|
||||
|
||||
features Feature[]
|
||||
items Item[]
|
||||
journalEntries JournalEntry[]
|
||||
journalCheckItems JournalCheckItem[]
|
||||
journalPendenzen JournalPendenz[]
|
||||
rapports Rapport[]
|
||||
|
||||
@@map("projects")
|
||||
}
|
||||
|
||||
model Feature {
|
||||
id String @id @default(uuid())
|
||||
type String
|
||||
geometry Json
|
||||
properties Json @default("{}")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("features")
|
||||
}
|
||||
|
||||
model IconCategory {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
sortOrder Int @default(0)
|
||||
isGlobal Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
tenantId String?
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)
|
||||
|
||||
icons IconAsset[]
|
||||
|
||||
@@map("icon_categories")
|
||||
}
|
||||
|
||||
model IconAsset {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
fileKey String
|
||||
mimeType String
|
||||
width Int?
|
||||
height Int?
|
||||
isSystem Boolean @default(false)
|
||||
isActive Boolean @default(true)
|
||||
iconType IconType @default(STANDARD)
|
||||
tags String[] @default([])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
categoryId String?
|
||||
category IconCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
||||
|
||||
ownerId String?
|
||||
owner User? @relation(fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
|
||||
tenantId String?
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@map("icon_assets")
|
||||
}
|
||||
|
||||
model HoseType {
|
||||
id String @id @default(uuid())
|
||||
name String @unique
|
||||
diameterMm Int
|
||||
lengthPerPieceM Int @default(10)
|
||||
flowRateLpm Float
|
||||
frictionCoeff Float
|
||||
description String?
|
||||
isDefault Boolean @default(false)
|
||||
isActive Boolean @default(true)
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tenantId String?
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@map("hose_types")
|
||||
}
|
||||
|
||||
// ─── Journal ───────────────────────────────────────────────
|
||||
|
||||
model JournalEntry {
|
||||
id String @id @default(uuid())
|
||||
time DateTime @default(now())
|
||||
what String
|
||||
who String?
|
||||
done Boolean @default(false)
|
||||
doneAt DateTime?
|
||||
sortOrder Int @default(0)
|
||||
isCorrected Boolean @default(false)
|
||||
correctionOfId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("journal_entries")
|
||||
}
|
||||
|
||||
model JournalCheckItem {
|
||||
id String @id @default(uuid())
|
||||
label String
|
||||
confirmed Boolean @default(false)
|
||||
confirmedAt DateTime?
|
||||
ok Boolean @default(false)
|
||||
okAt DateTime?
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("journal_check_items")
|
||||
}
|
||||
|
||||
model JournalPendenz {
|
||||
id String @id @default(uuid())
|
||||
what String
|
||||
who String?
|
||||
whenHow String?
|
||||
done Boolean @default(false)
|
||||
doneAt DateTime?
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("journal_pendenzen")
|
||||
}
|
||||
|
||||
model JournalCheckTemplate {
|
||||
id String @id @default(uuid())
|
||||
label String
|
||||
sortOrder Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
tenantId String?
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: SetNull)
|
||||
|
||||
@@map("journal_check_templates")
|
||||
}
|
||||
|
||||
model Item {
|
||||
id String @id @default(uuid())
|
||||
kind ItemKind
|
||||
geometry Json
|
||||
style Json @default("{}")
|
||||
properties Json @default("{}")
|
||||
isVisible Boolean @default(true)
|
||||
sortOrder Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
iconId String?
|
||||
|
||||
@@map("items")
|
||||
}
|
||||
|
||||
// ─── Upgrade Requests ─────────────────────────────────────
|
||||
|
||||
enum UpgradeRequestStatus {
|
||||
PENDING
|
||||
APPROVED
|
||||
REJECTED
|
||||
}
|
||||
|
||||
model UpgradeRequest {
|
||||
id String @id @default(uuid())
|
||||
requestedPlan SubscriptionPlan
|
||||
currentPlan SubscriptionPlan
|
||||
message String?
|
||||
status UpgradeRequestStatus @default(PENDING)
|
||||
adminNote String?
|
||||
processedAt DateTime?
|
||||
processedById String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
tenantId String
|
||||
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
|
||||
requestedById String
|
||||
requestedBy User @relation(fields: [requestedById], references: [id], onDelete: Cascade)
|
||||
|
||||
@@map("upgrade_requests")
|
||||
}
|
||||
|
||||
// ─── Dictionary (Global + Tenant word library) ────────────
|
||||
|
||||
model DictionaryEntry {
|
||||
id String @id @default(uuid())
|
||||
word String
|
||||
scope DictionaryScope @default(GLOBAL)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
tenantId String?
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([word, tenantId])
|
||||
@@map("dictionary_entries")
|
||||
}
|
||||
|
||||
// ─── Rapport (PDF reports with public token access) ───────
|
||||
|
||||
model Rapport {
|
||||
id String @id @default(uuid())
|
||||
reportNumber String
|
||||
token String @unique @default(uuid())
|
||||
data Json
|
||||
generatedAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
projectId String
|
||||
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
||||
|
||||
tenantId String?
|
||||
tenant Tenant? @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
||||
|
||||
createdById String?
|
||||
createdBy User? @relation(fields: [createdById], references: [id], onDelete: SetNull)
|
||||
|
||||
@@map("rapports")
|
||||
}
|
||||
Reference in New Issue
Block a user