feat(settings): store Khanegi keys in settings tables instead of tenant JSON

Template defaults seed from deploy_settings_const; new tenants copy them, import decides per key, and /get_settings reads the per-tenant rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-17 20:14:17 +03:30
co-authored by Cursor
parent 8f9988eb15
commit d57ce0a3cb
15 changed files with 2659 additions and 354 deletions
+46 -2
View File
@@ -69,8 +69,6 @@ model Tenant {
/// Legacy cache from older sync attempts — SuperAdmin SMS account is now source of truth
smsSettingsCache Json? @map("sms_settings_cache")
smsSyncedAt DateTime? @map("sms_synced_at")
/// Khanegi deploy settings snapshot (can_edit=0) imported via admin login + get_settings.
setting Json?
/// Full Khanegi UI JSON (theme, navigation, pages). Hamkar: unused for now.
appUiConfig Json? @map("app_ui_config")
/// Khanegi only: which appearance editor / get_user payload shape to use.
@@ -90,12 +88,58 @@ model Tenant {
serverAccounts ServerAccount[]
pluginSubscriptions PluginSubscription[]
supportSubscriptions SupportSubscription[]
settings Setting[]
@@index([product])
@@index([isActive])
@@map("tenants")
}
/// قالب پیش‌فرض تنظیمات (از deploy_settings_const). نسخهٔ جدید از اینجا کپی می‌شود.
model SettingTemplate {
id String @id @default(cuid())
key String @unique @db.VarChar(50)
titleFa String? @map("title_fa") @db.VarChar(255)
canEdit Int? @default(0) @map("can_edit") @db.SmallInt
value String? @db.Text
description String? @db.Text
type String? @db.VarChar(50)
/// ستون همکار — برای سازگاری آینده
typeData String? @map("type_data") @db.VarChar(255)
isExist Boolean @default(true) @map("is_exist")
isActive Int? @default(1) @map("is_active") @db.SmallInt
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@map("setting_templates")
}
/// تنظیمات هر نسخه — مثل جدول settings خانگی + tenant_id
model Setting {
id String @id @default(cuid())
tenantId String @map("tenant_id")
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
key String @db.VarChar(50)
titleFa String? @map("title_fa") @db.VarChar(255)
canEdit Int? @default(0) @map("can_edit") @db.SmallInt
value String? @db.Text
description String? @db.Text
type String? @db.VarChar(50)
/// ستون همکار — برای سازگاری آینده
typeData String? @map("type_data") @db.VarChar(255)
isExist Boolean @default(true) @map("is_exist")
isActive Int? @default(1) @map("is_active") @db.SmallInt
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
@@unique([tenantId, key])
@@index([key])
@@index([tenantId])
@@map("settings")
}
/// SuperAdmin-owned SMS wallet + gateway config per sold version.
/// Does NOT replace Hamkar/Khanegi internal SMS panels yet.
model SmsAccount {