Latest updarte
This commit is contained in:
187
prisma/schema.prisma
Normal file
187
prisma/schema.prisma
Normal file
@@ -0,0 +1,187 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
// ─── Auth (NextAuth v5) ────────────────────────────────────────────────────
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String @unique
|
||||
emailVerified DateTime?
|
||||
image String?
|
||||
role Role @default(CUSTOMER)
|
||||
password String?
|
||||
|
||||
accounts Account[]
|
||||
sessions Session[]
|
||||
orders Order[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Account {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
type String
|
||||
provider String
|
||||
providerAccountId String
|
||||
refresh_token String?
|
||||
access_token String?
|
||||
expires_at Int?
|
||||
token_type String?
|
||||
scope String?
|
||||
id_token String?
|
||||
session_state String?
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([provider, providerAccountId])
|
||||
}
|
||||
|
||||
model Session {
|
||||
id String @id @default(cuid())
|
||||
sessionToken String @unique
|
||||
userId String
|
||||
expires DateTime
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model VerificationToken {
|
||||
identifier String
|
||||
token String
|
||||
expires DateTime
|
||||
|
||||
@@unique([identifier, token])
|
||||
}
|
||||
|
||||
enum Role {
|
||||
CUSTOMER
|
||||
ADMIN
|
||||
}
|
||||
|
||||
// ─── Katalog ──────────────────────────────────────────────────────────────
|
||||
|
||||
model Category {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
image String?
|
||||
products Product[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Product {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
slug String @unique
|
||||
description String?
|
||||
image String?
|
||||
published Boolean @default(false)
|
||||
categoryId String
|
||||
|
||||
category Category @relation(fields: [categoryId], references: [id])
|
||||
variants ProductVariant[]
|
||||
orderItems OrderItem[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model ProductVariant {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
price Int // cena v haléřích (CZK)
|
||||
stock Int @default(0)
|
||||
sku String? @unique
|
||||
productId String
|
||||
|
||||
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
||||
cartItems CartItem[]
|
||||
orderItems OrderItem[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// ─── Košík ────────────────────────────────────────────────────────────────
|
||||
|
||||
model Cart {
|
||||
id String @id @default(cuid())
|
||||
sessionId String? @unique // pro guest uživatele
|
||||
userId String? @unique // pro přihlášené
|
||||
items CartItem[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model CartItem {
|
||||
id String @id @default(cuid())
|
||||
cartId String
|
||||
variantId String
|
||||
quantity Int
|
||||
|
||||
cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade)
|
||||
variant ProductVariant @relation(fields: [variantId], references: [id])
|
||||
|
||||
@@unique([cartId, variantId])
|
||||
}
|
||||
|
||||
// ─── Objednávky ───────────────────────────────────────────────────────────
|
||||
|
||||
model Order {
|
||||
id String @id @default(cuid())
|
||||
userId String?
|
||||
guestEmail String?
|
||||
status OrderStatus @default(PENDING)
|
||||
totalAmount Int // v haléřích
|
||||
stripeSessionId String? @unique
|
||||
|
||||
shippingName String
|
||||
shippingEmail String
|
||||
shippingPhone String?
|
||||
shippingStreet String
|
||||
shippingCity String
|
||||
shippingZip String
|
||||
shippingCountry String @default("CZ")
|
||||
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
items OrderItem[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model OrderItem {
|
||||
id String @id @default(cuid())
|
||||
orderId String
|
||||
productId String
|
||||
variantId String
|
||||
quantity Int
|
||||
unitPrice Int // cena v době objednávky (snapshot)
|
||||
|
||||
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
||||
product Product @relation(fields: [productId], references: [id])
|
||||
variant ProductVariant @relation(fields: [variantId], references: [id])
|
||||
}
|
||||
|
||||
enum OrderStatus {
|
||||
PENDING
|
||||
PAID
|
||||
PROCESSING
|
||||
SHIPPED
|
||||
DELIVERED
|
||||
CANCELLED
|
||||
REFUNDED
|
||||
}
|
||||
148
prisma/seed.ts
Normal file
148
prisma/seed.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const db = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
console.log("🌱 Seeding databáze...");
|
||||
|
||||
// Kategorie
|
||||
const dorty = await db.category.upsert({
|
||||
where: { slug: "dorty" },
|
||||
update: {},
|
||||
create: { name: "Dorty", slug: "dorty", description: "Celé dorty na objednávku i jako dárek" },
|
||||
});
|
||||
|
||||
const zakusky = await db.category.upsert({
|
||||
where: { slug: "zakusky" },
|
||||
update: {},
|
||||
create: { name: "Zákusky", slug: "zakusky", description: "Čerstvé zákusky pečené každý den" },
|
||||
});
|
||||
|
||||
const pralinky = await db.category.upsert({
|
||||
where: { slug: "pralinky" },
|
||||
update: {},
|
||||
create: { name: "Pralinky", slug: "pralinky", description: "Ručně vyráběné čokoládové pralinky" },
|
||||
});
|
||||
|
||||
// Produkty
|
||||
await db.product.upsert({
|
||||
where: { slug: "cokoladovy-dort" },
|
||||
update: {},
|
||||
create: {
|
||||
name: "Čokoládový dort",
|
||||
slug: "cokoladovy-dort",
|
||||
description: "Tříposchoďový dort z belgické čokolády s ganache polevou a čokoládovými hoblinami.",
|
||||
published: true,
|
||||
categoryId: dorty.id,
|
||||
variants: {
|
||||
create: [
|
||||
{ name: "Malý (6 porcí)", price: 59000, stock: 5 },
|
||||
{ name: "Střední (10 porcí)", price: 89000, stock: 3 },
|
||||
{ name: "Velký (16 porcí)", price: 129000, stock: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await db.product.upsert({
|
||||
where: { slug: "jahodovy-dort" },
|
||||
update: {},
|
||||
create: {
|
||||
name: "Jahodový dort",
|
||||
slug: "jahodovy-dort",
|
||||
description: "Lehký piškotový dort s šlehačkou a čerstvými jahodami. Sezónní specialita.",
|
||||
published: true,
|
||||
categoryId: dorty.id,
|
||||
variants: {
|
||||
create: [
|
||||
{ name: "Malý (6 porcí)", price: 65000, stock: 4 },
|
||||
{ name: "Velký (12 porcí)", price: 119000, stock: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await db.product.upsert({
|
||||
where: { slug: "kremovy-zakusek" },
|
||||
update: {},
|
||||
create: {
|
||||
name: "Krémový zákusek",
|
||||
slug: "kremovy-zakusek",
|
||||
description: "Klasický kremrole s vanilkovým krémem a cukrovou polevou.",
|
||||
published: true,
|
||||
categoryId: zakusky.id,
|
||||
variants: {
|
||||
create: [
|
||||
{ name: "1 kus", price: 4500, stock: 20 },
|
||||
{ name: "Balení 6 kusů", price: 24000, stock: 10 },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await db.product.upsert({
|
||||
where: { slug: "eclair-cokoladovy" },
|
||||
update: {},
|
||||
create: {
|
||||
name: "Éclair čokoládový",
|
||||
slug: "eclair-cokoladovy",
|
||||
description: "Francouzský éclair z odpalovaného těsta s čokoládovým krémem.",
|
||||
published: true,
|
||||
categoryId: zakusky.id,
|
||||
variants: {
|
||||
create: [
|
||||
{ name: "1 kus", price: 5500, stock: 15 },
|
||||
{ name: "Balení 4 kusy", price: 20000, stock: 8 },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await db.product.upsert({
|
||||
where: { slug: "pralinky-belgicke" },
|
||||
update: {},
|
||||
create: {
|
||||
name: "Belgické pralinky",
|
||||
slug: "pralinky-belgicke",
|
||||
description: "Ručně vyráběné pralinky z hořké, mléčné a bílé belgické čokolády s různými náplněmi.",
|
||||
published: true,
|
||||
categoryId: pralinky.id,
|
||||
variants: {
|
||||
create: [
|
||||
{ name: "Krabička 9 kusů", price: 29000, stock: 12 },
|
||||
{ name: "Krabička 18 kusů", price: 55000, stock: 8 },
|
||||
{ name: "Krabička 36 kusů", price: 99000, stock: 5 },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await db.product.upsert({
|
||||
where: { slug: "makronky-mix" },
|
||||
update: {},
|
||||
create: {
|
||||
name: "Makronky mix",
|
||||
slug: "makronky-mix",
|
||||
description: "Francouzské makronky v 6 příchutích: vanilka, malina, pistácie, citron, karamel, čokoláda.",
|
||||
published: true,
|
||||
categoryId: pralinky.id,
|
||||
variants: {
|
||||
create: [
|
||||
{ name: "6 kusů (mix)", price: 22000, stock: 10 },
|
||||
{ name: "12 kusů (mix)", price: 40000, stock: 6 },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
console.log("✅ Seed dokončen!");
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await db.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user