Files
backend/prisma/schema.prisma
T
Alireza HassaniandCursor c7d5204b49 Add workshops CMS API with schedule, registrations, and public storefront routes.
Includes SQL migrations, Prisma models, dashboard CRUD, registration status workflow, and website OpenAPI updates for workshop listing and signup.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-22 12:22:24 +03:30

1636 lines
89 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id BigInt @id @default(autoincrement())
cellNumber String @unique(map: "users_cell_number_unique") @map("cell_number") @db.VarChar(20)
passwordHash String @map("password_hash") @db.VarChar(255)
email String? @db.VarChar(255)
firstName String? @map("first_name") @db.VarChar(100)
lastName String? @map("last_name") @db.VarChar(100)
isActive Boolean @default(true) @map("is_active")
cellVerifiedAt DateTime? @map("cell_verified_at") @db.Timestamptz(6)
lastLoginAt DateTime? @map("last_login_at") @db.Timestamptz(6)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
profile Json @default("{}")
firstNameEn String? @map("first_name_en") @db.VarChar(100)
lastNameEn String? @map("last_name_en") @db.VarChar(100)
oldId BigInt? @map("old_id")
addresses Address[]
authoredBlogs blogs[] @relation("BlogAuthor")
businessCustomers BusinessCustomer[]
businessUsersInvited BusinessUser[] @relation("BusinessInviter")
businessUsers BusinessUser[] @relation("BusinessMember")
carts Cart[]
commentsApproved Comment[] @relation("CommentApprover")
expertReviewsApproved ExpertReview[] @relation("ExpertReviewApprover")
favorites Favorite[]
invoicesIssued Invoice[] @relation("InvoiceIssuer")
invoicesBilled Invoice[] @relation("InvoiceBilledUser")
mediaUploaded Media[]
ordersCreated Order[] @relation("OrderCreator")
orders Order[] @relation("OrderCustomer")
authoredPortfolios portfolios[] @relation("PortfolioAuthor")
authoredVideos videos[] @relation("VideoAuthor")
authoredInstructions instructions[] @relation("InstructionAuthor")
authoredWorkshops workshops[] @relation("WorkshopAuthor")
workshopRegistrations workshop_registrations[]
shoppingCardsCreated ShoppingCard[] @relation("ShoppingCardCreator")
shoppingCards ShoppingCard[] @relation("ShoppingCardCustomer")
transactionsCreated Transaction[] @relation("TransactionCreator")
transactions Transaction[] @relation("TransactionCustomer")
userProducts UserProduct[]
userRoles UserRole[]
@@index([cellNumber], map: "idx_users_cell_number")
@@map("users")
}
model Business {
id BigInt @id @default(autoincrement())
name String @db.VarChar(255)
slug String @unique(map: "businesses_slug_unique") @db.VarChar(100)
description String?
settings Json @default("{}")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
nameFa String? @map("name_fa") @db.VarChar(255)
about String?
vision String?
emails Json @default("[]")
phoneNumbers Json @default("[]") @map("phone_numbers")
socialMedia Json @default("{}") @map("social_media")
logoMediaId BigInt? @map("logo_media_id")
faviconMediaId BigInt? @map("favicon_media_id")
oldBusinessId BigInt? @map("old_business_id")
addresses Address[]
blogs blogs[]
brands Brand[]
categoryAssignments BusinessCategoryAssignment[]
businessCustomers BusinessCustomer[]
businessUsers BusinessUser[]
faviconMedia Media? @relation("BusinessFavicon", fields: [faviconMediaId], references: [id], onUpdate: NoAction)
logoMedia Media? @relation("BusinessLogo", fields: [logoMediaId], references: [id], onUpdate: NoAction)
carts Cart[]
categories Category[]
contentCategoryAssignments CategoryAssignment[]
categoryTechnicalForms CategoryTechnicalForm[]
categoryVariations CategoryVariation[]
comments Comment[]
contactSubmissions ContactSubmission[]
domains Domain[]
expertReviews ExpertReview[]
favorites Favorite[]
invoiceItemTemplates InvoiceItemTemplate[]
invoiceTemplates InvoiceTemplate[]
invoices Invoice[] @relation("InvoiceBusiness")
invoicesIssued Invoice[] @relation("InvoiceIssuerBusiness")
media Media[]
mediaAttachments MediaAttachment[]
orders Order[]
portfolios portfolios[]
videos videos[]
instructions instructions[]
workshops workshops[]
workshop_registrations workshop_registrations[]
productTechnicalFieldValues ProductTechnicalFieldValue[]
products Product[]
shoppingCards ShoppingCard[]
storeItemVariants StoreItemVariant[]
storeItems StoreItem[]
storeSpecials StoreSpecial[]
transactions Transaction[]
userProductTechnicalFieldValues UserProductTechnicalFieldValue[]
userProducts UserProduct[]
website_brand_groups website_brand_groups[]
website_category_groups website_category_groups[]
website_image_slots website_image_slots[]
website_sliders website_sliders[]
@@map("businesses")
}
model BusinessCategory {
id BigInt @id @default(autoincrement())
parentId BigInt? @map("parent_id")
name String @db.VarChar(255)
slug String @unique(map: "business_categories_slug_unique") @db.VarChar(255)
description String?
icon String? @db.VarChar(100)
sortOrder Int @default(0) @map("sort_order")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
parent BusinessCategory? @relation("BusinessCategoryTree", fields: [parentId], references: [id], onUpdate: NoAction)
children BusinessCategory[] @relation("BusinessCategoryTree")
assignments BusinessCategoryAssignment[]
@@index([parentId], map: "idx_business_categories_parent_id")
@@index([sortOrder], map: "idx_business_categories_sort_order")
@@map("business_categories")
}
model BusinessCategoryAssignment {
businessId BigInt @map("business_id")
categoryId BigInt @map("category_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
category BusinessCategory @relation(fields: [categoryId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@id([businessId, categoryId])
@@index([categoryId], map: "idx_business_category_assignments_category_id")
@@map("business_category_assignments")
}
model Domain {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
host String @unique(map: "domains_host_unique") @db.VarChar(253)
isPrimary Boolean @default(false) @map("is_primary")
isVerified Boolean @default(false) @map("is_verified")
verifiedAt DateTime? @map("verified_at") @db.Timestamptz(6)
sslEnabled Boolean @default(false) @map("ssl_enabled")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
expiresAt DateTime? @map("expires_at") @db.Timestamptz(6)
isActive Boolean @default(true) @map("is_active")
lastDeployedAt DateTime? @map("last_deployed_at") @db.Timestamptz(6)
lastDeployStatus String? @map("last_deploy_status") @db.VarChar(32)
deploySlug String? @map("deploy_slug") @db.VarChar(64)
gitRepoUrl String? @map("git_repo_url") @db.VarChar(512)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([businessId], map: "idx_domains_business_id")
@@index([host], map: "idx_domains_host")
@@index([isActive], map: "idx_domains_is_active")
@@map("domains")
}
model BusinessUser {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userId BigInt @map("user_id")
isOwner Boolean @default(false) @map("is_owner")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
roleId BigInt? @map("role_id")
invitedBy BigInt? @map("invited_by")
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
inviter User? @relation("BusinessInviter", fields: [invitedBy], references: [id], onUpdate: NoAction)
role Role? @relation(fields: [roleId], references: [id], onDelete: Restrict, onUpdate: NoAction)
user User @relation("BusinessMember", fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([businessId, userId], map: "business_users_business_user_unique")
@@index([userId], map: "idx_business_users_user_id")
@@index([businessId], map: "idx_business_users_business_id")
@@index([roleId], map: "idx_business_users_role_id")
@@map("business_users")
}
model BusinessCustomer {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userId BigInt @map("user_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
isEnabled Boolean @default(true) @map("is_enabled")
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([businessId, userId], map: "business_customers_business_user_unique")
@@index([userId], map: "idx_business_customers_user_id")
@@index([businessId], map: "idx_business_customers_business_id")
@@index([businessId, isEnabled], map: "idx_business_customers_is_enabled")
@@map("business_customers")
}
model Role {
id BigInt @id @default(autoincrement())
name String @db.VarChar(100)
slug String @unique(map: "roles_slug_unique") @db.VarChar(100)
description String?
isSystem Boolean @default(true) @map("is_system")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
businessUsers BusinessUser[]
rolePermissions RolePermission[]
userRoles UserRole[]
@@map("roles")
}
model UserRole {
id BigInt @id @default(autoincrement())
userId BigInt @map("user_id")
roleId BigInt @map("role_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade, onUpdate: NoAction)
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([userId, roleId], map: "user_roles_user_role_unique")
@@index([userId], map: "idx_user_roles_user_id")
@@map("user_roles")
}
model Permission {
id BigInt @id @default(autoincrement())
name String @db.VarChar(100)
slug String @unique(map: "permissions_slug_unique") @db.VarChar(100)
groupName String @map("group_name") @db.VarChar(50)
description String?
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
rolePermissions RolePermission[]
@@map("permissions")
}
model RolePermission {
roleId BigInt @map("role_id")
permissionId BigInt @map("permission_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
permission Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade, onUpdate: NoAction)
role Role @relation(fields: [roleId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@id([roleId, permissionId])
@@index([permissionId], map: "idx_role_permissions_permission_id")
@@map("role_permissions")
}
model Media {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
uploadedBy BigInt? @map("uploaded_by")
mediaType MediaType @map("media_type")
storageDisk String @default("local") @map("storage_disk") @db.VarChar(50)
storagePath String @map("storage_path")
publicUrl String @map("public_url")
fileName String @map("file_name") @db.VarChar(255)
originalFileName String @map("original_file_name") @db.VarChar(255)
mimeType String @map("mime_type") @db.VarChar(100)
fileSizeBytes BigInt @map("file_size_bytes")
width Int?
height Int?
durationSeconds Decimal? @map("duration_seconds") @db.Decimal(10, 2)
altText String? @map("alt_text") @db.VarChar(255)
caption String?
metadata Json @default("{}")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
oldId BigInt? @map("old_id")
blogs blogs[]
brandImages Brand[]
faviconBusinesses Business[] @relation("BusinessFavicon")
logoBusinesses Business[] @relation("BusinessLogo")
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
uploader User? @relation(fields: [uploadedBy], references: [id], onUpdate: NoAction)
attachments MediaAttachment[]
portfolios portfolios[]
videos videos[]
instructions instructions[]
workshops workshops[]
featuredProducts Product[] @relation("ProductFeaturedMedia")
featuredUserProducts UserProduct[] @relation("UserProductFeaturedMedia")
website_image_slot_items website_image_slot_items[]
website_slider_slides website_slider_slides[]
@@index([businessId], map: "idx_media_business_id")
@@index([businessId, mediaType], map: "idx_media_business_type")
@@index([businessId, createdAt(sort: Desc)], map: "idx_media_created_at")
@@map("media")
}
model MediaAttachment {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
mediaId BigInt @map("media_id")
entityType MediaEntityType @map("entity_type")
entityId BigInt @map("entity_id")
sortOrder Int @default(0) @map("sort_order")
isFeatured Boolean @default(false) @map("is_featured")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
media Media @relation(fields: [mediaId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([mediaId, entityType, entityId], map: "media_attachments_unique")
@@index([businessId, entityType, entityId, sortOrder], map: "idx_media_attachments_entity")
@@index([mediaId], map: "idx_media_attachments_media_id")
@@map("media_attachments")
}
model Category {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
entityType MediaEntityType @map("entity_type")
parentId BigInt? @map("parent_id")
name String @db.VarChar(255)
slug String @db.VarChar(255)
description String?
sortOrder Int @default(0) @map("sort_order")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
nameFa String? @map("name_fa") @db.VarChar(255)
oldId BigInt? @map("old_id")
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
parent Category? @relation("CategoryTree", fields: [parentId], references: [id], onUpdate: NoAction)
children Category[] @relation("CategoryTree")
assignments CategoryAssignment[]
technicalForm CategoryTechnicalForm?
variations CategoryVariation[]
website_category_group_items website_category_group_items[]
@@unique([businessId, entityType, slug], map: "categories_business_entity_slug_unique")
@@index([businessId, entityType, sortOrder], map: "idx_categories_business_entity")
@@index([parentId], map: "idx_categories_parent_id")
@@map("categories")
}
model CategoryVariation {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
categoryId BigInt @map("category_id")
name String @db.VarChar(255)
variationType VariationType @map("variation_type")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
options CategoryVariationOption[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade, onUpdate: NoAction)
productVariationValues ProductVariationValue[]
storeItemVariantSelections StoreItemVariantSelection[]
@@index([categoryId], map: "idx_category_variations_category_id")
@@index([businessId], map: "idx_category_variations_business_id")
@@map("category_variations")
}
model CategoryVariationOption {
id BigInt @id @default(autoincrement())
variationId BigInt @map("variation_id")
label String @db.VarChar(255)
value String @db.VarChar(255)
colorHex String? @map("color_hex") @db.VarChar(7)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
variation CategoryVariation @relation(fields: [variationId], references: [id], onDelete: Cascade, onUpdate: NoAction)
productVariationValues ProductVariationValue[]
storeItemVariantSelections StoreItemVariantSelection[]
@@unique([variationId, value], map: "category_variation_options_unique_value")
@@index([variationId], map: "idx_category_variation_options_variation_id")
@@map("category_variation_options")
}
model Brand {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
nameEn String @map("name_en") @db.VarChar(255)
nameFa String? @map("name_fa") @db.VarChar(255)
imageMediaId BigInt? @map("image_media_id")
about String?
slug String @db.VarChar(255)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
sort_order Int @default(0)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
imageMedia Media? @relation(fields: [imageMediaId], references: [id], onUpdate: NoAction)
products Product[]
userProducts UserProduct[]
website_brand_group_items website_brand_group_items[]
@@unique([businessId, slug], map: "brands_business_slug_unique")
@@index([businessId], map: "idx_brands_business_id")
@@index([imageMediaId], map: "idx_brands_image_media_id")
@@index([businessId, sort_order], map: "idx_brands_business_sort_order")
@@map("brands")
}
model Product {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
title String @db.VarChar(255)
slug String @db.VarChar(255)
description String?
content Json @default("{}")
price Decimal? @db.Decimal(12, 2)
compareAtPrice Decimal? @map("compare_at_price") @db.Decimal(12, 2)
sku String? @db.VarChar(100)
stockQuantity Int? @map("stock_quantity")
status ContentStatus @default(draft)
featuredMediaId BigInt? @map("featured_media_id")
sortOrder Int @default(0) @map("sort_order")
publishedAt DateTime? @map("published_at") @db.Timestamptz(6)
metadata Json @default("{}")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
brandId BigInt? @map("brand_id")
expertReviews ExpertReview[]
favorites Favorite[]
orderItems OrderItem[]
technicalFieldValues ProductTechnicalFieldValue[]
variationValues ProductVariationValue[]
brand Brand? @relation(fields: [brandId], references: [id], onUpdate: NoAction)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
featuredMedia Media? @relation("ProductFeaturedMedia", fields: [featuredMediaId], references: [id], onUpdate: NoAction)
shoppingCardItems ShoppingCardItem[]
storeItem StoreItem[]
@@unique([businessId, slug], map: "products_business_slug_unique")
@@index([businessId], map: "idx_products_business_id")
@@index([brandId], map: "idx_products_brand_id")
@@index([businessId, status], map: "idx_products_business_status")
@@index([businessId, publishedAt(sort: Desc)], map: "idx_products_business_published")
@@map("products")
}
model CategoryAssignment {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
categoryId BigInt @map("category_id")
entityType MediaEntityType @map("entity_type")
entityId BigInt @map("entity_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([categoryId, entityType, entityId], map: "category_assignments_unique")
@@index([businessId, entityType, entityId], map: "idx_category_assignments_entity")
@@index([categoryId], map: "idx_category_assignments_category_id")
@@map("category_assignments")
}
model ProductVariationValue {
productId BigInt @map("product_id")
variationId BigInt @map("variation_id")
optionId BigInt @map("option_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
option CategoryVariationOption @relation(fields: [optionId], references: [id], onUpdate: NoAction)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: NoAction)
variation CategoryVariation @relation(fields: [variationId], references: [id], onUpdate: NoAction)
@@id([productId, optionId])
@@index([variationId], map: "idx_product_variation_values_variation_id")
@@map("product_variation_values")
}
model CategoryTechnicalForm {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
categoryId BigInt @unique(map: "category_technical_forms_category_unique") @map("category_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
fields CategoryTechnicalFormField[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([businessId], map: "idx_category_technical_forms_business_id")
@@map("category_technical_forms")
}
model CategoryTechnicalFormField {
id BigInt @id @default(autoincrement())
formId BigInt @map("form_id")
label String @db.VarChar(255)
fieldKey String @map("field_key") @db.VarChar(255)
fieldType TechnicalFieldType @map("field_type")
isRequired Boolean @default(false) @map("is_required")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
options CategoryTechnicalFormFieldOption[]
form CategoryTechnicalForm @relation(fields: [formId], references: [id], onDelete: Cascade, onUpdate: NoAction)
values ProductTechnicalFieldValue[]
userProductFieldValues UserProductTechnicalFieldValue[]
@@unique([formId, fieldKey], map: "category_technical_form_fields_unique_key")
@@index([formId], map: "idx_category_technical_form_fields_form_id")
@@map("category_technical_form_fields")
}
model CategoryTechnicalFormFieldOption {
id BigInt @id @default(autoincrement())
fieldId BigInt @map("field_id")
label String @db.VarChar(255)
value String @db.VarChar(255)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
field CategoryTechnicalFormField @relation(fields: [fieldId], references: [id], onDelete: Cascade, onUpdate: NoAction)
multiSelectValues ProductTechnicalFieldValueOption[]
selectedValues ProductTechnicalFieldValue[]
userProductMultiSelectValues UserProductTechnicalFieldValueOption[]
userProductSelectedValues UserProductTechnicalFieldValue[]
@@unique([fieldId, value], map: "category_technical_form_field_options_unique_value")
@@index([fieldId], map: "idx_category_technical_form_field_options_field_id")
@@map("category_technical_form_field_options")
}
model ProductTechnicalFieldValue {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
productId BigInt @map("product_id")
fieldId BigInt @map("field_id")
textValue String? @map("text_value")
optionId BigInt? @map("option_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
selectedOptions ProductTechnicalFieldValueOption[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
field CategoryTechnicalFormField @relation(fields: [fieldId], references: [id], onDelete: Cascade, onUpdate: NoAction)
option CategoryTechnicalFormFieldOption? @relation(fields: [optionId], references: [id], onUpdate: NoAction)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([productId, fieldId], map: "product_technical_field_values_unique")
@@index([productId], map: "idx_product_technical_field_values_product_id")
@@index([businessId], map: "idx_product_technical_field_values_business_id")
@@map("product_technical_field_values")
}
model ProductTechnicalFieldValueOption {
fieldValueId BigInt @map("field_value_id")
optionId BigInt @map("option_id")
fieldValue ProductTechnicalFieldValue @relation(fields: [fieldValueId], references: [id], onDelete: Cascade, onUpdate: NoAction)
option CategoryTechnicalFormFieldOption @relation(fields: [optionId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@id([fieldValueId, optionId])
@@index([optionId], map: "idx_product_technical_field_value_options_option_id")
@@map("product_technical_field_value_options")
}
model Comment {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
entityType MediaEntityType @map("entity_type")
entityId BigInt @map("entity_id")
authorName String @map("author_name") @db.VarChar(255)
authorEmail String? @map("author_email") @db.VarChar(255)
text String
isApproved Boolean @default(false) @map("is_approved")
approvedAt DateTime? @map("approved_at") @db.Timestamptz(6)
approvedBy BigInt? @map("approved_by")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
approver User? @relation("CommentApprover", fields: [approvedBy], references: [id], onUpdate: NoAction)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([businessId, isApproved, createdAt(sort: Desc)], map: "idx_comments_business_approval")
@@index([businessId, entityType, entityId, isApproved, createdAt(sort: Desc)], map: "idx_comments_entity")
@@map("comments")
}
model ContactSubmission {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
title String @db.VarChar(255)
name String @db.VarChar(255)
email String? @db.VarChar(255)
cellNumber String? @map("cell_number") @db.VarChar(20)
text String
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([businessId, createdAt(sort: Desc)], map: "idx_contact_submissions_business_created")
@@map("contact_submissions")
}
model ExpertReview {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
productId BigInt @map("product_id")
authorName String @map("author_name") @db.VarChar(255)
authorEmail String? @map("author_email") @db.VarChar(255)
rate Int @db.SmallInt
positivePoints String[] @default([]) @map("positive_points")
negativePoints String[] @default([]) @map("negative_points")
text String
isApproved Boolean @default(false) @map("is_approved")
approvedAt DateTime? @map("approved_at") @db.Timestamptz(6)
approvedBy BigInt? @map("approved_by")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
approver User? @relation("ExpertReviewApprover", fields: [approvedBy], references: [id], onUpdate: NoAction)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([businessId, isApproved, createdAt(sort: Desc)], map: "idx_expert_reviews_business_approval")
@@index([businessId, productId, isApproved, createdAt(sort: Desc)], map: "idx_expert_reviews_product")
@@map("expert_reviews")
}
model blogs {
id BigInt @id @default(autoincrement())
business_id BigInt
author_id BigInt?
title String @db.VarChar(255)
slug String @db.VarChar(255)
excerpt String?
content Json @default("{}")
status ContentStatus @default(draft)
featured_media_id BigInt?
published_at DateTime? @db.Timestamptz(6)
metadata Json @default("{}")
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
post_type BlogPostType @default(blog)
old_id BigInt?
author User? @relation("BlogAuthor", fields: [author_id], references: [id], onUpdate: NoAction)
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
media Media? @relation(fields: [featured_media_id], references: [id], onUpdate: NoAction)
@@unique([business_id, slug], map: "blogs_business_slug_unique")
@@index([business_id], map: "idx_blogs_business_id")
@@index([business_id, post_type], map: "idx_blogs_business_post_type")
@@index([business_id, published_at(sort: Desc)], map: "idx_blogs_business_published")
@@index([business_id, status], map: "idx_blogs_business_status")
}
model portfolios {
id BigInt @id @default(autoincrement())
business_id BigInt
title String @db.VarChar(255)
slug String @db.VarChar(255)
description String?
content Json @default("{}")
client_name String? @db.VarChar(255)
project_url String?
status ContentStatus @default(draft)
featured_media_id BigInt?
sort_order Int @default(0)
published_at DateTime? @db.Timestamptz(6)
metadata Json @default("{}")
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
old_id BigInt?
title_fa String? @db.VarChar(255)
title_en String? @db.VarChar(255)
author_id BigInt?
author User? @relation("PortfolioAuthor", fields: [author_id], references: [id], onUpdate: NoAction)
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
media Media? @relation(fields: [featured_media_id], references: [id], onUpdate: NoAction)
@@unique([business_id, slug], map: "portfolios_business_slug_unique")
@@index([business_id], map: "idx_portfolios_business_id")
@@index([business_id, published_at(sort: Desc)], map: "idx_portfolios_business_published")
@@index([business_id, status], map: "idx_portfolios_business_status")
@@index([author_id], map: "idx_portfolios_author_id")
}
model videos {
id BigInt @id @default(autoincrement())
business_id BigInt
author_id BigInt?
title String @db.VarChar(255)
title_fa String? @db.VarChar(255)
title_en String? @db.VarChar(255)
slug String @db.VarChar(255)
excerpt String?
content Json @default("{}")
video_provider VideoProvider
embed_code String
status ContentStatus @default(draft)
featured_media_id BigInt?
published_at DateTime? @db.Timestamptz(6)
metadata Json @default("{}")
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
old_id BigInt?
author User? @relation("VideoAuthor", fields: [author_id], references: [id], onUpdate: NoAction)
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
media Media? @relation(fields: [featured_media_id], references: [id], onUpdate: NoAction)
@@unique([business_id, slug], map: "videos_business_slug_unique")
@@unique([business_id, old_id], map: "videos_business_old_id_unique")
@@index([business_id], map: "idx_videos_business_id")
@@index([business_id, published_at(sort: Desc)], map: "idx_videos_business_published")
@@index([business_id, status], map: "idx_videos_business_status")
@@index([author_id], map: "idx_videos_author_id")
}
model instructions {
id BigInt @id @default(autoincrement())
business_id BigInt
author_id BigInt?
title String @db.VarChar(255)
title_fa String? @db.VarChar(255)
title_en String? @db.VarChar(255)
slug String @db.VarChar(255)
excerpt String?
content Json @default("{}")
video_provider VideoProvider?
embed_code String?
status ContentStatus @default(draft)
featured_media_id BigInt?
published_at DateTime? @db.Timestamptz(6)
metadata Json @default("{}")
old_id BigInt?
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
author User? @relation("InstructionAuthor", fields: [author_id], references: [id], onUpdate: NoAction)
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
media Media? @relation(fields: [featured_media_id], references: [id], onUpdate: NoAction)
@@unique([business_id, slug], map: "instructions_business_slug_unique")
@@unique([business_id, old_id], map: "instructions_business_old_id_unique")
@@index([business_id], map: "idx_instructions_business_id")
@@index([business_id, published_at(sort: Desc)], map: "idx_instructions_business_published")
@@index([business_id, status], map: "idx_instructions_business_status")
@@index([author_id], map: "idx_instructions_author_id")
}
model workshops {
id BigInt @id @default(autoincrement())
business_id BigInt
author_id BigInt?
title String @db.VarChar(255)
title_fa String? @db.VarChar(255)
title_en String? @db.VarChar(255)
slug String @db.VarChar(255)
excerpt String?
content Json @default("{}")
status ContentStatus @default(draft)
featured_media_id BigInt?
published_at DateTime? @db.Timestamptz(6)
metadata Json @default("{}")
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
author User? @relation("WorkshopAuthor", fields: [author_id], references: [id], onUpdate: NoAction)
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
media Media? @relation(fields: [featured_media_id], references: [id], onUpdate: NoAction)
workshop_registrations workshop_registrations[]
event_date DateTime? @db.Date
event_time String? @db.VarChar(5)
duration String? @db.VarChar(100)
@@unique([business_id, slug], map: "workshops_business_slug_unique")
@@index([business_id], map: "idx_workshops_business_id")
@@index([business_id, published_at(sort: Desc)], map: "idx_workshops_business_published")
@@index([business_id, status], map: "idx_workshops_business_status")
@@index([author_id], map: "idx_workshops_author_id")
}
enum WorkshopRegistrationStatus {
pending
approved
rejected
@@map("workshop_registration_status")
}
model workshop_registrations {
id BigInt @id @default(autoincrement())
business_id BigInt
workshop_id BigInt
user_id BigInt
status WorkshopRegistrationStatus @default(pending)
created_at DateTime @default(now()) @db.Timestamptz(6)
business Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
workshop workshops @relation(fields: [workshop_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
user User @relation(fields: [user_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([workshop_id, user_id], map: "workshop_registrations_workshop_user_unique")
@@index([business_id], map: "idx_workshop_registrations_business_id")
@@index([workshop_id], map: "idx_workshop_registrations_workshop_id")
@@index([user_id], map: "idx_workshop_registrations_user_id")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model Address {
id BigInt @id @default(autoincrement())
userId BigInt? @map("user_id")
businessId BigInt? @map("business_id")
province String @db.VarChar(100)
city String @db.VarChar(100)
address String
postalCode String? @map("postal_code") @db.VarChar(20)
landline String? @db.VarChar(30)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
label String? @db.VarChar(100)
business Business? @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
user User? @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
orders Order[]
@@map("addresses")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model City {
id BigInt @id @default(autoincrement())
parentId BigInt? @map("parent_id")
level CityLevel
nameFa String @map("name_fa") @db.VarChar(255)
nameEn String @map("name_en") @db.VarChar(255)
landlineCode String? @map("landline_code") @db.VarChar(10)
slug String @unique(map: "cities_slug_unique") @db.VarChar(100)
sortOrder Int @default(0) @map("sort_order")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
parent City? @relation("CityTree", fields: [parentId], references: [id], onDelete: Cascade, onUpdate: NoAction)
children City[] @relation("CityTree")
userProductsAsCity UserProduct[] @relation("UserProductCity")
userProductsAsCountry UserProduct[] @relation("UserProductCountry")
userProductsAsDistrict UserProduct[] @relation("UserProductDistrict")
@@index([level], map: "idx_cities_level")
@@index([level, parentId, sortOrder], map: "idx_cities_level_parent")
@@index([parentId], map: "idx_cities_parent_id")
@@map("cities")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model CartItem {
id BigInt @id @default(autoincrement())
cartId BigInt @map("cart_id")
storeItemVariantId BigInt @map("store_item_variant_id")
quantity Int @default(1)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade, onUpdate: NoAction)
storeItemVariant StoreItemVariant @relation(fields: [storeItemVariantId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([cartId, storeItemVariantId], map: "cart_items_cart_store_item_variant_unique")
@@index([cartId], map: "idx_cart_items_cart_id")
@@index([storeItemVariantId], map: "idx_cart_items_store_item_variant_id")
@@map("cart_items")
}
model Cart {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userId BigInt @map("user_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
items CartItem[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([businessId, userId], map: "carts_business_user_unique")
@@index([businessId], map: "idx_carts_business_id")
@@index([userId], map: "idx_carts_user_id")
@@map("carts")
}
model Favorite {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userId BigInt @map("user_id")
productId BigInt @map("product_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: NoAction)
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([businessId, userId, productId], map: "favorites_business_user_product_unique")
@@index([businessId, userId, createdAt(sort: Desc)], map: "idx_favorites_business_user_created")
@@index([productId], map: "idx_favorites_product_id")
@@map("favorites")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model OrderItem {
id BigInt @id @default(autoincrement())
orderId BigInt @map("order_id")
storeItemVariantId BigInt? @map("store_item_variant_id")
productId BigInt @map("product_id")
productTitle String @map("product_title") @db.VarChar(255)
variantSku String? @map("variant_sku") @db.VarChar(100)
unitPrice Decimal @map("unit_price") @db.Decimal(12, 2)
compareAtPrice Decimal? @map("compare_at_price") @db.Decimal(12, 2)
quantity Int
lineTotal Decimal @map("line_total") @db.Decimal(12, 2)
selectionsSnapshot Json @default("[]") @map("selections_snapshot")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
order Order @relation(fields: [orderId], references: [id], onDelete: Cascade, onUpdate: NoAction)
product Product @relation(fields: [productId], references: [id], onUpdate: NoAction)
storeItemVariant StoreItemVariant? @relation(fields: [storeItemVariantId], references: [id], onUpdate: NoAction)
@@index([orderId], map: "idx_order_items_order_id")
@@index([storeItemVariantId], map: "idx_order_items_store_item_variant_id")
@@map("order_items")
}
model ShoppingCardItem {
id BigInt @id @default(autoincrement())
shoppingCardId BigInt @map("shopping_card_id")
storeItemVariantId BigInt? @map("store_item_variant_id")
productId BigInt @map("product_id")
productTitle String @map("product_title") @db.VarChar(255)
variantSku String? @map("variant_sku") @db.VarChar(100)
unitPrice Decimal @map("unit_price") @db.Decimal(12, 2)
compareAtPrice Decimal? @map("compare_at_price") @db.Decimal(12, 2)
quantity Int
lineTotal Decimal @map("line_total") @db.Decimal(12, 2)
selectionsSnapshot Json @default("[]") @map("selections_snapshot")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
shoppingCard ShoppingCard @relation(fields: [shoppingCardId], references: [id], onDelete: Cascade, onUpdate: NoAction, map: "shopping_card_items_card_id_fkey")
product Product @relation(fields: [productId], references: [id], onUpdate: NoAction)
storeItemVariant StoreItemVariant? @relation(fields: [storeItemVariantId], references: [id], onUpdate: NoAction, map: "shopping_card_items_variant_id_fkey")
@@index([shoppingCardId], map: "idx_shopping_card_items_card_id")
@@index([storeItemVariantId], map: "idx_shopping_card_items_variant_id")
@@map("shopping_card_items")
}
model ShoppingCard {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userId BigInt @map("user_id")
subtotal Decimal @default(0) @db.Decimal(12, 2)
total Decimal @default(0) @db.Decimal(12, 2)
createdBy BigInt? @map("created_by")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
items ShoppingCardItem[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
creator User? @relation("ShoppingCardCreator", fields: [createdBy], references: [id], onUpdate: NoAction)
customer User @relation("ShoppingCardCustomer", fields: [userId], references: [id], onUpdate: NoAction)
@@index([businessId, createdAt(sort: Desc)], map: "idx_shopping_cards_business_created")
@@index([businessId, userId, createdAt(sort: Desc)], map: "idx_shopping_cards_business_user")
@@map("shopping_cards")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model Order {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userId BigInt @map("user_id")
orderNumber String @map("order_number") @db.VarChar(30)
status OrderStatus @default(pending)
source OrderSource @default(website)
subtotal Decimal @default(0) @db.Decimal(12, 2)
shippingTotal Decimal @default(0) @map("shipping_total") @db.Decimal(12, 2)
discountTotal Decimal @default(0) @map("discount_total") @db.Decimal(12, 2)
total Decimal @default(0) @db.Decimal(12, 2)
shippingAddress Json @default("{}") @map("shipping_address")
addressId BigInt? @map("address_id")
customerNotes String? @map("customer_notes")
adminNotes String? @map("admin_notes")
createdBy BigInt? @map("created_by")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
processStepId String @default("processing") @map("process_step_id") @db.VarChar(64)
items OrderItem[]
address Address? @relation(fields: [addressId], references: [id], onUpdate: NoAction)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
creator User? @relation("OrderCreator", fields: [createdBy], references: [id], onUpdate: NoAction)
customer User @relation("OrderCustomer", fields: [userId], references: [id], onUpdate: NoAction)
transactions Transaction[]
@@unique([businessId, orderNumber], map: "orders_business_order_number_unique")
@@index([businessId, createdAt(sort: Desc)], map: "idx_orders_business_created")
@@index([businessId, status, createdAt(sort: Desc)], map: "idx_orders_business_status")
@@index([businessId, processStepId], map: "idx_orders_business_process_step")
@@index([businessId, userId, createdAt(sort: Desc)], map: "idx_orders_business_user")
@@map("orders")
}
model StoreItemVariantSelection {
variantId BigInt @map("variant_id")
variationId BigInt @map("variation_id")
optionId BigInt @map("option_id")
option CategoryVariationOption @relation(fields: [optionId], references: [id], onUpdate: NoAction)
variant StoreItemVariant @relation(fields: [variantId], references: [id], onDelete: Cascade, onUpdate: NoAction)
variation CategoryVariation @relation(fields: [variationId], references: [id], onUpdate: NoAction)
@@id([variantId, variationId])
@@unique([variantId, optionId], map: "store_item_variant_selections_unique_option")
@@index([optionId], map: "idx_store_item_variant_selections_option_id")
@@map("store_item_variant_selections")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model StoreItemVariant {
id BigInt @id @default(autoincrement())
storeItemId BigInt @map("store_item_id")
businessId BigInt @map("business_id")
sku String? @db.VarChar(100)
price Decimal? @db.Decimal(12, 2)
compareAtPrice Decimal? @map("compare_at_price") @db.Decimal(12, 2)
stockQuantity Int? @map("stock_quantity")
isActive Boolean @default(true) @map("is_active")
isFestival Boolean @default(false) @map("is_festival")
rewardPoints Int? @map("reward_points")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
cartItems CartItem[]
orderItems OrderItem[]
shoppingCardItems ShoppingCardItem[]
selections StoreItemVariantSelection[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
storeItem StoreItem @relation(fields: [storeItemId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([businessId], map: "idx_store_item_variants_business_id")
@@index([storeItemId], map: "idx_store_item_variants_store_item_id")
@@map("store_item_variants")
}
model StoreItem {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
productId BigInt @map("product_id")
isActive Boolean @default(true) @map("is_active")
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
variants StoreItemVariant[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade, onUpdate: NoAction)
specialItems StoreSpecialItem[]
@@unique([businessId, productId], map: "store_items_business_product_unique")
@@index([businessId], map: "idx_store_items_business_id")
@@index([productId], map: "idx_store_items_product_id")
@@map("store_items")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model Transaction {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
orderId BigInt? @map("order_id")
userId BigInt @map("user_id")
type TransactionType
status TransactionStatus @default(pending)
amount Decimal @db.Decimal(12, 2)
posType String? @map("pos_type") @db.VarChar(100)
gatewayType String? @map("gateway_type") @db.VarChar(100)
transferAccount String? @map("transfer_account") @db.VarChar(255)
transferRefNumber String? @map("transfer_ref_number") @db.VarChar(100)
gatewayRef String? @map("gateway_ref") @db.VarChar(255)
gatewayTrackId String? @map("gateway_track_id") @db.VarChar(255)
gatewayMeta Json? @map("gateway_meta")
notes String?
createdBy BigInt? @map("created_by")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
creator User? @relation("TransactionCreator", fields: [createdBy], references: [id], onUpdate: NoAction)
order Order? @relation(fields: [orderId], references: [id], onUpdate: NoAction)
customer User @relation("TransactionCustomer", fields: [userId], references: [id], onUpdate: NoAction)
@@index([businessId, createdAt(sort: Desc)], map: "idx_transactions_business_created")
@@index([orderId], map: "idx_transactions_order_id")
@@index([businessId, userId, createdAt(sort: Desc)], map: "idx_transactions_business_user")
@@map("transactions")
}
model StoreSpecialItem {
id BigInt @id @default(autoincrement())
specialId BigInt @map("special_id")
storeItemId BigInt @map("store_item_id")
sortOrder Int @default(0) @map("sort_order")
special StoreSpecial @relation(fields: [specialId], references: [id], onDelete: Cascade, onUpdate: NoAction)
storeItem StoreItem @relation(fields: [storeItemId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([specialId, storeItemId], map: "store_special_items_unique")
@@index([specialId], map: "idx_store_special_items_special_id")
@@index([storeItemId], map: "idx_store_special_items_store_item_id")
@@map("store_special_items")
}
model StoreSpecial {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
title String @db.VarChar(255)
sortOrder Int @default(0) @map("sort_order")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
key String @db.VarChar(100)
items StoreSpecialItem[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([businessId, key], map: "store_specials_business_id_key_unique")
@@index([businessId], map: "idx_store_specials_business_id")
@@map("store_specials")
}
model website_brand_group_items {
id BigInt @id @default(autoincrement())
group_id BigInt
brand_id BigInt
sort_order Int @default(0)
brands Brand @relation(fields: [brand_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
website_brand_groups website_brand_groups @relation(fields: [group_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([group_id, brand_id], map: "website_brand_group_items_unique")
@@index([brand_id], map: "idx_website_brand_group_items_brand_id")
@@index([group_id], map: "idx_website_brand_group_items_group_id")
}
model website_brand_groups {
id BigInt @id @default(autoincrement())
business_id BigInt
title String @db.VarChar(255)
sort_order Int @default(0)
is_active Boolean @default(true)
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
key String @db.VarChar(100)
website_brand_group_items website_brand_group_items[]
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([business_id, key], map: "website_brand_groups_business_id_key_unique")
@@index([business_id], map: "idx_website_brand_groups_business_id")
}
model website_category_group_items {
id BigInt @id @default(autoincrement())
group_id BigInt
category_id BigInt
sort_order Int @default(0)
categories Category @relation(fields: [category_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
website_category_groups website_category_groups @relation(fields: [group_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([group_id, category_id], map: "website_category_group_items_unique")
@@index([category_id], map: "idx_website_category_group_items_category_id")
@@index([group_id], map: "idx_website_category_group_items_group_id")
}
model website_category_groups {
id BigInt @id @default(autoincrement())
business_id BigInt
title String @db.VarChar(255)
sort_order Int @default(0)
is_active Boolean @default(true)
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
key String @db.VarChar(100)
website_category_group_items website_category_group_items[]
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([business_id, key], map: "website_category_groups_business_id_key_unique")
@@index([business_id], map: "idx_website_category_groups_business_id")
}
model website_image_slot_items {
id BigInt @id @default(autoincrement())
slot_id BigInt
image_media_id BigInt
title String? @db.VarChar(255)
title_fa String? @db.VarChar(255)
title_en String? @db.VarChar(255)
subtext String? @db.VarChar(500)
link_url String? @db.VarChar(2048)
sort_order Int @default(0)
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
media Media @relation(fields: [image_media_id], references: [id], onUpdate: NoAction)
website_image_slots website_image_slots @relation(fields: [slot_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([image_media_id], map: "idx_website_image_slot_items_image_media_id")
@@index([slot_id], map: "idx_website_image_slot_items_slot_id")
}
model website_image_slots {
id BigInt @id @default(autoincrement())
business_id BigInt
slot_key String @db.VarChar(100)
kind String @db.VarChar(20)
label String @db.VarChar(255)
aspect_ratio String? @db.VarChar(20)
recommended_width Int?
item_count Int?
page_key String @default("home") @db.VarChar(100)
sort_order Int @default(0)
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
website_image_slot_items website_image_slot_items[]
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([business_id, slot_key], map: "website_image_slots_business_id_slot_key_unique")
@@index([business_id], map: "idx_website_image_slots_business_id")
@@index([business_id, page_key], map: "idx_website_image_slots_business_id_page_key")
}
model website_slider_slides {
id BigInt @id @default(autoincrement())
slider_id BigInt
image_media_id BigInt
title String? @db.VarChar(255)
link_url String? @db.VarChar(2048)
sort_order Int @default(0)
is_active Boolean @default(true)
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
media Media @relation(fields: [image_media_id], references: [id], onUpdate: NoAction)
website_sliders website_sliders @relation(fields: [slider_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([image_media_id], map: "idx_website_slider_slides_image_media_id")
@@index([slider_id], map: "idx_website_slider_slides_slider_id")
}
model website_sliders {
id BigInt @id @default(autoincrement())
business_id BigInt
title String @db.VarChar(255)
sort_order Int @default(0)
is_active Boolean @default(true)
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
website_slider_slides website_slider_slides[]
businesses Business @relation(fields: [business_id], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([business_id], map: "idx_website_sliders_business_id")
}
model InvoiceItemTemplate {
id BigInt @id @default(autoincrement())
ownerScope InvoiceOwnerScope @map("owner_scope")
businessId BigInt? @map("business_id")
title String @db.VarChar(255)
duration String? @db.VarChar(100)
worktime String? @db.VarChar(100)
description String?
price Decimal @default(0) @db.Decimal(12, 2)
discountedPrice Decimal? @map("discounted_price") @db.Decimal(12, 2)
sortOrder Int @default(0) @map("sort_order")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
business Business? @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
invoiceItems InvoiceItem[]
invoiceTemplateItems InvoiceTemplateItem[]
@@index([ownerScope, sortOrder], map: "idx_invoice_item_templates_owner_scope")
@@map("invoice_item_templates")
}
model InvoiceTemplate {
id BigInt @id @default(autoincrement())
ownerScope InvoiceOwnerScope @map("owner_scope")
businessId BigInt? @map("business_id")
name String @db.VarChar(255)
topText String? @map("top_text")
sortOrder Int @default(0) @map("sort_order")
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
accounts InvoiceTemplateAccount[]
items InvoiceTemplateItem[]
keyPoints InvoiceTemplateKeyPoint[]
business Business? @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
invoices Invoice[]
@@index([ownerScope, sortOrder], map: "idx_invoice_templates_owner_scope")
@@map("invoice_templates")
}
model InvoiceTemplateItem {
id BigInt @id @default(autoincrement())
templateId BigInt @map("template_id")
itemTemplateId BigInt? @map("item_template_id")
title String @db.VarChar(255)
duration String? @db.VarChar(100)
worktime String? @db.VarChar(100)
description String?
price Decimal @default(0) @db.Decimal(12, 2)
discountedPrice Decimal? @map("discounted_price") @db.Decimal(12, 2)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
itemTemplate InvoiceItemTemplate? @relation(fields: [itemTemplateId], references: [id], onUpdate: NoAction)
template InvoiceTemplate @relation(fields: [templateId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([templateId, sortOrder], map: "idx_invoice_template_items_template_id")
@@map("invoice_template_items")
}
model InvoiceTemplateKeyPoint {
id BigInt @id @default(autoincrement())
templateId BigInt @map("template_id")
text String
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
template InvoiceTemplate @relation(fields: [templateId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([templateId, sortOrder], map: "idx_invoice_template_key_points_template_id")
@@map("invoice_template_key_points")
}
model InvoiceTemplateAccount {
id BigInt @id @default(autoincrement())
templateId BigInt @map("template_id")
bankName String @map("bank_name") @db.VarChar(255)
cardNumber String? @map("card_number") @db.VarChar(64)
iban String? @db.VarChar(64)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
accountHolderName String? @map("account_holder_name") @db.VarChar(255)
template InvoiceTemplate @relation(fields: [templateId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([templateId, sortOrder], map: "idx_invoice_template_accounts_template_id")
@@map("invoice_template_accounts")
}
model Invoice {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
ownerScope InvoiceOwnerScope @default(platform) @map("owner_scope")
issuerBusinessId BigInt? @map("issuer_business_id")
status InvoiceStatus @default(issued)
notes String?
issuedBy BigInt? @map("issued_by")
issuedAt DateTime @default(now()) @map("issued_at") @db.Timestamptz(6)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
name String? @db.VarChar(255)
topText String? @map("top_text")
invoiceTemplateId BigInt? @map("invoice_template_id")
publicId String @unique(map: "idx_invoices_public_id") @map("public_id") @db.VarChar(32)
userId BigInt @map("user_id")
accounts InvoiceAccount[]
items InvoiceItem[]
keyPoints InvoiceKeyPoint[]
business Business @relation("InvoiceBusiness", fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
invoiceTemplate InvoiceTemplate? @relation(fields: [invoiceTemplateId], references: [id], onUpdate: NoAction)
issuer User? @relation("InvoiceIssuer", fields: [issuedBy], references: [id], onUpdate: NoAction)
issuerBusiness Business? @relation("InvoiceIssuerBusiness", fields: [issuerBusinessId], references: [id], onUpdate: NoAction)
user User @relation("InvoiceBilledUser", fields: [userId], references: [id], onUpdate: NoAction)
@@index([businessId, createdAt(sort: Desc)], map: "idx_invoices_business_created")
@@index([ownerScope, createdAt(sort: Desc)], map: "idx_invoices_owner_scope")
@@index([status], map: "idx_invoices_status")
@@index([userId, createdAt(sort: Desc)], map: "idx_invoices_user_created")
@@map("invoices")
}
model InvoiceItem {
id BigInt @id @default(autoincrement())
invoiceId BigInt @map("invoice_id")
templateId BigInt? @map("template_id")
title String @db.VarChar(255)
duration String? @db.VarChar(100)
worktime String? @db.VarChar(100)
description String?
price Decimal @default(0) @db.Decimal(12, 2)
discountedPrice Decimal? @map("discounted_price") @db.Decimal(12, 2)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade, onUpdate: NoAction)
template InvoiceItemTemplate? @relation(fields: [templateId], references: [id], onUpdate: NoAction)
@@index([invoiceId, sortOrder], map: "idx_invoice_items_invoice_id")
@@map("invoice_items")
}
model InvoiceKeyPoint {
id BigInt @id @default(autoincrement())
invoiceId BigInt @map("invoice_id")
text String
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([invoiceId, sortOrder], map: "idx_invoice_key_points_invoice_id")
@@map("invoice_key_points")
}
model InvoiceAccount {
id BigInt @id @default(autoincrement())
invoiceId BigInt @map("invoice_id")
bankName String @map("bank_name") @db.VarChar(255)
cardNumber String? @map("card_number") @db.VarChar(64)
iban String? @db.VarChar(64)
sortOrder Int @default(0) @map("sort_order")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
accountHolderName String? @map("account_holder_name") @db.VarChar(255)
invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@index([invoiceId, sortOrder], map: "idx_invoice_accounts_invoice_id")
@@map("invoice_accounts")
}
model UserProductTechnicalFieldValueOption {
fieldValueId BigInt @map("field_value_id")
optionId BigInt @map("option_id")
fieldValue UserProductTechnicalFieldValue @relation(fields: [fieldValueId], references: [id], onDelete: Cascade, onUpdate: NoAction)
option CategoryTechnicalFormFieldOption @relation(fields: [optionId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@id([fieldValueId, optionId])
@@index([optionId], map: "idx_user_product_technical_field_value_options_option_id")
@@map("user_product_technical_field_value_options")
}
model UserProductTechnicalFieldValue {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userProductId BigInt @map("user_product_id")
fieldId BigInt @map("field_id")
textValue String? @map("text_value")
optionId BigInt? @map("option_id")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
selectedOptions UserProductTechnicalFieldValueOption[]
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
field CategoryTechnicalFormField @relation(fields: [fieldId], references: [id], onDelete: Cascade, onUpdate: NoAction)
option CategoryTechnicalFormFieldOption? @relation(fields: [optionId], references: [id], onUpdate: NoAction)
userProduct UserProduct @relation(fields: [userProductId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([userProductId, fieldId], map: "user_product_technical_field_values_unique")
@@index([businessId], map: "idx_user_product_technical_field_values_business_id")
@@index([userProductId], map: "idx_user_product_technical_field_values_user_product_id")
@@map("user_product_technical_field_values")
}
/// This table contains check constraints and requires additional setup for migrations. Visit https://pris.ly/d/check-constraints for more info.
model UserProduct {
id BigInt @id @default(autoincrement())
businessId BigInt @map("business_id")
userId BigInt @map("user_id")
title String @db.VarChar(255)
slug String @db.VarChar(255)
description String?
content Json @default("{}")
price Decimal? @db.Decimal(12, 2)
compareAtPrice Decimal? @map("compare_at_price") @db.Decimal(12, 2)
sku String? @db.VarChar(100)
stockQuantity Int? @map("stock_quantity")
status ContentStatus @default(draft)
featuredMediaId BigInt? @map("featured_media_id")
brandId BigInt? @map("brand_id")
countryId BigInt @map("country_id")
cityId BigInt @map("city_id")
districtId BigInt? @map("district_id")
sortOrder Int @default(0) @map("sort_order")
publishedAt DateTime? @map("published_at") @db.Timestamptz(6)
metadata Json @default("{}")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
priceCurrency String @default("IRT") @map("price_currency") @db.VarChar(8)
deliveryNote String? @map("delivery_note")
condition UserProductCondition @default(new)
technicalNotes String? @map("technical_notes")
technicalFieldValues UserProductTechnicalFieldValue[]
brand Brand? @relation(fields: [brandId], references: [id], onUpdate: NoAction)
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
city City @relation("UserProductCity", fields: [cityId], references: [id], onUpdate: NoAction)
country City @relation("UserProductCountry", fields: [countryId], references: [id], onUpdate: NoAction)
district City? @relation("UserProductDistrict", fields: [districtId], references: [id], onUpdate: NoAction)
featuredMedia Media? @relation("UserProductFeaturedMedia", fields: [featuredMediaId], references: [id], onUpdate: NoAction)
user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@unique([businessId, slug], map: "user_products_business_slug_unique")
@@index([brandId], map: "idx_user_products_brand_id")
@@index([businessId], map: "idx_user_products_business_id")
@@index([businessId, publishedAt(sort: Desc)], map: "idx_user_products_business_published")
@@index([businessId, status], map: "idx_user_products_business_status")
@@index([businessId, userId], map: "idx_user_products_business_user")
@@index([cityId], map: "idx_user_products_city_id")
@@index([countryId], map: "idx_user_products_country_id")
@@index([districtId], map: "idx_user_products_district_id")
@@index([userId], map: "idx_user_products_user_id")
@@map("user_products")
}
enum MediaType {
image
video
@@map("media_type")
}
enum MediaEntityType {
product
blog
portfolio
customer
user_product
video
instruction
workshop
@@map("media_entity_type")
}
enum VideoProvider {
youtube
aparat
@@map("video_provider")
}
enum VariationType {
color
size
custom
@@map("variation_type")
}
enum ContentStatus {
draft
published
archived
rejected
@@map("content_status")
}
enum BlogPostType {
news
article
blog
@@map("blog_post_type")
}
enum TechnicalFieldType {
text
textarea
select
multi_select
@@map("technical_field_type")
}
enum CityLevel {
country
province
city
district
@@map("city_level")
}
enum OrderSource {
website
admin
@@map("order_source")
}
enum OrderStatus {
pending
confirmed
processing
shipped
delivered
cancelled
@@map("order_status")
}
enum TransactionType {
pos
cash
transfer
e_payment_gate
@@map("transaction_type")
}
enum TransactionStatus {
pending
completed
failed
refunded
@@map("transaction_status")
}
enum InvoiceOwnerScope {
platform
business
@@map("invoice_owner_scope")
}
enum InvoiceStatus {
draft
issued
paid
cancelled
approved
@@map("invoice_status")
}
enum UserProductCondition {
new
stock
needs_repair
scrap
@@map("user_product_condition")
}