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[] @@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 Blog { id String @id @default(uuid()) @db.Uuid title String @db.VarChar(200) slug String @unique @db.VarChar(200) content String @db.Text authorId String @map("author_id") @db.Uuid imageUrl String? @map("image_url") @db.Text metaTitle String? @map("meta_title") @db.VarChar(200) metaDescription String? @map("meta_description") @db.Text keywords String? @db.Text isPublished Boolean @default(true) @map("is_published") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz() updatedAt DateTime @default(now()) @map("updated_at") @db.Timestamptz() author User @relation(fields: [authorId], references: [id]) @@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) 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 videoUrl String? @map("video_url") @db.Text pdfUrl String? @map("pdf_url") @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 createdAt DateTime @default(now()) @map("created_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") } model Doctor { id String @id @default(uuid()) @db.Uuid name String @db.VarChar(150) title String @db.VarChar(150) avatarUrl String? @map("avatar_url") @db.Text bio String? @db.Text clinic String? @db.VarChar(200) createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz() @@map("doctors") } 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) 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[] @@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 Video { id String @id @default(uuid()) @db.Uuid title String @db.VarChar(200) doctor String @db.VarChar(150) 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() @@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() @@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") 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]) @@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() @@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") }