Files
boka-gasol247/prisma/schema.prisma
2026-05-22 10:50:48 +02:00

136 lines
3.7 KiB
Plaintext

// Boka Gasol247 — Prisma schema
// SQLite for MVP. Migrating to Postgres later: change provider + DATABASE_URL.
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
// Singleton settings row. Always accessed with id = "singleton" so we never
// have more than one row. Add new fields as feature flags grow.
model Settings {
id String @id @default("singleton")
pickupEnabled Boolean @default(true)
updatedAt DateTime @updatedAt
}
model Admin {
id String @id @default(cuid())
email String @unique
name String
passwordHash String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Product {
id String @id @default(cuid())
sku String @unique
nameSv String
nameEn String
descriptionSv String
descriptionEn String
// Price in öre (SEK * 100) to avoid float issues.
priceOre Int
// VAT in basis points (e.g. 2500 = 25.00%).
vatBp Int @default(2500)
active Boolean @default(true)
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
bookingItems BookingItem[]
}
model PickupSlot {
id String @id @default(cuid())
// Human label fallback (e.g. "Måndag förmiddag").
labelSv String
labelEn String
startsAt DateTime
endsAt DateTime
capacity Int @default(50)
active Boolean @default(true)
bookings Booking[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// BookingStatus values (string, since SQLite has no enums):
// PENDING | CONFIRMED
// DELIVERED_PARTIAL | DELIVERED (handout out, none returned)
// RETURNED_PARTIAL | RETURNED (everything has come back)
// INVOICED (billing done, terminal)
// CANCELLED (terminal)
// Derived statuses (DELIVERED*/RETURNED*) are normally auto-set from item
// counters; INVOICED and CANCELLED are set explicitly by admin.
model Booking {
id String @id @default(cuid())
bookingNumber String @unique
status String @default("CONFIRMED")
// Contact
contactName String
email String
phone String
// Organization
orgName String
orgNumber String
// Invoice address
address String
postalCode String
city String
country String @default("SE")
// Pickup
pickupSlotId String?
pickupSlot PickupSlot? @relation(fields: [pickupSlotId], references: [id])
notes String?
// Snapshots in öre at booking time
subtotalOre Int
vatOre Int
totalOre Int
locale String @default("sv")
items BookingItem[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([createdAt])
@@index([status])
}
model BookingItem {
id String @id @default(cuid())
bookingId String
booking Booking @relation(fields: [bookingId], references: [id], onDelete: Cascade)
productId String
product Product @relation(fields: [productId], references: [id])
// Snapshots so historical bookings don't break if a product changes
sku String
nameSv String
nameEn String
unitPriceOre Int
vatBp Int
quantity Int
lineTotalOre Int
// Fulfillment tracking — set by admin as cylinders go out and come back.
// Invariants: 0 <= deliveredQuantity <= quantity
// 0 <= returnedQuantity <= deliveredQuantity
deliveredQuantity Int @default(0)
returnedQuantity Int @default(0)
@@index([bookingId])
}