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
| Category | Models |
|---|---|
| Core | User, Shop, Product, ProductMedia |
| Financial | Wallet, WalletTransaction, SecurePayment, SecurePaymentLog |
| Social | Favorite, Bookmark, ShopFollow, Comment, CommentLike |
| Messaging | Chat, ChatParticipant, Message, MessageAttachment |
| Analytics | ProductStats, ShopStats, View, Share, UserBehavior |
| System | Country, Notification, Category, Report |
| Total | ~50 models |