Skip to content

YeboShops Data Models

Full Prisma schema documentation with every field for all 14 core models.

Database Configuration

prisma
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["postgresqlExtensions"]
}

datasource db {
  provider   = "postgresql"
  extensions = [vector]  // pgvector for embeddings
}

Core Models

User

Central user model for all authentication and profile data.

prisma
model User {
  id                    String            @id @default(cuid())
  username              String            @unique
  phoneNumber           String            @unique
  password              String
  name                  String?
  role                  UserRole          @default(USER)  // USER | ADMIN | VENDOR
  countryId             String?
  countryCode           String?
  callingCode           String?
  
  // Verification
  isPhoneVerified       Boolean           @default(false)
  isIdVerified          Boolean           @default(false)
  idVerificationStatus  VerificationStatus @default(NONE)
  idVerificationDetails Json?
  
  // Account Status
  isActive              Boolean           @default(true)
  accountStatus         AccountStatus     @default(ACTIVE)
  lastOnline            DateTime?
  
  // Auth Tokens
  refreshToken          String?
  otp                   String?
  otpExpiry             DateTime?
  otpAttempts           Int               @default(0)
  otpLockedUntil        DateTime?
  resetPasswordOTP      String?
  resetPasswordOTPExpiry DateTime?
  
  // Profile
  avatar                String?
  bio                   String?
  followingCount        Int               @default(0)
  
  // Soft Delete
  deletedAt             DateTime?
  scheduledDeletionDate DateTime?
  
  createdAt             DateTime          @default(now())
  updatedAt             DateTime          @updatedAt
}

Enums:

prisma
enum UserRole { USER, ADMIN, VENDOR }
enum AccountStatus { ACTIVE, DEACTIVATION_REQUESTED, DELETION_REQUESTED, SUSPENDED }
enum VerificationStatus { NONE, PENDING, APPROVED, REJECTED }

Shop

Represents a seller's storefront.

prisma
model Shop {
  id              String    @id @default(cuid())
  name            String
  slug            String    @unique
  description     String?
  ownerId         String
  countryId       String?
  
  // Branding
  logo            String?
  coverImage      String?
  address         Json?     // { street, city, state, country, zip }
  contactPhone    String?
  
  // Status
  isActive        Boolean   @default(true)
  isVerified      Boolean   @default(false)
  categories      String[]
  
  // Plan & Limits
  plan            ShopPlan  @default(FREE)  // FREE | BASIC | PRO | ENTERPRISE
  planLimits      Json?
  openingHours    Json?     // { monday: { open, close }, ... }
  
  // Metrics
  ratingAverage   Float     @default(0)
  ratingCount     Int       @default(0)
  followersCount  Int       @default(0)
  score           Float     @default(0)
  
  // AI
  embedding       Float[]   // Shop embedding for similarity search
  
  // Currency
  defaultCurrency Json?
  countryDetails  Json?
  
  createdAt       DateTime  @default(now())
  updatedAt       DateTime  @updatedAt
}

Product

Core product listing model with AI processing metadata.

prisma
model Product {
  id                    String        @id @default(cuid())
  title                 String
  slug                  String        @unique
  description           String?
  shopId                String
  
  // Pricing
  priceAmount           Decimal       @db.Decimal(12, 2)
  priceCurrency         String        @default("SZL")
  priceDiscount         Decimal?      @db.Decimal(5, 2)
  
  // Categorization
  category              String?
  tags                  String[]
  seoDescription        String?
  
  // AI-Detected Attributes
  color                 String[]
  material              String?
  condition             String?       // new | like_new | good | fair | poor
  detectedText          String[]
  hasNudity             Boolean       @default(false)
  hasPrice              Boolean       @default(false)
  mediaQuality          String?       // high | medium | low
  mediaType             String?       // image | video
  needsManualApproval   Boolean       @default(false)
  mediaProcessing       Json?         // { status, lastAttempt, retryCount }
  aiProcessingCompleted Boolean       @default(false)
  
  // Inventory
  stockQuantity         Int           @default(0)
  stockSku              String?
  stockIsInStock        Boolean       @default(true)
  specifications        Json?
  
  // Status
  status                ProductStatus @default(DRAFT)  // DRAFT | PUBLISHED | ARCHIVED | REJECTED
  isActive              Boolean       @default(true)
  isAvailable           Boolean       @default(true)
  isDeleted             Boolean       @default(false)
  deletedAt             DateTime?
  deletedById           String?
  
  // Metrics & AI
  score                 Float         @default(0)
  embedding             Float[]       // 512-dim vector for similarity search
  favoriteCount         Int           @default(0)
  viewCount             Int           @default(0)
  commentCount          Int           @default(0)
  bookmarkCount         Int           @default(0)
  inquiryCount          Int           @default(0)
  
  createdAt             DateTime      @default(now())
  updatedAt             DateTime      @updatedAt
}

ProductMedia

Media attachments for products.

prisma
model ProductMedia {
  id        String   @id @default(cuid())
  productId String
  key       String   // Storage key (GCS path)
  url       String   // Public URL
  size      Int?     // File size in bytes
  type      String   // image | video
  isPrimary Boolean  @default(false)
  order     Int      @default(0)
  createdAt DateTime @default(now())
}

Wallet

User wallet for secure payments.

prisma
model Wallet {
  id                 String    @id @default(cuid())
  userId             String    @unique
  balance            Decimal   @default(0) @db.Decimal(12, 2)
  unconfirmedBalance Decimal   @default(0) @db.Decimal(12, 2)  // Escrow
  currency           String    @default("SZL")
  isActive           Boolean   @default(true)
  lastTransactionAt  DateTime?
  createdAt          DateTime  @default(now())
  updatedAt          DateTime  @updatedAt
}

WalletTransaction

Transaction history for wallets.

prisma
model WalletTransaction {
  id            String         @id @default(cuid())
  walletId      String
  userId        String
  type          TransactionType // CREDIT | DEBIT
  amount        Decimal        @db.Decimal(12, 2)
  balanceBefore Decimal        @db.Decimal(12, 2)
  balanceAfter  Decimal        @db.Decimal(12, 2)
  description   String?
  reference     String?        // Link to SecurePayment, etc.
  referenceType WalletRefType? // SECURE_PAYMENT | DEPOSIT | WITHDRAWAL | REFUND
  metadata      Json?
  createdAt     DateTime       @default(now())
}

enum WalletRefType {
  SECURE_PAYMENT
  DEPOSIT
  WITHDRAWAL
  TRANSFER
  REFUND
}

SecurePayment

Escrow payment records.

prisma
model SecurePayment {
  id                 String              @id @default(cuid())
  paymentId          String              @unique  // SP + timestamp + random
  buyerId            String
  shopId             String
  shopOwnerId        String
  shopName           String
  shopPhone          String?
  
  // Payment Details
  amount             Decimal             @db.Decimal(12, 2)
  description        String?
  productId          String?
  chatId             String?
  
  // Status
  status             SecurePaymentStatus @default(PENDING)
  completionCode     String              @unique  // 6-digit code
  
  // Timestamps
  acceptedAt         DateTime?
  refusedAt          DateTime?
  refusalReason      String?
  completedAt        DateTime?
  disputedAt         DateTime?
  disputeReason      String?
  cancelledAt        DateTime?
  cancellationReason String?
  
  createdAt          DateTime            @default(now())
  updatedAt          DateTime            @updatedAt
}

enum SecurePaymentStatus {
  PENDING
  ACCEPTED
  REFUSED
  COMPLETED
  DISPUTED
  CANCELLED
  EXPIRED
}

Chat

Chat conversations between users and shops.

prisma
model Chat {
  id            String   @id @default(cuid())
  shopId        String?
  lastProductId String?  // Currently discussed product
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
}

Message

Individual messages in chats.

prisma
model Message {
  id             String     @id @default(cuid())
  chatId         String
  senderId       String
  senderType     SenderType @default(USER)  // USER | SHOP
  content        String?
  productContext Json?      // { productId, title, image, price, url }
  replyToId      String?
  read           Boolean    @default(false)
  readAt         DateTime?
  createdAt      DateTime   @default(now())
}

enum SenderType { USER, SHOP }
enum MessageType {
  TEXT
  PRODUCT_SHARE
  PRODUCT_INQUIRY
  IMAGE
  SYSTEM
}

Comment

Comments on products or shops.

prisma
model Comment {
  id         String        @id @default(cuid())
  productId  String?
  shopId     String?
  targetType CommentTarget // PRODUCT | SHOP
  userId     String
  comment    String
  parentId   String?       // For nested replies
  likeCount  Int           @default(0)
  rating     Int?          // 1-5 for reviews
  isDeleted  Boolean       @default(false)
  deletedAt  DateTime?
  editedAt   DateTime?
  createdAt  DateTime      @default(now())
  updatedAt  DateTime      @updatedAt
}

Notification

User notifications.

prisma
model Notification {
  id        String           @id @default(cuid())
  userId    String
  type      NotificationType
  title     String
  message   String
  isRead    Boolean          @default(false)
  data      Json?            // { entityType, entityId, ... }
  createdAt DateTime         @default(now())
  updatedAt DateTime         @updatedAt
}

enum NotificationType {
  ORDER, COMMENT, REVIEW, SYSTEM, PAYMENT, SHOP, PRODUCT, CHAT, FOLLOW
}

Favorite / Bookmark

User favorites and bookmarks.

prisma
model Favorite {
  id        String   @id @default(cuid())
  userId    String
  productId String
  createdAt DateTime @default(now())
  
  @@unique([userId, productId])
}

model Bookmark {
  id        String   @id @default(cuid())
  userId    String
  productId String
  createdAt DateTime @default(now())
  
  @@unique([userId, productId])
}

ShopFollow

Shop followers.

prisma
model ShopFollow {
  id        String   @id @default(cuid())
  userId    String
  shopId    String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  
  @@unique([userId, shopId])
}

Country

Multi-country support.

prisma
model Country {
  id          String   @id @default(cuid())
  name        String
  code        String   @unique  // ISO 3166-1 alpha-2 (SZ, ZA, etc.)
  code3       String   @unique  // ISO 3166-1 alpha-3 (SWZ, ZAF, etc.)
  callingCode String
  region      String?
  subregion   String?
  currency    Json     // { code: "SZL", name: "Swazi Lilangeni", symbol: "E" }
  languages   String[]
  flag        String?
  isActive    Boolean  @default(true)
  isSupported Boolean  @default(false)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
}

Statistics Models

ProductStats

prisma
model ProductStats {
  id            String    @id @default(cuid())
  productId     String    @unique
  views         Int       @default(0)
  likes         String[]  // User IDs
  favorites     String[]
  bookmarks     String[]
  inquiries     Int       @default(0)
  isFlagged     Boolean   @default(false)
  flaggedReason String?
  lastViewedAt  DateTime?
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
}

ShopStats

prisma
model ShopStats {
  id             String    @id @default(cuid())
  shopId         String    @unique
  totalProducts  Int       @default(0)
  totalViews     Int       @default(0)
  totalFavorites Int       @default(0)
  totalSold      Int       @default(0)
  followers      String[]
  lastActive     DateTime?
  createdAt      DateTime  @default(now())
  updatedAt      DateTime  @updatedAt
}

Database Indexes

Key indexes for performance:

prisma
// User indexes
@@index([username])
@@index([phoneNumber])
@@index([role])

// Product indexes
@@index([shopId])
@@index([slug])
@@index([category])
@@index([status])
@@index([isActive, isAvailable, isDeleted])

// Payment indexes
@@index([paymentId])
@@index([buyerId, createdAt])
@@index([status, createdAt])
@@index([completionCode])

// Message indexes
@@index([chatId, createdAt])
@@index([senderId])

Model Count Summary

CategoryModels
CoreUser, Shop, Product, ProductMedia
FinancialWallet, WalletTransaction, SecurePayment, SecurePaymentLog
SocialFavorite, Bookmark, ShopFollow, Comment, CommentLike
MessagingChat, ChatParticipant, Message, MessageAttachment
AnalyticsProductStats, ShopStats, View, Share, UserBehavior
SystemCountry, Notification, Category, Report
Total~50 models

One chat. Everything done.