feat: update session payment logic to ensure accurate payable amounts and reflect consumables in cost breakdown

- Adjusted the calculation of payable amounts in PaymentStep to align with server logic, ensuring overpayments are handled correctly.
- Enhanced DetailsStep to include consumables in the itemized cost breakdown, ensuring consistency with patient share calculations.
- Updated tests for SessionPaymentPage to validate new behavior regarding overpayments and consumable listings.
- Modified PatientController to register SessionPayment correctly when settling sessions via wallet, preventing double charges.
- Refactored WalletService to remove outdated methods and ensure wallet transactions reflect the correct amounts after discounts.
- Improved accessibility in SearchableSelect component by adding aria labels and ensuring proper role attributes for screen readers.
- Updated styles to ensure minimum touch targets meet WCAG guidelines for mobile usability.
This commit is contained in:
hamed
2026-07-19 13:29:46 +03:30
parent 0d9784b03a
commit 773f9d4d16
22 changed files with 251 additions and 70 deletions
+2 -2
View File
@@ -377,7 +377,7 @@ Returns paginated sessions for a patient record.
| Field | Type | Notes |
|-------|------|-------|
| `is_paid` | bool | `true` وقتی `payment_method !== "pending"` |
| `is_paid` | bool | `true` وقتی `remaining_rials === 0` (یعنی مجموع `SessionPayment`ها + تخفیف به مبلغ نهایی رسیده) — نه صرفاً از روی `payment_method` |
| `services` | array | سرویس‌های ثبت‌شده در این session (نام، انجام‌دهنده/`staff`, قیمت، تعداد) |
| `invoice_uuid` | string\|null | uuid فاکتور مرتبط (اگر ساخته شده باشد؛ برای «مشاهده فاکتور») |
| `invoice_status` | string\|null | `draft`\|`finalized`\|`paid`\|`void` |
@@ -552,7 +552,7 @@ Updates mutable fields on a session.
}
```
- `payment_method: "wallet"` روی مراجعه‌ی تسویه‌نشده، کل مبلغ نهایی را از کیف پول بیمار کسر می‌کند (موجودی ناکافی → `422 ERR_WALLET_INSUFFICIENT`).
- `payment_method: "wallet"` روی مراجعه‌ی تسویه‌نشده، **مانده** (`remaining_rials` = مبلغ نهایی − تخفیف − پرداخت‌های قبلی) را از کیف پول بیمار کسر می‌کند و همزمان یک `SessionPayment` با روش `wallet` ثبت می‌کند؛ در نتیجه `is_paid=true` و `paid_at` ست می‌شود و تراکنش debit با `reference: "session:{uuid}"` ثبت می‌گردد. موجودی ناکافی → `422 ERR_WALLET_INSUFFICIENT`. اگر مانده صفر باشد (مراجعه از قبل تسویه شده) هیچ کسری انجام نمی‌شود — فراخوانی دوباره **کسر مضاعف نمی‌کند**.
- **تخفیف تسویه (دستی):** `discount_type` = `percent` (۰..۱۰۰) یا `fixed` (ریال، حداکثر برابر مبلغ نهایی) یا `null` (حذف تخفیف). مبلغ محاسبه‌شده در `discount_rials` برمی‌گردد. تخفیف نمی‌تواند از «مبلغ نهایی منهای پرداخت‌های ثبت‌شده» بیشتر شود. تخفیفی که مانده را صفر کند مراجعه را تسویه‌شده می‌کند (`is_paid`, `paid_at`).
- **تخفیف بر اساس قانون:** `discount_rule_uuid` (رشته) → قانون تخفیف (owner-scoped) اعمال می‌شود؛ مقدار ریالی از خود قانون توسط موتور محاسبه می‌گردد (نوع/مبنا بر اساس قانون). `''`/`null` → حذف تخفیف. اولویت بر `discount_type` دستی. قانونِ نامعتبر → `404`. منبع اعمال‌شده در پاسخ به‌صورت `applied_discount_rule_id` و `applied_discount_rule_label` (audit) برمی‌گردد. قوانین قابل‌اعمال از `GET /api/v1/session/{uuid}/discount-suggestions` (نگاه کنید به `discount.md`).
- `paid_at`: unix timestamp زمان تسویه.