carservice: initial commit
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique
|
||||
password String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Car {
|
||||
id Int @id @default(autoincrement())
|
||||
regNumber String @unique
|
||||
make String?
|
||||
model String?
|
||||
color String?
|
||||
year Int?
|
||||
ownerName String?
|
||||
ownerPhone String?
|
||||
ownerEmail String?
|
||||
vin String?
|
||||
engineNumber String?
|
||||
mileage Int?
|
||||
notes String? @default("")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
orders Order[]
|
||||
parts Part[]
|
||||
|
||||
@@index([regNumber])
|
||||
@@index([ownerName])
|
||||
}
|
||||
|
||||
model Order {
|
||||
id Int @id @default(autoincrement())
|
||||
carId Int
|
||||
car Car @relation(fields: [carId], references: [id], onDelete: Cascade)
|
||||
status String @default("open") // open, closed
|
||||
mileage Int?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
tasks Task[]
|
||||
total Float @default(0)
|
||||
laborHours Float @default(0)
|
||||
hourlyRate Float @default(50)
|
||||
}
|
||||
|
||||
model Task {
|
||||
id Int @id @default(autoincrement())
|
||||
orderId Int
|
||||
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
status String @default("todo") // todo, finished
|
||||
finishedAt DateTime?
|
||||
laborHours Float @default(0)
|
||||
hourlyRate Float @default(50)
|
||||
partsCost Float @default(0)
|
||||
laborCost Float @default(0)
|
||||
price Float @default(0)
|
||||
notes String? @default("")
|
||||
orderIndex Int @default(0)
|
||||
mileage Int?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
parts TaskPart[]
|
||||
|
||||
@@index([status])
|
||||
@@index([finishedAt])
|
||||
}
|
||||
|
||||
model Part {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
manufacturer String?
|
||||
supplierLink String?
|
||||
url String?
|
||||
purchasePrice Float @default(0)
|
||||
notes String? @default("")
|
||||
carId Int?
|
||||
car Car? @relation(fields: [carId], references: [id], onDelete: SetNull)
|
||||
isGlobal Boolean @default(false)
|
||||
orderId Int?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
tasks TaskPart[]
|
||||
|
||||
@@index([name])
|
||||
}
|
||||
|
||||
model TaskPart {
|
||||
id Int @id @default(autoincrement())
|
||||
taskId Int
|
||||
task Task @relation(fields: [taskId], references: [id], onDelete: Cascade)
|
||||
partId Int
|
||||
part Part @relation(fields: [partId], references: [id], onDelete: Cascade)
|
||||
qty Int @default(1)
|
||||
price Float @default(0)
|
||||
|
||||
@@unique([taskId, partId])
|
||||
}
|
||||
|
||||
model QuickTask {
|
||||
id Int @id @default(autoincrement())
|
||||
title String @unique
|
||||
useCount Int @default(0)
|
||||
laborHours Float @default(0)
|
||||
hourlyRate Float @default(50)
|
||||
price Float? // manual override stored in cents/euros
|
||||
createdAt DateTime @default(now())
|
||||
parts QuickTaskPart[]
|
||||
}
|
||||
|
||||
model QuickTaskPart {
|
||||
id Int @id @default(autoincrement())
|
||||
quickTaskId Int
|
||||
quickTask QuickTask @relation(fields: [quickTaskId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
qty Int @default(1)
|
||||
price Float @default(0)
|
||||
isGlobal Boolean @default(false)
|
||||
globalPartId Int?
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
const { PrismaClient } = require("@prisma/client");
|
||||
const bcrypt = require("bcryptjs");
|
||||
|
||||
async function main() {
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const existing = await prisma.user.findUnique({ where: { username: "admin" } });
|
||||
if (!existing) {
|
||||
const hash = await bcrypt.hash("password", 10);
|
||||
await prisma.user.create({
|
||||
data: { username: "admin", password: hash },
|
||||
});
|
||||
console.log("Created default user: admin / password");
|
||||
} else {
|
||||
console.log("User already exists");
|
||||
}
|
||||
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
const { PrismaClient } = require("@prisma/client");
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const commonTasks = [
|
||||
"Oil change",
|
||||
"Oil filter replacement",
|
||||
"Air filter replacement",
|
||||
"Cabin filter replacement",
|
||||
"Front brake pads replacement",
|
||||
"Rear brake pads replacement",
|
||||
"Brake fluid change",
|
||||
"Tyre rotation",
|
||||
"Wheel alignment",
|
||||
"Battery test",
|
||||
"Coolant change",
|
||||
"Timing belt inspection",
|
||||
"Spark plug replacement",
|
||||
"Full diagnostic scan",
|
||||
"Suspension check",
|
||||
"Exhaust inspection",
|
||||
"NCT pre-check",
|
||||
];
|
||||
|
||||
async function main() {
|
||||
for (const title of commonTasks) {
|
||||
await prisma.quickTask.upsert({
|
||||
where: { title },
|
||||
update: {},
|
||||
create: { title, useCount: 1 },
|
||||
});
|
||||
}
|
||||
console.log("Seeded quick tasks");
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user