Rebuild order flow: settle after pricing, notifications, and invoice expiry.

Hide prices until admin sends the invoice, enforce status transitions, add customer/admin SMS+in-app notifications, schedule cash invoice reminders, and ship updated dist/prisma-client/deploy-bundle for git-pull deploys.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-09 12:00:13 +03:30
co-authored by Cursor
parent 06e5f48d07
commit d4aaa8e997
102 changed files with 2989 additions and 509 deletions
+35 -7
View File
@@ -94,7 +94,8 @@ model Company {
logoUrl String?
isActive Boolean @default(true)
displayOrder Int @default(0)
maxMeteragePerInvoice Int @default(5000)
/// خالی یعنی از تنظیمات سیستم ارث می‌برد
maxMeteragePerInvoice Int?
cashInvoiceValidityHours Int @default(8)
cashInvoiceValidUntilHour Int?
createdAt DateTime @default(now())
@@ -183,9 +184,10 @@ model Customer {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
carts Cart[]
orders Order[]
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
carts Cart[]
orders Order[]
notifications CustomerNotification[]
@@index([companyId])
}
@@ -258,7 +260,8 @@ model Order {
userId String
companyId String
companyName String
settlementType SettlementType
// روش تسویه بعد از قیمت‌گذاری ادمین توسط مشتری انتخاب می‌شود
settlementType SettlementType?
checkMode CheckRegistrationMode?
status OrderStatus @default(awaiting_review)
totalMeterage Float @default(0)
@@ -270,21 +273,25 @@ model Order {
checkRassDays Int?
checkRassDate DateTime?
cashInvoiceExpiresAt DateTime?
/// زمان ارسال یادآوری پایان مهلت پرداخت تا دوباره ارسال نشود
cashReminderSentAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user Customer @relation(fields: [userId], references: [id], onDelete: Restrict)
company Company @relation(fields: [companyId], references: [id], onDelete: Restrict)
user Customer @relation(fields: [userId], references: [id], onDelete: Restrict)
company Company @relation(fields: [companyId], references: [id], onDelete: Restrict)
items OrderItem[]
checks Check[]
cashReceipt CashPaymentReceipt?
shipment Shipment?
statusHistory OrderStatusHistory[]
notifications CustomerNotification[]
@@index([userId])
@@index([companyId])
@@index([status])
@@index([createdAt])
@@index([status, cashInvoiceExpiresAt])
}
model OrderItem {
@@ -393,6 +400,7 @@ model SystemSettings {
defaultSettlementCheck Boolean @default(true)
defaultSettlementCash Boolean @default(true)
smsOrderRegistered Boolean @default(true)
smsPricingReady Boolean @default(true)
smsPaymentReminder Boolean @default(true)
smsCheckReview Boolean @default(true)
smsShippingUpdate Boolean @default(true)
@@ -411,6 +419,26 @@ model AdminNotification {
sentAt DateTime @default(now())
}
model CustomerNotification {
id String @id @default(cuid())
customerId String
orderId String?
event String
title String
body String
tone NotificationTone? @default(info)
link String?
isRead Boolean @default(false)
smsSent Boolean @default(false)
sentAt DateTime @default(now())
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
order Order? @relation(fields: [orderId], references: [id], onDelete: SetNull)
@@index([customerId, isRead])
@@index([sentAt])
}
model InternalMessage {
id String @id @default(cuid())
senderName String