// This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // User Management & Authentication model User { id String @id @default(cuid()) email String @unique username String? @unique firstName String? lastName String? phone String? avatar String? // Authentication passwordHash String isVerified Boolean @default(false) isActive Boolean @default(true) // Roles & Permissions role UserRole @default(CUSTOMER) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt lastLoginAt DateTime? // Relations addresses Address[] orders Order[] reviews Review[] wishlist WishlistItem[] cart CartItem[] orderStatusChanges OrderStatusHistory[] @@map("users") } enum UserRole { CUSTOMER ADMIN SUPER_ADMIN EDITOR MODERATOR SELLER } // Address Management model Address { id String @id @default(cuid()) userId String type AddressType @default(SHIPPING) isDefault Boolean @default(false) // Address Details firstName String lastName String company String? addressLine1 String addressLine2 String? city String state String postalCode String country String phone String? // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) orders Order[] @@map("addresses") } enum AddressType { SHIPPING BILLING } // Order Management model Order { id String @id @default(cuid()) orderNumber String @unique userId String status OrderStatus @default(PENDING) // Pricing subtotal Decimal @db.Decimal(10, 2) taxAmount Decimal @db.Decimal(10, 2) shippingAmount Decimal @db.Decimal(10, 2) discountAmount Decimal @db.Decimal(10, 2) @default(0) totalAmount Decimal @db.Decimal(10, 2) // Payment paymentStatus PaymentStatus @default(PENDING) paymentMethod String? paymentId String? // Shipping shippingAddressId String trackingNumber String? // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt shippedAt DateTime? deliveredAt DateTime? // ✅ Add this field returnRequestedAt DateTime? returnStatus ReturnStatus @default(NONE) // Relations user User @relation(fields: [userId], references: [id]) address Address @relation(fields: [shippingAddressId], references: [id]) items OrderItem[] statusHistory OrderStatusHistory[] @@map("orders") } model OrderStatusHistory { id String @id @default(cuid()) orderId String fromStatus OrderStatus? toStatus OrderStatus changedBy String? trackingNumber String? notes String? ipAddress String? userAgent String? createdAt DateTime @default(now()) // Relations order Order @relation(fields: [orderId], references: [id], onDelete: Cascade) admin User? @relation(fields: [changedBy], references: [id]) @@index([orderId]) @@index([createdAt]) @@map("order_status_history") } enum OrderStatus { PENDING CONFIRMED PROCESSING SHIPPED DELIVERED CANCELLED REFUNDED RETURN_REQUESTED } enum PaymentStatus { PENDING PAID FAILED REFUNDED PARTIALLY_REFUNDED } enum ReturnStatus { NONE REQUESTED APPROVED REJECTED COMPLETED } // Order Items model OrderItem { id String @id @default(cuid()) orderId String productId String // Reference to MongoDB product // Product Details (snapshot at time of order) productName String productSku String price Decimal @db.Decimal(10, 2) quantity Int // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations order Order @relation(fields: [orderId], references: [id], onDelete: Cascade) @@map("order_items") } // Reviews & Ratings model Review { id String @id @default(cuid()) userId String productId String // Reference to MongoDB product orderId String? // Optional reference to order rating Int // 1-5 stars title String? comment String? isVerified Boolean @default(false) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id]) @@unique([userId, productId]) @@map("reviews") } // Wishlist Management model WishlistItem { id String @id @default(cuid()) userId String productId String // Reference to MongoDB product // Timestamps createdAt DateTime @default(now()) // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, productId]) @@map("wishlist_items") } // Shopping Cart model CartItem { id String @id @default(cuid()) userId String productId String // Reference to MongoDB product quantity Int @default(1) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([userId, productId]) @@map("cart_items") } // Categories (Reference data) // Categories (Reference data) model Category { id String @id @default(cuid()) name String // Removed @unique - same name can exist under different parents slug String // Removed @unique - will use composite unique instead description String? image String? parentId String? isActive Boolean @default(true) sequence Int @default(0) // SEO metaTitle String? metaDescription String? // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations parent Category? @relation("CategoryHierarchy", fields: [parentId], references: [id]) children Category[] @relation("CategoryHierarchy") // Composite unique constraint: same slug allowed if different parent @@unique([slug, parentId], name: "unique_slug_per_parent") @@map("categories") } // Coupons & Discounts model Coupon { id String @id @default(cuid()) code String @unique description String? type CouponType value Decimal @db.Decimal(10, 2) // Conditions minOrderAmount Decimal? @db.Decimal(10, 2) maxUses Int? usedCount Int @default(0) // Validity validFrom DateTime validUntil DateTime isActive Boolean @default(true) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("coupons") } enum CouponType { PERCENTAGE FIXED_AMOUNT FREE_SHIPPING } // System Configuration model SystemConfig { id String @id @default(cuid()) key String @unique value String type ConfigType @default(STRING) // Timestamps createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@map("system_config") } enum ConfigType { STRING NUMBER BOOLEAN JSON } model InventoryLog { id String @id @default(cuid()) productId String productName String type InventoryLogType quantityChange Int previousStock Int newStock Int orderId String? adjustedBy String? notes String? createdAt DateTime @default(now()) @@index([productId]) @@index([orderId]) @@index([type]) @@map("inventory_logs") } enum InventoryLogType { SOLD RESTOCK ADJUSTMENT RETURN DAMAGED }