Files
shop-server/server/prisma/schema.prisma
T
@kirill.komarov fe10f25b8c base commit
2026-05-03 19:57:12 +05:00

246 lines
6.6 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
/// Категория изделий (игрушки, сувениры и т.д.)
model Category {
id String @id @default(cuid())
name String
slug String @unique
sort Int @default(0)
products Product[]
}
model Product {
id String @id @default(cuid())
title String
slug String @unique
shortDescription String?
description String?
/// Количество на складе
quantity Int @default(0)
/// Материалы (список, например: ["хлопок","дерево"])
materials String @default("[]")
/// Цена в копейках (целое число, без дробной части)
priceCents Int
imageUrl String?
published Boolean @default(false)
inStock Boolean @default(true)
leadTimeDays Int?
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade)
categoryId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
images ProductImage[]
reviews Review[]
orderItems OrderItem[]
cartItems CartItem[]
}
model ProductImage {
id String @id @default(cuid())
url String
sort Int @default(0)
createdAt DateTime @default(now())
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
productId String
@@index([productId, sort])
}
model User {
id String @id @default(cuid())
email String @unique
name String?
phone String?
passwordHash String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
codes AuthCode[]
addresses ShippingAddress[]
cartItems CartItem[]
orders Order[]
reviews Review[]
orderMessageReadStates UserOrderMessageReadState[]
oauthAccounts OAuthAccount[]
}
/// Прочитанность чата по заказу (для сообщений от админа после lastReadAt)
model UserOrderMessageReadState {
id String @id @default(cuid())
lastReadAt DateTime @default("1970-01-01T00:00:00.000Z")
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
orderId String
@@unique([userId, orderId])
@@index([userId])
}
model CartItem {
id String @id @default(cuid())
qty Int
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
productId String
@@unique([userId, productId])
@@index([userId])
}
model Order {
id String @id @default(cuid())
/// Статус заказа (валидация переходов на уровне API)
status String @default("DRAFT")
/// 'delivery' | 'pickup'
deliveryType String @default("delivery")
itemsSubtotalCents Int @default(0)
deliveryFeeCents Int @default(0)
totalCents Int @default(0)
currency String @default("RUB")
addressSnapshotJson String?
comment String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
items OrderItem[]
messages OrderMessage[]
messageReadStates UserOrderMessageReadState[]
@@index([userId, createdAt])
@@index([status, updatedAt])
}
model OrderItem {
id String @id @default(cuid())
qty Int
titleSnapshot String
priceCentsSnapshot Int
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
orderId String
product Product @relation(fields: [productId], references: [id], onDelete: Restrict)
productId String
@@index([orderId])
}
model OrderMessage {
id String @id @default(cuid())
/// 'user' | 'admin'
authorType String
text String
createdAt DateTime @default(now())
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
orderId String
@@index([orderId, createdAt])
}
model Review {
id String @id @default(cuid())
rating Int
text String?
imageUrl String?
/// 'pending' | 'approved' | 'rejected'
status String @default("pending")
createdAt DateTime @default(now())
moderatedAt DateTime?
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
productId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
@@index([productId, status, createdAt])
@@index([status, createdAt])
@@unique([productId, userId])
}
model ShippingAddress {
id String @id @default(cuid())
label String?
recipientName String
recipientPhone String
addressLine String
comment String?
lat Float
lng Float
isDefault Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
@@index([userId, isDefault])
@@index([userId, updatedAt])
}
model OAuthAccount {
id String @id @default(cuid())
/// 'vk' | 'yandex'
provider String
providerUserId String
accessToken String?
refreshToken String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
@@unique([provider, providerUserId])
@@index([userId])
}
model AuthCode {
id String @id @default(cuid())
email String
codeHash String
purpose String
expiresAt DateTime
usedAt DateTime?
createdAt DateTime @default(now())
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String?
@@index([email, purpose])
@@index([expiresAt])
}
model InfoPageBlock {
id String @id @default(cuid())
key String @unique
title String
body String
sort Int @default(0)
published Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([published, sort])
}