Merge release/delivery (IAM single sign-on) into the triage work

Brings the four release/delivery commits (IAM SSO for the admin panel,
both apps and the API; IAM env in docker-compose) onto fix/issues-triage.

Conflicts:
- customer-auth.service.ts imports: both kept.
- both apps' api/client.ts: both kept (AccountingBalance/WageQuote, and
  iamAppUrl).
- all build output (admin-panel, user-app, user-app-v2 dist, and the api
  release bundle): rebuilt from the merged source instead of picking a
  side.

Fixed while verifying:
- The IAM change calls iam.browserBootstrapUrl after every login, but
  the identity-service stand-ins in three test files lacked it. 15 tests
  failed on release/delivery itself.
- SMS relay: SMS_RELAY_PLATFORM was read but never sent, so the gateway
  never got `platform` (documented body: phone, host, text, platform).
  relayConfig() now returns it ("default" → null) and the request carries
  it. sms.service.spec now passes.

All 249 API tests pass; the three front-ends type-check and build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
s.esmaeili
2026-10-10 09:03:53 +03:30
co-authored by Claude Opus 5.5
315 changed files with 82919 additions and 7020 deletions
+9
View File
@@ -0,0 +1,9 @@
class PrismaClient {
constructor() {
throw new Error(
'@prisma/client/deno/edge did not initialize yet. Please run "prisma generate" and try to import it again.',
)
}
}
export { PrismaClient }
File diff suppressed because one or more lines are too long
+97 -3
View File
@@ -125,7 +125,7 @@ exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
exports.Prisma.CityScalarFieldEnum = {
id: 'id',
name: 'name',
province: 'province',
parentId: 'parentId',
percent: 'percent',
percentAux: 'percentAux'
};
@@ -203,6 +203,7 @@ exports.Prisma.CustomerScalarFieldEnum = {
nationalCode: 'nationalCode',
passwordHash: 'passwordHash',
cityId: 'cityId',
cityNameRaw: 'cityNameRaw',
kind: 'kind',
phone: 'phone',
address: 'address',
@@ -214,11 +215,17 @@ exports.Prisma.CustomerScalarFieldEnum = {
goldCreditLimitGrams: 'goldCreditLimitGrams',
goldDebtGrams: 'goldDebtGrams',
fiatDebtRial: 'fiatDebtRial',
accountingGoldBalance: 'accountingGoldBalance',
accountingRialBalance: 'accountingRialBalance',
accountingBalanceAt: 'accountingBalanceAt',
makingChargeOffsetPercent: 'makingChargeOffsetPercent',
verificationStep: 'verificationStep',
nationalIdImageUrl: 'nationalIdImageUrl',
businessLicenseUrl: 'businessLicenseUrl',
shopImageUrl: 'shopImageUrl',
verificationRejectionReason: 'verificationRejectionReason',
verificationRejectedAt: 'verificationRejectedAt',
birthDate: 'birthDate',
avatarFileId: 'avatarFileId',
canPlaceOrders: 'canPlaceOrders',
isActive: 'isActive',
@@ -227,6 +234,12 @@ exports.Prisma.CustomerScalarFieldEnum = {
updatedAt: 'updatedAt'
};
exports.Prisma.CustomerFavoriteScalarFieldEnum = {
customerId: 'customerId',
productId: 'productId',
createdAt: 'createdAt'
};
exports.Prisma.CustomerAddressScalarFieldEnum = {
id: 'id',
customerId: 'customerId',
@@ -290,7 +303,10 @@ exports.Prisma.ProductScalarFieldEnum = {
productCode: 'productCode',
showType: 'showType',
isActive: 'isActive',
createdAt: 'createdAt'
createdAt: 'createdAt',
accountingStockWeight: 'accountingStockWeight',
accountingStockCount: 'accountingStockCount',
accountingStockAt: 'accountingStockAt'
};
exports.Prisma.ProductImageScalarFieldEnum = {
@@ -326,6 +342,8 @@ exports.Prisma.OrderScalarFieldEnum = {
flatRialCharge: 'flatRialCharge',
isSuspendedOverCreditLimit: 'isSuspendedOverCreditLimit',
deliveredAt: 'deliveredAt',
salesAgentId: 'salesAgentId',
referrerCustomerId: 'referrerCustomerId',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
@@ -453,6 +471,51 @@ exports.Prisma.SettingScalarFieldEnum = {
updatedAt: 'updatedAt'
};
exports.Prisma.AccountingLinkScalarFieldEnum = {
id: 'id',
provider: 'provider',
entityType: 'entityType',
entityId: 'entityId',
externalCode: 'externalCode',
externalName: 'externalName',
origin: 'origin',
snapshot: 'snapshot',
syncedAt: 'syncedAt',
createdAt: 'createdAt'
};
exports.Prisma.AccountingOutboxScalarFieldEnum = {
id: 'id',
provider: 'provider',
kind: 'kind',
entityId: 'entityId',
status: 'status',
attempts: 'attempts',
nextAttemptAt: 'nextAttemptAt',
lastError: 'lastError',
externalRef: 'externalRef',
progress: 'progress',
lastRequest: 'lastRequest',
lastResponse: 'lastResponse',
sentAt: 'sentAt',
resolvedById: 'resolvedById',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.AccountingIssueScalarFieldEnum = {
id: 'id',
provider: 'provider',
kind: 'kind',
externalCode: 'externalCode',
entityId: 'entityId',
message: 'message',
data: 'data',
createdAt: 'createdAt',
updatedAt: 'updatedAt',
resolvedAt: 'resolvedAt'
};
exports.Prisma.PromotionScalarFieldEnum = {
id: 'id',
title: 'title',
@@ -567,6 +630,11 @@ exports.Prisma.JsonNullValueInput = {
JsonNull: Prisma.JsonNull
};
exports.Prisma.NullableJsonNullValueInput = {
DbNull: Prisma.DbNull,
JsonNull: Prisma.JsonNull
};
exports.Prisma.QueryMode = {
default: 'default',
insensitive: 'insensitive'
@@ -603,7 +671,8 @@ exports.VerificationStep = exports.$Enums.VerificationStep = {
UNVERIFIED: 'UNVERIFIED',
STEP_ONE_SUBMITTED: 'STEP_ONE_SUBMITTED',
STEP_TWO_SUBMITTED: 'STEP_TWO_SUBMITTED',
VERIFIED: 'VERIFIED'
VERIFIED: 'VERIFIED',
REJECTED: 'REJECTED'
};
exports.ProductImageRole = exports.$Enums.ProductImageRole = {
@@ -665,6 +734,27 @@ exports.CommentStatus = exports.$Enums.CommentStatus = {
REJECTED: 'REJECTED'
};
exports.AccountingEntityType = exports.$Enums.AccountingEntityType = {
CUSTOMER: 'CUSTOMER',
PRODUCT: 'PRODUCT'
};
exports.AccountingOutboxKind = exports.$Enums.AccountingOutboxKind = {
CUSTOMER_PUSH: 'CUSTOMER_PUSH',
PRODUCT_PUSH: 'PRODUCT_PUSH',
ORDER_DOCUMENT: 'ORDER_DOCUMENT',
ORDER_DOCUMENT_DELETE: 'ORDER_DOCUMENT_DELETE'
};
exports.AccountingOutboxStatus = exports.$Enums.AccountingOutboxStatus = {
PENDING: 'PENDING',
SENDING: 'SENDING',
SENT: 'SENT',
FAILED: 'FAILED',
NEEDS_REVIEW: 'NEEDS_REVIEW',
RESOLVED: 'RESOLVED'
};
exports.PromotionScope = exports.$Enums.PromotionScope = {
PRODUCT: 'PRODUCT',
CATEGORY: 'CATEGORY',
@@ -693,6 +783,7 @@ exports.Prisma.ModelName = {
AdminSession: 'AdminSession',
SalesExpertProfile: 'SalesExpertProfile',
Customer: 'Customer',
CustomerFavorite: 'CustomerFavorite',
CustomerAddress: 'CustomerAddress',
Branch: 'Branch',
Workshop: 'Workshop',
@@ -715,6 +806,9 @@ exports.Prisma.ModelName = {
Permission: 'Permission',
Comment: 'Comment',
Setting: 'Setting',
AccountingLink: 'AccountingLink',
AccountingOutbox: 'AccountingOutbox',
AccountingIssue: 'AccountingIssue',
Promotion: 'Promotion',
PromotionExclusion: 'PromotionExclusion',
BranchAllocation: 'BranchAllocation',
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "prisma-client-e72c5c915e96796902913fde6ec160a337ad8fec683314696d8bd7a12ac26468",
"name": "prisma-client-9161dfb7f2a3ada2b72c27c7a91664048e7f0e5d5d265a0abff1e443711c8388",
"main": "index.js",
"types": "index.d.ts",
"browser": "index-browser.js",
+233 -2
View File
@@ -56,6 +56,13 @@ enum VerificationStep {
STEP_ONE_SUBMITTED
STEP_TWO_SUBMITTED
VERIFIED
/// Legacy had THREE states per step, not two
/// (MajorCustomerController.php:106-135): 1 = awaiting, 2 = approved,
/// 3 = REJECTED. Mapping rejected customers to UNVERIFIED would put closed
/// cases back in the review queue, so the owner ruled it out (2026-10-07).
/// 14 legacy rows land here; see Customer.verificationRejectionReason.
REJECTED
}
/// Legacy kept retail and wholesale orders in two SEPARATE tables
@@ -111,10 +118,15 @@ enum LedgerSourceType {
// Identity
// ─────────────────────────────────────────────────────────────────────────
/// Legacy `cities` is a tree (country > province > city > district) and so is
/// this: a city hangs under its `parent`. In the admin pickers a top-level row
/// (the country) is a heading, not selectable (henza_admin citiesModel.js:38).
model City {
id String @id @default(cuid())
name String
province String?
parentId String?
parent City? @relation("CityTree", fields: [parentId], references: [id], onDelete: Restrict)
children City[] @relation("CityTree")
/// Legacy cities.percent / percent_aux — per-city wage surcharges the city
/// screen edits through GET cities/get-percent/{id} and get-percent-aux/{id}.
percent Decimal? @db.Decimal(6, 3)
@@ -124,6 +136,8 @@ model City {
branches Branch[]
preOrders PreOrder[]
salesExpertProfiles SalesExpertProfile[]
@@index([parentId])
}
model AdminUser {
@@ -172,6 +186,8 @@ model AdminUser {
memberCode String? // legacy mcode
referredCustomers Customer[] @relation("ReferralAgent")
/// Orders credited to this sales expert — see Order.salesAgentId.
creditedOrders Order[] @relation("OrderSalesAgent")
supervisedWorkshops Workshop[] @relation("WorkshopSupervisor")
branchAllocations BranchAllocation[] @relation("AllocationAuthor")
postedLedgerEntries LedgerEntry[]
@@ -367,11 +383,32 @@ model Customer {
lastName String?
mobile String @unique
nationalCode String @unique
/// Legacy customers.ncode. OPTIONAL since 2026-10-07: not one of the 1,616
/// legacy customers has a national code (1595/1595 empty), and fabricating
/// one is a data violation that would block later legal identity checks
/// (owner ruling). Still @unique — in PostgreSQL NULLs do not collide, so
/// the migration tool must write NULL and never '', which would collide on
/// the second row.
///
/// Three service-layer workarounds exist ONLY because this used to be
/// required, and they store the MOBILE NUMBER here:
/// admin-customers.service.ts:625,685 and customer-auth.service.ts:258.
/// Retiring them is a separate change; see docs/DATA-MIGRATION-MAP.md §10.4.
nationalCode String? @unique
passwordHash String
cityId String?
city City? @relation(fields: [cityId], references: [id])
/// Legacy customers.new_city — the city name exactly as the customer typed it
/// at app sign-up (Major/CustomerController.php:36). Kept verbatim because
/// the legacy city table has only 15 rows, so the typed name is often the only
/// record of where the customer is (172 customers; 43 match no known city).
/// cityId is set alongside it only on an exact, ي/ك-normalised name match.
/// Legacy sign-up also forced city_id = 5 (Tehran) on everyone
/// (Major/CustomerController.php:21), so for those rows the typed name, not
/// cityId, is the truth. Owner ruling 2026-10-07: keep both.
cityNameRaw String?
/// Legacy Customer.type — distinguishes بنکدار from مغازه دار, which the
/// BankerList / ShopkeeperList screens filter on.
kind CustomerKind @default(APP_SHOPKEEPER)
@@ -393,6 +430,9 @@ model Customer {
/// account (see SalesExpertProfile.tradingCustomerId). Empty for every
/// ordinary customer.
salesExpertTradingFor SalesExpertProfile? @relation("SalesExpertTradingAccount")
/// Legacy orders that named THIS customer as their referrer — see
/// Order.referrerCustomerId. History only.
referredOrders Order[] @relation("OrderReferrerCustomer")
// Credit limit + cached ledger balances (source of truth is LedgerEntry; these
// are denormalized for fast reads and reconciled by a scheduled job).
@@ -400,6 +440,14 @@ model Customer {
goldDebtGrams Decimal @default(0) @db.Decimal(14, 4) // legacy remain
fiatDebtRial Decimal @default(0) @db.Decimal(20, 2) // legacy rial_remain
/// Balance as last read from the accounting software (D27), in the app's own
/// sign convention (positive = owes). Shown to the customer when the
/// integration is on; the credit-limit check still uses goldDebtGrams above.
/// Null until the first successful sync.
accountingGoldBalance Decimal? @db.Decimal(14, 4)
accountingRialBalance Decimal? @db.Decimal(20, 2)
accountingBalanceAt DateTime?
/// Legacy `customers.percent` — the per-customer making-charge offset. It is
/// ADDED to the variant's making charge when pricing an order line
/// (henza_pwa src/Mixins/product/index.ts:69-75:
@@ -421,6 +469,30 @@ model Customer {
businessLicenseUrl String?
shopImageUrl String?
/// Why verification was rejected (VerificationStep.REJECTED).
///
/// Legacy recorded NO reason: none of its 49 `customers` columns is a
/// reason/note field, and on rejection it only sent a fixed SMS. So the 14
/// rows migrated from henza carry the sentinel
/// «رد شده در سیستم قدیم — فاقد شرح علت ثبت‌شده» instead of NULL, so support
/// knows why it is blank (owner ruling 2026-10-07). The migration tool
/// writes it only WHERE this IS NULL, so a re-run cannot overwrite a real
/// reason entered in the new system.
verificationRejectionReason String?
/// NULL for rows migrated from henza — legacy recorded no rejection time.
verificationRejectedAt DateTime?
/// Legacy customers.birth_date, populated on 917 of 1,595 rows. Kept for the
/// birthday SMS / loyalty campaigns (owner ruling 2026-10-07).
///
/// ⚠ Legacy stores dates as JALALI STRINGS in other tables
/// (cashes.recive_date is varchar, 88/89 values starting "14…"), so this
/// timestamp may hold mis-entered Jalali years. Confirm the calendar with
/// docs/migration-precheck-3.sql BEFORE backfilling: copying them unchanged
/// would produce 917 wrong birthdays, worse for an SMS campaign than none.
birthDate DateTime?
/// Legacy `image_id` — the profile photo (عکس پروفایل) on the sales-agent
/// form. Legacy stored an FK to its Image table and read it back as a nested
/// `image: { id, image }`, so this is a relation, not a bare URL string.
@@ -449,12 +521,35 @@ model Customer {
notifications NotificationRecipient[]
activityLogs CustomerActivityLog[]
otpChallenges CustomerOtp[]
favorites CustomerFavorite[]
@@index([referredByAgentId])
@@index([firstName])
@@index([lastName])
}
/// Legacy `fav` (251 rows) — saved products. The target had no model for this,
/// so every customer's favourites would have been lost in the migration; the
/// owner confirmed on 2026-10-06 that they matter.
///
/// Legacy `fav` has two columns and NO primary key. The composite key here
/// supplies the constraint the source lacks (the precheck found 0 duplicate
/// pairs, but the tool should still SELECT DISTINCT). 14 of the 251 rows point
/// at a deleted customer and must be skipped.
///
/// Legacy's denormalised `product.count_fav` counter is deliberately NOT
/// recreated as a column — derive it from this table.
model CustomerFavorite {
customerId String
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
productId String
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
@@id([customerId, productId])
@@index([productId])
}
model CustomerAddress {
id String @id @default(cuid())
customerId String
@@ -557,12 +652,21 @@ model Product {
isActive Boolean @default(true)
createdAt DateTime @default(now())
/// Stock of the linked کارساخته as last read from the accounting software
/// (D27). Weight for gram-type items, count for count-type ones — whichever
/// the software reports. At zero or below the product is unavailable in the
/// app (pre-order variants excepted). Null = not linked or never synced.
accountingStockWeight Decimal? @db.Decimal(14, 4)
accountingStockCount Decimal? @db.Decimal(14, 4)
accountingStockAt DateTime?
variants ProductVariant[]
images ProductImage[]
collections CollectionProduct[]
comments Comment[]
promotions Promotion[]
allocationItems BranchAllocationItem[]
favoritedBy CustomerFavorite[]
}
model ProductImage {
@@ -644,6 +748,22 @@ model Order {
isSuspendedOverCreditLimit Boolean @default(false)
deliveredAt DateTime? // setting this is what triggers debt recognition
/// The sales expert this order is credited to, fixed when it is placed:
/// the customer's referring expert AT THAT MOMENT. Legacy `orders.reagent_id`,
/// set once at creation (ApiMobileController.php:601) and never moved, so a
/// customer changing expert later does not move past sales or commission
/// (owner ruling 2026-10-08). «میزان فروش» counts from here, never from the
/// customer's current referrer.
salesAgentId String?
salesAgent AdminUser? @relation("OrderSalesAgent", fields: [salesAgentId], references: [id], onDelete: SetNull)
/// History only: a legacy order whose `reagent_id` named a customer who is
/// not a sales expert (one such customer, 17 orders in 2022). Legacy counted
/// those orders in that customer's own «میزان فروش»; this keeps that figure
/// exact. Never set for a new order.
referrerCustomerId String?
referrerCustomer Customer? @relation("OrderReferrerCustomer", fields: [referrerCustomerId], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -654,6 +774,8 @@ model Order {
@@index([customerId])
@@index([status])
@@index([salesAgentId])
@@index([referrerCustomerId])
}
model OrderItem {
@@ -911,6 +1033,115 @@ model Setting {
updatedAt DateTime @updatedAt
}
// ─────────────────────────────────────────────────────────────────────────
// Accounting integration (D27) — the shop's accounting software, Tahesab or
// Zarrin, chosen in the admin panel. Configuration lives in the Setting row
// `accounting.config` (never served by the generic `const` routes). Plan:
// docs/ACCOUNTING-INTEGRATION-PLAN.md.
//
// `provider` is the driver name ('tahesab' | 'zarrin'), a plain string like
// SMS_PROVIDER so a new driver needs no migration. Links are per provider, so
// switching provider and back loses nothing.
// ─────────────────────────────────────────────────────────────────────────
enum AccountingEntityType {
CUSTOMER
PRODUCT
}
/// One app row ↔ one record in the accounting software (customer account or
/// کارساخته).
model AccountingLink {
id String @id @default(cuid())
provider String
entityType AccountingEntityType
entityId String
/// The record's code in the accounting software (Tahesab Moshtari_Code /
/// Zarrin idHesab; for products the Zarrin idKar or the Tahesab Name_Kar).
externalCode String
externalName String?
/// How the link came to be: LINKED (matched by mobile/name), IMPORTED (app
/// row created from the accounting record), PUSHED (accounting record created
/// from the app row) or MANUAL (an admin typed the code).
origin String
/// The record as last read, for display only.
snapshot Json?
syncedAt DateTime @default(now())
createdAt DateTime @default(now())
@@unique([provider, entityType, entityId])
@@unique([provider, entityType, externalCode])
@@index([entityType, entityId])
}
enum AccountingOutboxKind {
CUSTOMER_PUSH
PRODUCT_PUSH
ORDER_DOCUMENT
ORDER_DOCUMENT_DELETE
}
enum AccountingOutboxStatus {
PENDING
/// A call was in flight. Found at startup, it means the process died mid-call
/// and the outcome is unknown — see AccountingOutboxWorker.
SENDING
SENT
FAILED
/// Unsafe to retry automatically (e.g. a Zarrin call timed out: Zarrin has no
/// idempotency key, so a blind retry could post the document twice).
NEEDS_REVIEW
/// Closed by an admin from the log screen.
RESOLVED
}
/// Work to push to the accounting software. Written in the SAME transaction as
/// the change that causes it, so an outage of the accounting software never
/// loses an event and never blocks the app.
model AccountingOutbox {
id String @id @default(cuid())
provider String
kind AccountingOutboxKind
entityId String
status AccountingOutboxStatus @default(PENDING)
attempts Int @default(0)
nextAttemptAt DateTime @default(now())
lastError String?
/// What the accounting software returned as the document/record id.
externalRef String?
/// Per-step progress of multi-call jobs (a Zarrin document is one call per
/// line), so a failure resumes where it stopped.
progress Json?
/// Last request/response, for the log screen. Never contains the token.
lastRequest Json?
lastResponse Json?
sentAt DateTime?
resolvedById String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([status, nextAttemptAt])
@@index([kind, entityId])
}
/// Something a pull found that needs a human: an account with no mobile, two
/// accounts sharing one mobile, a کارساخته group with no category mapping.
model AccountingIssue {
id String @id @default(cuid())
provider String
kind String
externalCode String
entityId String?
message String
data Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
resolvedAt DateTime?
@@unique([provider, kind, externalCode])
@@index([resolvedAt])
}
// ─────────────────────────────────────────────────────────────────────────
// Promotions / discounts — legacy views/promotion/*, served by
// PromotionController (`product/variant/promotion`). The redesigned schema had
+97 -3
View File
@@ -125,7 +125,7 @@ exports.Prisma.TransactionIsolationLevel = makeStrictEnum({
exports.Prisma.CityScalarFieldEnum = {
id: 'id',
name: 'name',
province: 'province',
parentId: 'parentId',
percent: 'percent',
percentAux: 'percentAux'
};
@@ -203,6 +203,7 @@ exports.Prisma.CustomerScalarFieldEnum = {
nationalCode: 'nationalCode',
passwordHash: 'passwordHash',
cityId: 'cityId',
cityNameRaw: 'cityNameRaw',
kind: 'kind',
phone: 'phone',
address: 'address',
@@ -214,11 +215,17 @@ exports.Prisma.CustomerScalarFieldEnum = {
goldCreditLimitGrams: 'goldCreditLimitGrams',
goldDebtGrams: 'goldDebtGrams',
fiatDebtRial: 'fiatDebtRial',
accountingGoldBalance: 'accountingGoldBalance',
accountingRialBalance: 'accountingRialBalance',
accountingBalanceAt: 'accountingBalanceAt',
makingChargeOffsetPercent: 'makingChargeOffsetPercent',
verificationStep: 'verificationStep',
nationalIdImageUrl: 'nationalIdImageUrl',
businessLicenseUrl: 'businessLicenseUrl',
shopImageUrl: 'shopImageUrl',
verificationRejectionReason: 'verificationRejectionReason',
verificationRejectedAt: 'verificationRejectedAt',
birthDate: 'birthDate',
avatarFileId: 'avatarFileId',
canPlaceOrders: 'canPlaceOrders',
isActive: 'isActive',
@@ -227,6 +234,12 @@ exports.Prisma.CustomerScalarFieldEnum = {
updatedAt: 'updatedAt'
};
exports.Prisma.CustomerFavoriteScalarFieldEnum = {
customerId: 'customerId',
productId: 'productId',
createdAt: 'createdAt'
};
exports.Prisma.CustomerAddressScalarFieldEnum = {
id: 'id',
customerId: 'customerId',
@@ -290,7 +303,10 @@ exports.Prisma.ProductScalarFieldEnum = {
productCode: 'productCode',
showType: 'showType',
isActive: 'isActive',
createdAt: 'createdAt'
createdAt: 'createdAt',
accountingStockWeight: 'accountingStockWeight',
accountingStockCount: 'accountingStockCount',
accountingStockAt: 'accountingStockAt'
};
exports.Prisma.ProductImageScalarFieldEnum = {
@@ -326,6 +342,8 @@ exports.Prisma.OrderScalarFieldEnum = {
flatRialCharge: 'flatRialCharge',
isSuspendedOverCreditLimit: 'isSuspendedOverCreditLimit',
deliveredAt: 'deliveredAt',
salesAgentId: 'salesAgentId',
referrerCustomerId: 'referrerCustomerId',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
@@ -453,6 +471,51 @@ exports.Prisma.SettingScalarFieldEnum = {
updatedAt: 'updatedAt'
};
exports.Prisma.AccountingLinkScalarFieldEnum = {
id: 'id',
provider: 'provider',
entityType: 'entityType',
entityId: 'entityId',
externalCode: 'externalCode',
externalName: 'externalName',
origin: 'origin',
snapshot: 'snapshot',
syncedAt: 'syncedAt',
createdAt: 'createdAt'
};
exports.Prisma.AccountingOutboxScalarFieldEnum = {
id: 'id',
provider: 'provider',
kind: 'kind',
entityId: 'entityId',
status: 'status',
attempts: 'attempts',
nextAttemptAt: 'nextAttemptAt',
lastError: 'lastError',
externalRef: 'externalRef',
progress: 'progress',
lastRequest: 'lastRequest',
lastResponse: 'lastResponse',
sentAt: 'sentAt',
resolvedById: 'resolvedById',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.AccountingIssueScalarFieldEnum = {
id: 'id',
provider: 'provider',
kind: 'kind',
externalCode: 'externalCode',
entityId: 'entityId',
message: 'message',
data: 'data',
createdAt: 'createdAt',
updatedAt: 'updatedAt',
resolvedAt: 'resolvedAt'
};
exports.Prisma.PromotionScalarFieldEnum = {
id: 'id',
title: 'title',
@@ -567,6 +630,11 @@ exports.Prisma.JsonNullValueInput = {
JsonNull: Prisma.JsonNull
};
exports.Prisma.NullableJsonNullValueInput = {
DbNull: Prisma.DbNull,
JsonNull: Prisma.JsonNull
};
exports.Prisma.QueryMode = {
default: 'default',
insensitive: 'insensitive'
@@ -603,7 +671,8 @@ exports.VerificationStep = exports.$Enums.VerificationStep = {
UNVERIFIED: 'UNVERIFIED',
STEP_ONE_SUBMITTED: 'STEP_ONE_SUBMITTED',
STEP_TWO_SUBMITTED: 'STEP_TWO_SUBMITTED',
VERIFIED: 'VERIFIED'
VERIFIED: 'VERIFIED',
REJECTED: 'REJECTED'
};
exports.ProductImageRole = exports.$Enums.ProductImageRole = {
@@ -665,6 +734,27 @@ exports.CommentStatus = exports.$Enums.CommentStatus = {
REJECTED: 'REJECTED'
};
exports.AccountingEntityType = exports.$Enums.AccountingEntityType = {
CUSTOMER: 'CUSTOMER',
PRODUCT: 'PRODUCT'
};
exports.AccountingOutboxKind = exports.$Enums.AccountingOutboxKind = {
CUSTOMER_PUSH: 'CUSTOMER_PUSH',
PRODUCT_PUSH: 'PRODUCT_PUSH',
ORDER_DOCUMENT: 'ORDER_DOCUMENT',
ORDER_DOCUMENT_DELETE: 'ORDER_DOCUMENT_DELETE'
};
exports.AccountingOutboxStatus = exports.$Enums.AccountingOutboxStatus = {
PENDING: 'PENDING',
SENDING: 'SENDING',
SENT: 'SENT',
FAILED: 'FAILED',
NEEDS_REVIEW: 'NEEDS_REVIEW',
RESOLVED: 'RESOLVED'
};
exports.PromotionScope = exports.$Enums.PromotionScope = {
PRODUCT: 'PRODUCT',
CATEGORY: 'CATEGORY',
@@ -693,6 +783,7 @@ exports.Prisma.ModelName = {
AdminSession: 'AdminSession',
SalesExpertProfile: 'SalesExpertProfile',
Customer: 'Customer',
CustomerFavorite: 'CustomerFavorite',
CustomerAddress: 'CustomerAddress',
Branch: 'Branch',
Workshop: 'Workshop',
@@ -715,6 +806,9 @@ exports.Prisma.ModelName = {
Permission: 'Permission',
Comment: 'Comment',
Setting: 'Setting',
AccountingLink: 'AccountingLink',
AccountingOutbox: 'AccountingOutbox',
AccountingIssue: 'AccountingIssue',
Promotion: 'Promotion',
PromotionExclusion: 'PromotionExclusion',
BranchAllocation: 'BranchAllocation',