generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } enum Category { ELECTRONICS FURNITURE CLOTHING HOME_GARDEN SPORTS BOOKS GAMES VEHICLES OTHER } enum ListingCondition { NEW LIKE_NEW GENTLY_USED USED FAIR } enum ListingStatus { DRAFT ACTIVE SOLD DELETED } enum OfferStatus { PENDING ACCEPTED DECLINED COUNTERED CANCELLED EXPIRED } enum NotificationType { NEW_OFFER OFFER_ACCEPTED OFFER_DECLINED ITEM_SOLD NEW_MESSAGE ITEM_FAVORITED } enum PaymentStatus { PENDING COMPLETED FAILED REFUNDED } model User { id String @id @default(cuid()) email String @unique passwordHash String fullName String nickname String? avatar String? phone String? location String? bio String? rating Float @default(0) ratingCount Int @default(0) showEmail Boolean @default(false) showPhone Boolean @default(true) showLocation Boolean @default(true) showOnline Boolean @default(true) showRating Boolean @default(true) twoFactorEnabled Boolean @default(false) isActive Boolean @default(true) notifNewOffer Boolean @default(true) notifMessages Boolean @default(true) notifItemSold Boolean @default(true) notifFavorites Boolean @default(true) notifEmail Boolean @default(true) marketingEmail Boolean @default(false) resetToken String? @unique resetTokenExpiry DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt sessions Session[] listings Listing[] images ListingImage[] sentOffers Offer[] @relation("BuyerOffers") receivedOffers Offer[] @relation("SellerOffers") conversations1 Conversation[] @relation("User1Conversations") conversations2 Conversation[] @relation("User2Conversations") messages Message[] favorites Favorite[] notifications Notification[] payments Payment[] blockedUsers BlockedUser[] @relation("Blocker") blockedBy BlockedUser[] @relation("Blocked") } model Session { id String @id @default(cuid()) userId String refreshToken String @unique userAgent String? ipAddress String? expiresAt DateTime createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) } model Listing { id String @id @default(cuid()) title String description String price Float obo Boolean @default(false) category Category condition ListingCondition status ListingStatus @default(DRAFT) location String viewCount Int @default(0) sellerId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt seller User @relation(fields: [sellerId], references: [id], onDelete: Cascade) images ListingImage[] offers Offer[] conversations Conversation[] favorites Favorite[] payments Payment[] @@index([sellerId]) @@index([category]) @@index([status]) @@index([createdAt]) } model ListingImage { id String @id @default(cuid()) url String order Int @default(0) listingId String uploadedBy String listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade) user User @relation(fields: [uploadedBy], references: [id], onDelete: Cascade) @@index([listingId]) } model Offer { id String @id @default(cuid()) amount Float message String? status OfferStatus @default(PENDING) counterAmount Float? expiresAt DateTime? buyerId String sellerId String listingId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt buyer User @relation("BuyerOffers", fields: [buyerId], references: [id], onDelete: Cascade) seller User @relation("SellerOffers", fields: [sellerId], references: [id], onDelete: Cascade) listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade) @@index([buyerId]) @@index([sellerId]) @@index([listingId]) } model Conversation { id String @id @default(cuid()) user1Id String user2Id String listingId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user1 User @relation("User1Conversations", fields: [user1Id], references: [id], onDelete: Cascade) user2 User @relation("User2Conversations", fields: [user2Id], references: [id], onDelete: Cascade) listing Listing? @relation(fields: [listingId], references: [id], onDelete: SetNull) messages Message[] @@unique([user1Id, user2Id, listingId]) @@index([user1Id]) @@index([user2Id]) } model Message { id String @id @default(cuid()) content String senderId String conversationId String isRead Boolean @default(false) offerAmount Float? createdAt DateTime @default(now()) sender User @relation(fields: [senderId], references: [id], onDelete: Cascade) conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade) @@index([conversationId]) @@index([senderId]) } model Favorite { id String @id @default(cuid()) userId String listingId String createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade) @@unique([userId, listingId]) } model Notification { id String @id @default(cuid()) userId String type NotificationType title String body String data Json? isRead Boolean @default(false) createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@index([createdAt]) } model Payment { id String @id @default(cuid()) userId String listingId String stripePaymentId String? @unique amount Float status PaymentStatus @default(PENDING) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) listing Listing @relation(fields: [listingId], references: [id], onDelete: Cascade) @@index([userId]) @@index([listingId]) } model BlockedUser { id String @id @default(cuid()) blockerId String blockedId String createdAt DateTime @default(now()) blocker User @relation("Blocker", fields: [blockerId], references: [id], onDelete: Cascade) blocked User @relation("Blocked", fields: [blockedId], references: [id], onDelete: Cascade) @@unique([blockerId, blockedId]) }