295 lines
7.8 KiB
Plaintext
295 lines
7.8 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
enum UserRole {
|
|
CUSTOMER
|
|
STORE_ADMIN
|
|
SUPER_ADMIN
|
|
}
|
|
|
|
enum StoreStatus {
|
|
pending
|
|
active
|
|
rejected
|
|
suspended
|
|
}
|
|
|
|
enum OrderStatus {
|
|
pending
|
|
confirmed
|
|
preparing
|
|
shipped
|
|
delivered
|
|
cancelled
|
|
}
|
|
|
|
enum OrderStoreStatus {
|
|
pending
|
|
confirmed
|
|
preparing
|
|
shipped
|
|
delivered
|
|
cancelled
|
|
}
|
|
|
|
enum SmsOtpPurpose {
|
|
register
|
|
login
|
|
resetPassword
|
|
storeRegister
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(cuid())
|
|
firstName String
|
|
lastName String
|
|
cellNumber String @unique
|
|
passwordHash String
|
|
email String?
|
|
instagram String?
|
|
about String?
|
|
avatarUrl String?
|
|
avatarKey String?
|
|
role UserRole @default(CUSTOMER)
|
|
disabled Boolean @default(false)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
refreshTokens RefreshToken[]
|
|
addresses UserAddress[]
|
|
ownedStore Store?
|
|
orders Order[] @relation("CustomerOrders")
|
|
|
|
@@index([role])
|
|
@@index([disabled])
|
|
}
|
|
|
|
model UserAddress {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
label String @default("")
|
|
province String
|
|
city String
|
|
fullAddress String
|
|
landline String?
|
|
|
|
@@index([userId])
|
|
}
|
|
|
|
model RefreshToken {
|
|
id String @id @default(cuid())
|
|
tokenHash String
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
expiresAt DateTime
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([userId])
|
|
@@index([tokenHash])
|
|
}
|
|
|
|
model SmsOtp {
|
|
id String @id @default(cuid())
|
|
cellNumber String
|
|
purpose SmsOtpPurpose
|
|
codeHash String
|
|
payload Json?
|
|
attempts Int @default(0)
|
|
expiresAt DateTime
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([cellNumber, purpose])
|
|
@@index([expiresAt])
|
|
}
|
|
|
|
model Store {
|
|
id String @id @default(cuid())
|
|
slug String @unique
|
|
nameFa String
|
|
nameEn String @default("")
|
|
description String?
|
|
logoUrl String?
|
|
logoKey String?
|
|
status StoreStatus @default(pending)
|
|
ownerId String @unique
|
|
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
|
|
rejectionReason String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
products Product[]
|
|
categories Category[]
|
|
brands Brand[]
|
|
blogs BlogPost[]
|
|
orderItems OrderItem[]
|
|
fulfillments OrderStoreFulfillment[]
|
|
|
|
@@index([status])
|
|
}
|
|
|
|
model Category {
|
|
id String @id @default(cuid())
|
|
storeId String
|
|
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
|
|
parentId String?
|
|
parent Category? @relation("CategoryTree", fields: [parentId], references: [id], onDelete: SetNull)
|
|
children Category[] @relation("CategoryTree")
|
|
nameFa String
|
|
nameEn String @default("")
|
|
sortOrder Int @default(0)
|
|
colors String[] @default([])
|
|
sizes String[] @default([])
|
|
packages String[] @default([])
|
|
products Product[]
|
|
|
|
@@index([storeId])
|
|
@@index([parentId])
|
|
@@index([sortOrder])
|
|
}
|
|
|
|
model Brand {
|
|
id String @id @default(cuid())
|
|
storeId String
|
|
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
|
|
nameFa String
|
|
nameEn String @default("")
|
|
imageUrl String?
|
|
imageKey String?
|
|
products Product[]
|
|
|
|
@@index([storeId])
|
|
}
|
|
|
|
model Product {
|
|
id String @id @default(cuid())
|
|
storeId String
|
|
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
|
|
categoryId String?
|
|
category Category? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
|
brandId String?
|
|
brand Brand? @relation(fields: [brandId], references: [id], onDelete: SetNull)
|
|
nameFa String
|
|
nameEn String @default("")
|
|
summary String @default("")
|
|
description String @default("")
|
|
price Int @default(0)
|
|
discountPrice Int?
|
|
imageUrl String?
|
|
imageKey String?
|
|
galleryUrls String[] @default([])
|
|
galleryKeys String[] @default([])
|
|
tags String[] @default([])
|
|
published Boolean @default(true)
|
|
vipEnabled Boolean @default(false)
|
|
vipOnly Boolean @default(false)
|
|
vipSpecialPrice Boolean @default(false)
|
|
vipPrice Int?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
variants ProductVariant[]
|
|
orderItems OrderItem[]
|
|
|
|
@@index([storeId])
|
|
@@index([categoryId])
|
|
@@index([brandId])
|
|
@@index([price])
|
|
@@index([published])
|
|
@@index([vipEnabled])
|
|
@@index([vipOnly])
|
|
}
|
|
|
|
model ProductVariant {
|
|
id String @id @default(cuid())
|
|
productId String
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
colorId String @default("")
|
|
sizeId String @default("")
|
|
packageId String @default("")
|
|
price Int @default(0)
|
|
discountPrice Int?
|
|
vipPrice Int?
|
|
|
|
@@index([productId])
|
|
}
|
|
|
|
model BlogPost {
|
|
id String @id @default(cuid())
|
|
storeId String
|
|
store Store @relation(fields: [storeId], references: [id], onDelete: Cascade)
|
|
title String
|
|
summary String @default("")
|
|
body String @default("")
|
|
author String @default("")
|
|
imageUrl String?
|
|
imageKey String?
|
|
published Boolean @default(true)
|
|
metaTitle String?
|
|
metaDescription String?
|
|
slug String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([storeId])
|
|
@@index([published])
|
|
@@index([slug])
|
|
}
|
|
|
|
model Order {
|
|
id String @id @default(cuid())
|
|
customerId String?
|
|
customer User? @relation("CustomerOrders", fields: [customerId], references: [id], onDelete: SetNull)
|
|
customerName String
|
|
customerPhone String
|
|
status OrderStatus @default(pending)
|
|
itemCount Int @default(0)
|
|
totalAmount Int @default(0)
|
|
note String @default("")
|
|
shippingAddress Json?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
items OrderItem[]
|
|
fulfillments OrderStoreFulfillment[]
|
|
|
|
@@index([customerId])
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
}
|
|
|
|
model OrderItem {
|
|
id String @id @default(cuid())
|
|
orderId String
|
|
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
|
storeId String
|
|
store Store @relation(fields: [storeId], references: [id], onDelete: Restrict)
|
|
productId String?
|
|
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
|
nameFa String
|
|
variantLabel String?
|
|
quantity Int @default(1)
|
|
unitPrice Int @default(0)
|
|
|
|
@@index([orderId])
|
|
@@index([storeId])
|
|
@@index([productId])
|
|
}
|
|
|
|
model OrderStoreFulfillment {
|
|
id String @id @default(cuid())
|
|
orderId String
|
|
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
|
storeId String
|
|
store Store @relation(fields: [storeId], references: [id], onDelete: Restrict)
|
|
status OrderStoreStatus @default(pending)
|
|
|
|
@@unique([orderId, storeId])
|
|
@@index([storeId])
|
|
@@index([status])
|
|
}
|