feat: port wallet charge/withdraw modal from tauri to patient admin page

Add manual wallet withdrawal (debit) endpoint mirroring the offline app's
balance guard, and rebuild the patient کیف پول tab around a single
charge/withdraw toggle modal (quick amounts, تومان→ریال conversion,
transaction filters).

Backend:
- POST /api/v1/patient/{uuid}/wallet/withdraw — creates a debit
  WalletTransaction; 422 ERR_WALLET_INSUFFICIENT when amount exceeds balance.
- ErrorCodes: ERR_WALLET_INSUFFICIENT ('موجودی کیف پول کافی نیست').
- docs/api/patient.md updated.

Frontend:
- usePatientWallet hook (balance + charge/withdraw mutations).
- WalletTransactionModal (toggle, quick amounts, UI-only payment fields).
- WalletTab: charge button, همه/واریزی/برداشت filters.

Tests: backend withdraw success/insufficient/non-positive/ownership;
frontend modal + wallet tab interactions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-16 11:56:39 +03:30
co-authored by Claude Opus 4.8
parent 4a70c87a8b
commit f028d6841a
9 changed files with 533 additions and 46 deletions
+9
View File
@@ -600,6 +600,13 @@ Response: `{ success, data: { balance_rials, recent_transactions: [{ uuid, amoun
```
`amount_rials` باید > 0 باشد وگرنه `422`. Response `201`: `{ success, data: { transaction, balance_rials } }`
### POST `/api/v1/patient/{uuid}/wallet/withdraw`
برداشت دستی از کیف‌پول (مثلاً عودت وجه حضوری). یک تراکنش `debit` برای کاربرِ صاحب رکورد می‌سازد.
```json
{ "amount_rials": 200000, "description": "عودت (اختیاری، پیش‌فرض «برداشت از کیف پول»)" }
```
`amount_rials` باید > 0 باشد وگرنه `422`. اگر مبلغ از موجودی فعلی بیشتر باشد `422` با کد `ERR_WALLET_INSUFFICIENT`. Response `201`: `{ success, data: { transaction, balance_rials } }`
### GET `/api/v1/patient/{uuid}/wallet/transactions`
دفترِ کاملِ تراکنش‌های کیف‌پول (paginated). Query: `page`, `limit` (≤100).
Response: `{ success, data: [{ uuid, amount_rials, type, description, balance_after, created_at }], meta: { totalRecords, totalPages, currentPage } }`
@@ -608,6 +615,8 @@ Response: `{ success, data: [{ uuid, amount_rials, type, description, balance_af
| HTTP | Code | Description |
|------|------|-------------|
| 404 | `ERR_PATIENT_001` | رکورد یافت نشد یا متعلق به مالک دیگر |
| 422 | `ERR_VALIDATION_001` | مبلغ شارژ/برداشت ≤ 0 |
| 422 | `ERR_WALLET_INSUFFICIENT` | مبلغ برداشت از موجودی کیف‌پول بیشتر است |
---