Initial Mento CRM: portal OTP, reports, SMS, and deploy for crm.montzar.ir.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,738 @@
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum UserRole {
|
||||
owner
|
||||
admin
|
||||
sales
|
||||
support
|
||||
}
|
||||
|
||||
enum DealStatus {
|
||||
open
|
||||
won
|
||||
lost
|
||||
}
|
||||
|
||||
enum ActivityType {
|
||||
call
|
||||
meeting
|
||||
task
|
||||
note
|
||||
}
|
||||
|
||||
enum ActivityStatus {
|
||||
open
|
||||
done
|
||||
canceled
|
||||
}
|
||||
|
||||
enum CustomFieldEntity {
|
||||
person
|
||||
company
|
||||
deal
|
||||
}
|
||||
|
||||
enum CustomFieldType {
|
||||
text
|
||||
number
|
||||
date
|
||||
boolean
|
||||
select
|
||||
}
|
||||
|
||||
enum QuoteStatus {
|
||||
draft
|
||||
sent
|
||||
accepted
|
||||
rejected
|
||||
expired
|
||||
}
|
||||
|
||||
enum InvoiceStatus {
|
||||
draft
|
||||
issued
|
||||
partially_paid
|
||||
paid
|
||||
canceled
|
||||
}
|
||||
|
||||
enum PaymentMethod {
|
||||
cash
|
||||
transfer
|
||||
card
|
||||
check
|
||||
other
|
||||
}
|
||||
|
||||
enum InstallmentStatus {
|
||||
pending
|
||||
paid
|
||||
canceled
|
||||
}
|
||||
|
||||
enum TicketStatus {
|
||||
open
|
||||
in_progress
|
||||
waiting
|
||||
resolved
|
||||
closed
|
||||
}
|
||||
|
||||
enum TicketPriority {
|
||||
low
|
||||
normal
|
||||
high
|
||||
urgent
|
||||
}
|
||||
|
||||
model Organization {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
slug String @unique
|
||||
baseCurrency String @default("IRR")
|
||||
enabledCurrencies String[] @default(["IRR", "USD", "EUR"])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
users User[]
|
||||
companies Company[]
|
||||
people Person[]
|
||||
pipelines Pipeline[]
|
||||
deals Deal[]
|
||||
activities Activity[]
|
||||
notes Note[]
|
||||
customFields CustomFieldDefinition[]
|
||||
products Product[]
|
||||
notifications Notification[]
|
||||
noteAttachments NoteAttachment[]
|
||||
leadForms LeadForm[]
|
||||
quotes Quote[]
|
||||
invoices Invoice[]
|
||||
salesGoals SalesGoal[]
|
||||
exchangeRates ExchangeRate[]
|
||||
tickets Ticket[]
|
||||
faqArticles FaqArticle[]
|
||||
portalOtps PortalOtp[]
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String
|
||||
passwordHash String
|
||||
fullName String
|
||||
role UserRole @default(sales)
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
ownedDeals Deal[] @relation("DealOwner")
|
||||
ownedQuotes Quote[] @relation("QuoteOwner")
|
||||
ownedInvoices Invoice[] @relation("InvoiceOwner")
|
||||
ownedPeople Person[] @relation("PersonOwner")
|
||||
ownedCompanies Company[] @relation("CompanyOwner")
|
||||
activities Activity[] @relation("ActivityAssignee")
|
||||
notes Note[] @relation("NoteAuthor")
|
||||
noteAttachments NoteAttachment[] @relation("NoteAttachmentUploader")
|
||||
notifications Notification[]
|
||||
salesGoals SalesGoal[] @relation("SalesGoalUser")
|
||||
assignedTickets Ticket[] @relation("TicketAssignee")
|
||||
reportedTickets Ticket[] @relation("TicketReporter")
|
||||
ticketMessages TicketMessage[] @relation("TicketMessageAuthor")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([organizationId, email])
|
||||
@@index([organizationId])
|
||||
}
|
||||
|
||||
model Company {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
nationalId String?
|
||||
phone String?
|
||||
email String?
|
||||
website String?
|
||||
address String?
|
||||
notes String?
|
||||
customFields Json @default("{}")
|
||||
people Person[]
|
||||
deals Deal[]
|
||||
activities Activity[]
|
||||
smartNotes Note[]
|
||||
quotes Quote[]
|
||||
invoices Invoice[]
|
||||
ownerId String?
|
||||
owner User? @relation("CompanyOwner", fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
tickets Ticket[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId])
|
||||
@@index([organizationId, name])
|
||||
@@index([organizationId, email])
|
||||
@@index([organizationId, phone])
|
||||
@@index([ownerId])
|
||||
}
|
||||
|
||||
model Person {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
companyId String?
|
||||
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
|
||||
firstName String
|
||||
lastName String
|
||||
email String?
|
||||
phone String?
|
||||
mobile String?
|
||||
position String?
|
||||
notes String?
|
||||
customFields Json @default("{}")
|
||||
deals Deal[]
|
||||
activities Activity[]
|
||||
smartNotes Note[]
|
||||
quotes Quote[]
|
||||
invoices Invoice[]
|
||||
ownerId String?
|
||||
owner User? @relation("PersonOwner", fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
tickets Ticket[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId])
|
||||
@@index([organizationId, email])
|
||||
@@index([organizationId, mobile])
|
||||
@@index([organizationId, lastName, firstName])
|
||||
@@index([companyId])
|
||||
@@index([ownerId])
|
||||
}
|
||||
|
||||
model Pipeline {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
isDefault Boolean @default(false)
|
||||
stages PipelineStage[]
|
||||
deals Deal[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId])
|
||||
@@index([organizationId, isDefault])
|
||||
}
|
||||
|
||||
model PipelineStage {
|
||||
id String @id @default(cuid())
|
||||
pipelineId String
|
||||
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
position Int
|
||||
isWon Boolean @default(false)
|
||||
isLost Boolean @default(false)
|
||||
deals Deal[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([pipelineId, position])
|
||||
}
|
||||
|
||||
model Deal {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
pipelineId String
|
||||
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
|
||||
stageId String
|
||||
stage PipelineStage @relation(fields: [stageId], references: [id], onDelete: Restrict)
|
||||
title String
|
||||
amount Decimal? @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
status DealStatus @default(open)
|
||||
source String?
|
||||
lostReason String?
|
||||
notes String?
|
||||
tags String[] @default([])
|
||||
isStale Boolean @default(false)
|
||||
isRotten Boolean @default(false)
|
||||
customFields Json @default("{}")
|
||||
expectedCloseAt DateTime?
|
||||
personId String?
|
||||
person Person? @relation(fields: [personId], references: [id], onDelete: SetNull)
|
||||
companyId String?
|
||||
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
|
||||
ownerId String?
|
||||
owner User? @relation("DealOwner", fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
position Int @default(0)
|
||||
activities Activity[]
|
||||
smartNotes Note[]
|
||||
lineItems DealLineItem[]
|
||||
quotes Quote[]
|
||||
invoices Invoice[]
|
||||
tickets Ticket[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId])
|
||||
@@index([pipelineId, stageId])
|
||||
@@index([stageId, position])
|
||||
@@index([personId])
|
||||
@@index([companyId])
|
||||
@@index([ownerId])
|
||||
}
|
||||
|
||||
model Activity {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
type ActivityType @default(task)
|
||||
status ActivityStatus @default(open)
|
||||
title String
|
||||
description String?
|
||||
dueAt DateTime?
|
||||
completedAt DateTime?
|
||||
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)
|
||||
assigneeId String?
|
||||
assignee User? @relation("ActivityAssignee", fields: [assigneeId], references: [id], onDelete: SetNull)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId, status, dueAt])
|
||||
@@index([organizationId, assigneeId])
|
||||
@@index([personId])
|
||||
@@index([companyId])
|
||||
@@index([dealId])
|
||||
}
|
||||
|
||||
model Note {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
title String?
|
||||
body String
|
||||
noteType String @default("general")
|
||||
pinned Boolean @default(false)
|
||||
color String? @default("default")
|
||||
tags String[] @default([])
|
||||
reminderAt DateTime?
|
||||
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)
|
||||
authorId String?
|
||||
author User? @relation("NoteAuthor", fields: [authorId], references: [id], onDelete: SetNull)
|
||||
attachments NoteAttachment[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId, pinned, updatedAt])
|
||||
@@index([organizationId, noteType, updatedAt])
|
||||
@@index([organizationId, reminderAt])
|
||||
@@index([personId])
|
||||
@@index([companyId])
|
||||
@@index([dealId])
|
||||
@@index([authorId])
|
||||
}
|
||||
|
||||
model NoteAttachment {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
noteId String
|
||||
note Note @relation(fields: [noteId], references: [id], onDelete: Cascade)
|
||||
fileName String
|
||||
mimeType String
|
||||
sizeBytes Int
|
||||
storageKey String
|
||||
uploadedById String?
|
||||
uploadedBy User? @relation("NoteAttachmentUploader", fields: [uploadedById], references: [id], onDelete: SetNull)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([noteId, createdAt])
|
||||
@@index([organizationId])
|
||||
@@index([uploadedById])
|
||||
}
|
||||
|
||||
model CustomFieldDefinition {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
entityType CustomFieldEntity
|
||||
key String
|
||||
label String
|
||||
fieldType CustomFieldType @default(text)
|
||||
options String[] @default([])
|
||||
required Boolean @default(false)
|
||||
position Int @default(0)
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([organizationId, entityType, key])
|
||||
@@index([organizationId, entityType, position])
|
||||
}
|
||||
|
||||
model Product {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
sku String?
|
||||
description String?
|
||||
unitPrice Decimal? @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
isActive Boolean @default(true)
|
||||
lineItems DealLineItem[]
|
||||
quoteLineItems QuoteLineItem[]
|
||||
invoiceLineItems InvoiceLineItem[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId, name])
|
||||
@@index([organizationId, isActive])
|
||||
}
|
||||
|
||||
model DealLineItem {
|
||||
id String @id @default(cuid())
|
||||
dealId String
|
||||
deal Deal @relation(fields: [dealId], references: [id], onDelete: Cascade)
|
||||
productId String?
|
||||
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
||||
name String
|
||||
quantity Decimal @default(1) @db.Decimal(18, 2)
|
||||
unitPrice Decimal @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
position Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([dealId, position])
|
||||
@@index([productId])
|
||||
}
|
||||
|
||||
model Notification {
|
||||
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)
|
||||
type String
|
||||
title String
|
||||
body String?
|
||||
link String?
|
||||
entityType String?
|
||||
entityId String?
|
||||
readAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([userId, readAt, createdAt])
|
||||
@@index([organizationId, createdAt])
|
||||
@@index([userId, type, entityId])
|
||||
}
|
||||
|
||||
model LeadForm {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
name String
|
||||
publicToken String @unique @default(cuid())
|
||||
isActive Boolean @default(true)
|
||||
createPerson Boolean @default(true)
|
||||
createDeal Boolean @default(true)
|
||||
pipelineId String?
|
||||
source String?
|
||||
thankYouMessage String?
|
||||
redirectUrl String?
|
||||
assigneeIds String[] @default([])
|
||||
roundRobinIndex Int @default(0)
|
||||
fields LeadFormField[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId, updatedAt])
|
||||
}
|
||||
|
||||
model LeadFormField {
|
||||
id String @id @default(cuid())
|
||||
formId String
|
||||
form LeadForm @relation(fields: [formId], references: [id], onDelete: Cascade)
|
||||
key String
|
||||
label String
|
||||
fieldType String @default("text")
|
||||
required Boolean @default(false)
|
||||
mapTo String
|
||||
position Int @default(0)
|
||||
|
||||
@@unique([formId, key])
|
||||
@@index([formId, position])
|
||||
}
|
||||
|
||||
model Quote {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
number String
|
||||
title String
|
||||
status QuoteStatus @default(draft)
|
||||
currency String @default("IRR")
|
||||
notes String?
|
||||
validUntil DateTime?
|
||||
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)
|
||||
ownerId String?
|
||||
owner User? @relation("QuoteOwner", fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
lineItems QuoteLineItem[]
|
||||
invoices Invoice[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([organizationId, number])
|
||||
@@index([organizationId, status, updatedAt])
|
||||
@@index([personId])
|
||||
@@index([companyId])
|
||||
@@index([dealId])
|
||||
@@index([ownerId])
|
||||
}
|
||||
|
||||
model QuoteLineItem {
|
||||
id String @id @default(cuid())
|
||||
quoteId String
|
||||
quote Quote @relation(fields: [quoteId], references: [id], onDelete: Cascade)
|
||||
productId String?
|
||||
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
||||
name String
|
||||
quantity Decimal @default(1) @db.Decimal(18, 2)
|
||||
unitPrice Decimal @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
position Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([quoteId, position])
|
||||
@@index([productId])
|
||||
}
|
||||
|
||||
model Invoice {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
number String
|
||||
title String
|
||||
status InvoiceStatus @default(draft)
|
||||
currency String @default("IRR")
|
||||
notes String?
|
||||
issuedAt DateTime?
|
||||
dueDate DateTime?
|
||||
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)
|
||||
quoteId String?
|
||||
quote Quote? @relation(fields: [quoteId], references: [id], onDelete: SetNull)
|
||||
ownerId String?
|
||||
owner User? @relation("InvoiceOwner", fields: [ownerId], references: [id], onDelete: SetNull)
|
||||
lineItems InvoiceLineItem[]
|
||||
payments Payment[]
|
||||
installments InvoiceInstallment[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([organizationId, number])
|
||||
@@index([organizationId, status, updatedAt])
|
||||
@@index([personId])
|
||||
@@index([companyId])
|
||||
@@index([dealId])
|
||||
@@index([quoteId])
|
||||
@@index([ownerId])
|
||||
}
|
||||
|
||||
model InvoiceLineItem {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
productId String?
|
||||
product Product? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
||||
name String
|
||||
quantity Decimal @default(1) @db.Decimal(18, 2)
|
||||
unitPrice Decimal @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
position Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([invoiceId, position])
|
||||
@@index([productId])
|
||||
}
|
||||
|
||||
model Payment {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
amount Decimal @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
method PaymentMethod @default(transfer)
|
||||
paidAt DateTime @default(now())
|
||||
notes String?
|
||||
installmentId String? @unique
|
||||
installment InvoiceInstallment? @relation(fields: [installmentId], references: [id], onDelete: SetNull)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([invoiceId, paidAt])
|
||||
}
|
||||
|
||||
model InvoiceInstallment {
|
||||
id String @id @default(cuid())
|
||||
invoiceId String
|
||||
invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade)
|
||||
position Int @default(0)
|
||||
dueDate DateTime
|
||||
amount Decimal @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
status InstallmentStatus @default(pending)
|
||||
paidAt DateTime?
|
||||
payment Payment?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([invoiceId, position])
|
||||
@@index([invoiceId, dueDate])
|
||||
@@index([status, dueDate])
|
||||
}
|
||||
|
||||
model SalesGoal {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
/// null = هدف سازمانی / تیمی
|
||||
userId String?
|
||||
user User? @relation("SalesGoalUser", fields: [userId], references: [id], onDelete: Cascade)
|
||||
title String
|
||||
periodStart DateTime
|
||||
periodEnd DateTime
|
||||
targetAmount Decimal @db.Decimal(18, 2)
|
||||
currency String @default("IRR")
|
||||
notes String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId, periodStart, periodEnd])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model ExchangeRate {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
/// ارز مبدأ؛ ۱ واحد این ارز = rateToBase واحد ارز پایه
|
||||
currency String
|
||||
rateToBase Decimal @db.Decimal(24, 6)
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([organizationId, currency])
|
||||
@@index([organizationId])
|
||||
}
|
||||
|
||||
model Ticket {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
number String
|
||||
subject String
|
||||
description String?
|
||||
status TicketStatus @default(open)
|
||||
priority TicketPriority @default(normal)
|
||||
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)
|
||||
assigneeId String?
|
||||
assignee User? @relation("TicketAssignee", fields: [assigneeId], references: [id], onDelete: SetNull)
|
||||
reporterId String?
|
||||
reporter User? @relation("TicketReporter", fields: [reporterId], references: [id], onDelete: SetNull)
|
||||
resolvedAt DateTime?
|
||||
/// مهلت پاسخ اول بر اساس اولویت
|
||||
slaDueAt DateTime?
|
||||
firstRespondedAt DateTime?
|
||||
csatScore Int?
|
||||
csatComment String?
|
||||
csatAt DateTime?
|
||||
messages TicketMessage[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([organizationId, number])
|
||||
@@index([organizationId, status, updatedAt])
|
||||
@@index([organizationId, slaDueAt])
|
||||
@@index([assigneeId])
|
||||
@@index([reporterId])
|
||||
@@index([personId])
|
||||
@@index([companyId])
|
||||
@@index([dealId])
|
||||
}
|
||||
|
||||
model TicketMessage {
|
||||
id String @id @default(cuid())
|
||||
ticketId String
|
||||
ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade)
|
||||
authorId String?
|
||||
author User? @relation("TicketMessageAuthor", fields: [authorId], references: [id], onDelete: SetNull)
|
||||
body String
|
||||
isInternal Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([ticketId, createdAt])
|
||||
@@index([authorId])
|
||||
}
|
||||
|
||||
model FaqArticle {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
question String
|
||||
answer String
|
||||
category String?
|
||||
isPublished Boolean @default(true)
|
||||
position Int @default(0)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId, isPublished, position])
|
||||
}
|
||||
|
||||
/// کد یکبارمصرف ورود پرتال مشتری (موبایل)
|
||||
model PortalOtp {
|
||||
id String @id @default(cuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
mobile String
|
||||
code String
|
||||
expiresAt DateTime
|
||||
consumedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([organizationId, mobile, createdAt])
|
||||
@@index([expiresAt])
|
||||
}
|
||||
Reference in New Issue
Block a user