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:
@@ -0,0 +1,247 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "RoutineTaskStatus" AS ENUM ('todo', 'in_progress', 'completed', 'overdue', 'skipped', 'cancelled');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "RoutineRecurrence" AS ENUM ('daily', 'weekdays', 'weekly', 'biweekly', 'monthly', 'every_n_days', 'specific_dates');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "RoutineTaskSource" AS ENUM ('routine', 'manual', 'follow_up', 'lead', 'customer', 'deal');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "RoutineCategory" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"color" TEXT NOT NULL DEFAULT '#14b8a6',
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "RoutineCategory_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Routine" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"assigneeId" TEXT,
|
||||
"teamId" TEXT,
|
||||
"categoryId" TEXT,
|
||||
"priority" "ActivityPriority" NOT NULL DEFAULT 'medium',
|
||||
"timeOfDay" TEXT NOT NULL DEFAULT '09:00',
|
||||
"durationMinutes" INTEGER,
|
||||
"startDate" DATE NOT NULL,
|
||||
"endDate" DATE,
|
||||
"recurrence" "RoutineRecurrence" NOT NULL DEFAULT 'daily',
|
||||
"weekdays" INTEGER[] DEFAULT ARRAY[]::INTEGER[],
|
||||
"intervalDays" INTEGER,
|
||||
"monthDay" INTEGER,
|
||||
"specificDates" DATE[],
|
||||
"isMandatory" BOOLEAN NOT NULL DEFAULT true,
|
||||
"allowSkip" BOOLEAN NOT NULL DEFAULT false,
|
||||
"skipReasonRequired" BOOLEAN NOT NULL DEFAULT true,
|
||||
"reportRequired" BOOLEAN NOT NULL DEFAULT false,
|
||||
"allowAfterDeadline" BOOLEAN NOT NULL DEFAULT true,
|
||||
"carryOverOverdue" BOOLEAN NOT NULL DEFAULT false,
|
||||
"entityLink" TEXT NOT NULL DEFAULT 'none',
|
||||
"reminderMinutesBefore" INTEGER,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdById" TEXT,
|
||||
"deletedAt" TIMESTAMP(3),
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Routine_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "RoutineTask" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"routineId" TEXT,
|
||||
"assigneeId" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"categoryId" TEXT,
|
||||
"priority" "ActivityPriority" NOT NULL DEFAULT 'medium',
|
||||
"status" "RoutineTaskStatus" NOT NULL DEFAULT 'todo',
|
||||
"scheduledFor" DATE NOT NULL,
|
||||
"dueAt" TIMESTAMP(3),
|
||||
"startedAt" TIMESTAMP(3),
|
||||
"completedAt" TIMESTAMP(3),
|
||||
"resultNote" TEXT,
|
||||
"skipReason" TEXT,
|
||||
"source" "RoutineTaskSource" NOT NULL DEFAULT 'manual',
|
||||
"isMandatory" BOOLEAN NOT NULL DEFAULT false,
|
||||
"leadId" TEXT,
|
||||
"personId" TEXT,
|
||||
"companyId" TEXT,
|
||||
"dealId" TEXT,
|
||||
"invoiceId" TEXT,
|
||||
"activityId" TEXT,
|
||||
"reminderAt" TIMESTAMP(3),
|
||||
"reminderSentAt" TIMESTAMP(3),
|
||||
"overdueNotifiedAt" TIMESTAMP(3),
|
||||
"createdById" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "RoutineTask_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "RoutineTaskEvent" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"taskId" TEXT NOT NULL,
|
||||
"actorId" TEXT,
|
||||
"type" TEXT NOT NULL,
|
||||
"fromStatus" "RoutineTaskStatus",
|
||||
"toStatus" "RoutineTaskStatus",
|
||||
"note" TEXT,
|
||||
"meta" JSONB NOT NULL DEFAULT '{}',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "RoutineTaskEvent_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "RoutineUserSettings" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"remindBeforeMinutes" INTEGER DEFAULT 30,
|
||||
"endOfDaySummary" BOOLEAN NOT NULL DEFAULT true,
|
||||
"overdueAlert" BOOLEAN NOT NULL DEFAULT true,
|
||||
"summaryHour" INTEGER NOT NULL DEFAULT 16,
|
||||
"lastSummaryOn" DATE,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "RoutineUserSettings_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineCategory_organizationId_sortOrder_idx" ON "RoutineCategory"("organizationId", "sortOrder");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "RoutineCategory_organizationId_name_key" ON "RoutineCategory"("organizationId", "name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Routine_organizationId_isActive_deletedAt_idx" ON "Routine"("organizationId", "isActive", "deletedAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Routine_assigneeId_idx" ON "Routine"("assigneeId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Routine_teamId_idx" ON "Routine"("teamId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_organizationId_assigneeId_scheduledFor_idx" ON "RoutineTask"("organizationId", "assigneeId", "scheduledFor");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_organizationId_status_dueAt_idx" ON "RoutineTask"("organizationId", "status", "dueAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_reminderAt_reminderSentAt_idx" ON "RoutineTask"("reminderAt", "reminderSentAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_leadId_idx" ON "RoutineTask"("leadId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_personId_idx" ON "RoutineTask"("personId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_companyId_idx" ON "RoutineTask"("companyId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_dealId_idx" ON "RoutineTask"("dealId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTask_activityId_idx" ON "RoutineTask"("activityId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "RoutineTask_routineId_assigneeId_scheduledFor_key" ON "RoutineTask"("routineId", "assigneeId", "scheduledFor");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTaskEvent_taskId_createdAt_idx" ON "RoutineTaskEvent"("taskId", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "RoutineTaskEvent_organizationId_createdAt_idx" ON "RoutineTaskEvent"("organizationId", "createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "RoutineUserSettings_organizationId_userId_key" ON "RoutineUserSettings"("organizationId", "userId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineCategory" ADD CONSTRAINT "RoutineCategory_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Routine" ADD CONSTRAINT "Routine_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Routine" ADD CONSTRAINT "Routine_assigneeId_fkey" FOREIGN KEY ("assigneeId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Routine" ADD CONSTRAINT "Routine_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "Team"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Routine" ADD CONSTRAINT "Routine_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "RoutineCategory"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Routine" ADD CONSTRAINT "Routine_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_routineId_fkey" FOREIGN KEY ("routineId") REFERENCES "Routine"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_assigneeId_fkey" FOREIGN KEY ("assigneeId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "RoutineCategory"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_leadId_fkey" FOREIGN KEY ("leadId") REFERENCES "Lead"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_personId_fkey" FOREIGN KEY ("personId") REFERENCES "Person"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_companyId_fkey" FOREIGN KEY ("companyId") REFERENCES "Company"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_dealId_fkey" FOREIGN KEY ("dealId") REFERENCES "Deal"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_invoiceId_fkey" FOREIGN KEY ("invoiceId") REFERENCES "Invoice"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_activityId_fkey" FOREIGN KEY ("activityId") REFERENCES "Activity"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTask" ADD CONSTRAINT "RoutineTask_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTaskEvent" ADD CONSTRAINT "RoutineTaskEvent_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTaskEvent" ADD CONSTRAINT "RoutineTaskEvent_taskId_fkey" FOREIGN KEY ("taskId") REFERENCES "RoutineTask"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineTaskEvent" ADD CONSTRAINT "RoutineTaskEvent_actorId_fkey" FOREIGN KEY ("actorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineUserSettings" ADD CONSTRAINT "RoutineUserSettings_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "RoutineUserSettings" ADD CONSTRAINT "RoutineUserSettings_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
|
||||
-- Enable the new routines module for organizations with an explicit module list
|
||||
UPDATE "Organization"
|
||||
SET "enabledModules" = array_append("enabledModules", 'routines')
|
||||
WHERE cardinality("enabledModules") > 0 AND NOT ('routines' = ANY("enabledModules"));
|
||||
@@ -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