708 lines
24 KiB
Plaintext
708 lines
24 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "mysql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// ==================== APP SETTINGS ====================
|
|
|
|
model AppSetting {
|
|
id Int @id @default(autoincrement())
|
|
key String @unique
|
|
value String @db.Text
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== USERS & AUTH ====================
|
|
|
|
model User {
|
|
id Int @id @default(autoincrement())
|
|
email String @unique
|
|
password String
|
|
firstName String
|
|
lastName String
|
|
isActive Boolean @default(true)
|
|
tokenInvalidatedAt DateTime? // Zeitpunkt ab dem alle Tokens ungültig sind (für Zwangslogout bei Rechteänderung)
|
|
customerId Int? @unique
|
|
customer Customer? @relation(fields: [customerId], references: [id])
|
|
roles UserRole[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model Role {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique
|
|
description String?
|
|
permissions RolePermission[]
|
|
users UserRole[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model Permission {
|
|
id Int @id @default(autoincrement())
|
|
resource String
|
|
action String
|
|
roles RolePermission[]
|
|
|
|
@@unique([resource, action])
|
|
}
|
|
|
|
model RolePermission {
|
|
roleId Int
|
|
permissionId Int
|
|
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([roleId, permissionId])
|
|
}
|
|
|
|
model UserRole {
|
|
userId Int
|
|
roleId Int
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([userId, roleId])
|
|
}
|
|
|
|
// ==================== CUSTOMERS ====================
|
|
|
|
enum CustomerType {
|
|
PRIVATE
|
|
BUSINESS
|
|
}
|
|
|
|
model Customer {
|
|
id Int @id @default(autoincrement())
|
|
customerNumber String @unique
|
|
type CustomerType @default(PRIVATE)
|
|
salutation String?
|
|
firstName String
|
|
lastName String
|
|
companyName String?
|
|
foundingDate DateTime? // Gründungsdatum (für Firmen)
|
|
birthDate DateTime?
|
|
birthPlace String?
|
|
email String?
|
|
phone String?
|
|
mobile String?
|
|
taxNumber String?
|
|
businessRegistrationPath String? // PDF-Pfad zur Gewerbeanmeldung
|
|
commercialRegisterPath String? // PDF-Pfad zum Handelsregisterauszug
|
|
commercialRegisterNumber String? // Handelsregisternummer (Text)
|
|
privacyPolicyPath String? // PDF-Pfad zur Datenschutzerklärung (für alle Kunden)
|
|
notes String? @db.Text
|
|
|
|
// ===== Portal-Zugangsdaten =====
|
|
portalEnabled Boolean @default(false) // Portal aktiviert?
|
|
portalEmail String? @unique // Portal-Login E-Mail
|
|
portalPasswordHash String? // Gehashtes Passwort (für Login)
|
|
portalPasswordEncrypted String? // Verschlüsseltes Passwort (für Anzeige)
|
|
portalLastLogin DateTime? // Letzte Anmeldung
|
|
|
|
user User?
|
|
addresses Address[]
|
|
bankCards BankCard[]
|
|
identityDocuments IdentityDocument[]
|
|
meters Meter[]
|
|
stressfreiEmails StressfreiEmail[]
|
|
contracts Contract[]
|
|
|
|
// Vertreter-Beziehungen (Kunde kann für andere Kunden handeln)
|
|
representingFor CustomerRepresentative[] @relation("RepresentativeCustomer")
|
|
representedBy CustomerRepresentative[] @relation("RepresentedCustomer")
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== CUSTOMER REPRESENTATIVES ====================
|
|
// Vertretungsbeziehung: Ein Kunde kann die Verträge eines anderen Kunden einsehen
|
|
// z.B. Sohn (representativeId) kann Verträge der Mutter (customerId) sehen
|
|
|
|
model CustomerRepresentative {
|
|
id Int @id @default(autoincrement())
|
|
customerId Int // Der Kunde, dessen Verträge eingesehen werden (z.B. Mutter)
|
|
customer Customer @relation("RepresentedCustomer", fields: [customerId], references: [id], onDelete: Cascade)
|
|
representativeId Int // Der Kunde, der einsehen darf (z.B. Sohn)
|
|
representative Customer @relation("RepresentativeCustomer", fields: [representativeId], references: [id], onDelete: Cascade)
|
|
notes String? // Notizen zur Vertretung
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([customerId, representativeId]) // Keine doppelten Einträge
|
|
}
|
|
|
|
// ==================== ADDRESSES ====================
|
|
|
|
enum AddressType {
|
|
DELIVERY_RESIDENCE
|
|
BILLING
|
|
}
|
|
|
|
model Address {
|
|
id Int @id @default(autoincrement())
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
type AddressType @default(DELIVERY_RESIDENCE)
|
|
street String
|
|
houseNumber String
|
|
postalCode String
|
|
city String
|
|
country String @default("Deutschland")
|
|
isDefault Boolean @default(false)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== BANK CARDS ====================
|
|
|
|
model BankCard {
|
|
id Int @id @default(autoincrement())
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
accountHolder String
|
|
iban String
|
|
bic String?
|
|
bankName String?
|
|
expiryDate DateTime?
|
|
documentPath String? // Pfad zur hochgeladenen PDF
|
|
isActive Boolean @default(true)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== IDENTITY DOCUMENTS ====================
|
|
|
|
enum DocumentType {
|
|
ID_CARD
|
|
PASSPORT
|
|
DRIVERS_LICENSE
|
|
OTHER
|
|
}
|
|
|
|
model IdentityDocument {
|
|
id Int @id @default(autoincrement())
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
type DocumentType @default(ID_CARD)
|
|
documentNumber String
|
|
issuingAuthority String?
|
|
issueDate DateTime?
|
|
expiryDate DateTime?
|
|
documentPath String? // Pfad zur hochgeladenen PDF
|
|
isActive Boolean @default(true)
|
|
// Führerschein-spezifische Felder
|
|
licenseClasses String? // z.B. "B, BE, AM, L" - kommasepariert
|
|
licenseIssueDate DateTime? // Datum des Führerscheinerwerbs (Klasse B)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== EMAIL PROVIDER CONFIG (Plesk, cPanel etc.) ====================
|
|
|
|
enum EmailProviderType {
|
|
PLESK
|
|
CPANEL
|
|
DIRECTADMIN
|
|
}
|
|
|
|
// Verschlüsselungstyp für E-Mail-Verbindungen
|
|
enum MailEncryption {
|
|
SSL // Implicit SSL/TLS (Ports 465/993) - Verschlüsselung von Anfang an
|
|
STARTTLS // STARTTLS (Ports 587/143) - Startet unverschlüsselt, dann Upgrade
|
|
NONE // Keine Verschlüsselung (Ports 25/143)
|
|
}
|
|
|
|
model EmailProviderConfig {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique // z.B. "Plesk Hauptserver"
|
|
type EmailProviderType
|
|
apiUrl String // API-URL (z.B. https://server.de:8443)
|
|
apiKey String? // API-Key (verschlüsselt)
|
|
username String? // Benutzername für API
|
|
passwordEncrypted String? // Passwort (verschlüsselt)
|
|
domain String // Domain für E-Mails (z.B. stressfrei-wechseln.de)
|
|
defaultForwardEmail String? // Standard-Weiterleitungsadresse (unsere eigene)
|
|
|
|
// IMAP/SMTP-Server für E-Mail-Client (optional, default: mail.{domain})
|
|
imapServer String? // z.B. "mail.stressfrei-wechseln.de"
|
|
imapPort Int? @default(993)
|
|
smtpServer String?
|
|
smtpPort Int? @default(465)
|
|
|
|
// Verschlüsselungs-Einstellungen
|
|
imapEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE
|
|
smtpEncryption MailEncryption @default(SSL) // SSL, STARTTLS oder NONE
|
|
allowSelfSignedCerts Boolean @default(false) // Selbstsignierte Zertifikate erlauben
|
|
|
|
isActive Boolean @default(true)
|
|
isDefault Boolean @default(false) // Standard-Provider
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== STRESSFREI-WECHSELN EMAIL ADDRESSES ====================
|
|
|
|
model StressfreiEmail {
|
|
id Int @id @default(autoincrement())
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
email String // Die Weiterleitungs-E-Mail-Adresse
|
|
platform String? // Für welche Plattform (z.B. "Freenet", "Klarmobil")
|
|
notes String? @db.Text // Optionale Notizen
|
|
isActive Boolean @default(true)
|
|
isProvisioned Boolean @default(false) // Wurde bei Provider angelegt?
|
|
provisionedAt DateTime? // Wann wurde provisioniert?
|
|
provisionError String? @db.Text // Fehlermeldung falls Provisionierung fehlschlug
|
|
|
|
// Mailbox-Zugangsdaten (für IMAP/SMTP-Zugang)
|
|
hasMailbox Boolean @default(false) // Hat echte Mailbox (nicht nur Weiterleitung)?
|
|
emailPasswordEncrypted String? // Verschlüsseltes Mailbox-Passwort (AES-256-GCM)
|
|
|
|
contracts Contract[] // Verträge die diese E-Mail als Benutzername verwenden
|
|
cachedEmails CachedEmail[] // Gecachte E-Mails aus dieser Mailbox
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== CACHED EMAILS (E-Mail-Client) ====================
|
|
|
|
enum EmailFolder {
|
|
INBOX
|
|
SENT
|
|
}
|
|
|
|
model CachedEmail {
|
|
id Int @id @default(autoincrement())
|
|
stressfreiEmailId Int
|
|
stressfreiEmail StressfreiEmail @relation(fields: [stressfreiEmailId], references: [id], onDelete: Cascade)
|
|
|
|
// Ordner (Posteingang oder Gesendet)
|
|
folder EmailFolder @default(INBOX)
|
|
|
|
// IMAP-Identifikation
|
|
messageId String // RFC 5322 Message-ID
|
|
uid Int // IMAP UID (für Synchronisierung, bei SENT = 0)
|
|
|
|
// E-Mail-Metadaten
|
|
subject String?
|
|
fromAddress String
|
|
fromName String?
|
|
toAddresses String @db.Text // JSON Array
|
|
ccAddresses String? @db.Text // JSON Array
|
|
receivedAt DateTime
|
|
|
|
// Inhalt
|
|
textBody String? @db.LongText
|
|
htmlBody String? @db.LongText
|
|
hasAttachments Boolean @default(false)
|
|
attachmentNames String? @db.Text // JSON Array
|
|
|
|
// Vertragszuordnung
|
|
contractId Int?
|
|
contract Contract? @relation(fields: [contractId], references: [id], onDelete: SetNull)
|
|
assignedAt DateTime?
|
|
assignedBy Int? // User ID der die Zuordnung gemacht hat
|
|
isAutoAssigned Boolean @default(false) // true = automatisch beim Senden aus Vertrag
|
|
|
|
// Flags
|
|
isRead Boolean @default(false)
|
|
isStarred Boolean @default(false)
|
|
|
|
// Papierkorb
|
|
isDeleted Boolean @default(false) // Im Papierkorb?
|
|
deletedAt DateTime? // Wann gelöscht?
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([stressfreiEmailId, messageId, folder]) // Folder hinzugefügt: gleiche MessageID kann in INBOX und SENT existieren
|
|
@@index([contractId])
|
|
@@index([stressfreiEmailId, folder, receivedAt])
|
|
@@index([stressfreiEmailId, isDeleted]) // Für Papierkorb-Abfragen
|
|
}
|
|
|
|
// ==================== METERS (Energy) ====================
|
|
|
|
enum MeterType {
|
|
ELECTRICITY
|
|
GAS
|
|
}
|
|
|
|
model Meter {
|
|
id Int @id @default(autoincrement())
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
meterNumber String
|
|
type MeterType
|
|
location String?
|
|
isActive Boolean @default(true)
|
|
readings MeterReading[]
|
|
energyDetails EnergyContractDetails[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model MeterReading {
|
|
id Int @id @default(autoincrement())
|
|
meterId Int
|
|
meter Meter @relation(fields: [meterId], references: [id], onDelete: Cascade)
|
|
readingDate DateTime
|
|
value Float
|
|
unit String @default("kWh")
|
|
notes String?
|
|
createdAt DateTime @default(now())
|
|
}
|
|
|
|
// ==================== SALES PLATFORMS ====================
|
|
|
|
model SalesPlatform {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique
|
|
contactInfo String? @db.Text
|
|
isActive Boolean @default(true)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== CANCELLATION PERIODS ====================
|
|
|
|
model CancellationPeriod {
|
|
id Int @id @default(autoincrement())
|
|
code String @unique // z.B. "14T", "1M", "3M", "12M", "1J"
|
|
description String // z.B. "14 Tage", "1 Monat", "3 Monate"
|
|
isActive Boolean @default(true)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== CONTRACT DURATIONS ====================
|
|
|
|
model ContractDuration {
|
|
id Int @id @default(autoincrement())
|
|
code String @unique // z.B. "12M", "24M", "1J", "2J"
|
|
description String // z.B. "12 Monate", "24 Monate", "1 Jahr"
|
|
isActive Boolean @default(true)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== PROVIDERS (Anbieter) ====================
|
|
|
|
model Provider {
|
|
id Int @id @default(autoincrement())
|
|
name String @unique // Anbietername
|
|
portalUrl String? // Kundenkontourl (Login-Seite)
|
|
usernameFieldName String? // Benutzernamefeld (z.B. "email", "username")
|
|
passwordFieldName String? // Kennwortfeld (z.B. "password", "pwd")
|
|
isActive Boolean @default(true)
|
|
tariffs Tariff[]
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== TARIFFS (Tarife) ====================
|
|
|
|
model Tariff {
|
|
id Int @id @default(autoincrement())
|
|
providerId Int
|
|
provider Provider @relation(fields: [providerId], references: [id], onDelete: Cascade)
|
|
name String // Tarifname
|
|
isActive Boolean @default(true)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([providerId, name]) // Eindeutiger Tarif pro Anbieter
|
|
}
|
|
|
|
// ==================== CONTRACT CATEGORIES ====================
|
|
|
|
model ContractCategory {
|
|
id Int @id @default(autoincrement())
|
|
code String @unique // Technischer Code (z.B. ELECTRICITY, GAS)
|
|
name String // Anzeigename (z.B. Strom, Gas)
|
|
icon String? // Icon-Name für UI (z.B. "Zap", "Flame")
|
|
color String? // Farbe für UI (z.B. "#FFC107")
|
|
sortOrder Int @default(0)
|
|
isActive Boolean @default(true)
|
|
contracts Contract[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== CONTRACTS ====================
|
|
|
|
// Legacy Enum - wird durch ContractCategory ersetzt
|
|
enum ContractType {
|
|
ELECTRICITY
|
|
GAS
|
|
DSL
|
|
CABLE
|
|
FIBER
|
|
MOBILE
|
|
TV
|
|
CAR_INSURANCE
|
|
}
|
|
|
|
enum ContractStatus {
|
|
DRAFT
|
|
PENDING
|
|
ACTIVE
|
|
CANCELLED
|
|
EXPIRED
|
|
DEACTIVATED
|
|
}
|
|
|
|
model Contract {
|
|
id Int @id @default(autoincrement())
|
|
contractNumber String @unique
|
|
customerId Int
|
|
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
|
type ContractType
|
|
status ContractStatus @default(DRAFT)
|
|
|
|
// Neue konfigurierbare Kategorie (ersetzt langfristig das type-Enum)
|
|
contractCategoryId Int?
|
|
contractCategory ContractCategory? @relation(fields: [contractCategoryId], references: [id])
|
|
|
|
addressId Int?
|
|
address Address? @relation(fields: [addressId], references: [id])
|
|
|
|
bankCardId Int?
|
|
bankCard BankCard? @relation(fields: [bankCardId], references: [id])
|
|
|
|
identityDocumentId Int?
|
|
identityDocument IdentityDocument? @relation(fields: [identityDocumentId], references: [id])
|
|
|
|
salesPlatformId Int?
|
|
salesPlatform SalesPlatform? @relation(fields: [salesPlatformId], references: [id])
|
|
|
|
cancellationPeriodId Int?
|
|
cancellationPeriod CancellationPeriod? @relation(fields: [cancellationPeriodId], references: [id])
|
|
|
|
contractDurationId Int?
|
|
contractDuration ContractDuration? @relation(fields: [contractDurationId], references: [id])
|
|
|
|
previousContractId Int? @unique
|
|
previousContract Contract? @relation("ContractHistory", fields: [previousContractId], references: [id])
|
|
followUpContract Contract? @relation("ContractHistory")
|
|
|
|
// Anbieter & Tarif (neue Verknüpfung)
|
|
providerId Int?
|
|
provider Provider? @relation(fields: [providerId], references: [id])
|
|
tariffId Int?
|
|
tariff Tariff? @relation(fields: [tariffId], references: [id])
|
|
|
|
// Legacy-Felder (für Abwärtskompatibilität)
|
|
providerName String?
|
|
tariffName String?
|
|
customerNumberAtProvider String?
|
|
priceFirst12Months String? // Preis erste 12 Monate
|
|
priceFrom13Months String? // Preis ab 13. Monat
|
|
priceAfter24Months String? // Preis nach 24 Monaten
|
|
|
|
startDate DateTime?
|
|
endDate DateTime? // Wird aus startDate + contractDuration berechnet
|
|
commission Float?
|
|
|
|
// Kündigungsdokumente
|
|
cancellationLetterPath String? // Kündigungsschreiben PDF
|
|
cancellationConfirmationPath String? // Kündigungsbestätigung PDF
|
|
cancellationLetterOptionsPath String? // Kündigungsschreiben Optionen PDF
|
|
cancellationConfirmationOptionsPath String? // Kündigungsbestätigung Optionen PDF
|
|
|
|
// Kündigungsdaten
|
|
cancellationConfirmationDate DateTime? // Kündigungsbestätigungsdatum
|
|
cancellationConfirmationOptionsDate DateTime? // Kündigungsbestätigungsoptionendatum
|
|
wasSpecialCancellation Boolean @default(false) // Wurde sondergekündigt?
|
|
|
|
portalUsername String?
|
|
portalPasswordEncrypted String?
|
|
|
|
// Stressfrei-Wechseln E-Mail als Benutzername (Alternative zu portalUsername)
|
|
stressfreiEmailId Int?
|
|
stressfreiEmail StressfreiEmail? @relation(fields: [stressfreiEmailId], references: [id])
|
|
|
|
notes String? @db.Text
|
|
|
|
energyDetails EnergyContractDetails?
|
|
internetDetails InternetContractDetails?
|
|
mobileDetails MobileContractDetails?
|
|
tvDetails TvContractDetails?
|
|
carInsuranceDetails CarInsuranceDetails?
|
|
|
|
tasks ContractTask[]
|
|
assignedEmails CachedEmail[] // Zugeordnete E-Mails aus dem E-Mail-Client
|
|
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== CONTRACT TASKS ====================
|
|
|
|
enum ContractTaskStatus {
|
|
OPEN
|
|
COMPLETED
|
|
}
|
|
|
|
model ContractTask {
|
|
id Int @id @default(autoincrement())
|
|
contractId Int
|
|
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
title String
|
|
description String? @db.Text
|
|
status ContractTaskStatus @default(OPEN)
|
|
visibleInPortal Boolean @default(false)
|
|
createdBy String? // Name des Erstellers
|
|
completedAt DateTime?
|
|
subtasks ContractTaskSubtask[]
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model ContractTaskSubtask {
|
|
id Int @id @default(autoincrement())
|
|
taskId Int
|
|
task ContractTask @relation(fields: [taskId], references: [id], onDelete: Cascade)
|
|
title String
|
|
status ContractTaskStatus @default(OPEN)
|
|
createdBy String?
|
|
completedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== ENERGY CONTRACT DETAILS ====================
|
|
|
|
model EnergyContractDetails {
|
|
id Int @id @default(autoincrement())
|
|
contractId Int @unique
|
|
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
meterId Int?
|
|
meter Meter? @relation(fields: [meterId], references: [id])
|
|
annualConsumption Float?
|
|
basePrice Float?
|
|
unitPrice Float?
|
|
bonus Float?
|
|
previousProviderName String?
|
|
previousCustomerNumber String?
|
|
}
|
|
|
|
// ==================== INTERNET CONTRACT DETAILS ====================
|
|
|
|
model InternetContractDetails {
|
|
id Int @id @default(autoincrement())
|
|
contractId Int @unique
|
|
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
downloadSpeed Int?
|
|
uploadSpeed Int?
|
|
routerModel String?
|
|
routerSerialNumber String?
|
|
installationDate DateTime?
|
|
// Internet-Zugangsdaten
|
|
internetUsername String?
|
|
internetPasswordEncrypted String? // Verschlüsselt gespeichert
|
|
// Glasfaser-spezifisch
|
|
homeId String?
|
|
// Vodafone DSL/Kabel spezifisch
|
|
activationCode String?
|
|
phoneNumbers PhoneNumber[]
|
|
}
|
|
|
|
model PhoneNumber {
|
|
id Int @id @default(autoincrement())
|
|
internetContractDetailsId Int
|
|
internetDetails InternetContractDetails @relation(fields: [internetContractDetailsId], references: [id], onDelete: Cascade)
|
|
phoneNumber String
|
|
isMain Boolean @default(false)
|
|
// SIP-Zugangsdaten
|
|
sipUsername String?
|
|
sipPasswordEncrypted String? // Verschlüsselt gespeichert
|
|
sipServer String?
|
|
}
|
|
|
|
// ==================== MOBILE CONTRACT DETAILS ====================
|
|
|
|
model MobileContractDetails {
|
|
id Int @id @default(autoincrement())
|
|
contractId Int @unique
|
|
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
requiresMultisim Boolean @default(false) // Multisim erforderlich?
|
|
dataVolume Float?
|
|
includedMinutes Int?
|
|
includedSMS Int?
|
|
deviceModel String?
|
|
deviceImei String?
|
|
simCards SimCard[]
|
|
// Legacy-Felder (für Abwärtskompatibilität, werden durch simCards ersetzt)
|
|
phoneNumber String?
|
|
simCardNumber String?
|
|
}
|
|
|
|
model SimCard {
|
|
id Int @id @default(autoincrement())
|
|
mobileDetailsId Int
|
|
mobileDetails MobileContractDetails @relation(fields: [mobileDetailsId], references: [id], onDelete: Cascade)
|
|
phoneNumber String? // Rufnummer
|
|
simCardNumber String? // SIM-Kartennummer
|
|
pin String? // PIN (verschlüsselt gespeichert)
|
|
puk String? // PUK (verschlüsselt gespeichert)
|
|
isMultisim Boolean @default(false) // Ist dies eine Multisim-Karte?
|
|
isMain Boolean @default(false) // Ist dies die Hauptkarte?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
// ==================== TV CONTRACT DETAILS ====================
|
|
|
|
model TvContractDetails {
|
|
id Int @id @default(autoincrement())
|
|
contractId Int @unique
|
|
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
receiverModel String?
|
|
smartcardNumber String?
|
|
package String?
|
|
}
|
|
|
|
// ==================== CAR INSURANCE DETAILS ====================
|
|
|
|
enum InsuranceType {
|
|
LIABILITY
|
|
PARTIAL
|
|
FULL
|
|
}
|
|
|
|
model CarInsuranceDetails {
|
|
id Int @id @default(autoincrement())
|
|
contractId Int @unique
|
|
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
licensePlate String?
|
|
hsn String?
|
|
tsn String?
|
|
vin String?
|
|
vehicleType String?
|
|
firstRegistration DateTime?
|
|
noClaimsClass String?
|
|
insuranceType InsuranceType @default(LIABILITY)
|
|
deductiblePartial Float?
|
|
deductibleFull Float?
|
|
policyNumber String?
|
|
previousInsurer String?
|
|
}
|