324 lines
8.5 KiB
Plaintext
324 lines
8.5 KiB
Plaintext
// /opt/erp-system/prisma/schema.prisma
|
|
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
}
|
|
|
|
enum TicketStatus {
|
|
OPEN
|
|
IN_PROGRESS
|
|
WAITING_FOR_CUSTOMER
|
|
RESOLVED
|
|
CLOSED
|
|
}
|
|
|
|
enum TicketPriority {
|
|
LOW
|
|
MEDIUM
|
|
HIGH
|
|
CRITICAL
|
|
}
|
|
|
|
model Role {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique
|
|
permissions String[]
|
|
createdAt DateTime @default(now())
|
|
users User[]
|
|
}
|
|
|
|
model User {
|
|
id Int @id @default(autoincrement())
|
|
email String @unique
|
|
passwordHash String
|
|
firstName String
|
|
lastName String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
roleId Int?
|
|
role Role? @relation(fields: [roleId], references: [id])
|
|
|
|
tickets Ticket[] @relation("AssignedTickets")
|
|
timeEntries TimeEntry[]
|
|
notes TicketNote[]
|
|
createdSalesDocs SalesDocument[] @relation("CreatedSalesDocs")
|
|
}
|
|
|
|
model Customer {
|
|
id Int @id @default(autoincrement())
|
|
companyName String?
|
|
firstName String
|
|
lastName String
|
|
email String @unique
|
|
additionalEmails String[]
|
|
phone String?
|
|
address String?
|
|
city String?
|
|
zipCode String?
|
|
passwordHash String?
|
|
forcePasswordChange Boolean @default(true) // NEU: Zwingt zum Wechsel
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
tickets Ticket[]
|
|
contacts CustomerContact[]
|
|
contracts Contract[]
|
|
documents CustomerDocument[]
|
|
credentials CustomerCredential[]
|
|
salesDocuments SalesDocument[]
|
|
}
|
|
|
|
model CustomerContact {
|
|
id Int @id @default(autoincrement())
|
|
firstName String
|
|
lastName String
|
|
email String @unique
|
|
phone String?
|
|
isPortalUser Boolean @default(false)
|
|
passwordHash String?
|
|
createdAt DateTime @default(now())
|
|
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model Ticket {
|
|
id Int @id @default(autoincrement())
|
|
title String
|
|
description String
|
|
internalNote String?
|
|
status TicketStatus @default(OPEN)
|
|
priority TicketPriority @default(MEDIUM)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id])
|
|
|
|
assignedToId Int?
|
|
assignedTo User? @relation("AssignedTickets", fields: [assignedToId], references: [id])
|
|
|
|
timeEntries TimeEntry[]
|
|
messages TicketMessage[]
|
|
survey TicketSurvey?
|
|
notes TicketNote[]
|
|
attachments Attachment[]
|
|
}
|
|
|
|
model TicketMessage {
|
|
id Int @id @default(autoincrement())
|
|
content String
|
|
isFromCustomer Boolean @default(false)
|
|
createdAt DateTime @default(now())
|
|
|
|
ticketId Int
|
|
ticket Ticket @relation(fields: [ticketId], references: [id])
|
|
}
|
|
|
|
model Attachment {
|
|
id Int @id @default(autoincrement())
|
|
fileName String
|
|
savedName String
|
|
fileSize Int
|
|
fileType String
|
|
createdAt DateTime @default(now())
|
|
|
|
ticketId Int
|
|
ticket Ticket @relation(fields: [ticketId], references: [id])
|
|
}
|
|
|
|
model TicketSurvey {
|
|
id Int @id @default(autoincrement())
|
|
rating Int
|
|
comment String?
|
|
createdAt DateTime @default(now())
|
|
|
|
ticketId Int @unique
|
|
ticket Ticket @relation(fields: [ticketId], references: [id])
|
|
}
|
|
|
|
model TimeEntry {
|
|
id Int @id @default(autoincrement())
|
|
durationMins Int
|
|
description String
|
|
isBilled Boolean @default(false)
|
|
billedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
ticketId Int
|
|
ticket Ticket @relation(fields: [ticketId], references: [id])
|
|
|
|
userId Int
|
|
user User @relation(fields: [userId], references: [id])
|
|
}
|
|
|
|
model TicketNote {
|
|
id Int @id @default(autoincrement())
|
|
content String
|
|
createdAt DateTime @default(now())
|
|
|
|
ticketId Int
|
|
ticket Ticket @relation(fields: [ticketId], references: [id])
|
|
|
|
userId Int
|
|
user User @relation(fields: [userId], references: [id])
|
|
}
|
|
|
|
model SystemSettings {
|
|
id Int @id @default(1)
|
|
hourlyRate Float @default(95.0)
|
|
taxRate Float @default(19.0)
|
|
companyName String?
|
|
companyInfo String?
|
|
|
|
smtpHost String?
|
|
smtpPort Int @default(587)
|
|
smtpUser String?
|
|
smtpPass String?
|
|
smtpFrom String?
|
|
|
|
imapHost String?
|
|
imapPort Int @default(993)
|
|
imapUser String?
|
|
imapPass String?
|
|
|
|
// Nummernkreise
|
|
nextQuoteNumber Int @default(1)
|
|
nextOrderNumber Int @default(1)
|
|
nextDeliveryNumber Int @default(1)
|
|
nextInvoiceNumber Int @default(1)
|
|
nextCreditNoteNumber Int @default(1)
|
|
defaultQuoteValidityDays Int @default(14)
|
|
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model Contract {
|
|
id Int @id @default(autoincrement())
|
|
title String
|
|
description String?
|
|
startDate DateTime
|
|
endDate DateTime?
|
|
monthlyPrice Float @default(0)
|
|
status String @default("ACTIVE")
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model CustomerDocument {
|
|
id Int @id @default(autoincrement())
|
|
fileName String
|
|
savedName String
|
|
fileSize Int
|
|
fileType String
|
|
createdAt DateTime @default(now())
|
|
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model CustomerCredential {
|
|
id Int @id @default(autoincrement())
|
|
title String
|
|
username String
|
|
password String
|
|
description String?
|
|
createdAt DateTime @default(now())
|
|
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
// ── WARENWIRTSCHAFT ──
|
|
|
|
model Product {
|
|
id Int @id @default(autoincrement())
|
|
name String
|
|
description String?
|
|
sku String? @unique
|
|
imagePath String?
|
|
purchasePrice Float @default(0)
|
|
salePrice Float @default(0)
|
|
stock Int @default(0)
|
|
reservedStock Int @default(0)
|
|
unit String @default("Stk")
|
|
taxRate Float @default(19)
|
|
trackStock Boolean @default(true)
|
|
category String?
|
|
active Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
salesItems SalesDocumentItem[]
|
|
}
|
|
|
|
enum SalesDocType {
|
|
QUOTE
|
|
ORDER_CONFIRMATION
|
|
DELIVERY_NOTE
|
|
INVOICE
|
|
CREDIT_NOTE
|
|
}
|
|
|
|
enum SalesDocStatus {
|
|
DRAFT
|
|
SENT
|
|
ACCEPTED
|
|
REJECTED
|
|
DELIVERED
|
|
PAID
|
|
CANCELLED
|
|
ARCHIVED
|
|
}
|
|
|
|
model SalesDocument {
|
|
id Int @id @default(autoincrement())
|
|
type SalesDocType
|
|
number String @unique
|
|
status SalesDocStatus @default(DRAFT)
|
|
previousStatus String?
|
|
subtotal Float @default(0)
|
|
taxAmount Float @default(0)
|
|
total Float @default(0)
|
|
notes String?
|
|
validUntil DateTime?
|
|
signatureData String?
|
|
signedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id])
|
|
|
|
createdById Int?
|
|
createdBy User? @relation("CreatedSalesDocs", fields: [createdById], references: [id])
|
|
|
|
sourceDocumentId Int?
|
|
|
|
items SalesDocumentItem[]
|
|
}
|
|
|
|
model SalesDocumentItem {
|
|
id Int @id @default(autoincrement())
|
|
description String
|
|
quantity Float @default(1)
|
|
unitPrice Float @default(0)
|
|
taxRate Float @default(19)
|
|
total Float @default(0)
|
|
|
|
salesDocumentId Int
|
|
salesDocument SalesDocument @relation(fields: [salesDocumentId], references: [id], onDelete: Cascade)
|
|
|
|
productId Int?
|
|
product Product? @relation(fields: [productId], references: [id])
|
|
}
|
|
|