feat: Add online share functionality for secretaries
- Introduced `online_share_enabled` and `online_share_percent` fields in the `doctor_secretaries` table to manage secretary shares from online appointments. - Added `bank_account` field in the `profiles` table to store user-level IBANs for settlements. - Created `secretary_earnings` table to track earnings per secretary from online appointments, including a foreign key relationship with `financial_breakdowns`. - Implemented `SecretaryEarning` entity and repository for managing secretary earnings. - Developed `SecretaryShareResolver` service to determine which secretaries earn from online payments. - Added `UserIbanResolver` service to handle user IBAN retrieval and management. - Created `HasIbansTrait` for entities to manage IBANs in a JSON format. - Implemented tests for secretary earnings and API endpoints for managing secretary shares and IBANs.
This commit is contained in:
+22
-2
@@ -107,7 +107,12 @@ Request a settlement (withdrawal from wallet to bank account).
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `amount_rials` | integer | ✅ | Amount to withdraw (must be ≤ wallet balance) |
|
||||
| `iban_id` | string | ✅ | شناسهی یکی از شباهای **تأییدشدهی** نماینده (از `GET /api/v1/representation/me` → `bank_account[].id`) |
|
||||
| `iban_id` | string | ✅ | شناسهی یکی از شباهای **تأییدشدهی همان کاربر** |
|
||||
|
||||
**شبا از کجا خوانده میشود؟** تسویه دیگر مخصوص نماینده نیست: `UserIbanResolver` ابتدا شبای
|
||||
نماینده (`GET /api/v1/representation/me` → `bank_account[].id`) و در نبودش شبای پروفایل
|
||||
کاربر (`GET /api/v1/secretary/me` → `bank_account[].id`) را بررسی میکند. بنابراین هر نقشی
|
||||
که موجودی کیف پول دارد — از جمله **منشی** با سهم نوبتهای آنلاین — میتواند برداشت کند.
|
||||
|
||||
> شبای انتخابی بهصورت snapshot (`iban`, `bank_name`, `owner_name`) داخل خود رکورد تسویه ذخیره میشود؛ حذف بعدی شبا در پروفایل، این رکورد را تغییر نمیدهد. مبلغ همان لحظهی ثبت از کیفپول کسر (debit) میشود.
|
||||
|
||||
@@ -263,7 +268,22 @@ Updated settlement object with `status: "rejected"`.
|
||||
|
||||
## FinancialBreakdown (لاگ مالی)
|
||||
|
||||
علاوه بر تسویهحساب دستی، کیفپول نماینده بهصورت خودکار از طریق `CommissionService` هنگام پرداخت موفقِ نوبت/اشتراک شارژ میشود (`WalletTransaction` credit). هر واریز یک ردیف `FinancialBreakdown` ثبت میکند که تفکیک کامل تراکنش (ناخالص، هزینه پیامک، مالیات، خالص، درصد و سهم پورسانت، سهم سیستم) را نگه میدارد. ثبت idempotent است (بر اساس `payment_id`). گزارشها از طریق `GET /api/v1/admin/financial-breakdowns` و `GET /api/v1/admin/financial-summary` در دسترساند — جزئیات در `docs/api/admin.md`.
|
||||
علاوه بر تسویهحساب دستی، کیفپول نماینده بهصورت خودکار از طریق `CommissionService` هنگام پرداخت موفقِ نوبت/اشتراک شارژ میشود (`WalletTransaction` credit). هر واریز یک ردیف `FinancialBreakdown` ثبت میکند که تفکیک کامل تراکنش (ناخالص، هزینه پیامک، مالیات، خالص، درصد و سهم پورسانت، **سهم منشی**، سهم سیستم) را نگه میدارد. ثبت idempotent است (بر اساس `payment_id`). گزارشها از طریق `GET /api/v1/admin/financial-breakdowns` و `GET /api/v1/admin/financial-summary` در دسترساند — جزئیات در `docs/api/admin.md`.
|
||||
|
||||
### ترتیب تقسیم و سهم منشی
|
||||
|
||||
```
|
||||
۱) هزینهٔ پنل پیامک ← از ناخالص کم میشود
|
||||
۲) مالیات ← استخراجی از باقیمانده: tax = amount × p/(100+p)
|
||||
۳) سهمها، همه از «خالصِ پس از مالیات»:
|
||||
پورسانت نماینده = netAfterTax × commission_percent / 100
|
||||
سهم هر منشی = netAfterTax × online_share_percent / 100
|
||||
سهم سیستم = ناخالص − پیامک − مالیات − پورسانت − مجموع سهم منشیها
|
||||
```
|
||||
|
||||
- سهم منشی **مستقل از نماینده** است: نوبتِ بدون نمایندهٔ منطبق هم اگر منشیِ سهمبر داشته باشد، تفکیک مالی میسازد.
|
||||
- `financial_breakdowns.secretary_share_rials` مجموع سهم منشیهای همان پرداخت است؛ تفکیک هر منشی در جدول `secretary_earnings` (با `share_percent` و `relation_uuid`) ذخیره میشود و گزارش پنل منشی از همان خوانده میشود ([secretary.md](secretary.md)).
|
||||
- اگر مجموع درصدها (پورسانت + سهم منشیها) از ۱۰۰ بگذرد، به نسبت کلیپ و یک هشدار با `payment_uuid` لاگ میشود تا سهم سیستم منفی نشود.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user