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>
This commit is contained in:
Alireza Hassani
2026-08-22 12:22:24 +03:30
co-authored by Cursor
parent 9d56ec7396
commit c7d5204b49
19 changed files with 1919 additions and 19 deletions
+63
View File
@@ -40,6 +40,8 @@ model User {
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")
@@ -97,6 +99,8 @@ model Business {
portfolios portfolios[]
videos videos[]
instructions instructions[]
workshops workshops[]
workshop_registrations workshop_registrations[]
productTechnicalFieldValues ProductTechnicalFieldValue[]
products Product[]
shoppingCards ShoppingCard[]
@@ -290,6 +294,7 @@ model Media {
portfolios portfolios[]
videos videos[]
instructions instructions[]
workshops workshops[]
featuredProducts Product[] @relation("ProductFeaturedMedia")
featuredUserProducts UserProduct[] @relation("UserProductFeaturedMedia")
website_image_slot_items website_image_slot_items[]
@@ -741,6 +746,63 @@ model instructions {
@@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())
@@ -1455,6 +1517,7 @@ enum MediaEntityType {
user_product
video
instruction
workshop
@@map("media_entity_type")
}