feat: routines module; super admin subscription badge, 7-day trial and lifetime plan
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -218,6 +218,11 @@ model Organization {
|
||||
conversationMessageReactions ConversationMessageReaction[]
|
||||
trackingLinks TrackingLink[]
|
||||
trackingEvents TrackingEvent[]
|
||||
routineCategories RoutineCategory[]
|
||||
routines Routine[]
|
||||
routineTasks RoutineTask[]
|
||||
routineTaskEvents RoutineTaskEvent[]
|
||||
routineUserSettings RoutineUserSettings[]
|
||||
}
|
||||
|
||||
model User {
|
||||
@@ -271,6 +276,12 @@ model User {
|
||||
reservationAssignments ReservationAppointment[] @relation("ReservationAssignee")
|
||||
assignedLeads Lead[] @relation("LeadAssignee")
|
||||
createdLeads Lead[] @relation("LeadCreator")
|
||||
assignedRoutines Routine[] @relation("RoutineAssignee")
|
||||
createdRoutines Routine[] @relation("RoutineCreator")
|
||||
routineTasks RoutineTask[] @relation("RoutineTaskAssignee")
|
||||
createdRoutineTasks RoutineTask[] @relation("RoutineTaskCreator")
|
||||
routineTaskEvents RoutineTaskEvent[]
|
||||
routineSettings RoutineUserSettings[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -338,6 +349,7 @@ model Team {
|
||||
name String
|
||||
description String @default("")
|
||||
members TeamMember[]
|
||||
routines Routine[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -379,7 +391,7 @@ model BillingAccount {
|
||||
id String @id @default(cuid())
|
||||
ownerUserId String @unique
|
||||
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
|
||||
/// trial | monthly | quarterly | semiannual | yearly | custom
|
||||
/// trial | monthly | quarterly | semiannual | yearly | lifetime | custom
|
||||
planCode String @default("trial")
|
||||
/// active | expired | suspended
|
||||
status String @default("active")
|
||||
@@ -435,6 +447,7 @@ model Company {
|
||||
owner User? @relation("CompanyOwner", fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
tickets Ticket[]
|
||||
projectCards ProjectCard[]
|
||||
routineTasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -503,6 +516,7 @@ model Person {
|
||||
cheques Cheque[]
|
||||
trackingLinks TrackingLink[]
|
||||
trackingEvents TrackingEvent[]
|
||||
routineTasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -601,6 +615,7 @@ model Deal {
|
||||
invoices Invoice[]
|
||||
tickets Ticket[]
|
||||
projectCards ProjectCard[]
|
||||
routineTasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -646,6 +661,7 @@ model Activity {
|
||||
createdById String?
|
||||
createdBy User? @relation("ActivityCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
||||
notes Note[]
|
||||
routineTasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -1023,6 +1039,7 @@ model Invoice {
|
||||
commissionFixedAmount Decimal? @db.Decimal(18, 2)
|
||||
commissionEntry CommissionEntry?
|
||||
cheques Cheque[]
|
||||
routineTasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -2176,6 +2193,7 @@ model Lead {
|
||||
events LeadEvent[]
|
||||
trackingLinks TrackingLink[]
|
||||
trackingEvents TrackingEvent[]
|
||||
routineTasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@ -2361,3 +2379,191 @@ model ConversationMessageReaction {
|
||||
@@unique([organizationId, externalRoomId, messageId, userId, emoji])
|
||||
@@index([organizationId, externalRoomId])
|
||||
}
|
||||
|
||||
enum RoutineTaskStatus {
|
||||
todo
|
||||
in_progress
|
||||
completed
|
||||
overdue
|
||||
skipped
|
||||
cancelled
|
||||
}
|
||||
|
||||
enum RoutineRecurrence {
|
||||
daily
|
||||
weekdays
|
||||
weekly
|
||||
biweekly
|
||||
monthly
|
||||
every_n_days
|
||||
specific_dates
|
||||
}
|
||||
|
||||
enum RoutineTaskSource {
|
||||
routine
|
||||
manual
|
||||
follow_up
|
||||
lead
|
||||
customer
|
||||
deal
|
||||
}
|
||||
|
||||
/// دستهبندی کارهای روتین (فروش، پیگیری، لید، …)
|
||||
model RoutineCategory {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
color String @default("#14b8a6")
|
||||
sortOrder Int @default(0)
|
||||
routines Routine[]
|
||||
tasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([organizationId, name])
|
||||
@@index([organizationId, sortOrder])
|
||||
}
|
||||
|
||||
/// الگوی کار تکرارشونده؛ هر روز Task مستقل (RoutineTask) تولید میکند
|
||||
model Routine {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
description String?
|
||||
assigneeId String?
|
||||
assignee User? @relation("RoutineAssignee", fields: [assigneeId], references: [id], onDelete: SetNull)
|
||||
/// اگر ست باشد برای هر عضو تیم یک Task جدا ساخته میشود
|
||||
teamId String?
|
||||
team Team? @relation(fields: [teamId], references: [id], onDelete: SetNull)
|
||||
categoryId String?
|
||||
category RoutineCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
||||
priority ActivityPriority @default(medium)
|
||||
/// HH:mm به وقت تهران
|
||||
timeOfDay String @default("09:00")
|
||||
durationMinutes Int?
|
||||
startDate DateTime @db.Date
|
||||
endDate DateTime? @db.Date
|
||||
recurrence RoutineRecurrence @default(daily)
|
||||
/// ۰ = شنبه … ۶ = جمعه
|
||||
weekdays Int[] @default([])
|
||||
intervalDays Int?
|
||||
monthDay Int?
|
||||
specificDates DateTime[] @db.Date
|
||||
isMandatory Boolean @default(true)
|
||||
allowSkip Boolean @default(false)
|
||||
skipReasonRequired Boolean @default(true)
|
||||
reportRequired Boolean @default(false)
|
||||
allowAfterDeadline Boolean @default(true)
|
||||
carryOverOverdue Boolean @default(false)
|
||||
/// none | optional | lead | customer
|
||||
entityLink String @default("none")
|
||||
reminderMinutesBefore Int?
|
||||
isActive Boolean @default(true)
|
||||
createdById String?
|
||||
createdBy User? @relation("RoutineCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
||||
deletedAt DateTime?
|
||||
tasks RoutineTask[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId, isActive, deletedAt])
|
||||
@@index([assigneeId])
|
||||
@@index([teamId])
|
||||
}
|
||||
|
||||
/// نمونه روزانه یک کار (از روتین، دستی، پیگیری، لید یا مشتری)
|
||||
model RoutineTask {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
routineId String?
|
||||
routine Routine? @relation(fields: [routineId], references: [id], onDelete: SetNull)
|
||||
assigneeId String
|
||||
assignee User @relation("RoutineTaskAssignee", fields: [assigneeId], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
description String?
|
||||
categoryId String?
|
||||
category RoutineCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull)
|
||||
priority ActivityPriority @default(medium)
|
||||
status RoutineTaskStatus @default(todo)
|
||||
/// روز برنامه به وقت تهران
|
||||
scheduledFor DateTime @db.Date
|
||||
dueAt DateTime?
|
||||
startedAt DateTime?
|
||||
completedAt DateTime?
|
||||
resultNote String?
|
||||
skipReason String?
|
||||
source RoutineTaskSource @default(manual)
|
||||
isMandatory Boolean @default(false)
|
||||
leadId String?
|
||||
lead Lead? @relation(fields: [leadId], references: [id], onDelete: SetNull)
|
||||
personId String?
|
||||
person Person? @relation(fields: [personId], references: [id], onDelete: SetNull)
|
||||
companyId String?
|
||||
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
|
||||
dealId String?
|
||||
deal Deal? @relation(fields: [dealId], references: [id], onDelete: SetNull)
|
||||
invoiceId String?
|
||||
invoice Invoice? @relation(fields: [invoiceId], references: [id], onDelete: SetNull)
|
||||
activityId String?
|
||||
activity Activity? @relation(fields: [activityId], references: [id], onDelete: SetNull)
|
||||
reminderAt DateTime?
|
||||
reminderSentAt DateTime?
|
||||
overdueNotifiedAt DateTime?
|
||||
createdById String?
|
||||
createdBy User? @relation("RoutineTaskCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
||||
events RoutineTaskEvent[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([routineId, assigneeId, scheduledFor])
|
||||
@@index([organizationId, assigneeId, scheduledFor])
|
||||
@@index([organizationId, status, dueAt])
|
||||
@@index([reminderAt, reminderSentAt])
|
||||
@@index([leadId])
|
||||
@@index([personId])
|
||||
@@index([companyId])
|
||||
@@index([dealId])
|
||||
@@index([activityId])
|
||||
}
|
||||
|
||||
/// تاریخچه تغییرات هر Task
|
||||
model RoutineTaskEvent {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
taskId String
|
||||
task RoutineTask @relation(fields: [taskId], references: [id], onDelete: Cascade)
|
||||
actorId String?
|
||||
actor User? @relation(fields: [actorId], references: [id], onDelete: SetNull)
|
||||
/// created | status_changed | rescheduled | note | reassigned | updated
|
||||
type String
|
||||
fromStatus RoutineTaskStatus?
|
||||
toStatus RoutineTaskStatus?
|
||||
note String?
|
||||
meta Json @default("{}")
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([taskId, createdAt])
|
||||
@@index([organizationId, createdAt])
|
||||
}
|
||||
|
||||
/// تنظیمات اعلان کارهای روتین هر کاربر
|
||||
model RoutineUserSettings {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
remindBeforeMinutes Int? @default(30)
|
||||
endOfDaySummary Boolean @default(true)
|
||||
overdueAlert Boolean @default(true)
|
||||
summaryHour Int @default(16)
|
||||
lastSummaryOn DateTime? @db.Date
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([organizationId, userId])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user