fix update build
This commit is contained in:
+15802
-407
File diff suppressed because it is too large
Load Diff
+2022
-13
File diff suppressed because it is too large
Load Diff
+221
-9
File diff suppressed because one or more lines are too long
+215
-2
@@ -125,7 +125,9 @@ exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
|
|||||||
exports.Prisma.CityScalarFieldEnum = {
|
exports.Prisma.CityScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
province: 'province'
|
province: 'province',
|
||||||
|
percent: 'percent',
|
||||||
|
percentAux: 'percentAux'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Prisma.AdminUserScalarFieldEnum = {
|
exports.Prisma.AdminUserScalarFieldEnum = {
|
||||||
@@ -134,6 +136,7 @@ exports.Prisma.AdminUserScalarFieldEnum = {
|
|||||||
mobile: 'mobile',
|
mobile: 'mobile',
|
||||||
passwordHash: 'passwordHash',
|
passwordHash: 'passwordHash',
|
||||||
role: 'role',
|
role: 'role',
|
||||||
|
userTypeId: 'userTypeId',
|
||||||
branchId: 'branchId',
|
branchId: 'branchId',
|
||||||
wagePercent: 'wagePercent',
|
wagePercent: 'wagePercent',
|
||||||
isActive: 'isActive',
|
isActive: 'isActive',
|
||||||
@@ -147,6 +150,13 @@ exports.Prisma.CustomerScalarFieldEnum = {
|
|||||||
nationalCode: 'nationalCode',
|
nationalCode: 'nationalCode',
|
||||||
passwordHash: 'passwordHash',
|
passwordHash: 'passwordHash',
|
||||||
cityId: 'cityId',
|
cityId: 'cityId',
|
||||||
|
kind: 'kind',
|
||||||
|
phone: 'phone',
|
||||||
|
address: 'address',
|
||||||
|
storeName: 'storeName',
|
||||||
|
pasazhName: 'pasazhName',
|
||||||
|
zone: 'zone',
|
||||||
|
memberCode: 'memberCode',
|
||||||
referredByAgentId: 'referredByAgentId',
|
referredByAgentId: 'referredByAgentId',
|
||||||
goldCreditLimitGrams: 'goldCreditLimitGrams',
|
goldCreditLimitGrams: 'goldCreditLimitGrams',
|
||||||
goldDebtGrams: 'goldDebtGrams',
|
goldDebtGrams: 'goldDebtGrams',
|
||||||
@@ -155,7 +165,10 @@ exports.Prisma.CustomerScalarFieldEnum = {
|
|||||||
nationalIdImageUrl: 'nationalIdImageUrl',
|
nationalIdImageUrl: 'nationalIdImageUrl',
|
||||||
businessLicenseUrl: 'businessLicenseUrl',
|
businessLicenseUrl: 'businessLicenseUrl',
|
||||||
shopImageUrl: 'shopImageUrl',
|
shopImageUrl: 'shopImageUrl',
|
||||||
|
avatarFileId: 'avatarFileId',
|
||||||
|
canPlaceOrders: 'canPlaceOrders',
|
||||||
isActive: 'isActive',
|
isActive: 'isActive',
|
||||||
|
isArchived: 'isArchived',
|
||||||
createdAt: 'createdAt',
|
createdAt: 'createdAt',
|
||||||
updatedAt: 'updatedAt'
|
updatedAt: 'updatedAt'
|
||||||
};
|
};
|
||||||
@@ -171,18 +184,29 @@ exports.Prisma.CustomerAddressScalarFieldEnum = {
|
|||||||
exports.Prisma.BranchScalarFieldEnum = {
|
exports.Prisma.BranchScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
address: 'address',
|
||||||
|
phone: 'phone',
|
||||||
|
isActive: 'isActive',
|
||||||
cityId: 'cityId'
|
cityId: 'cityId'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Prisma.WorkshopScalarFieldEnum = {
|
exports.Prisma.WorkshopScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
address: 'address',
|
||||||
|
phone: 'phone',
|
||||||
|
supervisorId: 'supervisorId',
|
||||||
isActive: 'isActive'
|
isActive: 'isActive'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Prisma.CategoryScalarFieldEnum = {
|
exports.Prisma.CategoryScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
title: 'title',
|
title: 'title',
|
||||||
|
type: 'type',
|
||||||
|
imageUrl: 'imageUrl',
|
||||||
|
iconUrl: 'iconUrl',
|
||||||
|
metaTag: 'metaTag',
|
||||||
|
description: 'description',
|
||||||
parentId: 'parentId'
|
parentId: 'parentId'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,6 +233,8 @@ exports.Prisma.ProductScalarFieldEnum = {
|
|||||||
description: 'description',
|
description: 'description',
|
||||||
categoryId: 'categoryId',
|
categoryId: 'categoryId',
|
||||||
brandId: 'brandId',
|
brandId: 'brandId',
|
||||||
|
productCode: 'productCode',
|
||||||
|
showType: 'showType',
|
||||||
isActive: 'isActive',
|
isActive: 'isActive',
|
||||||
createdAt: 'createdAt'
|
createdAt: 'createdAt'
|
||||||
};
|
};
|
||||||
@@ -227,6 +253,8 @@ exports.Prisma.ProductVariantScalarFieldEnum = {
|
|||||||
sku: 'sku',
|
sku: 'sku',
|
||||||
rashWeightGrams: 'rashWeightGrams',
|
rashWeightGrams: 'rashWeightGrams',
|
||||||
defaultWagePercent: 'defaultWagePercent',
|
defaultWagePercent: 'defaultWagePercent',
|
||||||
|
qty: 'qty',
|
||||||
|
isPreOrder: 'isPreOrder',
|
||||||
isActive: 'isActive'
|
isActive: 'isActive'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -235,6 +263,7 @@ exports.Prisma.OrderScalarFieldEnum = {
|
|||||||
orderNumber: 'orderNumber',
|
orderNumber: 'orderNumber',
|
||||||
customerId: 'customerId',
|
customerId: 'customerId',
|
||||||
branchId: 'branchId',
|
branchId: 'branchId',
|
||||||
|
channel: 'channel',
|
||||||
status: 'status',
|
status: 'status',
|
||||||
totalGoldWeightGrams: 'totalGoldWeightGrams',
|
totalGoldWeightGrams: 'totalGoldWeightGrams',
|
||||||
wageWeightGrams: 'wageWeightGrams',
|
wageWeightGrams: 'wageWeightGrams',
|
||||||
@@ -308,6 +337,14 @@ exports.Prisma.LedgerEntryScalarFieldEnum = {
|
|||||||
confirmed: 'confirmed',
|
confirmed: 'confirmed',
|
||||||
confirmedAt: 'confirmedAt',
|
confirmedAt: 'confirmedAt',
|
||||||
postedByAdminUserId: 'postedByAdminUserId',
|
postedByAdminUserId: 'postedByAdminUserId',
|
||||||
|
labName: 'labName',
|
||||||
|
hallmark: 'hallmark',
|
||||||
|
accountName: 'accountName',
|
||||||
|
bankName: 'bankName',
|
||||||
|
transferTo: 'transferTo',
|
||||||
|
originalValue: 'originalValue',
|
||||||
|
priceRial: 'priceRial',
|
||||||
|
receivedAt: 'receivedAt',
|
||||||
note: 'note',
|
note: 'note',
|
||||||
createdAt: 'createdAt'
|
createdAt: 'createdAt'
|
||||||
};
|
};
|
||||||
@@ -331,6 +368,128 @@ exports.Prisma.WalletBonusScalarFieldEnum = {
|
|||||||
isActive: 'isActive'
|
isActive: 'isActive'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.Prisma.UserTypeScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
title: 'title',
|
||||||
|
isActive: 'isActive',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.PermissionScalarFieldEnum = {
|
||||||
|
rid: 'rid',
|
||||||
|
userTypeId: 'userTypeId'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.CommentScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
productId: 'productId',
|
||||||
|
customerId: 'customerId',
|
||||||
|
body: 'body',
|
||||||
|
status: 'status',
|
||||||
|
replyToId: 'replyToId',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.SettingScalarFieldEnum = {
|
||||||
|
key: 'key',
|
||||||
|
value: 'value',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.PromotionScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
title: 'title',
|
||||||
|
description: 'description',
|
||||||
|
scope: 'scope',
|
||||||
|
usage: 'usage',
|
||||||
|
discountPercent: 'discountPercent',
|
||||||
|
isActive: 'isActive',
|
||||||
|
platform: 'platform',
|
||||||
|
startsAt: 'startsAt',
|
||||||
|
endsAt: 'endsAt',
|
||||||
|
productId: 'productId',
|
||||||
|
categoryId: 'categoryId',
|
||||||
|
customerId: 'customerId',
|
||||||
|
brandId: 'brandId',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.PromotionExclusionScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
type: 'type',
|
||||||
|
itemId: 'itemId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.BranchAllocationScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
branchId: 'branchId',
|
||||||
|
allocatorAdminUserId: 'allocatorAdminUserId',
|
||||||
|
note: 'note',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.BranchAllocationItemScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
allocationId: 'allocationId',
|
||||||
|
productId: 'productId',
|
||||||
|
weightGrams: 'weightGrams'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.SmsMessageScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
audience: 'audience',
|
||||||
|
recipients: 'recipients',
|
||||||
|
body: 'body',
|
||||||
|
sentCount: 'sentCount',
|
||||||
|
sentByAdminUserId: 'sentByAdminUserId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.NotificationScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
title: 'title',
|
||||||
|
body: 'body',
|
||||||
|
audience: 'audience',
|
||||||
|
sentByAdminUserId: 'sentByAdminUserId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.NotificationRecipientScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
notificationId: 'notificationId',
|
||||||
|
customerId: 'customerId',
|
||||||
|
readAt: 'readAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.NewsletterSubscriberScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
email: 'email',
|
||||||
|
mobile: 'mobile',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.CustomerActivityLogScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
customerId: 'customerId',
|
||||||
|
action: 'action',
|
||||||
|
detail: 'detail',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.UploadedFileScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
url: 'url',
|
||||||
|
originalName: 'originalName',
|
||||||
|
mimeType: 'mimeType',
|
||||||
|
sizeBytes: 'sizeBytes',
|
||||||
|
purpose: 'purpose',
|
||||||
|
uploadedByAdminUserId: 'uploadedByAdminUserId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
exports.Prisma.SortOrder = {
|
exports.Prisma.SortOrder = {
|
||||||
asc: 'asc',
|
asc: 'asc',
|
||||||
desc: 'desc'
|
desc: 'desc'
|
||||||
@@ -363,6 +522,14 @@ exports.AdminRole = exports.$Enums.AdminRole = {
|
|||||||
ACCOUNTANT: 'ACCOUNTANT'
|
ACCOUNTANT: 'ACCOUNTANT'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.CustomerKind = exports.$Enums.CustomerKind = {
|
||||||
|
SALES_AGENT: 'SALES_AGENT',
|
||||||
|
APP_SHOPKEEPER: 'APP_SHOPKEEPER',
|
||||||
|
WALK_IN_SHOPKEEPER: 'WALK_IN_SHOPKEEPER',
|
||||||
|
BANKER: 'BANKER',
|
||||||
|
WORKSHOP_SUPERVISOR: 'WORKSHOP_SUPERVISOR'
|
||||||
|
};
|
||||||
|
|
||||||
exports.VerificationStep = exports.$Enums.VerificationStep = {
|
exports.VerificationStep = exports.$Enums.VerificationStep = {
|
||||||
UNVERIFIED: 'UNVERIFIED',
|
UNVERIFIED: 'UNVERIFIED',
|
||||||
STEP_ONE_SUBMITTED: 'STEP_ONE_SUBMITTED',
|
STEP_ONE_SUBMITTED: 'STEP_ONE_SUBMITTED',
|
||||||
@@ -370,6 +537,11 @@ exports.VerificationStep = exports.$Enums.VerificationStep = {
|
|||||||
VERIFIED: 'VERIFIED'
|
VERIFIED: 'VERIFIED'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.OrderChannel = exports.$Enums.OrderChannel = {
|
||||||
|
RETAIL: 'RETAIL',
|
||||||
|
WHOLESALE: 'WHOLESALE'
|
||||||
|
};
|
||||||
|
|
||||||
exports.OrderStatus = exports.$Enums.OrderStatus = {
|
exports.OrderStatus = exports.$Enums.OrderStatus = {
|
||||||
SUSPENDED: 'SUSPENDED',
|
SUSPENDED: 'SUSPENDED',
|
||||||
PLACED: 'PLACED',
|
PLACED: 'PLACED',
|
||||||
@@ -411,6 +583,33 @@ exports.LedgerSourceType = exports.$Enums.LedgerSourceType = {
|
|||||||
ADJUSTMENT: 'ADJUSTMENT'
|
ADJUSTMENT: 'ADJUSTMENT'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.CommentStatus = exports.$Enums.CommentStatus = {
|
||||||
|
PENDING: 'PENDING',
|
||||||
|
APPROVED: 'APPROVED',
|
||||||
|
REJECTED: 'REJECTED'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.PromotionScope = exports.$Enums.PromotionScope = {
|
||||||
|
PRODUCT: 'PRODUCT',
|
||||||
|
CATEGORY: 'CATEGORY',
|
||||||
|
CUSTOMER: 'CUSTOMER',
|
||||||
|
BRAND: 'BRAND'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.PromotionUsage = exports.$Enums.PromotionUsage = {
|
||||||
|
ONCE: 'ONCE',
|
||||||
|
UNTIL_END_DATE: 'UNTIL_END_DATE'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.MessageAudience = exports.$Enums.MessageAudience = {
|
||||||
|
SINGLE_NUMBER: 'SINGLE_NUMBER',
|
||||||
|
MULTIPLE_NUMBERS: 'MULTIPLE_NUMBERS',
|
||||||
|
ALL_CUSTOMERS: 'ALL_CUSTOMERS',
|
||||||
|
WHOLESALE_CUSTOMERS: 'WHOLESALE_CUSTOMERS',
|
||||||
|
RETAIL_CUSTOMERS: 'RETAIL_CUSTOMERS',
|
||||||
|
SALES_AGENTS: 'SALES_AGENTS'
|
||||||
|
};
|
||||||
|
|
||||||
exports.Prisma.ModelName = {
|
exports.Prisma.ModelName = {
|
||||||
City: 'City',
|
City: 'City',
|
||||||
AdminUser: 'AdminUser',
|
AdminUser: 'AdminUser',
|
||||||
@@ -432,7 +631,21 @@ exports.Prisma.ModelName = {
|
|||||||
PreOrderStatusEvent: 'PreOrderStatusEvent',
|
PreOrderStatusEvent: 'PreOrderStatusEvent',
|
||||||
LedgerEntry: 'LedgerEntry',
|
LedgerEntry: 'LedgerEntry',
|
||||||
GoldPriceQuote: 'GoldPriceQuote',
|
GoldPriceQuote: 'GoldPriceQuote',
|
||||||
WalletBonus: 'WalletBonus'
|
WalletBonus: 'WalletBonus',
|
||||||
|
UserType: 'UserType',
|
||||||
|
Permission: 'Permission',
|
||||||
|
Comment: 'Comment',
|
||||||
|
Setting: 'Setting',
|
||||||
|
Promotion: 'Promotion',
|
||||||
|
PromotionExclusion: 'PromotionExclusion',
|
||||||
|
BranchAllocation: 'BranchAllocation',
|
||||||
|
BranchAllocationItem: 'BranchAllocationItem',
|
||||||
|
SmsMessage: 'SmsMessage',
|
||||||
|
Notification: 'Notification',
|
||||||
|
NotificationRecipient: 'NotificationRecipient',
|
||||||
|
NewsletterSubscriber: 'NewsletterSubscriber',
|
||||||
|
CustomerActivityLog: 'CustomerActivityLog',
|
||||||
|
UploadedFile: 'UploadedFile'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+26395
-157
File diff suppressed because it is too large
Load Diff
+221
-9
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "prisma-client-d0d5db76aa59566edce744ecac2768fcb398c1a9f370089a45b9416272282fab",
|
"name": "prisma-client-9a5464add1bac751da0fd2476fcc0a15f434a77547c687bcb5959b29d451c62b",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"types": "index.d.ts",
|
"types": "index.d.ts",
|
||||||
"browser": "index-browser.js",
|
"browser": "index-browser.js",
|
||||||
|
|||||||
+469
-37
@@ -26,6 +26,16 @@ enum AdminRole {
|
|||||||
ACCOUNTANT
|
ACCOUNTANT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Legacy Customer.type — what kind of wholesale customer this is. Values and
|
||||||
|
/// labels taken verbatim from bulkCustomer.vue's userTypes list.
|
||||||
|
enum CustomerKind {
|
||||||
|
SALES_AGENT // 1 کارشناس فروش
|
||||||
|
APP_SHOPKEEPER // 2 مغازه دار اپلیکیشن
|
||||||
|
WALK_IN_SHOPKEEPER // 3 مغازه دار حضوری
|
||||||
|
BANKER // 4 بنکدار
|
||||||
|
WORKSHOP_SUPERVISOR // 5 سرپرست کارگاه
|
||||||
|
}
|
||||||
|
|
||||||
enum VerificationStep {
|
enum VerificationStep {
|
||||||
UNVERIFIED
|
UNVERIFIED
|
||||||
STEP_ONE_SUBMITTED
|
STEP_ONE_SUBMITTED
|
||||||
@@ -33,6 +43,14 @@ enum VerificationStep {
|
|||||||
VERIFIED
|
VERIFIED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Legacy kept retail and wholesale orders in two SEPARATE tables
|
||||||
|
/// (orders_orders vs orders). The redesigned schema has one Order model, so the
|
||||||
|
/// distinction lives here instead.
|
||||||
|
enum OrderChannel {
|
||||||
|
RETAIL // تک فروشی
|
||||||
|
WHOLESALE // عمده فروشی
|
||||||
|
}
|
||||||
|
|
||||||
enum OrderStatus {
|
enum OrderStatus {
|
||||||
SUSPENDED // credit limit (goldCreditLimitGrams) exceeded at placement
|
SUSPENDED // credit limit (goldCreditLimitGrams) exceeded at placement
|
||||||
PLACED
|
PLACED
|
||||||
@@ -79,13 +97,17 @@ enum LedgerSourceType {
|
|||||||
// ─────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
model City {
|
model City {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
province String?
|
province String?
|
||||||
customers Customer[]
|
/// Legacy cities.percent / percent_aux — per-city wage surcharges the city
|
||||||
addresses CustomerAddress[]
|
/// screen edits through GET cities/get-percent/{id} and get-percent-aux/{id}.
|
||||||
branches Branch[]
|
percent Decimal? @db.Decimal(6, 3)
|
||||||
preOrders PreOrder[]
|
percentAux Decimal? @db.Decimal(6, 3)
|
||||||
|
customers Customer[]
|
||||||
|
addresses CustomerAddress[]
|
||||||
|
branches Branch[]
|
||||||
|
preOrders PreOrder[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model AdminUser {
|
model AdminUser {
|
||||||
@@ -94,6 +116,11 @@ model AdminUser {
|
|||||||
mobile String @unique
|
mobile String @unique
|
||||||
passwordHash String
|
passwordHash String
|
||||||
role AdminRole
|
role AdminRole
|
||||||
|
/// Legacy `users.ut`. Granular ACL lives here (Permission rows hang off UserType);
|
||||||
|
/// the coarse `role` enum above is retained for the business rules that already
|
||||||
|
/// switch on it. Nullable so existing seeded admins remain valid.
|
||||||
|
userTypeId Int?
|
||||||
|
userType UserType? @relation(fields: [userTypeId], references: [id])
|
||||||
branchId String?
|
branchId String?
|
||||||
branch Branch? @relation(fields: [branchId], references: [id])
|
branch Branch? @relation(fields: [branchId], references: [id])
|
||||||
wagePercent Decimal? @db.Decimal(6, 3) // legacy Customer.percent, commission on referred orders
|
wagePercent Decimal? @db.Decimal(6, 3) // legacy Customer.percent, commission on referred orders
|
||||||
@@ -101,11 +128,17 @@ model AdminUser {
|
|||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
referredCustomers Customer[] @relation("ReferralAgent")
|
referredCustomers Customer[] @relation("ReferralAgent")
|
||||||
|
supervisedWorkshops Workshop[] @relation("WorkshopSupervisor")
|
||||||
|
branchAllocations BranchAllocation[] @relation("AllocationAuthor")
|
||||||
postedLedgerEntries LedgerEntry[]
|
postedLedgerEntries LedgerEntry[]
|
||||||
orderStatusEvents OrderStatusEvent[]
|
orderStatusEvents OrderStatusEvent[]
|
||||||
preOrderStatusEvents PreOrderStatusEvent[]
|
preOrderStatusEvents PreOrderStatusEvent[]
|
||||||
|
sentSmsMessages SmsMessage[] @relation("SmsAuthor")
|
||||||
|
sentNotifications Notification[] @relation("NotificationAuthor")
|
||||||
|
uploadedFiles UploadedFile[] @relation("FileUploader")
|
||||||
|
|
||||||
@@index([role])
|
@@index([role])
|
||||||
|
@@index([userTypeId])
|
||||||
}
|
}
|
||||||
|
|
||||||
model Customer {
|
model Customer {
|
||||||
@@ -117,6 +150,20 @@ model Customer {
|
|||||||
cityId String?
|
cityId String?
|
||||||
city City? @relation(fields: [cityId], references: [id])
|
city City? @relation(fields: [cityId], references: [id])
|
||||||
|
|
||||||
|
/// Legacy Customer.type — distinguishes بنکدار from مغازه دار, which the
|
||||||
|
/// BankerList / ShopkeeperList screens filter on.
|
||||||
|
kind CustomerKind @default(APP_SHOPKEEPER)
|
||||||
|
|
||||||
|
/// Legacy contact + shop columns, shown on the wholesale customer form and as
|
||||||
|
/// (hidden-by-default) columns in its grid.
|
||||||
|
phone String?
|
||||||
|
address String?
|
||||||
|
storeName String?
|
||||||
|
pasazhName String?
|
||||||
|
zone String?
|
||||||
|
/// Legacy mcode — the operator-assigned customer code.
|
||||||
|
memberCode String?
|
||||||
|
|
||||||
referredByAgentId String?
|
referredByAgentId String?
|
||||||
referredByAgent AdminUser? @relation("ReferralAgent", fields: [referredByAgentId], references: [id])
|
referredByAgent AdminUser? @relation("ReferralAgent", fields: [referredByAgentId], references: [id])
|
||||||
|
|
||||||
@@ -131,15 +178,33 @@ model Customer {
|
|||||||
businessLicenseUrl String?
|
businessLicenseUrl String?
|
||||||
shopImageUrl String?
|
shopImageUrl String?
|
||||||
|
|
||||||
isActive Boolean @default(true)
|
/// Legacy `image_id` — the profile photo (عکس پروفایل) on the sales-agent
|
||||||
createdAt DateTime @default(now())
|
/// form. Legacy stored an FK to its Image table and read it back as a nested
|
||||||
updatedAt DateTime @updatedAt
|
/// `image: { id, image }`, so this is a relation, not a bare URL string.
|
||||||
|
avatarFileId String?
|
||||||
|
avatarFile UploadedFile? @relation("CustomerAvatar", fields: [avatarFileId], references: [id])
|
||||||
|
|
||||||
|
/// Legacy had TWO independent switches on a customer:
|
||||||
|
/// sts -> may they place orders (this field)
|
||||||
|
/// active -> is the account enabled (isActive, below)
|
||||||
|
/// The port previously drove both from isActive; they are separate again.
|
||||||
|
canPlaceOrders Boolean @default(true)
|
||||||
|
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
/// Legacy archive flag — the archived list filtered on this, not on isActive.
|
||||||
|
isArchived Boolean @default(false)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
addresses CustomerAddress[]
|
addresses CustomerAddress[]
|
||||||
orders Order[]
|
orders Order[]
|
||||||
preOrders PreOrder[]
|
preOrders PreOrder[]
|
||||||
ledgerEntries LedgerEntry[]
|
ledgerEntries LedgerEntry[]
|
||||||
walletBonuses WalletBonus[]
|
walletBonuses WalletBonus[]
|
||||||
|
comments Comment[]
|
||||||
|
promotions Promotion[]
|
||||||
|
notifications NotificationRecipient[]
|
||||||
|
activityLogs CustomerActivityLog[]
|
||||||
|
|
||||||
@@index([referredByAgentId])
|
@@index([referredByAgentId])
|
||||||
}
|
}
|
||||||
@@ -155,19 +220,31 @@ model CustomerAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Branch {
|
model Branch {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
cityId String?
|
/// Legacy Branch.address / phone — both are columns in the branch grid.
|
||||||
city City? @relation(fields: [cityId], references: [id])
|
address String?
|
||||||
adminUsers AdminUser[]
|
phone String?
|
||||||
orders Order[]
|
/// Legacy GET branch/active/{id} toggles this.
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
cityId String?
|
||||||
|
city City? @relation(fields: [cityId], references: [id])
|
||||||
|
adminUsers AdminUser[]
|
||||||
|
orders Order[]
|
||||||
|
allocations BranchAllocation[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Workshop {
|
model Workshop {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
name String
|
name String
|
||||||
isActive Boolean @default(true)
|
/// Legacy Workshop.address / phone — both are columns in the workshop grid.
|
||||||
preOrders PreOrder[]
|
address String?
|
||||||
|
phone String?
|
||||||
|
/// The supervisor created alongside the workshop by the legacy Add form.
|
||||||
|
supervisorId String?
|
||||||
|
supervisor AdminUser? @relation("WorkshopSupervisor", fields: [supervisorId], references: [id])
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
preOrders PreOrder[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
@@ -175,18 +252,29 @@ model Workshop {
|
|||||||
// ─────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
model Category {
|
model Category {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
title String
|
title String
|
||||||
parentId String?
|
/// Legacy Category.type — which storefront the category belongs to:
|
||||||
parent Category? @relation("CategoryTree", fields: [parentId], references: [id])
|
/// 1 سایت | 2 اپلیکشن موبایل. Drives the "type_str" grid column.
|
||||||
children Category[] @relation("CategoryTree")
|
type Int @default(1)
|
||||||
products Product[]
|
/// Legacy Category.image / icon — the grid renders the image, the storefront the icon.
|
||||||
|
imageUrl String?
|
||||||
|
iconUrl String?
|
||||||
|
/// Legacy meta tag + description, used for SEO on the site categories.
|
||||||
|
metaTag String?
|
||||||
|
description String?
|
||||||
|
parentId String?
|
||||||
|
parent Category? @relation("CategoryTree", fields: [parentId], references: [id])
|
||||||
|
children Category[] @relation("CategoryTree")
|
||||||
|
products Product[]
|
||||||
|
promotions Promotion[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Brand {
|
model Brand {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
title String
|
title String
|
||||||
products Product[]
|
products Product[]
|
||||||
|
promotions Promotion[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Curated product groupings — replaces legacy "Ciny/CinyProduct" (a tagging
|
/// Curated product groupings — replaces legacy "Ciny/CinyProduct" (a tagging
|
||||||
@@ -216,12 +304,19 @@ model Product {
|
|||||||
category Category? @relation(fields: [categoryId], references: [id])
|
category Category? @relation(fields: [categoryId], references: [id])
|
||||||
brandId String?
|
brandId String?
|
||||||
brand Brand? @relation(fields: [brandId], references: [id])
|
brand Brand? @relation(fields: [brandId], references: [id])
|
||||||
|
/// Legacy Product.product_code — the human-facing SKU shown in the grid.
|
||||||
|
productCode String? @unique
|
||||||
|
/// Legacy Product.show_type: 1 site, 2 mobile, 3 both.
|
||||||
|
showType Int @default(3)
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
variants ProductVariant[]
|
variants ProductVariant[]
|
||||||
images ProductImage[]
|
images ProductImage[]
|
||||||
collections CollectionProduct[]
|
collections CollectionProduct[]
|
||||||
|
comments Comment[]
|
||||||
|
promotions Promotion[]
|
||||||
|
allocationItems BranchAllocationItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model ProductImage {
|
model ProductImage {
|
||||||
@@ -242,6 +337,12 @@ model ProductVariant {
|
|||||||
rashWeightGrams Decimal @db.Decimal(14, 4)
|
rashWeightGrams Decimal @db.Decimal(14, 4)
|
||||||
/// Default making-charge percentage applied on top of rash weight.
|
/// Default making-charge percentage applied on top of rash weight.
|
||||||
defaultWagePercent Decimal @db.Decimal(6, 3)
|
defaultWagePercent Decimal @db.Decimal(6, 3)
|
||||||
|
/// Legacy ProductVariant.qty — on-hand stock. The cart refuses a variant with
|
||||||
|
/// qty 0 unless it is flagged pre-order, so both fields are required for that
|
||||||
|
/// guard to work (see apps/admin-panel/src/stores/cart.ts).
|
||||||
|
qty Int @default(0)
|
||||||
|
/// Legacy is_pre_order: orderable even at zero stock.
|
||||||
|
isPreOrder Boolean @default(false)
|
||||||
isActive Boolean @default(true)
|
isActive Boolean @default(true)
|
||||||
|
|
||||||
orderItems OrderItem[]
|
orderItems OrderItem[]
|
||||||
@@ -252,13 +353,15 @@ model ProductVariant {
|
|||||||
// ─────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
model Order {
|
model Order {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
orderNumber String @unique
|
orderNumber String @unique
|
||||||
customerId String
|
customerId String
|
||||||
customer Customer @relation(fields: [customerId], references: [id])
|
customer Customer @relation(fields: [customerId], references: [id])
|
||||||
branchId String?
|
branchId String?
|
||||||
branch Branch? @relation(fields: [branchId], references: [id])
|
branch Branch? @relation(fields: [branchId], references: [id])
|
||||||
status OrderStatus @default(PLACED)
|
/// Which sales channel placed this order — see OrderChannel.
|
||||||
|
channel OrderChannel @default(RETAIL)
|
||||||
|
status OrderStatus @default(PLACED)
|
||||||
|
|
||||||
/// Total gold weight incl. wage across all items ("allGram" / order.w).
|
/// Total gold weight incl. wage across all items ("allGram" / order.w).
|
||||||
totalGoldWeightGrams Decimal @db.Decimal(14, 4)
|
totalGoldWeightGrams Decimal @db.Decimal(14, 4)
|
||||||
@@ -391,6 +494,22 @@ model LedgerEntry {
|
|||||||
postedByAdminUserId String?
|
postedByAdminUserId String?
|
||||||
postedByAdminUser AdminUser? @relation(fields: [postedByAdminUserId], references: [id])
|
postedByAdminUser AdminUser? @relation(fields: [postedByAdminUserId], references: [id])
|
||||||
|
|
||||||
|
/// Instrument metadata from the legacy "cash" document form. Which fields are
|
||||||
|
/// filled depends on sourceType: a melted-gold receipt carries lab/hallmark and
|
||||||
|
/// the pre-normalization weight, a cheque carries the account and bank, and a
|
||||||
|
/// transfer carries its destination.
|
||||||
|
/// Legacy columns: lab, ang, account_name, bank_name, to, original_value, recive_date.
|
||||||
|
labName String?
|
||||||
|
hallmark String?
|
||||||
|
accountName String?
|
||||||
|
bankName String?
|
||||||
|
transferTo String?
|
||||||
|
/// Weight as handed over, BEFORE karat normalization (legacy original_value).
|
||||||
|
originalValue Decimal? @db.Decimal(14, 4)
|
||||||
|
/// Rial amount for cash/cheque documents (legacy price).
|
||||||
|
priceRial Decimal? @db.Decimal(20, 2)
|
||||||
|
receivedAt DateTime?
|
||||||
|
|
||||||
note String?
|
note String?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
@@ -423,3 +542,316 @@ model WalletBonus {
|
|||||||
|
|
||||||
@@index([customerId, isActive])
|
@@index([customerId, isActive])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// Admin ACL — faithful port of the legacy granular permission model.
|
||||||
|
//
|
||||||
|
// Legacy (henza_server):
|
||||||
|
// Schema::create('permission', function (Blueprint $table) {
|
||||||
|
// $table->string('rid');
|
||||||
|
// $table->integer('ut');
|
||||||
|
// $table->primary(['rid' , 'ut']);
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// Permissions attach to the USER TYPE (`ut`), never to an individual user, so
|
||||||
|
// every admin of a given type shares one permission set. `ut` pointed at a row
|
||||||
|
// in the legacy `config_static` lookup table; UserType is that table, narrowed
|
||||||
|
// to the admin-user-type rows it was actually used for.
|
||||||
|
//
|
||||||
|
// A `rid` is a dotted permission id such as "persons.list.client.omde". The
|
||||||
|
// frontend expands each stored rid into its ancestors at runtime via
|
||||||
|
// checkParent() — see apps/admin-panel/src/stores/users.ts. Only the 58 leaf
|
||||||
|
// rids the routers actually gate are seeded; ancestors are derived, not stored.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
model UserType {
|
||||||
|
/// Legacy `permission.ut` / `users.ut` — an integer, kept as the PK so seeded
|
||||||
|
/// rows keep their legacy identity rather than getting new cuids.
|
||||||
|
id Int @id
|
||||||
|
title String
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
permissions Permission[]
|
||||||
|
adminUsers AdminUser[]
|
||||||
|
|
||||||
|
@@map("user_type")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Permission {
|
||||||
|
/// Dotted permission id, e.g. "order.list", "persons.list.client.omde".
|
||||||
|
rid String
|
||||||
|
userTypeId Int
|
||||||
|
userType UserType @relation(fields: [userTypeId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
/// Legacy's composite primary key (rid, ut), preserved exactly.
|
||||||
|
@@id([rid, userTypeId])
|
||||||
|
@@index([userTypeId])
|
||||||
|
@@map("permission")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// Product comments / reviews — legacy `comment` table (App\Models\Comment),
|
||||||
|
// moderated from views/customer/Comments/Comments.vue.
|
||||||
|
//
|
||||||
|
// Legacy fillable: product_id, comment, reply_to, sts, customer_id
|
||||||
|
// Legacy Comment::$STS = [1 => 'در انتظار تایید', 2 => 'تایید شده', 3 => 'رد شده']
|
||||||
|
// which is represented here as an enum rather than a magic integer.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
enum CommentStatus {
|
||||||
|
PENDING // 1 — در انتظار تایید
|
||||||
|
APPROVED // 2 — تایید شده
|
||||||
|
REJECTED // 3 — رد شده
|
||||||
|
}
|
||||||
|
|
||||||
|
model Comment {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
productId String
|
||||||
|
product Product @relation(fields: [productId], references: [id])
|
||||||
|
customerId String
|
||||||
|
customer Customer @relation(fields: [customerId], references: [id])
|
||||||
|
body String
|
||||||
|
status CommentStatus @default(PENDING)
|
||||||
|
|
||||||
|
/// Legacy `reply_to`: a staff reply threads under the comment it answers.
|
||||||
|
replyToId String?
|
||||||
|
replyTo Comment? @relation("CommentReplies", fields: [replyToId], references: [id])
|
||||||
|
replies Comment[] @relation("CommentReplies")
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@index([productId])
|
||||||
|
@@index([customerId])
|
||||||
|
@@index([status])
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// Settings — replaces legacy `config_static`, a key/value table the admin
|
||||||
|
// panel read and wrote through endpoints like /wallet/config and
|
||||||
|
// /const/__list__ut. Values are stored as JSON so a setting can hold a scalar,
|
||||||
|
// an object, or the dynamic option lists legacy kept under `__list__*` keys.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
model Setting {
|
||||||
|
key String @id
|
||||||
|
value Json
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// Promotions / discounts — legacy views/promotion/*, served by
|
||||||
|
// PromotionController (`product/variant/promotion`). The redesigned schema had
|
||||||
|
// no promotion concept at all; this models what the legacy forms actually
|
||||||
|
// collect.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Legacy Promotion.type — what the discount is scoped to.
|
||||||
|
enum PromotionScope {
|
||||||
|
PRODUCT // 1 محصولات
|
||||||
|
CATEGORY // 2 دسته بندی
|
||||||
|
CUSTOMER // 3 مشتری
|
||||||
|
BRAND // 4 برند
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Legacy Promotion.use_only — how often a customer may redeem it.
|
||||||
|
enum PromotionUsage {
|
||||||
|
ONCE // 1 فقط یکبار
|
||||||
|
UNTIL_END_DATE // 2 تا تاریخ پایان
|
||||||
|
}
|
||||||
|
|
||||||
|
model Promotion {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
description String?
|
||||||
|
scope PromotionScope @default(PRODUCT)
|
||||||
|
usage PromotionUsage @default(ONCE)
|
||||||
|
/// Percentage off, 0-100 (legacy discount_percent).
|
||||||
|
discountPercent Decimal @db.Decimal(6, 3)
|
||||||
|
isActive Boolean @default(true)
|
||||||
|
/// Which storefront it shows on, mirroring Product.showType (legacy platform).
|
||||||
|
platform Int @default(3)
|
||||||
|
|
||||||
|
startsAt DateTime?
|
||||||
|
endsAt DateTime?
|
||||||
|
|
||||||
|
/// Exactly one of these is populated, per `scope`.
|
||||||
|
productId String?
|
||||||
|
product Product? @relation(fields: [productId], references: [id])
|
||||||
|
categoryId String?
|
||||||
|
category Category? @relation(fields: [categoryId], references: [id])
|
||||||
|
customerId String?
|
||||||
|
customer Customer? @relation(fields: [customerId], references: [id])
|
||||||
|
brandId String?
|
||||||
|
brand Brand? @relation(fields: [brandId], references: [id])
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
|
@@index([scope, isActive])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Legacy "ignore" table (views/offersIgnore) — specific products, categories,
|
||||||
|
/// customers or brands excluded from the automatic discount engine.
|
||||||
|
/// Legacy posts { type, item_id[] }: "type" reuses the promotion scope codes
|
||||||
|
/// (1 محصولات | 2 دسته بندی | 3 مشتری | 4 برند) and "itemId" is the excluded row.
|
||||||
|
model PromotionExclusion {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
type Int
|
||||||
|
itemId String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@unique([type, itemId])
|
||||||
|
@@index([type])
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// Branch stock allocation — legacy views/invoice/* ("فاکتور انتقال"), served by
|
||||||
|
// BranchController as `branch/product`. Despite the screen being called an
|
||||||
|
// invoice, it is not a sales document: it records which products head office
|
||||||
|
// allocated to a branch, and who allocated them.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
model BranchAllocation {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
branchId String
|
||||||
|
branch Branch @relation(fields: [branchId], references: [id])
|
||||||
|
|
||||||
|
/// Legacy `allocator_user` — the admin who filed the allocation.
|
||||||
|
allocatorAdminUserId String?
|
||||||
|
allocatorAdminUser AdminUser? @relation("AllocationAuthor", fields: [allocatorAdminUserId], references: [id])
|
||||||
|
|
||||||
|
note String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
items BranchAllocationItem[]
|
||||||
|
|
||||||
|
@@index([branchId])
|
||||||
|
}
|
||||||
|
|
||||||
|
model BranchAllocationItem {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
allocationId String
|
||||||
|
allocation BranchAllocation @relation(fields: [allocationId], references: [id], onDelete: Cascade)
|
||||||
|
productId String
|
||||||
|
product Product @relation(fields: [productId], references: [id])
|
||||||
|
/// Weight snapshot at allocation time, so later catalog edits do not rewrite history.
|
||||||
|
weightGrams Decimal? @db.Decimal(14, 4)
|
||||||
|
|
||||||
|
@@unique([allocationId, productId])
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// Messaging + audit — legacy views/sms, views/notify, views/newsletters and
|
||||||
|
// views/statics. None of these had a model in the redesigned schema.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Who an SMS or notification was aimed at. Legacy's sms/create offered these
|
||||||
|
/// audiences, each gated by its own rid (sms.create.all, .omde, .single, ...).
|
||||||
|
enum MessageAudience {
|
||||||
|
SINGLE_NUMBER // یک شماره
|
||||||
|
MULTIPLE_NUMBERS // چند شماره
|
||||||
|
ALL_CUSTOMERS // همه
|
||||||
|
WHOLESALE_CUSTOMERS // عمده
|
||||||
|
RETAIL_CUSTOMERS // تک
|
||||||
|
SALES_AGENTS // کارشناسان فروش
|
||||||
|
}
|
||||||
|
|
||||||
|
model SmsMessage {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
audience MessageAudience
|
||||||
|
/// Comma-separated recipients for the SINGLE/MULTIPLE audiences.
|
||||||
|
recipients String?
|
||||||
|
body String
|
||||||
|
/// How many numbers the send actually resolved to.
|
||||||
|
sentCount Int @default(0)
|
||||||
|
|
||||||
|
sentByAdminUserId String?
|
||||||
|
sentByAdminUser AdminUser? @relation("SmsAuthor", fields: [sentByAdminUserId], references: [id])
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@index([createdAt])
|
||||||
|
}
|
||||||
|
|
||||||
|
model Notification {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
title String
|
||||||
|
body String
|
||||||
|
audience MessageAudience @default(ALL_CUSTOMERS)
|
||||||
|
|
||||||
|
sentByAdminUserId String?
|
||||||
|
sentByAdminUser AdminUser? @relation("NotificationAuthor", fields: [sentByAdminUserId], references: [id])
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
recipients NotificationRecipient[]
|
||||||
|
|
||||||
|
@@index([createdAt])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Per-customer delivery + read state — legacy `GET notify/read/{id}`.
|
||||||
|
model NotificationRecipient {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
notificationId String
|
||||||
|
notification Notification @relation(fields: [notificationId], references: [id], onDelete: Cascade)
|
||||||
|
customerId String
|
||||||
|
customer Customer @relation(fields: [customerId], references: [id])
|
||||||
|
readAt DateTime?
|
||||||
|
|
||||||
|
@@unique([notificationId, customerId])
|
||||||
|
@@index([customerId, readAt])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Legacy views/newsletters — the mailing-list signups collected by the site.
|
||||||
|
model NewsletterSubscriber {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
email String?
|
||||||
|
mobile String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@unique([email])
|
||||||
|
@@unique([mobile])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Legacy views/statics — the customer activity log the "آمار" screen reads
|
||||||
|
/// (`log/list/customer`, `log/ago/{customerId}`).
|
||||||
|
model CustomerActivityLog {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
customerId String
|
||||||
|
customer Customer @relation(fields: [customerId], references: [id])
|
||||||
|
/// Free-form action key, e.g. 'login', 'order.placed', 'profile.updated'.
|
||||||
|
action String
|
||||||
|
detail String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@index([customerId, createdAt])
|
||||||
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// Uploads — replaces the legacy MyUpload / SingleUploadInput widgets, which
|
||||||
|
// POSTed to a file endpoint and stored the returned URL on the owning record.
|
||||||
|
// Ports of those forms currently take a URL by hand; this gives them a real
|
||||||
|
// destination to upload to.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
model UploadedFile {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
/// Public URL the stored file is served from.
|
||||||
|
url String
|
||||||
|
originalName String
|
||||||
|
mimeType String
|
||||||
|
sizeBytes Int
|
||||||
|
/// Free-form tag for what the file belongs to, e.g. 'product', 'category',
|
||||||
|
/// 'customer.nationalId'. Kept loose so a new form needs no schema change.
|
||||||
|
purpose String?
|
||||||
|
|
||||||
|
uploadedByAdminUserId String?
|
||||||
|
uploadedByAdminUser AdminUser? @relation("FileUploader", fields: [uploadedByAdminUserId], references: [id])
|
||||||
|
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
customerAvatars Customer[] @relation("CustomerAvatar")
|
||||||
|
|
||||||
|
@@index([purpose])
|
||||||
|
}
|
||||||
|
|||||||
+215
-2
@@ -125,7 +125,9 @@ exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
|
|||||||
exports.Prisma.CityScalarFieldEnum = {
|
exports.Prisma.CityScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
province: 'province'
|
province: 'province',
|
||||||
|
percent: 'percent',
|
||||||
|
percentAux: 'percentAux'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Prisma.AdminUserScalarFieldEnum = {
|
exports.Prisma.AdminUserScalarFieldEnum = {
|
||||||
@@ -134,6 +136,7 @@ exports.Prisma.AdminUserScalarFieldEnum = {
|
|||||||
mobile: 'mobile',
|
mobile: 'mobile',
|
||||||
passwordHash: 'passwordHash',
|
passwordHash: 'passwordHash',
|
||||||
role: 'role',
|
role: 'role',
|
||||||
|
userTypeId: 'userTypeId',
|
||||||
branchId: 'branchId',
|
branchId: 'branchId',
|
||||||
wagePercent: 'wagePercent',
|
wagePercent: 'wagePercent',
|
||||||
isActive: 'isActive',
|
isActive: 'isActive',
|
||||||
@@ -147,6 +150,13 @@ exports.Prisma.CustomerScalarFieldEnum = {
|
|||||||
nationalCode: 'nationalCode',
|
nationalCode: 'nationalCode',
|
||||||
passwordHash: 'passwordHash',
|
passwordHash: 'passwordHash',
|
||||||
cityId: 'cityId',
|
cityId: 'cityId',
|
||||||
|
kind: 'kind',
|
||||||
|
phone: 'phone',
|
||||||
|
address: 'address',
|
||||||
|
storeName: 'storeName',
|
||||||
|
pasazhName: 'pasazhName',
|
||||||
|
zone: 'zone',
|
||||||
|
memberCode: 'memberCode',
|
||||||
referredByAgentId: 'referredByAgentId',
|
referredByAgentId: 'referredByAgentId',
|
||||||
goldCreditLimitGrams: 'goldCreditLimitGrams',
|
goldCreditLimitGrams: 'goldCreditLimitGrams',
|
||||||
goldDebtGrams: 'goldDebtGrams',
|
goldDebtGrams: 'goldDebtGrams',
|
||||||
@@ -155,7 +165,10 @@ exports.Prisma.CustomerScalarFieldEnum = {
|
|||||||
nationalIdImageUrl: 'nationalIdImageUrl',
|
nationalIdImageUrl: 'nationalIdImageUrl',
|
||||||
businessLicenseUrl: 'businessLicenseUrl',
|
businessLicenseUrl: 'businessLicenseUrl',
|
||||||
shopImageUrl: 'shopImageUrl',
|
shopImageUrl: 'shopImageUrl',
|
||||||
|
avatarFileId: 'avatarFileId',
|
||||||
|
canPlaceOrders: 'canPlaceOrders',
|
||||||
isActive: 'isActive',
|
isActive: 'isActive',
|
||||||
|
isArchived: 'isArchived',
|
||||||
createdAt: 'createdAt',
|
createdAt: 'createdAt',
|
||||||
updatedAt: 'updatedAt'
|
updatedAt: 'updatedAt'
|
||||||
};
|
};
|
||||||
@@ -171,18 +184,29 @@ exports.Prisma.CustomerAddressScalarFieldEnum = {
|
|||||||
exports.Prisma.BranchScalarFieldEnum = {
|
exports.Prisma.BranchScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
address: 'address',
|
||||||
|
phone: 'phone',
|
||||||
|
isActive: 'isActive',
|
||||||
cityId: 'cityId'
|
cityId: 'cityId'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Prisma.WorkshopScalarFieldEnum = {
|
exports.Prisma.WorkshopScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
address: 'address',
|
||||||
|
phone: 'phone',
|
||||||
|
supervisorId: 'supervisorId',
|
||||||
isActive: 'isActive'
|
isActive: 'isActive'
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.Prisma.CategoryScalarFieldEnum = {
|
exports.Prisma.CategoryScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
title: 'title',
|
title: 'title',
|
||||||
|
type: 'type',
|
||||||
|
imageUrl: 'imageUrl',
|
||||||
|
iconUrl: 'iconUrl',
|
||||||
|
metaTag: 'metaTag',
|
||||||
|
description: 'description',
|
||||||
parentId: 'parentId'
|
parentId: 'parentId'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -209,6 +233,8 @@ exports.Prisma.ProductScalarFieldEnum = {
|
|||||||
description: 'description',
|
description: 'description',
|
||||||
categoryId: 'categoryId',
|
categoryId: 'categoryId',
|
||||||
brandId: 'brandId',
|
brandId: 'brandId',
|
||||||
|
productCode: 'productCode',
|
||||||
|
showType: 'showType',
|
||||||
isActive: 'isActive',
|
isActive: 'isActive',
|
||||||
createdAt: 'createdAt'
|
createdAt: 'createdAt'
|
||||||
};
|
};
|
||||||
@@ -227,6 +253,8 @@ exports.Prisma.ProductVariantScalarFieldEnum = {
|
|||||||
sku: 'sku',
|
sku: 'sku',
|
||||||
rashWeightGrams: 'rashWeightGrams',
|
rashWeightGrams: 'rashWeightGrams',
|
||||||
defaultWagePercent: 'defaultWagePercent',
|
defaultWagePercent: 'defaultWagePercent',
|
||||||
|
qty: 'qty',
|
||||||
|
isPreOrder: 'isPreOrder',
|
||||||
isActive: 'isActive'
|
isActive: 'isActive'
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -235,6 +263,7 @@ exports.Prisma.OrderScalarFieldEnum = {
|
|||||||
orderNumber: 'orderNumber',
|
orderNumber: 'orderNumber',
|
||||||
customerId: 'customerId',
|
customerId: 'customerId',
|
||||||
branchId: 'branchId',
|
branchId: 'branchId',
|
||||||
|
channel: 'channel',
|
||||||
status: 'status',
|
status: 'status',
|
||||||
totalGoldWeightGrams: 'totalGoldWeightGrams',
|
totalGoldWeightGrams: 'totalGoldWeightGrams',
|
||||||
wageWeightGrams: 'wageWeightGrams',
|
wageWeightGrams: 'wageWeightGrams',
|
||||||
@@ -308,6 +337,14 @@ exports.Prisma.LedgerEntryScalarFieldEnum = {
|
|||||||
confirmed: 'confirmed',
|
confirmed: 'confirmed',
|
||||||
confirmedAt: 'confirmedAt',
|
confirmedAt: 'confirmedAt',
|
||||||
postedByAdminUserId: 'postedByAdminUserId',
|
postedByAdminUserId: 'postedByAdminUserId',
|
||||||
|
labName: 'labName',
|
||||||
|
hallmark: 'hallmark',
|
||||||
|
accountName: 'accountName',
|
||||||
|
bankName: 'bankName',
|
||||||
|
transferTo: 'transferTo',
|
||||||
|
originalValue: 'originalValue',
|
||||||
|
priceRial: 'priceRial',
|
||||||
|
receivedAt: 'receivedAt',
|
||||||
note: 'note',
|
note: 'note',
|
||||||
createdAt: 'createdAt'
|
createdAt: 'createdAt'
|
||||||
};
|
};
|
||||||
@@ -331,6 +368,128 @@ exports.Prisma.WalletBonusScalarFieldEnum = {
|
|||||||
isActive: 'isActive'
|
isActive: 'isActive'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.Prisma.UserTypeScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
title: 'title',
|
||||||
|
isActive: 'isActive',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.PermissionScalarFieldEnum = {
|
||||||
|
rid: 'rid',
|
||||||
|
userTypeId: 'userTypeId'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.CommentScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
productId: 'productId',
|
||||||
|
customerId: 'customerId',
|
||||||
|
body: 'body',
|
||||||
|
status: 'status',
|
||||||
|
replyToId: 'replyToId',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.SettingScalarFieldEnum = {
|
||||||
|
key: 'key',
|
||||||
|
value: 'value',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.PromotionScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
title: 'title',
|
||||||
|
description: 'description',
|
||||||
|
scope: 'scope',
|
||||||
|
usage: 'usage',
|
||||||
|
discountPercent: 'discountPercent',
|
||||||
|
isActive: 'isActive',
|
||||||
|
platform: 'platform',
|
||||||
|
startsAt: 'startsAt',
|
||||||
|
endsAt: 'endsAt',
|
||||||
|
productId: 'productId',
|
||||||
|
categoryId: 'categoryId',
|
||||||
|
customerId: 'customerId',
|
||||||
|
brandId: 'brandId',
|
||||||
|
createdAt: 'createdAt',
|
||||||
|
updatedAt: 'updatedAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.PromotionExclusionScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
type: 'type',
|
||||||
|
itemId: 'itemId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.BranchAllocationScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
branchId: 'branchId',
|
||||||
|
allocatorAdminUserId: 'allocatorAdminUserId',
|
||||||
|
note: 'note',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.BranchAllocationItemScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
allocationId: 'allocationId',
|
||||||
|
productId: 'productId',
|
||||||
|
weightGrams: 'weightGrams'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.SmsMessageScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
audience: 'audience',
|
||||||
|
recipients: 'recipients',
|
||||||
|
body: 'body',
|
||||||
|
sentCount: 'sentCount',
|
||||||
|
sentByAdminUserId: 'sentByAdminUserId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.NotificationScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
title: 'title',
|
||||||
|
body: 'body',
|
||||||
|
audience: 'audience',
|
||||||
|
sentByAdminUserId: 'sentByAdminUserId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.NotificationRecipientScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
notificationId: 'notificationId',
|
||||||
|
customerId: 'customerId',
|
||||||
|
readAt: 'readAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.NewsletterSubscriberScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
email: 'email',
|
||||||
|
mobile: 'mobile',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.CustomerActivityLogScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
customerId: 'customerId',
|
||||||
|
action: 'action',
|
||||||
|
detail: 'detail',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Prisma.UploadedFileScalarFieldEnum = {
|
||||||
|
id: 'id',
|
||||||
|
url: 'url',
|
||||||
|
originalName: 'originalName',
|
||||||
|
mimeType: 'mimeType',
|
||||||
|
sizeBytes: 'sizeBytes',
|
||||||
|
purpose: 'purpose',
|
||||||
|
uploadedByAdminUserId: 'uploadedByAdminUserId',
|
||||||
|
createdAt: 'createdAt'
|
||||||
|
};
|
||||||
|
|
||||||
exports.Prisma.SortOrder = {
|
exports.Prisma.SortOrder = {
|
||||||
asc: 'asc',
|
asc: 'asc',
|
||||||
desc: 'desc'
|
desc: 'desc'
|
||||||
@@ -363,6 +522,14 @@ exports.AdminRole = exports.$Enums.AdminRole = {
|
|||||||
ACCOUNTANT: 'ACCOUNTANT'
|
ACCOUNTANT: 'ACCOUNTANT'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.CustomerKind = exports.$Enums.CustomerKind = {
|
||||||
|
SALES_AGENT: 'SALES_AGENT',
|
||||||
|
APP_SHOPKEEPER: 'APP_SHOPKEEPER',
|
||||||
|
WALK_IN_SHOPKEEPER: 'WALK_IN_SHOPKEEPER',
|
||||||
|
BANKER: 'BANKER',
|
||||||
|
WORKSHOP_SUPERVISOR: 'WORKSHOP_SUPERVISOR'
|
||||||
|
};
|
||||||
|
|
||||||
exports.VerificationStep = exports.$Enums.VerificationStep = {
|
exports.VerificationStep = exports.$Enums.VerificationStep = {
|
||||||
UNVERIFIED: 'UNVERIFIED',
|
UNVERIFIED: 'UNVERIFIED',
|
||||||
STEP_ONE_SUBMITTED: 'STEP_ONE_SUBMITTED',
|
STEP_ONE_SUBMITTED: 'STEP_ONE_SUBMITTED',
|
||||||
@@ -370,6 +537,11 @@ exports.VerificationStep = exports.$Enums.VerificationStep = {
|
|||||||
VERIFIED: 'VERIFIED'
|
VERIFIED: 'VERIFIED'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.OrderChannel = exports.$Enums.OrderChannel = {
|
||||||
|
RETAIL: 'RETAIL',
|
||||||
|
WHOLESALE: 'WHOLESALE'
|
||||||
|
};
|
||||||
|
|
||||||
exports.OrderStatus = exports.$Enums.OrderStatus = {
|
exports.OrderStatus = exports.$Enums.OrderStatus = {
|
||||||
SUSPENDED: 'SUSPENDED',
|
SUSPENDED: 'SUSPENDED',
|
||||||
PLACED: 'PLACED',
|
PLACED: 'PLACED',
|
||||||
@@ -411,6 +583,33 @@ exports.LedgerSourceType = exports.$Enums.LedgerSourceType = {
|
|||||||
ADJUSTMENT: 'ADJUSTMENT'
|
ADJUSTMENT: 'ADJUSTMENT'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.CommentStatus = exports.$Enums.CommentStatus = {
|
||||||
|
PENDING: 'PENDING',
|
||||||
|
APPROVED: 'APPROVED',
|
||||||
|
REJECTED: 'REJECTED'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.PromotionScope = exports.$Enums.PromotionScope = {
|
||||||
|
PRODUCT: 'PRODUCT',
|
||||||
|
CATEGORY: 'CATEGORY',
|
||||||
|
CUSTOMER: 'CUSTOMER',
|
||||||
|
BRAND: 'BRAND'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.PromotionUsage = exports.$Enums.PromotionUsage = {
|
||||||
|
ONCE: 'ONCE',
|
||||||
|
UNTIL_END_DATE: 'UNTIL_END_DATE'
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.MessageAudience = exports.$Enums.MessageAudience = {
|
||||||
|
SINGLE_NUMBER: 'SINGLE_NUMBER',
|
||||||
|
MULTIPLE_NUMBERS: 'MULTIPLE_NUMBERS',
|
||||||
|
ALL_CUSTOMERS: 'ALL_CUSTOMERS',
|
||||||
|
WHOLESALE_CUSTOMERS: 'WHOLESALE_CUSTOMERS',
|
||||||
|
RETAIL_CUSTOMERS: 'RETAIL_CUSTOMERS',
|
||||||
|
SALES_AGENTS: 'SALES_AGENTS'
|
||||||
|
};
|
||||||
|
|
||||||
exports.Prisma.ModelName = {
|
exports.Prisma.ModelName = {
|
||||||
City: 'City',
|
City: 'City',
|
||||||
AdminUser: 'AdminUser',
|
AdminUser: 'AdminUser',
|
||||||
@@ -432,7 +631,21 @@ exports.Prisma.ModelName = {
|
|||||||
PreOrderStatusEvent: 'PreOrderStatusEvent',
|
PreOrderStatusEvent: 'PreOrderStatusEvent',
|
||||||
LedgerEntry: 'LedgerEntry',
|
LedgerEntry: 'LedgerEntry',
|
||||||
GoldPriceQuote: 'GoldPriceQuote',
|
GoldPriceQuote: 'GoldPriceQuote',
|
||||||
WalletBonus: 'WalletBonus'
|
WalletBonus: 'WalletBonus',
|
||||||
|
UserType: 'UserType',
|
||||||
|
Permission: 'Permission',
|
||||||
|
Comment: 'Comment',
|
||||||
|
Setting: 'Setting',
|
||||||
|
Promotion: 'Promotion',
|
||||||
|
PromotionExclusion: 'PromotionExclusion',
|
||||||
|
BranchAllocation: 'BranchAllocation',
|
||||||
|
BranchAllocationItem: 'BranchAllocationItem',
|
||||||
|
SmsMessage: 'SmsMessage',
|
||||||
|
Notification: 'Notification',
|
||||||
|
NotificationRecipient: 'NotificationRecipient',
|
||||||
|
NewsletterSubscriber: 'NewsletterSubscriber',
|
||||||
|
CustomerActivityLog: 'CustomerActivityLog',
|
||||||
|
UploadedFile: 'UploadedFile'
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user