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.