886 lines
35 KiB
Plaintext
886 lines
35 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
binaryTargets = ["native", "linux-musl-openssl-3.0.x"]
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
firstName String @map("first_name") @db.VarChar(100)
|
|
lastName String @map("last_name") @db.VarChar(100)
|
|
email String? @unique @db.VarChar(150)
|
|
mobile String @unique @db.VarChar(15)
|
|
password String? @db.VarChar(255)
|
|
role String @default("User_PetOwner") @db.VarChar(30)
|
|
walletBalance Decimal @default(0.00) @map("wallet_balance") @db.Decimal(15, 2)
|
|
charityDonationTotal Decimal @default(0.00) @map("charity_donation_total") @db.Decimal(15, 2)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz()
|
|
|
|
addresses UserAddress[]
|
|
walletTransactions WalletTransaction[]
|
|
pets Pet[]
|
|
orders Order[]
|
|
blogs Blog[]
|
|
prescriptions Prescription[]
|
|
partnerAccount PartnerAccount?
|
|
paymentTransactions PaymentTransaction[]
|
|
tickets Ticket[]
|
|
reviews ProductReview[]
|
|
blogComments BlogComment[]
|
|
|
|
@@index([role])
|
|
@@index([createdAt])
|
|
@@map("users")
|
|
}
|
|
|
|
model UserAddress {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
userId String @map("user_id") @db.Uuid
|
|
title String @db.VarChar(100)
|
|
receptorName String @map("receptor_name") @db.VarChar(150)
|
|
phone String @db.VarChar(15)
|
|
province String @db.VarChar(100)
|
|
city String @db.VarChar(100)
|
|
detail String @db.Text
|
|
zipCode String @map("zip_code") @db.VarChar(10)
|
|
isDefault Boolean @default(false) @map("is_default")
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([userId])
|
|
@@map("user_addresses")
|
|
}
|
|
|
|
model WalletTransaction {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
userId String @map("user_id") @db.Uuid
|
|
amount Decimal @db.Decimal(15, 2)
|
|
type String @db.VarChar(20) // deposit, withdrawal
|
|
status String @db.VarChar(20) // pending, completed, failed
|
|
transactionReference String? @unique @map("transaction_reference") @db.VarChar(100)
|
|
description String? @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("wallet_transactions")
|
|
}
|
|
|
|
model Media {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
filename String @db.VarChar(200)
|
|
url String @db.Text
|
|
mimetype String @db.VarChar(50)
|
|
size Int
|
|
altText String? @map("alt_text") @db.VarChar(250)
|
|
title String? @db.VarChar(250)
|
|
description String? @db.Text
|
|
caption String? @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
@@map("media")
|
|
}
|
|
|
|
model Category {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
name String @db.VarChar(150)
|
|
slug String @unique @db.VarChar(150)
|
|
description String? @db.Text
|
|
parentId String? @map("parent_id") @db.Uuid
|
|
metaTitle String? @map("meta_title") @db.VarChar(200)
|
|
metaDescription String? @map("meta_description") @db.Text
|
|
keywords String? @db.Text
|
|
imageUrl String? @map("image_url") @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
parent Category? @relation("SubCategories", fields: [parentId], references: [id])
|
|
children Category[] @relation("SubCategories")
|
|
products Product[]
|
|
|
|
@@map("categories")
|
|
}
|
|
|
|
model BlogCategory {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
name String @db.VarChar(150)
|
|
slug String @unique @db.VarChar(150)
|
|
description String? @db.Text
|
|
parentId String? @map("parent_id") @db.Uuid
|
|
imageUrl String? @map("image_url") @db.Text
|
|
order Int @default(0)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
parent BlogCategory? @relation("BlogSubCategories", fields: [parentId], references: [id], onDelete: Cascade)
|
|
children BlogCategory[] @relation("BlogSubCategories")
|
|
blogs Blog[]
|
|
|
|
@@map("blog_categories")
|
|
}
|
|
|
|
model BlogTag {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
name String @unique @db.VarChar(100)
|
|
slug String @unique @db.VarChar(100)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
blogs Blog[]
|
|
|
|
@@map("blog_tags")
|
|
}
|
|
|
|
model Blog {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
title String @db.VarChar(200)
|
|
slug String @unique @db.VarChar(200)
|
|
content String @db.Text
|
|
excerpt String? @db.Text
|
|
authorId String @map("author_id") @db.Uuid
|
|
categoryId String? @map("category_id") @db.Uuid
|
|
imageUrl String? @map("image_url") @db.Text
|
|
imageAlt String? @map("image_alt") @db.VarChar(255)
|
|
imageCaption String? @map("image_caption") @db.Text
|
|
metaTitle String? @map("meta_title") @db.VarChar(200)
|
|
metaDescription String? @map("meta_description") @db.Text
|
|
keywords String? @db.Text
|
|
focusKeywords String? @map("focus_keywords") @db.Text
|
|
canonicalUrl String? @map("canonical_url") @db.Text
|
|
noIndex Boolean @default(false) @map("no_index")
|
|
noFollow Boolean @default(false) @map("no_follow")
|
|
schemaType String @default("BlogPosting") @map("schema_type") @db.VarChar(50)
|
|
ogTitle String? @map("og_title") @db.VarChar(200)
|
|
ogDescription String? @map("og_description") @db.Text
|
|
ogImage String? @map("og_image") @db.Text
|
|
status String @default("PUBLISHED") @db.VarChar(20) // DRAFT, PUBLISHED, SCHEDULED, ARCHIVED
|
|
isPublished Boolean @default(true) @map("is_published")
|
|
publishedAt DateTime? @map("published_at") @db.Timestamptz()
|
|
readingTime Int @default(3) @map("reading_time")
|
|
featured Boolean @default(false)
|
|
allowComments Boolean @default(true) @map("allow_comments")
|
|
viewCount Int @default(0) @map("view_count")
|
|
showOnHome Boolean @default(false) @map("show_on_home")
|
|
homeDisplayMode String @default("selected") @map("home_display_mode") @db.VarChar(30)
|
|
relatedProductIds String[] @default([]) @map("related_product_ids")
|
|
relatedBlogIds String[] @default([]) @map("related_blog_ids")
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
author User @relation(fields: [authorId], references: [id])
|
|
category BlogCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
|
tags BlogTag[]
|
|
comments BlogComment[]
|
|
|
|
@@index([categoryId])
|
|
@@index([status])
|
|
@@index([publishedAt])
|
|
@@index([featured])
|
|
@@map("blogs")
|
|
}
|
|
|
|
model Product {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
artNo String @unique @map("art_no") @db.VarChar(20)
|
|
barcode String? @unique @db.VarChar(30)
|
|
slug String @unique @db.VarChar(150)
|
|
productGroup String? @map("product_group") @db.VarChar(100)
|
|
nameFa String @map("name_fa") @db.VarChar(200)
|
|
nameEn String @map("name_en") @db.VarChar(200)
|
|
scientificTagline String? @map("scientific_tagline") @db.VarChar(250)
|
|
description String @db.Text
|
|
shortDescription String? @map("short_description") @db.Text
|
|
ingredients String? @db.Text
|
|
categoryId String @map("category_id") @db.Uuid
|
|
categorySlug String @map("category_slug") @db.VarChar(100)
|
|
priceValue Decimal @map("price_value") @db.Decimal(15, 2)
|
|
wholesalePrice Decimal? @map("wholesale_price") @db.Decimal(15, 2)
|
|
requiresRx Boolean @default(false) @map("requires_rx")
|
|
buyPrice Decimal @default(0) @map("buy_price") @db.Decimal(15, 2)
|
|
marginRetailPercent Decimal? @map("margin_retail_percent") @db.Decimal(6, 2)
|
|
marginWholesalePercent Decimal? @map("margin_wholesale_percent") @db.Decimal(6, 2)
|
|
roundingStep Int? @map("rounding_step")
|
|
roundingMode String? @map("rounding_mode") @db.VarChar(10)
|
|
priceDisplay String @map("price_display") @db.VarChar(50)
|
|
unit String @db.VarChar(50)
|
|
packageSize Decimal @map("package_size") @db.Decimal(10, 2)
|
|
dosageLogic String? @map("dosage_logic") @db.Text
|
|
dosageConfig Json? @map("dosage_config")
|
|
suitableFor String @map("suitable_for") @db.VarChar(15) // سگ, گربه, هر دو
|
|
imageUrl String @map("image_url") @db.Text
|
|
images String[] @default([])
|
|
podcastUrl String? @map("podcast_url") @db.Text
|
|
podcastTitle String? @map("podcast_title") @db.VarChar(250)
|
|
podcastDescription String? @map("podcast_description") @db.Text
|
|
podcastCover String? @map("podcast_cover") @db.Text
|
|
videoUrl String? @map("video_url") @db.Text
|
|
videoTitle String? @map("video_title") @db.VarChar(250)
|
|
videoDescription String? @map("video_description") @db.Text
|
|
videoCover String? @map("video_cover") @db.Text
|
|
pdfUrl String? @map("pdf_url") @db.Text
|
|
pdfTitle String? @map("pdf_title") @db.VarChar(250)
|
|
pdfDescription String? @map("pdf_description") @db.Text
|
|
pdfCover String? @map("pdf_cover") @db.Text
|
|
metaTitle String? @map("meta_title") @db.VarChar(200)
|
|
metaDescription String? @map("meta_description") @db.Text
|
|
canonicalUrl String? @map("canonical_url") @db.Text
|
|
keywords String? @db.Text
|
|
stockStatus StockStatus @default(IN_STOCK) @map("stock_status")
|
|
noIndex Boolean @default(false) @map("no_index")
|
|
noFollow Boolean @default(false) @map("no_follow")
|
|
ogImage String? @map("og_image") @db.Text
|
|
featuredImageAlt String? @map("featured_image_alt") @db.VarChar(255)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
category Category @relation(fields: [categoryId], references: [id])
|
|
ingredientList ProductIngredient[]
|
|
symptoms ProductSymptom[]
|
|
reminders Reminder[]
|
|
orderItems OrderItem[]
|
|
advisorRules SmartAdvisorRule[]
|
|
inventoryReservations InventoryReservation[]
|
|
reviews ProductReview[]
|
|
|
|
@@index([categorySlug])
|
|
@@index([suitableFor])
|
|
@@index([productGroup])
|
|
@@index([requiresRx])
|
|
@@index([categorySlug, suitableFor])
|
|
@@map("products")
|
|
}
|
|
|
|
enum StockStatus {
|
|
IN_STOCK
|
|
OUT_OF_STOCK
|
|
PRE_ORDER
|
|
DISCONTINUED
|
|
}
|
|
|
|
|
|
|
|
model ProductIngredient {
|
|
productId String @map("product_id") @db.Uuid
|
|
ingredient String @db.VarChar(150)
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([productId, ingredient])
|
|
@@map("product_ingredients")
|
|
}
|
|
|
|
model ProductSymptom {
|
|
productId String @map("product_id") @db.Uuid
|
|
symptom String @db.VarChar(150)
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([productId, symptom])
|
|
@@map("product_symptoms")
|
|
}
|
|
|
|
model Pet {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
userId String @map("user_id") @db.Uuid
|
|
name String @db.VarChar(100)
|
|
type String @db.VarChar(10) // سگ, گربه
|
|
breed String @db.VarChar(100)
|
|
age Int
|
|
weight Decimal @db.Decimal(5, 2)
|
|
activityLevel String @map("activity_level") @db.VarChar(15) // کم, متوسط, زیاد
|
|
imageUrl String? @map("image_url") @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
medicalConditions PetMedicalCondition[]
|
|
reminders Reminder[]
|
|
healthLogs HealthLog[]
|
|
prescriptions Prescription[]
|
|
tickets Ticket[]
|
|
|
|
@@map("pets")
|
|
}
|
|
|
|
model PetMedicalCondition {
|
|
petId String @map("pet_id") @db.Uuid
|
|
condition String @db.VarChar(150)
|
|
pet Pet @relation(fields: [petId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([petId, condition])
|
|
@@map("pet_medical_conditions")
|
|
}
|
|
|
|
model Reminder {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
petId String @map("pet_id") @db.Uuid
|
|
productId String? @map("product_id") @db.Uuid
|
|
title String @db.VarChar(150)
|
|
time String @db.VarChar(5) // 08:30
|
|
frequency String @db.VarChar(20) // روزانه, هفتگی
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
pet Pet @relation(fields: [petId], references: [id], onDelete: Cascade)
|
|
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
|
completions ReminderCompletion[]
|
|
|
|
@@index([petId])
|
|
@@map("reminders")
|
|
}
|
|
|
|
model ReminderCompletion {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
reminderId String @map("reminder_id") @db.Uuid
|
|
completedDate DateTime @map("completed_date") @db.Date
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
reminder Reminder @relation(fields: [reminderId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([reminderId, completedDate])
|
|
@@index([reminderId, completedDate])
|
|
@@map("reminder_completions")
|
|
}
|
|
|
|
model HealthLog {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
petId String @map("pet_id") @db.Uuid
|
|
appetite String @db.VarChar(15)
|
|
energy String @db.VarChar(15)
|
|
digestion String @db.VarChar(15)
|
|
note String? @db.Text
|
|
loggedDate DateTime @default(now()) @map("logged_date") @db.Date
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
pet Pet @relation(fields: [petId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("health_logs")
|
|
}
|
|
|
|
model Coupon {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
code String @unique @db.VarChar(50)
|
|
type String @default("percent") @db.VarChar(20) // fixed, percent
|
|
value Decimal @db.Decimal(15, 2)
|
|
minCartValue Decimal? @map("min_cart_value") @db.Decimal(15, 2)
|
|
maxCartValue Decimal? @map("max_cart_value") @db.Decimal(15, 2)
|
|
maxUses Int? @map("max_uses")
|
|
usedCount Int @default(0) @map("used_count")
|
|
expiresAt DateTime? @map("expires_at") @db.Timestamptz()
|
|
isActive Boolean @default(true) @map("is_active")
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
orders Order[]
|
|
targets CouponTarget[]
|
|
|
|
@@map("coupons")
|
|
}
|
|
|
|
model CouponTarget {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
couponId String @map("coupon_id") @db.Uuid
|
|
targetType String @map("target_type") @db.VarChar(50) // USER, PET, ROLE, PRODUCT, CATEGORY
|
|
targetId String @map("target_id") @db.VarChar(100) // UUID or role name
|
|
modifierType String @default("override") @map("modifier_type") @db.VarChar(20) // override, add, subtract
|
|
modifierValue Decimal? @map("modifier_value") @db.Decimal(15, 2)
|
|
|
|
coupon Coupon @relation(fields: [couponId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([targetType, targetId])
|
|
@@map("coupon_targets")
|
|
}
|
|
|
|
model Order {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
userId String @map("user_id") @db.Uuid
|
|
couponId String? @map("coupon_id") @db.Uuid
|
|
totalAmount Decimal @map("total_amount") @db.Decimal(15, 2)
|
|
charityDonation Decimal @default(0.00) @map("charity_donation") @db.Decimal(15, 2)
|
|
isRefill Boolean @default(false) @map("is_refill")
|
|
refillIntervalDays Int? @map("refill_interval_days")
|
|
status String @default("processing") @db.VarChar(30) // pending_payment, processing, shipped, delivered, cancelled
|
|
paymentMethod String? @default("card") @map("payment_method") @db.VarChar(30)
|
|
shippingAddress String? @map("shipping_address") @db.Text
|
|
trackingNumber String? @unique @map("tracking_number") @db.VarChar(100)
|
|
refundStatus String? @default("none") @map("refund_status") @db.VarChar(30) // none, wallet, gateway, partial
|
|
refundedAmount Decimal @default(0.00) @map("refunded_amount") @db.Decimal(15, 2)
|
|
refundMethod String? @map("refund_method") @db.VarChar(30) // wallet, zibal
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
coupon Coupon? @relation(fields: [couponId], references: [id])
|
|
orderItems OrderItem[]
|
|
paymentTransactions PaymentTransaction[]
|
|
inventoryReservations InventoryReservation[]
|
|
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
@@map("orders")
|
|
}
|
|
|
|
model PaymentTransaction {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
userId String @map("user_id") @db.Uuid
|
|
orderId String? @map("order_id") @db.Uuid
|
|
amount Decimal @db.Decimal(15, 2) // in Tomans
|
|
amountRials BigInt? @map("amount_rials")
|
|
gateway String @default("zibal") @db.VarChar(50)
|
|
trackId String? @unique @map("track_id") @db.VarChar(100)
|
|
refNumber String? @map("ref_number") @db.VarChar(100)
|
|
cardNumber String? @map("card_number") @db.VarChar(30)
|
|
hashedCardNumber String? @map("hashed_card_number") @db.VarChar(100)
|
|
status String @default("PENDING") @db.VarChar(30) // PENDING, PAID, FAILED, VERIFIED
|
|
resultCode Int? @map("result_code")
|
|
message String? @db.Text
|
|
description String? @db.Text
|
|
type String @default("ORDER") @db.VarChar(30) // ORDER, WALLET_TOPUP
|
|
ipAddress String? @map("ip_address") @db.VarChar(50)
|
|
userAgent String? @map("user_agent") @db.Text
|
|
rawRequest Json? @map("raw_request")
|
|
rawResponse Json? @map("raw_response")
|
|
paidAt DateTime? @map("paid_at") @db.Timestamptz()
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
order Order? @relation(fields: [orderId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([userId])
|
|
@@index([orderId])
|
|
@@index([trackId])
|
|
@@map("payment_transactions")
|
|
}
|
|
|
|
model InventoryReservation {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
orderId String @map("order_id") @db.Uuid
|
|
productId String @map("product_id") @db.Uuid
|
|
quantity Int @default(1)
|
|
expiresAt DateTime @map("expires_at") @db.Timestamptz()
|
|
status String @default("ACTIVE") @db.VarChar(20) // ACTIVE, CONSUMED, RELEASED
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([orderId])
|
|
@@index([productId])
|
|
@@index([status])
|
|
@@index([expiresAt])
|
|
@@map("inventory_reservations")
|
|
}
|
|
|
|
model OrderItem {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
orderId String @map("order_id") @db.Uuid
|
|
productId String? @map("product_id") @db.Uuid
|
|
quantity Int
|
|
doseQty Decimal? @map("dose_qty") @db.Decimal(10, 2)
|
|
doseUnit String? @map("dose_unit") @db.VarChar(50)
|
|
|
|
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
|
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
|
|
|
@@map("order_items")
|
|
}
|
|
|
|
model UiText {
|
|
key String @id @db.VarChar(100)
|
|
value String @db.Text
|
|
|
|
@@map("ui_texts")
|
|
}
|
|
|
|
model ScientificTerm {
|
|
key String @id @db.VarChar(100)
|
|
term String @db.VarChar(150)
|
|
definition String @db.Text
|
|
wikiId String @map("wiki_id") @db.VarChar(50)
|
|
metaTitle String? @map("meta_title") @db.VarChar(200)
|
|
metaDescription String? @map("meta_description") @db.Text
|
|
keywords String? @db.Text
|
|
|
|
@@map("scientific_terms")
|
|
}
|
|
|
|
model HeroBanner {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
title String @db.VarChar(200)
|
|
subtitle String? @db.Text
|
|
imageUrl String @map("image_url") @db.Text
|
|
buttonText String? @map("button_text") @db.VarChar(100)
|
|
buttonLink String? @map("button_link") @db.Text
|
|
isActive Boolean @default(true) @map("is_active")
|
|
order Int @default(0)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
@@map("hero_banners")
|
|
}
|
|
|
|
model VetTestimonial {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
vetName String @map("vet_name") @db.VarChar(150)
|
|
clinicName String? @map("clinic_name") @db.VarChar(150)
|
|
imageUrl String? @map("image_url") @db.Text
|
|
quote String @db.Text
|
|
rating Int @default(5)
|
|
isActive Boolean @default(true) @map("is_active")
|
|
order Int @default(0)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
@@map("vet_testimonials")
|
|
}
|
|
|
|
model SmartAdvisorRule {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
condition String @db.VarChar(200)
|
|
targetPetType String? @map("target_pet_type") @db.VarChar(50)
|
|
recommendedProduct String @map("recommended_product_id") @db.Uuid
|
|
reason String @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
product Product @relation(fields: [recommendedProduct], references: [id], onDelete: Cascade)
|
|
|
|
@@map("smart_advisor_rules")
|
|
}
|
|
|
|
model Doctor {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
name String @db.VarChar(150)
|
|
title String? @db.VarChar(150)
|
|
clinicName String? @map("clinic_name") @db.VarChar(200)
|
|
avatarUrl String? @map("avatar_url") @db.Text
|
|
bio String? @db.Text
|
|
cv String? @db.Text
|
|
phone String? @db.VarChar(50)
|
|
email String? @db.VarChar(150)
|
|
instagram String? @db.VarChar(100)
|
|
quote String? @db.Text
|
|
quoteProductRef String? @map("quote_product_ref") @db.VarChar(200)
|
|
showQuoteOnHome Boolean @default(false) @map("show_quote_on_home")
|
|
isActive Boolean @default(true) @map("is_active")
|
|
order Int @default(0)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
videos Video[]
|
|
|
|
@@map("doctors")
|
|
}
|
|
|
|
model Video {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
title String @db.VarChar(200)
|
|
doctor String @db.VarChar(150)
|
|
doctorId String? @map("doctor_id") @db.Uuid
|
|
duration String @default("02:00") @db.VarChar(20)
|
|
thumbnail String? @db.Text
|
|
videoUrl String @map("video_url") @db.Text
|
|
description String? @db.Text
|
|
viewsCount Int @default(0) @map("views_count")
|
|
isFeatured Boolean @default(false) @map("is_featured")
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
doctorRef Doctor? @relation(fields: [doctorId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([doctorId])
|
|
@@map("videos")
|
|
}
|
|
|
|
model ContactSubmission {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
name String @db.VarChar(100)
|
|
phone String @db.VarChar(20)
|
|
email String? @db.VarChar(150)
|
|
subject String? @db.VarChar(200)
|
|
message String @db.Text
|
|
status String @default("PENDING") @db.VarChar(20) // PENDING, IN_PROGRESS, RESOLVED
|
|
adminNotes String? @map("admin_notes") @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
@@map("contact_submissions")
|
|
}
|
|
|
|
model ContactInfo {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
key String @unique @db.VarChar(100)
|
|
title String @db.VarChar(200)
|
|
value String @db.Text
|
|
icon String? @db.VarChar(100)
|
|
order Int @default(0)
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@map("contact_info")
|
|
}
|
|
|
|
model Banner {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
title String @db.VarChar(200)
|
|
subtitle String? @db.Text
|
|
imageUrl String @map("image_url") @db.Text
|
|
linkUrl String? @map("link_url") @db.Text
|
|
position String @default("home_hero") @db.VarChar(50)
|
|
isActive Boolean @default(true) @map("is_active")
|
|
order Int @default(0)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@map("banners")
|
|
}
|
|
|
|
model Testimonial {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
authorName String @map("author_name") @db.VarChar(150)
|
|
roleTitle String? @map("role_title") @db.VarChar(150)
|
|
avatarUrl String? @map("avatar_url") @db.Text
|
|
content String @db.Text
|
|
rating Int @default(5)
|
|
isFeatured Boolean @default(false) @map("is_featured")
|
|
isActive Boolean @default(true) @map("is_active")
|
|
showOnHome Boolean @default(false) @map("show_on_home")
|
|
order Int @default(0)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@map("testimonials")
|
|
}
|
|
|
|
model Ingredient {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
nameFa String @map("name_fa") @db.VarChar(150)
|
|
nameEn String @map("name_en") @db.VarChar(150)
|
|
slug String @unique @db.VarChar(150)
|
|
description String? @db.Text
|
|
scientificName String? @map("scientific_name") @db.VarChar(200)
|
|
imageUrl String? @map("image_url") @db.Text
|
|
benefits String[] @default([])
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@map("ingredients")
|
|
}
|
|
|
|
model Prescription {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
userId String? @map("user_id") @db.Uuid
|
|
petId String? @map("pet_id") @db.Uuid
|
|
fileUrl String @map("file_url") @db.Text
|
|
status String @default("PENDING") @db.VarChar(30)
|
|
notes String? @db.Text
|
|
adminNotes String? @map("admin_notes") @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
pet Pet? @relation(fields: [petId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
@@map("prescriptions")
|
|
}
|
|
|
|
model B2BInquiry {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
companyName String @map("company_name") @db.VarChar(200)
|
|
contactName String @map("contact_name") @db.VarChar(150)
|
|
email String @db.VarChar(150)
|
|
phone String @db.VarChar(20)
|
|
businessType String @map("business_type") @db.VarChar(50)
|
|
estimatedVolume String? @map("estimated_volume") @db.VarChar(100)
|
|
message String @db.Text
|
|
status String @default("PENDING") @db.VarChar(30)
|
|
adminNotes String? @map("admin_notes") @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
@@map("b2b_inquiries")
|
|
}
|
|
|
|
model PartnerAccount {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
userId String @unique @map("user_id") @db.Uuid
|
|
companyName String @map("company_name") @db.VarChar(200)
|
|
taxId String? @map("tax_id") @db.VarChar(50)
|
|
creditLimit Decimal @default(0.00) @map("credit_limit") @db.Decimal(15, 2)
|
|
discountTier String @default("STANDARD") @map("discount_tier") @db.VarChar(30)
|
|
status String @default("ACTIVE") @db.VarChar(30)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
@@map("partner_accounts")
|
|
}
|
|
|
|
model Setting {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
category String @db.VarChar(50)
|
|
key String @unique @db.VarChar(100)
|
|
value Json
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@index([category])
|
|
@@map("settings")
|
|
}
|
|
|
|
model SmsLog {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
receptor String @db.VarChar(20)
|
|
type String @db.VarChar(50) // OTP, ORDER_CONFIRMATION, SHIPPING_TRACKING, B2B_NOTIFICATION, PET_CARE_REMINDER, TEST, GENERIC
|
|
patternId Int? @map("pattern_id")
|
|
args String[] @default([])
|
|
messageText String? @map("message_text") @db.Text
|
|
status String @db.VarChar(20) // SUCCESS, FAILED, DISABLED
|
|
recId String? @map("rec_id") @db.VarChar(50)
|
|
errorMessage String? @map("error_message") @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
@@index([receptor])
|
|
@@index([type])
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
@@map("sms_logs")
|
|
}
|
|
|
|
model Ticket {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
ticketNumber String @unique @map("ticket_number") @db.VarChar(50)
|
|
userId String @map("user_id") @db.Uuid
|
|
petId String? @map("pet_id") @db.Uuid
|
|
subject String @db.VarChar(255)
|
|
category String @default("VET_CONSULTATION") @db.VarChar(50) // VET_CONSULTATION, ORDER_SUPPORT, PRODUCT_INQUIRY, GENERAL
|
|
priority String @default("MEDIUM") @db.VarChar(20) // LOW, MEDIUM, HIGH, URGENT
|
|
status String @default("OPEN") @db.VarChar(30) // OPEN, ANSWERED, IN_PROGRESS, CLOSED
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
pet Pet? @relation(fields: [petId], references: [id], onDelete: SetNull)
|
|
messages TicketMessage[]
|
|
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@index([category])
|
|
@@index([createdAt])
|
|
@@map("tickets")
|
|
}
|
|
|
|
model TicketMessage {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
ticketId String @map("ticket_id") @db.Uuid
|
|
senderId String? @map("sender_id") @db.Uuid
|
|
senderRole String @default("USER") @map("sender_role") @db.VarChar(30) // USER, ADMIN, VET_DOCTOR
|
|
senderName String @map("sender_name") @db.VarChar(100)
|
|
message String @db.Text
|
|
attachment String? @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([ticketId])
|
|
@@index([createdAt])
|
|
@@map("ticket_messages")
|
|
}
|
|
|
|
model ProductReview {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
productId String @map("product_id") @db.Uuid
|
|
userId String? @map("user_id") @db.Uuid
|
|
userName String @map("user_name") @db.VarChar(100)
|
|
userPhone String? @map("user_phone") @db.VarChar(20)
|
|
rating Int @default(5)
|
|
comment String @db.Text
|
|
status String @default("PENDING") @db.VarChar(20) // PENDING, APPROVED, REJECTED
|
|
adminReply String? @map("admin_reply") @db.Text
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([productId])
|
|
@@index([status])
|
|
@@index([createdAt])
|
|
@@map("product_reviews")
|
|
}
|
|
|
|
|
|
|
|
model BlogComment {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
blogId String @map("blog_id") @db.Uuid
|
|
userId String? @map("user_id") @db.Uuid
|
|
userName String @map("user_name") @db.VarChar(100)
|
|
content String @db.Text
|
|
status String @default("PENDING") @db.VarChar(20)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
|
|
blog Blog @relation(fields: [blogId], references: [id], onDelete: Cascade)
|
|
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
|
|
@@index([blogId])
|
|
@@index([status])
|
|
@@map("blog_comments")
|
|
}
|
|
|
|
model FAQ {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
question String @db.Text
|
|
answer String @db.Text
|
|
order Int @default(0)
|
|
isActive Boolean @default(true) @map("is_active")
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@map("faqs")
|
|
}
|
|
|
|
model MenuItem {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
menuType String @map("menu_type") @db.VarChar(30)
|
|
label String @db.VarChar(150)
|
|
href String @db.VarChar(500)
|
|
parentId String? @map("parent_id") @db.Uuid
|
|
order Int @default(0)
|
|
isActive Boolean @default(true) @map("is_active")
|
|
isExternal Boolean @default(false) @map("is_external")
|
|
icon String? @db.VarChar(100)
|
|
badge String? @db.VarChar(50)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
parent MenuItem? @relation("MenuChildren", fields: [parentId], references: [id])
|
|
children MenuItem[] @relation("MenuChildren")
|
|
|
|
@@index([menuType])
|
|
@@index([parentId])
|
|
@@map("menu_items")
|
|
}
|
|
|
|
model ApiKey {
|
|
id String @id @default(uuid()) @db.Uuid
|
|
name String @db.VarChar(150)
|
|
keyHash String @unique @map("key_hash") @db.VarChar(255)
|
|
keyPrefix String @map("key_prefix") @db.VarChar(30)
|
|
scopes String @default("*") @db.Text
|
|
status String @default("ACTIVE") @db.VarChar(20)
|
|
expiresAt DateTime? @map("expires_at") @db.Timestamptz()
|
|
lastUsedAt DateTime? @map("last_used_at") @db.Timestamptz()
|
|
description String? @db.VarChar(255)
|
|
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz()
|
|
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz()
|
|
|
|
@@index([keyHash])
|
|
@@index([status])
|
|
@@map("api_keys")
|
|
}
|