把 3 分钟身体状态评估做成独立获客链路,匿名测评后登录认领完整报告,并接入体验预约与今日待办。 Co-authored-by: Cursor <cursoragent@cursor.com>
623 lines
23 KiB
Plaintext
623 lines
23 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "mysql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
// ===== Enums =====
|
|
|
|
enum UserRole {
|
|
MEMBER
|
|
ADMIN
|
|
}
|
|
|
|
enum CardTypeCategory {
|
|
TIMES
|
|
DURATION
|
|
TRIAL
|
|
}
|
|
|
|
enum MembershipStatus {
|
|
ACTIVE
|
|
EXPIRED
|
|
USED_UP
|
|
}
|
|
|
|
enum TimeSlotStatus {
|
|
OPEN
|
|
FULL
|
|
CLOSED
|
|
}
|
|
|
|
enum TimeSlotSource {
|
|
TEMPLATE
|
|
MANUAL
|
|
}
|
|
|
|
enum BookingStatus {
|
|
PENDING_CONFIRMATION
|
|
CONFIRMED
|
|
CANCELLED
|
|
COMPLETED
|
|
NO_SHOW
|
|
}
|
|
|
|
enum OrderStatus {
|
|
PENDING
|
|
PAID
|
|
REFUNDED
|
|
}
|
|
|
|
enum InviteReferralStatus {
|
|
REGISTERED
|
|
TRIAL_PURCHASED
|
|
QUALIFIED
|
|
}
|
|
|
|
// ===== Models =====
|
|
|
|
model User {
|
|
id String @id @default(uuid())
|
|
inviteCode String? @unique @map("invite_code") @db.VarChar(6)
|
|
openid String @unique
|
|
unionid String?
|
|
phone String?
|
|
nickname String @default("")
|
|
avatarUrl String? @map("avatar_url")
|
|
role UserRole @default(MEMBER)
|
|
adminBookingSubscriptionCount Int @default(0) @map("admin_booking_subscription_count")
|
|
lastLoginAt DateTime? @map("last_login_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
bodyMetrics BodyMetric[]
|
|
memberNotes MemberNote[]
|
|
progressPhotos ProgressPhoto[]
|
|
lessonSupplements LessonSupplement[]
|
|
memberships Membership[]
|
|
bookings Booking[]
|
|
orders Order[]
|
|
subscriptionMessageConsents SubscriptionMessageConsent[]
|
|
sentInviteReferrals InviteReferral[] @relation("InviteReferralInviter")
|
|
receivedInviteReferral InviteReferral[] @relation("InviteReferralInvitee")
|
|
inviteRewardGrants InviteRewardGrant[] @relation("InviteRewardGrantInviter")
|
|
bodyPortraitVisits BodyPortraitVisit[] @relation("PortraitVisitUser")
|
|
referredPortraitVisits BodyPortraitVisit[] @relation("PortraitReferrer")
|
|
bodyPortraitAssessments BodyPortraitAssessment[]
|
|
growthLead GrowthLead?
|
|
growthEvents GrowthEvent[]
|
|
professionalAssessments ProfessionalAssessmentSession[]
|
|
trainingPlans TrainingPlan[]
|
|
reassessmentTodos ReassessmentTodo[]
|
|
growthShareCards GrowthShareCard[]
|
|
|
|
@@map("users")
|
|
}
|
|
|
|
model SubscriptionMessageConsent {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
templateId String @map("template_id")
|
|
scene String
|
|
totalRequestCount Int @default(0) @map("total_request_count")
|
|
acceptCount Int @default(0) @map("accept_count")
|
|
rejectCount Int @default(0) @map("reject_count")
|
|
banCount Int @default(0) @map("ban_count")
|
|
filterCount Int @default(0) @map("filter_count")
|
|
sentCount Int @default(0) @map("sent_count")
|
|
lastResult String @map("last_result")
|
|
lastRequestedAt DateTime @default(now()) @map("last_requested_at")
|
|
lastSentAt DateTime? @map("last_sent_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
|
|
@@unique([userId, templateId, scene])
|
|
@@index([userId])
|
|
@@index([scene])
|
|
@@map("subscription_message_consents")
|
|
}
|
|
|
|
model CardType {
|
|
id String @id @default(uuid())
|
|
name String
|
|
type CardTypeCategory
|
|
totalTimes Int? @map("total_times")
|
|
durationDays Int @map("duration_days")
|
|
price Decimal @db.Decimal(10, 0)
|
|
originalPrice Decimal? @map("original_price") @db.Decimal(10, 0)
|
|
description String?
|
|
coverUrl String? @map("cover_url")
|
|
isActive Boolean @default(true) @map("is_active")
|
|
sortOrder Int @default(0) @map("sort_order")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
memberships Membership[]
|
|
orders Order[]
|
|
|
|
@@map("card_types")
|
|
}
|
|
|
|
model Membership {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
cardTypeId String @map("card_type_id")
|
|
remainingTimes Int? @map("remaining_times")
|
|
totalTimes Int? @map("total_times")
|
|
startDate DateTime @map("start_date")
|
|
expireDate DateTime @map("expire_date")
|
|
status MembershipStatus @default(ACTIVE)
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
lessonSupplements LessonSupplement[]
|
|
user User @relation(fields: [userId], references: [id])
|
|
cardType CardType @relation(fields: [cardTypeId], references: [id])
|
|
bookings Booking[]
|
|
orders Order[]
|
|
inviteRewardGrants InviteRewardGrant[]
|
|
|
|
@@index([userId])
|
|
@@index([userId, cardTypeId])
|
|
@@index([status])
|
|
@@map("memberships")
|
|
}
|
|
|
|
model WeekTemplate {
|
|
id String @id @default(uuid())
|
|
dayOfWeek Int @map("day_of_week")
|
|
startTime String @map("start_time")
|
|
endTime String @map("end_time")
|
|
capacity Int @default(1)
|
|
isActive Boolean @default(true) @map("is_active")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
timeSlots TimeSlot[]
|
|
|
|
@@map("week_templates")
|
|
}
|
|
|
|
model TimeSlot {
|
|
id String @id @default(uuid())
|
|
date DateTime @db.Date
|
|
startTime String @map("start_time")
|
|
endTime String @map("end_time")
|
|
capacity Int @default(1)
|
|
bookedCount Int @default(0) @map("booked_count")
|
|
status TimeSlotStatus @default(OPEN)
|
|
source TimeSlotSource @default(TEMPLATE)
|
|
templateId String? @map("template_id")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
template WeekTemplate? @relation(fields: [templateId], references: [id])
|
|
bookings Booking[]
|
|
|
|
@@unique([date, startTime, endTime])
|
|
@@index([date])
|
|
@@index([status])
|
|
@@map("time_slots")
|
|
}
|
|
|
|
model Booking {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
timeSlotId String @map("time_slot_id")
|
|
membershipId String @map("membership_id")
|
|
membershipTimesDeducted Boolean? @map("membership_times_deducted")
|
|
status BookingStatus @default(PENDING_CONFIRMATION)
|
|
cancelledAt DateTime? @map("cancelled_at")
|
|
confirmedAt DateTime? @map("confirmed_at")
|
|
completedAt DateTime? @map("completed_at")
|
|
operatorId String? @map("operator_id")
|
|
originAssessmentId String? @map("origin_assessment_id")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
timeSlot TimeSlot @relation(fields: [timeSlotId], references: [id])
|
|
membership Membership @relation(fields: [membershipId], references: [id])
|
|
originAssessment BodyPortraitAssessment? @relation(fields: [originAssessmentId], references: [id])
|
|
qualifiedInviteReferrals InviteReferral[]
|
|
professionalAssessments ProfessionalAssessmentSession[]
|
|
|
|
review BookingReview?
|
|
memberNotes MemberNote[]
|
|
reviewReminderDueAt DateTime? @map("review_reminder_due_at")
|
|
reviewReminderClaimedAt DateTime? @map("review_reminder_claimed_at")
|
|
reviewReminderSentAt DateTime? @map("review_reminder_sent_at")
|
|
classReminderDueAt DateTime? @map("class_reminder_due_at")
|
|
classReminderClaimedAt DateTime? @map("class_reminder_claimed_at")
|
|
classReminderSentAt DateTime? @map("class_reminder_sent_at")
|
|
statusHistory BookingStatusHistory[]
|
|
|
|
@@unique([userId, timeSlotId])
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@index([originAssessmentId])
|
|
@@map("bookings")
|
|
}
|
|
|
|
model BookingStatusHistory {
|
|
id String @id @default(uuid())
|
|
bookingId String @map("booking_id")
|
|
fromStatus String? @map("from_status")
|
|
toStatus String @map("to_status")
|
|
operatorId String? @map("operator_id")
|
|
remark String?
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
booking Booking @relation(fields: [bookingId], references: [id])
|
|
|
|
@@index([bookingId])
|
|
@@map("booking_status_history")
|
|
}
|
|
|
|
model Order {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
cardTypeId String @map("card_type_id")
|
|
membershipId String? @map("membership_id")
|
|
orderNo String @unique @map("order_no")
|
|
inviteInviterId String? @map("invite_inviter_id")
|
|
purchasedCategory String? @map("purchased_category")
|
|
amount Decimal @db.Decimal(10, 0)
|
|
status OrderStatus @default(PENDING)
|
|
wxTransactionId String? @map("wx_transaction_id")
|
|
paidAt DateTime? @map("paid_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
cardType CardType @relation(fields: [cardTypeId], references: [id])
|
|
membership Membership? @relation(fields: [membershipId], references: [id])
|
|
inviteReferrals InviteReferral[]
|
|
|
|
@@index([userId])
|
|
@@index([status])
|
|
@@index([membershipId])
|
|
@@map("orders")
|
|
}
|
|
|
|
model InviteReferral {
|
|
id String @id @default(uuid())
|
|
inviterId String @map("inviter_id")
|
|
inviteeId String @unique @map("invitee_id")
|
|
status InviteReferralStatus @default(REGISTERED)
|
|
trialOrderId String? @unique @map("trial_order_id")
|
|
qualifiedBookingId String? @unique @map("qualified_booking_id")
|
|
invitedAt DateTime @default(now()) @map("invited_at")
|
|
trialPurchasedAt DateTime? @map("trial_purchased_at")
|
|
qualifiedAt DateTime? @map("qualified_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
inviter User @relation("InviteReferralInviter", fields: [inviterId], references: [id])
|
|
invitee User @relation("InviteReferralInvitee", fields: [inviteeId], references: [id])
|
|
trialOrder Order? @relation(fields: [trialOrderId], references: [id])
|
|
qualifiedBooking Booking? @relation(fields: [qualifiedBookingId], references: [id])
|
|
|
|
@@unique([inviterId, inviteeId])
|
|
@@index([inviterId, status])
|
|
@@index([status])
|
|
@@map("invite_referrals")
|
|
}
|
|
|
|
model InviteRewardGrant {
|
|
id String @id @default(uuid())
|
|
inviterId String @map("inviter_id")
|
|
membershipId String? @map("membership_id")
|
|
qualifiedReferralCount Int @map("qualified_referral_count")
|
|
rewardTimes Int @default(1) @map("reward_times")
|
|
grantedAt DateTime @default(now()) @map("granted_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
inviter User @relation("InviteRewardGrantInviter", fields: [inviterId], references: [id])
|
|
membership Membership? @relation(fields: [membershipId], references: [id], onDelete: Restrict)
|
|
|
|
@@index([inviterId, grantedAt])
|
|
@@map("invite_reward_grants")
|
|
}
|
|
|
|
model StudioConfig {
|
|
id String @id @default(uuid())
|
|
name String
|
|
logo String?
|
|
bannerUrl String? @map("banner_url")
|
|
address String @default("")
|
|
phone String @default("")
|
|
latitude Decimal? @db.Decimal(10, 7)
|
|
longitude Decimal? @db.Decimal(10, 7)
|
|
cancelHoursLimit Int @default(2) @map("cancel_hours_limit")
|
|
photos Json @default("[]")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
@@map("studio_config")
|
|
}
|
|
|
|
// Historical totals without fabricated scheduled dates.
|
|
model LessonSupplement {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
requestId String @map("request_id") @db.VarChar(80)
|
|
quantity Int
|
|
membershipId String? @map("membership_id")
|
|
deductedTimes Int @default(0) @map("deducted_times")
|
|
cardName String? @map("card_name")
|
|
remark String? @db.VarChar(200)
|
|
operatorId String @map("operator_id")
|
|
operatorName String @map("operator_name")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
revokedAt DateTime? @map("revoked_at")
|
|
revokedBy String? @map("revoked_by")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
membership Membership? @relation(fields: [membershipId], references: [id], onDelete: Restrict)
|
|
|
|
@@unique([userId, requestId])
|
|
@@index([userId, revokedAt, createdAt])
|
|
@@map("lesson_supplements")
|
|
}
|
|
|
|
model BookingReview {
|
|
id String @id @default(uuid())
|
|
bookingId String @unique @map("booking_id")
|
|
rating Int
|
|
recommendation Int?
|
|
tags Json
|
|
comment String @db.VarChar(200)
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
booking Booking @relation(fields: [bookingId], references: [id])
|
|
@@index([createdAt])
|
|
@@map("booking_reviews")
|
|
}
|
|
|
|
model BodyMetric {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
recordedAt DateTime @db.Date @map("recorded_at")
|
|
weight Float?
|
|
bodyFat Float? @map("body_fat")
|
|
waist Float?
|
|
hip Float?
|
|
flexibility Float?
|
|
remark String @default("") @db.VarChar(200)
|
|
operatorId String @map("operator_id")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
user User @relation(fields: [userId], references: [id])
|
|
@@index([userId, recordedAt])
|
|
@@map("body_metrics")
|
|
}
|
|
|
|
model MemberNote {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
bookingId String? @map("booking_id")
|
|
content String @db.VarChar(1000)
|
|
shared Boolean @default(false)
|
|
operatorId String @map("operator_id")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
user User @relation(fields: [userId], references: [id])
|
|
booking Booking? @relation(fields: [bookingId], references: [id])
|
|
@@index([userId, createdAt])
|
|
@@map("member_notes")
|
|
}
|
|
|
|
model ProgressPhoto {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
objectKey String @unique @map("object_key")
|
|
caption String @default("") @db.VarChar(200)
|
|
recordedAt DateTime @db.Date @map("recorded_at")
|
|
uploadedAt DateTime? @map("uploaded_at")
|
|
consentedAt DateTime? @map("consented_at")
|
|
revokedAt DateTime? @map("revoked_at")
|
|
operatorId String @map("operator_id")
|
|
angle String? @db.VarChar(16)
|
|
sessionId String? @map("session_id")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
user User @relation(fields: [userId], references: [id])
|
|
session ProfessionalAssessmentSession? @relation(fields: [sessionId], references: [id])
|
|
@@index([userId, recordedAt])
|
|
@@index([sessionId])
|
|
@@map("progress_photos")
|
|
}
|
|
|
|
model BodyPortraitVisit {
|
|
id String @id @default(uuid())
|
|
tokenHash String @unique @map("token_hash") @db.VarChar(64)
|
|
source String @default("organic") @db.VarChar(32)
|
|
campaignId String? @map("campaign_id") @db.VarChar(40)
|
|
referralCode String? @map("referral_code") @db.VarChar(12)
|
|
referrerUserId String? @map("referrer_user_id")
|
|
landingPath String @default("") @map("landing_path") @db.VarChar(120)
|
|
userId String? @map("user_id")
|
|
firstSeenAt DateTime @default(now()) @map("first_seen_at")
|
|
lastSeenAt DateTime @default(now()) @map("last_seen_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
user User? @relation("PortraitVisitUser", fields: [userId], references: [id])
|
|
referrer User? @relation("PortraitReferrer", fields: [referrerUserId], references: [id])
|
|
assessments BodyPortraitAssessment[]
|
|
events GrowthEvent[]
|
|
|
|
@@index([source, createdAt])
|
|
@@index([userId])
|
|
@@map("body_portrait_visits")
|
|
}
|
|
|
|
model BodyPortraitAssessment {
|
|
id String @id @default(uuid())
|
|
visitId String @map("visit_id")
|
|
userId String? @map("user_id")
|
|
tokenHash String @unique @map("token_hash") @db.VarChar(64)
|
|
questionnaireVersion String @map("questionnaire_version") @db.VarChar(32)
|
|
rulesVersion String @map("rules_version") @db.VarChar(32)
|
|
status String @default("DRAFT") @db.VarChar(16)
|
|
answers Json @default("{}")
|
|
safetyFlagged Boolean @default(false) @map("safety_flagged")
|
|
report Json?
|
|
completedAt DateTime? @map("completed_at")
|
|
claimedAt DateTime? @map("claimed_at")
|
|
expiresAt DateTime @map("expires_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
visit BodyPortraitVisit @relation(fields: [visitId], references: [id])
|
|
user User? @relation(fields: [userId], references: [id])
|
|
bookings Booking[]
|
|
growthLeads GrowthLead[]
|
|
events GrowthEvent[]
|
|
professionalAssessments ProfessionalAssessmentSession[]
|
|
|
|
@@index([visitId])
|
|
@@index([userId, createdAt])
|
|
@@index([status, expiresAt])
|
|
@@map("body_portrait_assessments")
|
|
}
|
|
|
|
model GrowthLead {
|
|
id String @id @default(uuid())
|
|
userId String @unique @map("user_id")
|
|
latestAssessmentId String? @map("latest_assessment_id")
|
|
stage String @default("CLAIMED") @db.VarChar(32)
|
|
source String? @db.VarChar(32)
|
|
campaignId String? @map("campaign_id") @db.VarChar(40)
|
|
lastActiveAt DateTime @default(now()) @map("last_active_at")
|
|
coachNote String @default("") @map("coach_note") @db.VarChar(500)
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
latestAssessment BodyPortraitAssessment? @relation(fields: [latestAssessmentId], references: [id])
|
|
|
|
@@index([stage, lastActiveAt])
|
|
@@map("growth_leads")
|
|
}
|
|
|
|
model GrowthEvent {
|
|
id String @id @default(uuid())
|
|
name String @db.VarChar(40)
|
|
idempotencyKey String @unique @map("idempotency_key") @db.VarChar(120)
|
|
visitId String? @map("visit_id")
|
|
assessmentId String? @map("assessment_id")
|
|
userId String? @map("user_id")
|
|
properties Json @default("{}")
|
|
occurredAt DateTime @default(now()) @map("occurred_at")
|
|
|
|
visit BodyPortraitVisit? @relation(fields: [visitId], references: [id])
|
|
assessment BodyPortraitAssessment? @relation(fields: [assessmentId], references: [id])
|
|
user User? @relation(fields: [userId], references: [id])
|
|
|
|
@@index([name, occurredAt])
|
|
@@index([userId, occurredAt])
|
|
@@map("growth_events")
|
|
}
|
|
|
|
model ProfessionalAssessmentSession {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
kind String @db.VarChar(16)
|
|
protocolVersion String @default("offline-v1") @map("protocol_version") @db.VarChar(32)
|
|
recordedAt DateTime @db.Date @map("recorded_at")
|
|
bookingId String? @map("booking_id")
|
|
originAssessmentId String? @map("origin_assessment_id")
|
|
observations Json
|
|
subjectiveTension Float? @map("subjective_tension")
|
|
coachSummary String @default("") @map("coach_summary") @db.VarChar(1000)
|
|
trainingFocus String @default("") @map("training_focus") @db.VarChar(500)
|
|
phaseGoal String @default("") @map("phase_goal") @db.VarChar(500)
|
|
photoAngle String? @map("photo_angle") @db.VarChar(16)
|
|
operatorId String @map("operator_id")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
booking Booking? @relation(fields: [bookingId], references: [id])
|
|
originAssessment BodyPortraitAssessment? @relation(fields: [originAssessmentId], references: [id])
|
|
photos ProgressPhoto[]
|
|
trainingPlans TrainingPlan[]
|
|
|
|
@@index([userId, recordedAt])
|
|
@@map("professional_assessment_sessions")
|
|
}
|
|
|
|
model TrainingPlan {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
sessionId String? @map("session_id")
|
|
title String @db.VarChar(80)
|
|
status String @default("ACTIVE") @db.VarChar(16)
|
|
weeks Int @default(12)
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
updatedAt DateTime @updatedAt @map("updated_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
session ProfessionalAssessmentSession? @relation(fields: [sessionId], references: [id])
|
|
phases TrainingPlanPhase[]
|
|
todos ReassessmentTodo[]
|
|
shares GrowthShareCard[]
|
|
|
|
@@index([userId, createdAt])
|
|
@@map("training_plans")
|
|
}
|
|
|
|
model TrainingPlanPhase {
|
|
id String @id @default(uuid())
|
|
planId String @map("plan_id")
|
|
name String @db.VarChar(40)
|
|
lessonStart Int @map("lesson_start")
|
|
lessonEnd Int @map("lesson_end")
|
|
focus Json
|
|
summary String @default("") @db.VarChar(300)
|
|
sortOrder Int @default(0) @map("sort_order")
|
|
|
|
plan TrainingPlan @relation(fields: [planId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([planId])
|
|
@@map("training_plan_phases")
|
|
}
|
|
|
|
model ReassessmentTodo {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
planId String @map("plan_id")
|
|
lessonCheckpoint Int @map("lesson_checkpoint")
|
|
dueAt DateTime @map("due_at")
|
|
completedAt DateTime? @map("completed_at")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
plan TrainingPlan @relation(fields: [planId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([planId, lessonCheckpoint])
|
|
@@index([userId, completedAt])
|
|
@@map("reassessment_todos")
|
|
}
|
|
|
|
model GrowthShareCard {
|
|
id String @id @default(uuid())
|
|
userId String @map("user_id")
|
|
planId String? @map("plan_id")
|
|
shareCode String @unique @map("share_code") @db.VarChar(12)
|
|
title String @db.VarChar(80)
|
|
caption String @db.VarChar(200)
|
|
completedCount Int @map("completed_count")
|
|
weeks Int @default(12)
|
|
rows Json
|
|
includePhotos Boolean @default(false) @map("include_photos")
|
|
createdAt DateTime @default(now()) @map("created_at")
|
|
|
|
user User @relation(fields: [userId], references: [id])
|
|
plan TrainingPlan? @relation(fields: [planId], references: [id])
|
|
|
|
@@index([userId, createdAt])
|
|
@@map("growth_share_cards")
|
|
}
|