Initial commit - SaveTheMoment Atlas Basis-Setup
This commit is contained in:
424
prisma/schema.prisma
Normal file
424
prisma/schema.prisma
Normal file
@@ -0,0 +1,424 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum UserRole {
|
||||
ADMIN
|
||||
DRIVER
|
||||
}
|
||||
|
||||
enum BookingStatus {
|
||||
RESERVED // Initial (nach E-Mail-Eingang)
|
||||
CONFIRMED // Admin hat bestätigt & gesendet
|
||||
READY_FOR_ASSIGNMENT // Vertrag unterschrieben → Admin-Freigabe
|
||||
OPEN_FOR_DRIVERS // Admin hat freigegeben → Fahrer können sich melden
|
||||
ASSIGNED // Admin hat Fahrer zugewiesen & Tour erstellt
|
||||
COMPLETED // Event abgeschlossen
|
||||
CANCELLED // Storniert
|
||||
}
|
||||
|
||||
enum PhotoboxStatus {
|
||||
AVAILABLE
|
||||
IN_USE
|
||||
MAINTENANCE
|
||||
DAMAGED
|
||||
}
|
||||
|
||||
enum PhotoboxModel {
|
||||
VINTAGE_SMILE
|
||||
VINTAGE_PHOTOS
|
||||
NOSTALGIE
|
||||
MAGIC_MIRROR
|
||||
}
|
||||
|
||||
enum InvoiceType {
|
||||
PRIVATE
|
||||
BUSINESS
|
||||
}
|
||||
|
||||
enum EquipmentType {
|
||||
PRINTER
|
||||
CARPET
|
||||
VIP_BARRIER
|
||||
ACCESSORIES_KIT
|
||||
PRINTER_PAPER
|
||||
TRIPOD
|
||||
OTHER
|
||||
}
|
||||
|
||||
enum EquipmentStatus {
|
||||
AVAILABLE
|
||||
IN_USE
|
||||
MAINTENANCE
|
||||
DAMAGED
|
||||
RESERVED
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String @unique
|
||||
name String
|
||||
password String
|
||||
role UserRole @default(DRIVER)
|
||||
phoneNumber String?
|
||||
vehiclePlate String?
|
||||
vehicleModel String?
|
||||
active Boolean @default(true)
|
||||
available Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
driverTours Tour[]
|
||||
notifications Notification[]
|
||||
driverAvailability DriverAvailability[]
|
||||
}
|
||||
|
||||
model Location {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
city String
|
||||
slug String @unique
|
||||
websiteUrl String
|
||||
contactEmail String
|
||||
active Boolean @default(true)
|
||||
|
||||
imapHost String?
|
||||
imapPort Int?
|
||||
imapUser String?
|
||||
imapPassword String?
|
||||
imapSecure Boolean @default(true)
|
||||
|
||||
smtpHost String?
|
||||
smtpPort Int?
|
||||
smtpUser String?
|
||||
smtpPassword String?
|
||||
smtpSecure Boolean @default(true)
|
||||
|
||||
emailSyncEnabled Boolean @default(false)
|
||||
lastEmailSync DateTime?
|
||||
|
||||
priceConfig PriceConfig[]
|
||||
photoboxes Photobox[]
|
||||
bookings Booking[]
|
||||
equipment Equipment[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([slug])
|
||||
}
|
||||
|
||||
model PriceConfig {
|
||||
id String @id @default(cuid())
|
||||
locationId String
|
||||
location Location @relation(fields: [locationId], references: [id], onDelete: Cascade)
|
||||
|
||||
model PhotoboxModel
|
||||
basePrice Float
|
||||
pricePerKm Float
|
||||
includedKm Int @default(0)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([locationId, model])
|
||||
}
|
||||
|
||||
model Photobox {
|
||||
id String @id @default(cuid())
|
||||
locationId String
|
||||
location Location @relation(fields: [locationId], references: [id], onDelete: Cascade)
|
||||
|
||||
model PhotoboxModel
|
||||
serialNumber String @unique
|
||||
status PhotoboxStatus @default(AVAILABLE)
|
||||
active Boolean @default(true)
|
||||
|
||||
description String?
|
||||
purchaseDate DateTime?
|
||||
lastMaintenance DateTime?
|
||||
|
||||
bookings Booking[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([locationId, model])
|
||||
@@index([status])
|
||||
}
|
||||
|
||||
model Booking {
|
||||
id String @id @default(cuid())
|
||||
bookingNumber String @unique
|
||||
|
||||
locationId String
|
||||
location Location @relation(fields: [locationId], references: [id])
|
||||
|
||||
photoboxId String?
|
||||
photobox Photobox? @relation(fields: [photoboxId], references: [id])
|
||||
|
||||
status BookingStatus @default(RESERVED)
|
||||
|
||||
customerName String
|
||||
customerEmail String
|
||||
customerPhone String
|
||||
customerAddress String?
|
||||
customerCity String?
|
||||
customerZip String?
|
||||
|
||||
invoiceType InvoiceType @default(PRIVATE)
|
||||
companyName String?
|
||||
|
||||
eventDate DateTime
|
||||
eventAddress String
|
||||
eventCity String
|
||||
eventZip String
|
||||
eventLocation String?
|
||||
|
||||
setupTimeStart DateTime
|
||||
setupTimeLatest DateTime
|
||||
dismantleTimeEarliest DateTime?
|
||||
dismantleTimeLatest DateTime?
|
||||
|
||||
distance Float?
|
||||
calculatedPrice Float?
|
||||
|
||||
// Contract Management
|
||||
contractSigned Boolean @default(false)
|
||||
contractSignedAt DateTime?
|
||||
contractGenerated Boolean @default(false)
|
||||
contractGeneratedAt DateTime?
|
||||
contractSentAt DateTime?
|
||||
contractSignedOnline Boolean @default(false)
|
||||
contractPdfUrl String?
|
||||
contractSignatureData String? @db.Text
|
||||
contractSignedBy String?
|
||||
contractSignedIp String?
|
||||
contractUploadedBy String?
|
||||
|
||||
lexofficeOfferId String?
|
||||
lexofficeInvoiceId String?
|
||||
lexofficeContactId String?
|
||||
lexofficeConfirmationId String?
|
||||
confirmationSentAt DateTime?
|
||||
|
||||
// KI-Analyse
|
||||
aiParsed Boolean @default(false)
|
||||
aiResponseDraft String? @db.Text
|
||||
aiProcessedAt DateTime?
|
||||
|
||||
// Freigabe-Status
|
||||
readyForAssignment Boolean @default(false)
|
||||
openForDrivers Boolean @default(false)
|
||||
|
||||
// Kalender-Sync (Nextcloud)
|
||||
calendarEventId String?
|
||||
calendarSynced Boolean @default(false)
|
||||
calendarSyncedAt DateTime?
|
||||
|
||||
tourId String?
|
||||
tour Tour? @relation(fields: [tourId], references: [id])
|
||||
|
||||
notes String?
|
||||
internalNotes String?
|
||||
|
||||
emails Email[]
|
||||
bookingEquipment BookingEquipment[]
|
||||
driverAvailability DriverAvailability[]
|
||||
setupWindows SetupWindow[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([eventDate])
|
||||
@@index([status])
|
||||
@@index([locationId])
|
||||
}
|
||||
|
||||
model SetupWindow {
|
||||
id String @id @default(cuid())
|
||||
bookingId String
|
||||
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
|
||||
|
||||
setupDate DateTime
|
||||
setupTimeStart DateTime
|
||||
setupTimeEnd DateTime
|
||||
preferred Boolean @default(false)
|
||||
selected Boolean @default(false)
|
||||
|
||||
notes String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([bookingId])
|
||||
@@index([setupDate])
|
||||
}
|
||||
|
||||
enum TourStatus {
|
||||
PLANNED
|
||||
IN_PROGRESS
|
||||
COMPLETED
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
model Tour {
|
||||
id String @id @default(cuid())
|
||||
tourDate DateTime
|
||||
tourNumber String @unique
|
||||
|
||||
driverId String?
|
||||
driver User? @relation(fields: [driverId], references: [id])
|
||||
|
||||
bookings Booking[]
|
||||
|
||||
routeOptimized Json?
|
||||
totalDistance Float?
|
||||
estimatedDuration Int?
|
||||
|
||||
status TourStatus @default(PLANNED)
|
||||
startedAt DateTime?
|
||||
completedAt DateTime?
|
||||
|
||||
notes String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([tourDate])
|
||||
@@index([driverId])
|
||||
@@index([status])
|
||||
}
|
||||
|
||||
model Notification {
|
||||
id String @id @default(cuid())
|
||||
userId String?
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
|
||||
type String
|
||||
title String
|
||||
message String
|
||||
read Boolean @default(false)
|
||||
|
||||
metadata Json?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([userId, read])
|
||||
}
|
||||
|
||||
model Email {
|
||||
id String @id @default(cuid())
|
||||
locationSlug String?
|
||||
|
||||
from String
|
||||
to String
|
||||
subject String
|
||||
textBody String?
|
||||
htmlBody String?
|
||||
|
||||
messageId String? @unique
|
||||
inReplyTo String?
|
||||
|
||||
bookingId String?
|
||||
booking Booking? @relation(fields: [bookingId], references: [id])
|
||||
|
||||
parsed Boolean @default(false)
|
||||
parsedData Json?
|
||||
|
||||
direction String @default("INBOUND")
|
||||
|
||||
receivedAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([locationSlug])
|
||||
@@index([bookingId])
|
||||
@@index([receivedAt])
|
||||
}
|
||||
|
||||
model Project {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
description String?
|
||||
active Boolean @default(true)
|
||||
|
||||
equipment Equipment[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Equipment {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
type EquipmentType
|
||||
brand String?
|
||||
model String?
|
||||
serialNumber String? @unique
|
||||
quantity Int @default(1)
|
||||
status EquipmentStatus @default(AVAILABLE)
|
||||
|
||||
locationId String?
|
||||
location Location? @relation(fields: [locationId], references: [id])
|
||||
|
||||
projectId String?
|
||||
project Project? @relation(fields: [projectId], references: [id])
|
||||
|
||||
notes String?
|
||||
purchaseDate DateTime?
|
||||
purchasePrice Decimal?
|
||||
|
||||
minStockLevel Int?
|
||||
currentStock Int?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
bookingEquipment BookingEquipment[]
|
||||
|
||||
@@index([type])
|
||||
@@index([status])
|
||||
@@index([locationId])
|
||||
}
|
||||
|
||||
model BookingEquipment {
|
||||
id String @id @default(cuid())
|
||||
|
||||
bookingId String
|
||||
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
|
||||
|
||||
equipmentId String
|
||||
equipment Equipment @relation(fields: [equipmentId], references: [id])
|
||||
|
||||
quantity Int @default(1)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([bookingId, equipmentId])
|
||||
@@index([bookingId])
|
||||
@@index([equipmentId])
|
||||
}
|
||||
|
||||
model DriverAvailability {
|
||||
id String @id @default(cuid())
|
||||
|
||||
bookingId String
|
||||
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
|
||||
|
||||
driverId String
|
||||
driver User @relation(fields: [driverId], references: [id], onDelete: Cascade)
|
||||
|
||||
available Boolean @default(true)
|
||||
message String? @db.Text
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([bookingId, driverId])
|
||||
@@index([bookingId])
|
||||
@@index([driverId])
|
||||
}
|
||||
179
prisma/seed-equipment.ts
Normal file
179
prisma/seed-equipment.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log('Starting equipment seed...');
|
||||
|
||||
const locations = await prisma.location.findMany();
|
||||
const luebeck = locations.find(l => l.slug === 'luebeck');
|
||||
const berlin = locations.find(l => l.slug === 'berlin');
|
||||
const rostock = locations.find(l => l.slug === 'rostock');
|
||||
|
||||
let dieFotoboxJungs = await prisma.project.findFirst({
|
||||
where: { name: 'Die Fotobox Jungs' },
|
||||
});
|
||||
|
||||
if (!dieFotoboxJungs) {
|
||||
dieFotoboxJungs = await prisma.project.create({
|
||||
data: {
|
||||
name: 'Die Fotobox Jungs',
|
||||
description: 'Aufgekauftes Projekt mit eigenem Equipment',
|
||||
active: true,
|
||||
},
|
||||
});
|
||||
console.log('Created project: Die Fotobox Jungs');
|
||||
}
|
||||
|
||||
const equipment = [];
|
||||
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
equipment.push({
|
||||
name: `Citizen CX-02 #${i}`,
|
||||
type: 'PRINTER',
|
||||
brand: 'Citizen',
|
||||
model: 'CX-02',
|
||||
serialNumber: `CX02-LUE-${String(i).padStart(3, '0')}`,
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: luebeck?.id,
|
||||
});
|
||||
}
|
||||
|
||||
equipment.push({
|
||||
name: 'Citizen CX-02 Berlin',
|
||||
type: 'PRINTER',
|
||||
brand: 'Citizen',
|
||||
model: 'CX-02',
|
||||
serialNumber: 'CX02-BER-001',
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: berlin?.id,
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'Citizen CX-02 Rostock',
|
||||
type: 'PRINTER',
|
||||
brand: 'Citizen',
|
||||
model: 'CX-02',
|
||||
serialNumber: 'CX02-ROS-001',
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: rostock?.id,
|
||||
});
|
||||
|
||||
for (let i = 1; i <= 4; i++) {
|
||||
equipment.push({
|
||||
name: `DNP 620 #${i} (Fotobox Jungs)`,
|
||||
type: 'PRINTER',
|
||||
brand: 'DNP',
|
||||
model: '620',
|
||||
serialNumber: `DNP620-FBJ-${String(i).padStart(3, '0')}`,
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
projectId: dieFotoboxJungs.id,
|
||||
});
|
||||
}
|
||||
|
||||
equipment.push({
|
||||
name: 'DNP DS-RX1 HS Rostock',
|
||||
type: 'PRINTER',
|
||||
brand: 'DNP',
|
||||
model: 'DS-RX1 HS',
|
||||
serialNumber: 'DSRX1HS-ROS-001',
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: rostock?.id,
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'Roter Teppich Set 1',
|
||||
type: 'CARPET',
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: luebeck?.id,
|
||||
notes: '3m x 1m, inkl. Befestigung',
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'VIP Absperrbänder Set',
|
||||
type: 'VIP_BARRIER',
|
||||
quantity: 2,
|
||||
status: 'AVAILABLE',
|
||||
locationId: luebeck?.id,
|
||||
notes: '2x Ständer mit rotem Samt-Band',
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'Accessoires-Koffer Standard',
|
||||
type: 'ACCESSORIES_KIT',
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: luebeck?.id,
|
||||
notes: 'Hüte, Brillen, Schnurrbärte, Schilder',
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'Druckerpapier Citizen 10x15',
|
||||
type: 'PRINTER_PAPER',
|
||||
brand: 'Citizen',
|
||||
model: '10x15cm',
|
||||
quantity: 1,
|
||||
currentStock: 50,
|
||||
minStockLevel: 10,
|
||||
status: 'AVAILABLE',
|
||||
locationId: luebeck?.id,
|
||||
notes: 'Für Citizen CX-02 Drucker',
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'Druckerpapier DNP 15x20',
|
||||
type: 'PRINTER_PAPER',
|
||||
brand: 'DNP',
|
||||
model: '15x20cm',
|
||||
quantity: 1,
|
||||
currentStock: 8,
|
||||
minStockLevel: 10,
|
||||
status: 'AVAILABLE',
|
||||
locationId: luebeck?.id,
|
||||
notes: 'Für DNP 620 Drucker',
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'Stativ Manfrotto #1',
|
||||
type: 'TRIPOD',
|
||||
brand: 'Manfrotto',
|
||||
model: 'Compact Advanced',
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: luebeck?.id,
|
||||
});
|
||||
|
||||
equipment.push({
|
||||
name: 'Stativ Manfrotto #2',
|
||||
type: 'TRIPOD',
|
||||
brand: 'Manfrotto',
|
||||
model: 'Compact Advanced',
|
||||
quantity: 1,
|
||||
status: 'AVAILABLE',
|
||||
locationId: berlin?.id,
|
||||
});
|
||||
|
||||
for (const item of equipment) {
|
||||
await prisma.equipment.create({
|
||||
data: item as any,
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`Created ${equipment.length} equipment items`);
|
||||
console.log('Equipment seed completed!');
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
179
prisma/seed.ts
Normal file
179
prisma/seed.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { hash } from 'bcryptjs';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log('Seeding database...');
|
||||
|
||||
const adminPassword = await hash('admin123', 12);
|
||||
const driverPassword = await hash('driver123', 12);
|
||||
|
||||
const admin = await prisma.user.upsert({
|
||||
where: { email: 'admin@savethemoment.de' },
|
||||
update: {},
|
||||
create: {
|
||||
email: 'admin@savethemoment.de',
|
||||
name: 'Dennis Forte',
|
||||
password: adminPassword,
|
||||
role: 'ADMIN',
|
||||
phoneNumber: '+49 123 456789',
|
||||
},
|
||||
});
|
||||
|
||||
const driver1 = await prisma.user.upsert({
|
||||
where: { email: 'fahrer1@savethemoment.de' },
|
||||
update: {},
|
||||
create: {
|
||||
email: 'fahrer1@savethemoment.de',
|
||||
name: 'Max Mustermann',
|
||||
password: driverPassword,
|
||||
role: 'DRIVER',
|
||||
phoneNumber: '+49 123 456780',
|
||||
},
|
||||
});
|
||||
|
||||
const driver2 = await prisma.user.upsert({
|
||||
where: { email: 'fahrer2@savethemoment.de' },
|
||||
update: {},
|
||||
create: {
|
||||
email: 'fahrer2@savethemoment.de',
|
||||
name: 'Anna Schmidt',
|
||||
password: driverPassword,
|
||||
role: 'DRIVER',
|
||||
phoneNumber: '+49 123 456781',
|
||||
},
|
||||
});
|
||||
|
||||
const luebeck = await prisma.location.upsert({
|
||||
where: { slug: 'luebeck' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Lübeck',
|
||||
city: 'Lübeck',
|
||||
slug: 'luebeck',
|
||||
websiteUrl: 'https://fotobox-luebeck.de',
|
||||
contactEmail: 'info@fotobox-luebeck.de',
|
||||
},
|
||||
});
|
||||
|
||||
const hamburg = await prisma.location.upsert({
|
||||
where: { slug: 'hamburg' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Hamburg',
|
||||
city: 'Hamburg',
|
||||
slug: 'hamburg',
|
||||
websiteUrl: 'https://hamburg-fotobox.de',
|
||||
contactEmail: 'info@hamburg-fotobox.de',
|
||||
},
|
||||
});
|
||||
|
||||
const kiel = await prisma.location.upsert({
|
||||
where: { slug: 'kiel' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Kiel',
|
||||
city: 'Kiel',
|
||||
slug: 'kiel',
|
||||
websiteUrl: 'https://fotobox-kiel.de',
|
||||
contactEmail: 'info@fotobox-kiel.de',
|
||||
},
|
||||
});
|
||||
|
||||
const berlin = await prisma.location.upsert({
|
||||
where: { slug: 'berlin' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Berlin',
|
||||
city: 'Berlin',
|
||||
slug: 'berlin',
|
||||
websiteUrl: 'https://fotobox-potsdam.de',
|
||||
contactEmail: 'info@fotobox-potsdam.de',
|
||||
},
|
||||
});
|
||||
|
||||
const rostock = await prisma.location.upsert({
|
||||
where: { slug: 'rostock' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'Rostock',
|
||||
city: 'Rostock',
|
||||
slug: 'rostock',
|
||||
websiteUrl: 'https://fotobox-rostock.de',
|
||||
contactEmail: 'info@fotobox-rostock.de',
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.priceConfig.createMany({
|
||||
data: [
|
||||
{ locationId: luebeck.id, model: 'VINTAGE_SMILE', basePrice: 399, pricePerKm: 0.8, includedKm: 30 },
|
||||
{ locationId: luebeck.id, model: 'VINTAGE_PHOTOS', basePrice: 449, pricePerKm: 0.8, includedKm: 30 },
|
||||
{ locationId: luebeck.id, model: 'NOSTALGIE', basePrice: 499, pricePerKm: 0.8, includedKm: 30 },
|
||||
{ locationId: luebeck.id, model: 'MAGIC_MIRROR', basePrice: 599, pricePerKm: 0.8, includedKm: 30 },
|
||||
|
||||
{ locationId: hamburg.id, model: 'VINTAGE_SMILE', basePrice: 419, pricePerKm: 0.9, includedKm: 25 },
|
||||
{ locationId: hamburg.id, model: 'VINTAGE_PHOTOS', basePrice: 469, pricePerKm: 0.9, includedKm: 25 },
|
||||
{ locationId: hamburg.id, model: 'NOSTALGIE', basePrice: 519, pricePerKm: 0.9, includedKm: 25 },
|
||||
{ locationId: hamburg.id, model: 'MAGIC_MIRROR', basePrice: 619, pricePerKm: 0.9, includedKm: 25 },
|
||||
|
||||
{ locationId: kiel.id, model: 'VINTAGE_SMILE', basePrice: 389, pricePerKm: 0.75, includedKm: 35 },
|
||||
{ locationId: kiel.id, model: 'VINTAGE_PHOTOS', basePrice: 439, pricePerKm: 0.75, includedKm: 35 },
|
||||
{ locationId: kiel.id, model: 'NOSTALGIE', basePrice: 489, pricePerKm: 0.75, includedKm: 35 },
|
||||
{ locationId: kiel.id, model: 'MAGIC_MIRROR', basePrice: 589, pricePerKm: 0.75, includedKm: 35 },
|
||||
|
||||
{ locationId: berlin.id, model: 'VINTAGE_SMILE', basePrice: 409, pricePerKm: 0.85, includedKm: 30 },
|
||||
{ locationId: berlin.id, model: 'VINTAGE_PHOTOS', basePrice: 459, pricePerKm: 0.85, includedKm: 30 },
|
||||
{ locationId: berlin.id, model: 'NOSTALGIE', basePrice: 509, pricePerKm: 0.85, includedKm: 30 },
|
||||
{ locationId: berlin.id, model: 'MAGIC_MIRROR', basePrice: 609, pricePerKm: 0.85, includedKm: 30 },
|
||||
|
||||
{ locationId: rostock.id, model: 'VINTAGE_SMILE', basePrice: 379, pricePerKm: 0.75, includedKm: 35 },
|
||||
{ locationId: rostock.id, model: 'VINTAGE_PHOTOS', basePrice: 429, pricePerKm: 0.75, includedKm: 35 },
|
||||
{ locationId: rostock.id, model: 'NOSTALGIE', basePrice: 479, pricePerKm: 0.75, includedKm: 35 },
|
||||
{ locationId: rostock.id, model: 'MAGIC_MIRROR', basePrice: 579, pricePerKm: 0.75, includedKm: 35 },
|
||||
],
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
await prisma.photobox.createMany({
|
||||
data: [
|
||||
{ locationId: luebeck.id, model: 'VINTAGE_SMILE', serialNumber: 'LUE-VS-001' },
|
||||
{ locationId: luebeck.id, model: 'VINTAGE_SMILE', serialNumber: 'LUE-VS-002' },
|
||||
{ locationId: luebeck.id, model: 'VINTAGE_PHOTOS', serialNumber: 'LUE-VP-001' },
|
||||
{ locationId: luebeck.id, model: 'NOSTALGIE', serialNumber: 'LUE-NOS-001' },
|
||||
{ locationId: luebeck.id, model: 'MAGIC_MIRROR', serialNumber: 'LUE-MM-001' },
|
||||
|
||||
{ locationId: hamburg.id, model: 'VINTAGE_SMILE', serialNumber: 'HAM-VS-001' },
|
||||
{ locationId: hamburg.id, model: 'VINTAGE_SMILE', serialNumber: 'HAM-VS-002' },
|
||||
{ locationId: hamburg.id, model: 'VINTAGE_PHOTOS', serialNumber: 'HAM-VP-001' },
|
||||
{ locationId: hamburg.id, model: 'NOSTALGIE', serialNumber: 'HAM-NOS-001' },
|
||||
{ locationId: hamburg.id, model: 'MAGIC_MIRROR', serialNumber: 'HAM-MM-001' },
|
||||
|
||||
{ locationId: kiel.id, model: 'VINTAGE_SMILE', serialNumber: 'KIEL-VS-001' },
|
||||
{ locationId: kiel.id, model: 'VINTAGE_PHOTOS', serialNumber: 'KIEL-VP-001' },
|
||||
{ locationId: kiel.id, model: 'NOSTALGIE', serialNumber: 'KIEL-NOS-001' },
|
||||
|
||||
{ locationId: berlin.id, model: 'VINTAGE_SMILE', serialNumber: 'BER-VS-001' },
|
||||
{ locationId: berlin.id, model: 'MAGIC_MIRROR', serialNumber: 'BER-MM-001' },
|
||||
|
||||
{ locationId: rostock.id, model: 'VINTAGE_SMILE', serialNumber: 'ROS-VS-001' },
|
||||
{ locationId: rostock.id, model: 'NOSTALGIE', serialNumber: 'ROS-NOS-001' },
|
||||
],
|
||||
skipDuplicates: true,
|
||||
});
|
||||
|
||||
console.log('Database seeded successfully!');
|
||||
console.log('\nTest Accounts:');
|
||||
console.log('Admin: admin@savethemoment.de / admin123');
|
||||
console.log('Fahrer 1: fahrer1@savethemoment.de / driver123');
|
||||
console.log('Fahrer 2: fahrer2@savethemoment.de / driver123');
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user