feat: اصلاح سند payment corrections + audit-log & daily P&L views
CI/CD / CI · API (dotnet build + test) (push) Successful in 51s
CI/CD / CI · Admin API (dotnet build) (push) Successful in 31s
CI/CD / CI · Dashboard (tsc) (push) Failing after 1m12s
CI/CD / CI · Admin Web (tsc) (push) Successful in 40s
CI/CD / CI · Website (tsc) (push) Successful in 46s
CI/CD / CI · Koja (tsc) (push) Successful in 51s
CI/CD / Deploy · all services (push) Has been skipped

Backend:
- POST /orders/{id}/payments/corrections (Manager/Owner): void wrong
  payments (marked Refunded, never deleted) and/or record replacements
  atomically; mandatory reason; requires an open register shift; full
  before/after written to the immutable audit trail.
- GET /orders/closed?date= — closed orders of one Iran-calendar day,
  paged, the browsing surface for corrections.
- CalculateExpectedCash now subtracts cash refunds so corrections keep
  the drawer expectation honest.

Dashboard (reports screen now has three tabs):
- عملکرد و سود: existing KPIs/charts + new day-by-day breakdown table
  (orders, revenue, expenses, net profit per Jalali day).
- اصلاح سند: closed-orders browser with payment chips + correction
  dialog (void checkboxes, replacement rows, live balance, reason).
- گزارش عملیات: filterable audit-log viewer (category, Jalali range,
  branch) with expandable structured details.

fa/en/ar translations included. 86 backend tests pass; dashboard tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-12 01:24:19 +03:30
parent 2a4cf1d20b
commit c47922414a
11 changed files with 1367 additions and 14 deletions
+74 -1
View File
@@ -529,7 +529,80 @@
"csvNetIncome": "صافي الدخل",
"csvVoids": "الإلغاءات",
"csvVoidAmount": "مبلغ الإلغاء",
"csvExpenses": "المصروفات"
"csvExpenses": "المصروفات",
"tabs": {
"performance": "الأداء والأرباح",
"corrections": "تصحيح المستندات",
"auditLog": "سجل العمليات"
},
"dailyBreakdownTitle": "التفصيل اليومي — المبيعات والمصروفات والأرباح",
"colDate": "التاريخ",
"colOrders": "الطلبات",
"colExpenses": "المصروفات",
"colNet": "صافي الربح",
"corrections": {
"date": "التاريخ",
"branch": "الفرع",
"allBranches": "كل الفروع",
"hint": "ابحث عن الطلب ذي الدفعة الخاطئة واضغط «تصحيح».",
"loadFailed": "فشل تحميل الطلبات.",
"retry": "إعادة المحاولة",
"empty": "لا توجد طلبات مغلقة في هذا اليوم.",
"colOrder": "الطلب",
"colTime": "الوقت",
"colStatus": "الحالة",
"colTotal": "المبلغ",
"colPayments": "الدفعات",
"table": "طاولة",
"statusPaid": "مسدّد",
"statusCancelled": "ملغى",
"correctAction": "تصحيح",
"prevPage": "السابق",
"nextPage": "التالي",
"dialogTitle": "تصحيح مستند الدفع",
"orderTotal": "مبلغ الطلب",
"voidSection": "الدفعات الخاطئة (اختر للإلغاء)",
"replacementSection": "الدفعات البديلة",
"addReplacement": "إضافة",
"noReplacements": "اتركه فارغاً إذا كنت تُلغي فقط.",
"method": "طريقة الدفع",
"amount": "المبلغ",
"removeReplacement": "حذف الصف",
"reason": "سبب التصحيح (إلزامي)",
"reasonPlaceholder": "مثلاً: سُجّلت نقداً بالخطأ وكان الدفع بالبطاقة",
"paidAfter": "إجمالي المدفوع بعد التصحيح",
"shortBy": "أقل من مبلغ الطلب بـ",
"overBy": "أكثر من مبلغ الطلب بـ",
"cancel": "إلغاء",
"submit": "تسجيل التصحيح",
"saved": "تم تسجيل التصحيح.",
"saveFailed": "فشل تسجيل التصحيح."
},
"auditLog": {
"category": "الفئة",
"allCategories": "الكل",
"categories": {
"Payment": "الدفع",
"Order": "الطلب",
"Register": "الصندوق",
"Staff": "الموظفون"
},
"fromDate": "من",
"toDate": "إلى",
"branch": "الفرع",
"allBranches": "كل الفروع",
"loadFailed": "فشل تحميل سجل العمليات.",
"retry": "إعادة المحاولة",
"empty": "لا يوجد شيء مسجّل.",
"colTime": "الوقت",
"colCategory": "الفئة",
"colActor": "المستخدم",
"colSummary": "الوصف",
"details": "التفاصيل",
"systemActor": "النظام",
"prevPage": "السابق",
"nextPage": "التالي"
}
},
"expenses": {
"title": "المصروفات",
+74 -1
View File
@@ -557,7 +557,80 @@
"csvNetIncome": "Net income",
"csvVoids": "Voids",
"csvVoidAmount": "Void amount",
"csvExpenses": "Expenses"
"csvExpenses": "Expenses",
"tabs": {
"performance": "Performance & profit",
"corrections": "Payment corrections",
"auditLog": "Activity log"
},
"dailyBreakdownTitle": "Daily breakdown — sales, expenses & profit",
"colDate": "Date",
"colOrders": "Orders",
"colExpenses": "Expenses",
"colNet": "Net profit",
"corrections": {
"date": "Date",
"branch": "Branch",
"allBranches": "All branches",
"hint": "Find the order with the wrongly-recorded payment and hit “Correct”.",
"loadFailed": "Failed to load orders.",
"retry": "Retry",
"empty": "No closed orders on this day.",
"colOrder": "Order",
"colTime": "Time",
"colStatus": "Status",
"colTotal": "Total",
"colPayments": "Payments",
"table": "Table",
"statusPaid": "Settled",
"statusCancelled": "Cancelled",
"correctAction": "Correct",
"prevPage": "Previous",
"nextPage": "Next",
"dialogTitle": "Payment correction",
"orderTotal": "Order total",
"voidSection": "Wrong payments (select to void)",
"replacementSection": "Replacement payments",
"addReplacement": "Add",
"noReplacements": "Leave empty if you are only voiding.",
"method": "Method",
"amount": "Amount",
"removeReplacement": "Remove row",
"reason": "Reason (required)",
"reasonPlaceholder": "e.g. recorded as cash by mistake, was paid by card",
"paidAfter": "Paid total after correction",
"shortBy": "Short of order total by",
"overBy": "Over order total by",
"cancel": "Cancel",
"submit": "Submit correction",
"saved": "Correction recorded.",
"saveFailed": "Failed to record correction."
},
"auditLog": {
"category": "Category",
"allCategories": "All",
"categories": {
"Payment": "Payment",
"Order": "Order",
"Register": "Register",
"Staff": "Staff"
},
"fromDate": "From",
"toDate": "To",
"branch": "Branch",
"allBranches": "All branches",
"loadFailed": "Failed to load the activity log.",
"retry": "Retry",
"empty": "Nothing recorded.",
"colTime": "Time",
"colCategory": "Category",
"colActor": "User",
"colSummary": "Summary",
"details": "Details",
"systemActor": "System",
"prevPage": "Previous",
"nextPage": "Next"
}
},
"shifts": {
"title": "Cash shift",
+74 -1
View File
@@ -557,7 +557,80 @@
"csvNetIncome": "درآمد خالص",
"csvVoids": "ابطال‌ها",
"csvVoidAmount": "مبلغ ابطال",
"csvExpenses": "هزینه‌ها"
"csvExpenses": "هزینه‌ها",
"tabs": {
"performance": "عملکرد و سود",
"corrections": "اصلاح سند",
"auditLog": "گزارش عملیات"
},
"dailyBreakdownTitle": "ریز روزانه — فروش، هزینه و سود",
"colDate": "تاریخ",
"colOrders": "سفارش‌ها",
"colExpenses": "هزینه‌ها",
"colNet": "سود خالص",
"corrections": {
"date": "تاریخ",
"branch": "شعبه",
"allBranches": "همه شعبه‌ها",
"hint": "برای اصلاح پرداختِ ثبت‌شده اشتباه، سفارش را پیدا کنید و «اصلاح سند» را بزنید.",
"loadFailed": "بارگذاری سفارش‌ها ناموفق بود.",
"retry": "تلاش دوباره",
"empty": "در این روز سفارش بسته‌شده‌ای نیست.",
"colOrder": "سفارش",
"colTime": "ساعت",
"colStatus": "وضعیت",
"colTotal": "مبلغ",
"colPayments": "پرداخت‌ها",
"table": "میز",
"statusPaid": "تسویه‌شده",
"statusCancelled": "لغوشده",
"correctAction": "اصلاح سند",
"prevPage": "قبلی",
"nextPage": "بعدی",
"dialogTitle": "اصلاح سند پرداخت",
"orderTotal": "مبلغ سفارش",
"voidSection": "پرداخت‌های اشتباه (برای ابطال انتخاب کنید)",
"replacementSection": "پرداخت‌های جایگزین",
"addReplacement": "افزودن",
"noReplacements": "اگر فقط ابطال می‌کنید، چیزی اضافه نکنید.",
"method": "روش پرداخت",
"amount": "مبلغ (تومان)",
"removeReplacement": "حذف ردیف",
"reason": "دلیل اصلاح (الزامی)",
"reasonPlaceholder": "مثلاً: به‌اشتباه نقد ثبت شده بود، پرداخت با کارت بود",
"paidAfter": "جمع پرداختی پس از اصلاح",
"shortBy": "کسری نسبت به مبلغ سفارش",
"overBy": "مازاد نسبت به مبلغ سفارش",
"cancel": "انصراف",
"submit": "ثبت اصلاح",
"saved": "اصلاح سند ثبت شد.",
"saveFailed": "ثبت اصلاح ناموفق بود."
},
"auditLog": {
"category": "دسته",
"allCategories": "همه",
"categories": {
"Payment": "پرداخت",
"Order": "سفارش",
"Register": "صندوق",
"Staff": "کارکنان"
},
"fromDate": "از تاریخ",
"toDate": "تا تاریخ",
"branch": "شعبه",
"allBranches": "همه شعبه‌ها",
"loadFailed": "بارگذاری گزارش عملیات ناموفق بود.",
"retry": "تلاش دوباره",
"empty": "موردی ثبت نشده است.",
"colTime": "زمان",
"colCategory": "دسته",
"colActor": "کاربر",
"colSummary": "شرح",
"details": "جزئیات",
"systemActor": "سیستم",
"prevPage": "قبلی",
"nextPage": "بعدی"
}
},
"shifts": {
"title": "شیفت صندوق",