feat: enhance payment status handling and summary in MyPaymentsPage
- Added support for 'partial' payment status in MyPaymentsPage and related components. - Updated API responses to include 'paid_rials' and 'summary' for invoices. - Introduced InvoicePaymentStatus service to derive payment status based on actual payments. - Enhanced tests to cover new payment scenarios including partial payments and payment methods. - Updated documentation to reflect changes in payment status and API responses.
This commit is contained in:
+30
-6
@@ -325,7 +325,7 @@
|
||||
| param | توضیح |
|
||||
|-------|-------|
|
||||
| `national_code` | جستوجوی جزئی روی کد ملی بیمار (`LIKE`) |
|
||||
| `status` | `paid` (پرداختشده) · `unsettled` (تسویهنشده = `finalized`) |
|
||||
| `status` | وضعیت **مشتقشدهی** پرداخت: `paid` · `partial` · `unsettled` |
|
||||
| `from` / `to` | بازهی `issued_at` بر حسب ثانیهی Unix |
|
||||
| `page` / `limit` | صفحهبندی (پیشفرض ۱ / ۲۰، سقف ۱۰۰) |
|
||||
|
||||
@@ -336,12 +336,21 @@
|
||||
"data": [
|
||||
{ "invoice_uuid": "…", "patient_uuid": "…", "patient_name": "دنیا خلیلی",
|
||||
"national_code": "1744023654", "issued_at": 1717000000,
|
||||
"amount_rials": 2350000, "status": "paid" }
|
||||
"amount_rials": 2350000, "paid_rials": 2350000, "status": "paid" }
|
||||
],
|
||||
"meta": { "totalRecords": 12, "totalPages": 1, "currentPage": 1 }
|
||||
}
|
||||
```
|
||||
> `amount_rials` = سهم بیمار (`patient_rials`) همان صورتحساب. `status` دو حالته: `paid` یا `unsettled`.
|
||||
> `amount_rials` = سهم بیمار (`patient_rials`) همان صورتحساب · `paid_rials` = مجموع پرداختهای ثبتشدهی مراجعهی متناظر.
|
||||
>
|
||||
> **وضعیت پرداخت مشتق است، ذخیره نمیشود.** ستون `invoices.status` فقط چرخهی حیات صورتحساب را نگه میدارد (`draft` → `finalized` → `void`) و هرگز `paid` نمیشود؛ پول واقعی در `session_payments` ثبت میشود. قاعده در `App\Billing\Service\InvoicePaymentStatus` است:
|
||||
> | حالت | شرط |
|
||||
> |------|-----|
|
||||
> | `paid` | `paid_rials >= amount_rials` (شامل صورتحساب صفرریالی) |
|
||||
> | `partial` | `0 < paid_rials < amount_rials` |
|
||||
> | `unsettled` | `paid_rials = 0` و `amount_rials > 0` |
|
||||
>
|
||||
> صورتحساب بدون مراجعه (`patient_session_id = null`) هیچ پرداختی ندارد، پس `unsettled` میماند.
|
||||
|
||||
**Errors:** `403` (`ERR_FORBIDDEN_001`) پروفایل tenant یافت نشد.
|
||||
|
||||
@@ -362,7 +371,7 @@
|
||||
}
|
||||
}
|
||||
```
|
||||
> مبالغ جمع `patient_rials` هستند. `unsettled_rials = total_rials - paid_rials`. با فیلتر `status=paid` مقدار `unsettled_rials` صفر میشود (رفتار درست، نه باگ). وقتی هیچ رکوردی مطابقت ندارد، همهی مقادیر `0` برمیگردند.
|
||||
> مبالغ جمع `patient_rials` هستند. `paid_rials` = جمع صورتحسابهایی که **کاملاً** وصول شدهاند؛ صورتحساب نیمهپرداخت (`partial`) کامل در `unsettled_rials` مینشیند. `unsettled_rials = total_rials - paid_rials`. با فیلتر `status=paid` مقدار `unsettled_rials` صفر میشود (رفتار درست، نه باگ). وقتی هیچ رکوردی مطابقت ندارد، همهی مقادیر `0` برمیگردند.
|
||||
|
||||
**Errors:** `403` (`ERR_FORBIDDEN_001`) پروفایل tenant یافت نشد.
|
||||
|
||||
@@ -377,14 +386,29 @@
|
||||
"patient": { "uuid": "…", "name": "دنیا خلیلی", "national_code": "1744023654" },
|
||||
"data": [
|
||||
{ "uuid": "…", "number": 12345, "issued_at": 1717000000, "total_rials": 2350000,
|
||||
"patient_rials": 2350000, "paid_rials": 2350000,
|
||||
"status": "paid", "service_title": "روکش دندان",
|
||||
"items": [ { "uuid": "…", "title": "روکش دندان", "quantity": 1, "total_rials": 2350000, "patient_rials": 2350000 } ] }
|
||||
"items": [ { "uuid": "…", "title": "روکش دندان", "quantity": 1, "total_rials": 2350000, "patient_rials": 2350000 } ],
|
||||
"payments": [
|
||||
{ "method": "cash", "amount_rials": 350000, "paid_at": 1717000000, "created_by_name": "منشی" },
|
||||
{ "method": "pos", "amount_rials": 2000000, "paid_at": 1717000500, "created_by_name": null }
|
||||
] }
|
||||
],
|
||||
"summary": {
|
||||
"total_rials": 8350000,
|
||||
"paid_rials": 2350000,
|
||||
"unsettled_rials": 6000000,
|
||||
"invoices_count": 3
|
||||
},
|
||||
"meta": { "totalRecords": 3, "totalPages": 1, "currentPage": 1 }
|
||||
}
|
||||
}
|
||||
```
|
||||
> `status` دو حالته: `paid` (پرداختشده) یا `unsettled` (تسویهنشده = `finalized`). `service_title` عنوان اولین آیتم است (+ «و موارد دیگر» اگر بیش از یک آیتم باشد).
|
||||
> `payments` پرداختهای ثبتشدهی مراجعهی همان صورتحساب است (قدیمیترین اول)؛ `method` یکی از `wallet` · `pos` · `cash` · `card` — برچسب فارسی سمت کلاینت در `assets/admin/lib/paymentMethods.ts`. صورتحساب بدون مراجعه آرایهی خالی میگیرد.
|
||||
>
|
||||
> `status` همان وضعیت مشتقشدهی بالاست (`paid` · `partial` · `unsettled`) و همیشه بر مبنای `patient_rials` سنجیده میشود، حتی در این نما که ستون مبلغش `total_rials` است. `service_title` عنوان اولین آیتم است (+ «و موارد دیگر» اگر بیش از یک آیتم باشد).
|
||||
>
|
||||
> `summary` روی **همهی** صورتحسابهای همان بیمار محاسبه میشود (نه فقط صفحهی جاری) و جمع `total_rials` صورتحسابهاست — بر خلاف `summary` اندپوینت لیست پرداختها که سهم بیمار (`patient_rials`) را جمع میزند. `invoices_count` همان `meta.totalRecords` است.
|
||||
|
||||
**Errors:** `403` پروفایل tenant یافت نشد · `404` (`ERR_NOT_FOUND_001`) بیمار متعلق به این tenant نیست/یافت نشد.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user