Add Didar gap features: lost-reason reports, audit logs, tags, card assignees, and saved-views API.

Ignore Graphify local artifacts and expose new modules in superadmin.
This commit is contained in:
2026-09-26 14:59:48 +03:30
parent 35a618d0af
commit 6463275c3d
30 changed files with 1406 additions and 21 deletions
+51
View File
@@ -192,6 +192,8 @@ model Organization {
partyOpenings PartyOpeningBalance[]
commissionEntries CommissionEntry[]
cheques Cheque[]
auditLogs AuditLog[]
savedViews SavedView[]
}
model User {
@@ -233,6 +235,9 @@ model User {
confirmedMemories MemoryItem[] @relation("MemoryConfirmedBy")
memberships Membership[]
billingAccount BillingAccount?
auditLogs AuditLog[] @relation("AuditLogActor")
savedViews SavedView[] @relation("SavedViewOwner")
assignedProjectCards ProjectCard[] @relation("ProjectCardAssignees")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -329,6 +334,7 @@ model Company {
website String?
address String?
notes String?
tags String[] @default([])
customFields Json @default("{}")
people Person[]
deals Deal[]
@@ -368,6 +374,7 @@ model Person {
referrer String?
notes String?
mood PersonMood @default(newcomer)
tags String[] @default([])
customFields Json @default("{}")
loyaltyPoints Int @default(0)
loyaltyTierId String?
@@ -493,6 +500,7 @@ model Activity {
/// پیامک به موبایل مسئول هنگام رسیدن یادآور
reminderNotifySms Boolean @default(false)
completedAt DateTime?
tags String[] @default([])
personId String?
person Person? @relation(fields: [personId], references: [id], onDelete: SetNull)
companyId String?
@@ -1067,6 +1075,7 @@ model ProjectCard {
stage ProjectBoardStage @relation(fields: [stageId], references: [id], onDelete: Restrict)
title String
notes String?
tags String[] @default([])
position Int @default(0)
personId String?
person Person? @relation(fields: [personId], references: [id], onDelete: SetNull)
@@ -1076,6 +1085,7 @@ model ProjectCard {
deal Deal? @relation(fields: [dealId], references: [id], onDelete: SetNull)
ownerId String?
owner User? @relation("ProjectCardOwner", fields: [ownerId], references: [id], onDelete: SetNull)
assignees User[] @relation("ProjectCardAssignees")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -1546,3 +1556,44 @@ model PartyOpeningBalance {
@@unique([organizationId, personId])
@@index([personId])
}
/// لاگ فعالیت کاربران روی منابع سازمان
model AuditLog {
id String @id @default(cuid())
organizationId String
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
actorUserId String?
actor User? @relation("AuditLogActor", fields: [actorUserId], references: [id], onDelete: SetNull)
action String
method String
path String
entityType String?
entityId String?
summary String
meta Json?
ip String?
createdAt DateTime @default(now())
@@index([organizationId, createdAt])
@@index([organizationId, actorUserId, createdAt])
@@index([organizationId, entityType, createdAt])
}
/// فیلترهای ذخیره‌شده برای لیست‌ها و کاریزها
model SavedView {
id String @id @default(cuid())
organizationId String
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
ownerUserId String?
owner User? @relation("SavedViewOwner", fields: [ownerUserId], references: [id], onDelete: SetNull)
name String
/// deals | people | companies | activities | project_cards
scope String
filters Json @default("{}")
isShared Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([organizationId, scope])
@@index([organizationId, ownerUserId])
}