Add page-view analytics, product counters, SSL expiry, and business renewal.
Auto-count storefront page views with 6-month event retention and lifetime counters, track product visit/cart/sale stats, persist SSL cert expiry with daily probes, and support owner titles plus annual contract renewal. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
6cd0b009ef
commit
92601ae729
+57
-12
@@ -23,6 +23,8 @@ model User {
|
||||
firstNameEn String? @map("first_name_en") @db.VarChar(100)
|
||||
lastNameEn String? @map("last_name_en") @db.VarChar(100)
|
||||
oldId BigInt? @map("old_id")
|
||||
titleId BigInt? @map("title_id")
|
||||
title UserTitle? @relation(fields: [titleId], references: [id], onDelete: SetNull, onUpdate: NoAction)
|
||||
addresses Address[]
|
||||
authoredBlogs blogs[] @relation("BlogAuthor")
|
||||
businessCustomers BusinessCustomer[]
|
||||
@@ -53,6 +55,20 @@ model User {
|
||||
@@map("users")
|
||||
}
|
||||
|
||||
model UserTitle {
|
||||
id BigInt @id @default(autoincrement())
|
||||
slug String @unique(map: "user_titles_slug_unique") @db.VarChar(32)
|
||||
nameEn String @map("name_en") @db.VarChar(64)
|
||||
nameFa String @map("name_fa") @db.VarChar(64)
|
||||
sortOrder Int @default(0) @map("sort_order")
|
||||
isActive Boolean @default(true) @map("is_active")
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
users User[]
|
||||
|
||||
@@index([sortOrder, id], map: "idx_user_titles_sort")
|
||||
@@map("user_titles")
|
||||
}
|
||||
|
||||
model Business {
|
||||
id BigInt @id @default(autoincrement())
|
||||
name String @db.VarChar(255)
|
||||
@@ -72,6 +88,7 @@ model Business {
|
||||
logoDarkMediaId BigInt? @map("logo_dark_media_id")
|
||||
faviconMediaId BigInt? @map("favicon_media_id")
|
||||
oldBusinessId BigInt? @map("old_business_id")
|
||||
annualRenewalAt DateTime? @map("annual_renewal_at") @db.Timestamptz(6)
|
||||
addresses Address[]
|
||||
blogs blogs[]
|
||||
brands Brand[]
|
||||
@@ -116,7 +133,8 @@ model Business {
|
||||
website_category_groups website_category_groups[]
|
||||
website_image_slots website_image_slots[]
|
||||
website_sliders website_sliders[]
|
||||
websiteContentViews WebsiteContentView[]
|
||||
websitePageViews WebsitePageView[]
|
||||
websitePageViewCounters WebsitePageViewCounter[]
|
||||
|
||||
@@map("businesses")
|
||||
}
|
||||
@@ -161,6 +179,7 @@ model Domain {
|
||||
isVerified Boolean @default(false) @map("is_verified")
|
||||
verifiedAt DateTime? @map("verified_at") @db.Timestamptz(6)
|
||||
sslEnabled Boolean @default(false) @map("ssl_enabled")
|
||||
sslExpiresAt DateTime? @map("ssl_expires_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)
|
||||
expiresAt DateTime? @map("expires_at") @db.Timestamptz(6)
|
||||
@@ -436,6 +455,9 @@ model Product {
|
||||
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")
|
||||
visitCount BigInt @default(0) @map("visit_count")
|
||||
cartAddCount BigInt @default(0) @map("cart_add_count")
|
||||
saleCount BigInt @default(0) @map("sale_count")
|
||||
expertReviews ExpertReview[]
|
||||
favorites Favorite[]
|
||||
orderItems OrderItem[]
|
||||
@@ -1638,24 +1660,47 @@ enum UserProductCondition {
|
||||
@@map("user_product_condition")
|
||||
}
|
||||
|
||||
enum WebsiteViewKind {
|
||||
website
|
||||
product
|
||||
portfolio
|
||||
blog
|
||||
enum WebsitePageKind {
|
||||
home
|
||||
portfolio_list
|
||||
portfolio_detail
|
||||
product_list
|
||||
product_detail
|
||||
store_item_list
|
||||
store_item_detail
|
||||
blog_list
|
||||
blog_detail
|
||||
video_list
|
||||
video_detail
|
||||
|
||||
@@map("website_view_kind")
|
||||
@@map("website_page_kind")
|
||||
}
|
||||
|
||||
model WebsiteContentView {
|
||||
/// Raw page-view events (retained ~6 months; purged by cron).
|
||||
model WebsitePageView {
|
||||
id BigInt @id @default(autoincrement())
|
||||
businessId BigInt @map("business_id")
|
||||
viewKind WebsiteViewKind @map("view_kind")
|
||||
entityId BigInt? @map("entity_id")
|
||||
pageKind WebsitePageKind @map("page_kind")
|
||||
entityId BigInt @default(0) @map("entity_id")
|
||||
pagePath String? @map("page_path")
|
||||
viewedAt DateTime @default(now()) @map("viewed_at") @db.Timestamptz(6)
|
||||
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
|
||||
@@index([businessId, viewKind, viewedAt(sort: Desc)], map: "idx_website_content_views_business_kind_time")
|
||||
@@map("website_content_views")
|
||||
@@index([businessId, pageKind, viewedAt(sort: Desc)], map: "idx_website_page_views_business_kind_time")
|
||||
@@map("website_page_views")
|
||||
}
|
||||
|
||||
/// Lifetime totals per page kind (+ entity for detail pages). Never purged.
|
||||
model WebsitePageViewCounter {
|
||||
id BigInt @id @default(autoincrement())
|
||||
businessId BigInt @map("business_id")
|
||||
pageKind WebsitePageKind @map("page_kind")
|
||||
entityId BigInt @default(0) @map("entity_id")
|
||||
totalCount BigInt @default(0) @map("total_count")
|
||||
updatedAt DateTime @default(now()) @updatedAt @map("updated_at") @db.Timestamptz(6)
|
||||
business Business @relation(fields: [businessId], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
||||
|
||||
@@unique([businessId, pageKind, entityId], map: "uq_website_page_view_counters_biz_kind_entity")
|
||||
@@index([businessId, pageKind], map: "idx_website_page_view_counters_business_kind")
|
||||
@@map("website_page_view_counters")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user