feat: Equipment-System, Buchungsbearbeitung, Kundenadresse, LexOffice-Fix

- Vintage Modell hinzugefuegt
- Equipment Multi-Select (Neue Buchung + Bearbeitung)
- Kundenadresse in Formularen
- Bearbeiten-Seite fuer Buchungen
- Abbau-Zeiten in Formularen und Uebersicht
- Vertrag PDF nur bei Privatkunden
- LexOffice Kontakt-Erstellung Fix (BUSINESS)
- Zurueck-Pfeil auf Touren-Seite
This commit is contained in:
Julia Wehden
2026-03-19 16:21:55 +01:00
parent 0b6e429329
commit a2c95c70e7
79 changed files with 7396 additions and 538 deletions

View File

@@ -34,6 +34,7 @@ enum PhotoboxModel {
VINTAGE_PHOTOS
NOSTALGIE
MAGIC_MIRROR
VINTAGE
}
enum InvoiceType {
@@ -74,6 +75,7 @@ model User {
updatedAt DateTime @updatedAt
driverTours Tour[]
driverLocations DriverLocation[]
notifications Notification[]
driverAvailability DriverAvailability[]
}
@@ -87,6 +89,10 @@ model Location {
contactEmail String
active Boolean @default(true)
warehouseAddress String?
warehouseZip String?
warehouseCity String?
imapHost String?
imapPort Int?
imapUser String?
@@ -120,8 +126,16 @@ model PriceConfig {
model PhotoboxModel
basePrice Float
pricePerKm Float
includedKm Int @default(0)
kmFlatRate Float @default(0)
kmFlatRateUpTo Int @default(15)
pricePerKm Float @default(0)
kmMultiplier Int @default(4)
lexofficeArticleId String?
lexofficeArticleIdWithFlat String?
lexofficeKmFlatArticleId String?
lexofficeKmExtraArticleId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -185,6 +199,8 @@ model Booking {
dismantleTimeEarliest DateTime?
dismantleTimeLatest DateTime?
withPrintFlat Boolean @default(true)
distance Float?
calculatedPrice Float?
@@ -223,6 +239,7 @@ model Booking {
tourId String?
tour Tour? @relation(fields: [tourId], references: [id])
tourStops TourStop[]
notes String?
internalNotes String?
@@ -267,6 +284,27 @@ enum TourStatus {
CANCELLED
}
enum StopStatus {
PENDING // Noch nicht erreicht
EN_ROUTE // Fahrer ist unterwegs
ARRIVED // Fahrer ist angekommen
SETUP_STARTED // Aufbau begonnen
SETUP_COMPLETE // Aufbau abgeschlossen
PICKUP_STARTED // Abbau/Abholung begonnen
PICKUP_COMPLETE // Abholung abgeschlossen
SKIPPED // Übersprungen
ISSUE // Problem aufgetreten
}
enum PhotoType {
SETUP_BEFORE // Vor dem Aufbau
SETUP_AFTER // Nach dem Aufbau
PICKUP_BEFORE // Vor dem Abbau
PICKUP_AFTER // Nach dem Abbau
ISSUE // Problem-Dokumentation
OTHER // Sonstiges
}
model Tour {
id String @id @default(cuid())
tourDate DateTime
@@ -276,6 +314,7 @@ model Tour {
driver User? @relation(fields: [driverId], references: [id])
bookings Booking[]
tourStops TourStop[]
routeOptimized Json?
totalDistance Float?
@@ -295,6 +334,93 @@ model Tour {
@@index([status])
}
model TourStop {
id String @id @default(cuid())
tourId String
tour Tour @relation(fields: [tourId], references: [id], onDelete: Cascade)
bookingId String
booking Booking @relation(fields: [bookingId], references: [id])
stopOrder Int // Reihenfolge der Stopps (1, 2, 3, ...)
stopType String @default("DELIVERY") // DELIVERY, PICKUP, BOTH
status StopStatus @default(PENDING)
// Timestamps für jeden Status
arrivedAt DateTime?
setupStartedAt DateTime?
setupCompleteAt DateTime?
pickupStartedAt DateTime?
pickupCompleteAt DateTime?
// Optional: GPS-Position bei Ankunft
arrivalLatitude Float?
arrivalLongitude Float?
// Notizen vom Fahrer
notes String? @db.Text
issueDescription String? @db.Text
photos DeliveryPhoto[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([tourId, bookingId])
@@index([tourId, stopOrder])
@@index([status])
}
model DriverLocation {
id String @id @default(cuid())
driverId String
driver User @relation(fields: [driverId], references: [id], onDelete: Cascade)
latitude Float
longitude Float
accuracy Float? // GPS-Genauigkeit in Metern
heading Float? // Richtung in Grad (0-360)
speed Float? // Geschwindigkeit in km/h
tourId String?
// Optional: Welcher Stopp ist aktuell?
currentStopId String?
createdAt DateTime @default(now())
@@index([driverId, createdAt])
@@index([tourId])
}
model DeliveryPhoto {
id String @id @default(cuid())
tourStopId String
tourStop TourStop @relation(fields: [tourStopId], references: [id], onDelete: Cascade)
photoType PhotoType
// Dateispeicherung (z.B. /uploads/photos/...)
fileName String
filePath String
fileSize Int?
mimeType String?
// Optional: GPS-Position wo das Foto aufgenommen wurde
latitude Float?
longitude Float?
caption String? @db.Text
uploadedAt DateTime @default(now())
@@index([tourStopId])
@@index([photoType])
}
model Notification {
id String @id @default(cuid())
userId String?
@@ -372,6 +498,9 @@ model Equipment {
notes String?
purchaseDate DateTime?
purchasePrice Decimal?
price Float?
lexofficeArticleId String?
minStockLevel Int?
currentStock Int?