feat: Enhance insurance billing system to support supplementary insurance
- Updated CoverageRule and related entities to include franchise_percent instead of franchise_rials. - Modified Appointment entity to carry supplementary insurance ID alongside base insurance. - Implemented SessionBillingService to ensure finalized invoices for insured patient sessions. - Created InvoiceFinalized event to trigger claims creation upon invoice finalization. - Added BackfillMissingClaimsCommand to generate claims for finalized invoices without existing claims. - Developed tests to validate the new functionality for supplementary insurance handling in appointments and claims.
This commit is contained in:
+25
-10
@@ -367,6 +367,7 @@ Get appointment detail.
|
||||
| `insurance_service_category` | string \| null | نوع خدمتِ بیمهایِ این نوبت — یکی از مقادیر [`GET /api/v1/service-categories`](clinic-services.md#get-apiv1service-categories). `null` = انتخاب نشده؛ محاسبه به نوع پیشفرضِ tenant برمیگردد (`default_service_category` در [insurance.md](insurance.md)) |
|
||||
| `insurance_service_category_label` | string \| null | برچسب فارسی همان نوع |
|
||||
| `insurance_base_id` | int \| null | بیمهٔ **پایهٔ** انتخابشده؛ باید قرارداد فعال روی همان پزشک/کلینیک داشته باشد |
|
||||
| `insurance_supplementary_id` | int \| null | بیمهٔ **تکمیلیِ** انتخابشده؛ قرارداد فعال لازم دارد و روی **باقیماندهٔ بعد از بیمهٔ پایه** محاسبه میشود ([فرمول زنجیرهای](billing.md)) |
|
||||
|
||||
نام بیمه در این پاسخ نیست؛ پنل آن را از `GET /api/v1/billing/tenant-insurances` (که کش میشود) مپ میکند تا لیستهای نوبت به N+1 نیفتند.
|
||||
|
||||
@@ -557,6 +558,7 @@ transaction**. If any step fails nothing is committed.
|
||||
| `version` | integer | ❌ | Optimistic lock version; defaults to the stored one |
|
||||
| `insurance_service_category` | string | ❌ | نوع خدمتِ بیمهای، همان قواعد و خطاهای `PATCH /api/v1/appointment/{uuid}`. قبل از ساخت مراجعه روی نوبت مینشیند تا سهمها با همان نوع محاسبه شوند. |
|
||||
| `insurance_base_id` | integer | ❌ | بیمهٔ پایه، همان قواعد و خطاهای `PATCH`. |
|
||||
| `insurance_supplementary_id` | integer | ❌ | بیمهٔ تکمیلی، همان قواعد `PATCH`. روی باقیماندهٔ بعد از بیمهٔ پایه اعمال میشود. |
|
||||
| `payments` | array | ❌ | Empty/absent = confirm without payment. Several rows allowed (split payment). |
|
||||
| `payments[].method` | string | ✅ | ∈ `wallet\|pos\|cash\|card` |
|
||||
| `payments[].amount_rials` | integer | ✅ | > 0 |
|
||||
@@ -584,8 +586,10 @@ collected later through `POST /api/v1/session/{uuid}/payments`.
|
||||
A `PatientSession` is opened with the visit price and one line per attached service.
|
||||
4. **تفکیک بیمه** روی همان مراجعه محاسبه میشود (`BillingCalculator`): درصد پوشش از
|
||||
نوع خدمتِ نوبت — یا تنها نوع فعالِ tenant، وگرنه سرپایی — و زنجیرهٔ resolve
|
||||
([insurance.md](insurance.md#قاعدهٔ-درصد-پوشش-coverage-percent-model)). نوبتِ بدون بیمه
|
||||
مثل قبل کاملاً سهم بیمار میماند.
|
||||
([insurance.md](insurance.md#قاعدهٔ-درصد-پوشش-coverage-percent-model)). محاسبه زنجیرهای
|
||||
است: پایه روی کل، تکمیلی روی باقیمانده. نوبتِ بدون بیمه مثل قبل کاملاً سهم بیمار میماند.
|
||||
مراجعهٔ بیمهدار همینجا صورتحساب نهایی و مطالبهٔ بیمه هم میگیرد
|
||||
(`SessionBillingService` → رویداد `InvoiceFinalized`؛ [billing.md](billing.md)).
|
||||
5. Each payment row is registered on that visit (`wallet` also debits the patient wallet).
|
||||
|
||||
> پیش از این، پروندهای که با قطعیکردن ساخته میشد همیشه کل مبلغ را سهم بیمار میگذاشت
|
||||
@@ -593,7 +597,7 @@ collected later through `POST /api/v1/session/{uuid}/payments`.
|
||||
|
||||
پاسخ، `session` را با تفکیک بیمه برمیگرداند: `gross_total_rials`، `base_insurance_rials`،
|
||||
`supplementary_insurance_rials`، `patient_share_rials`، `insurance_service_category`،
|
||||
`insurance_base_id` — تا مودال همان مبلغی را نشان دهد که ثبت شده است.
|
||||
`insurance_base_id`، `insurance_supplementary_id` — تا مودال همان مبلغی را نشان دهد که ثبت شده است.
|
||||
|
||||
### Response `200`
|
||||
```json
|
||||
@@ -603,18 +607,28 @@ collected later through `POST /api/v1/session/{uuid}/payments`.
|
||||
"appointment": { "uuid": "…", "status": "confirmed", "version": 4 },
|
||||
"session": {
|
||||
"uuid": "…",
|
||||
"visit_price_rials": 5000000,
|
||||
"services_total_rials": 1500000,
|
||||
"final_price_rials": 6500000,
|
||||
"visit_price_rials": 5950000,
|
||||
"services_total_rials": 0,
|
||||
"final_price_rials": 833000,
|
||||
"discount_rials": 0,
|
||||
"paid_total_rials": 5000000,
|
||||
"remaining_rials": 1500000,
|
||||
"is_paid": false
|
||||
"paid_total_rials": 0,
|
||||
"remaining_rials": 833000,
|
||||
"is_paid": false,
|
||||
"insurance_service_category": "outpatient",
|
||||
"insurance_base_id": 176,
|
||||
"insurance_supplementary_id": 182,
|
||||
"gross_total_rials": 5950000,
|
||||
"base_insurance_rials": 1785000,
|
||||
"supplementary_insurance_rials": 3332000,
|
||||
"patient_share_rials": 833000
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> نمونهٔ بالا خروجی واقعیِ همان مسیر است: ویزیت ۵٬۹۵۰٬۰۰۰ · پایه ۳۰٪ سرپایی → ۱٬۷۸۵٬۰۰۰ ·
|
||||
> تکمیلیِ ۹۰٪ با فرانشیز ۱۰٪ روی باقیماندهٔ ۴٬۱۶۵٬۰۰۰ → ۳٬۳۳۲٬۰۰۰ · سهم بیمار ۸۳۳٬۰۰۰.
|
||||
|
||||
`session` is `null` when the tenant does not have the `patient_records` subscription
|
||||
feature — the appointment is still confirmed, it simply has no case file. **Sending
|
||||
`payments` in that situation fails with `403 ERR_SUBSCRIPTION_REQUIRED` and confirms
|
||||
@@ -876,7 +890,8 @@ General update (ویرایش / جا به جایی / انتقال به رزرو /
|
||||
- `slot_start`/`slot_end` must be sent together; moving to an occupied slot → `409`.
|
||||
- Relation uuids: empty string clears; unknown uuid → `422`.
|
||||
- `insurance_service_category` — نوعِ خدمت باید در تنظیمات بیمهٔ همان tenant **فعال** باشد؛ `null`/`""` انتخاب را پاک میکند. نوع نامعتبر یا غیرفعال → `422 ERR_VALIDATION_001` با فیلد `insurance_service_category`.
|
||||
- `insurance_base_id` — بیمه باید قرارداد فعال روی همان پزشک/کلینیک داشته باشد و **پایه** باشد؛ `null`/`0` انتخاب را پاک میکند. بیمهٔ بدون قرارداد فعال یا بیمهٔ تکمیلی → `422 ERR_VALIDATION_001` با فیلد `insurance_base_id`.
|
||||
- `insurance_base_id` — بیمه باید قرارداد فعال روی همان پزشک/کلینیک داشته باشد و **پایه** باشد؛ `null`/`0` انتخاب را پاک میکند. بیمهٔ بدون قرارداد فعال → `422 ERR_VALIDATION_001` («این بیمه برای این پزشک/کلینیک قرارداد فعال ندارد»)؛ فرستادن بیمهٔ تکمیلی در این فیلد → `422` («اینجا فقط بیمهٔ پایه قابل انتخاب است»)، هر دو با فیلد `insurance_base_id`.
|
||||
- `insurance_supplementary_id` — همان قواعد، برعکس: فقط قرارداد فعالِ **تکمیلی** پذیرفته میشود؛ فرستادن بیمهٔ پایه → `422` («اینجا فقط بیمهٔ تکمیلی قابل انتخاب است») با فیلد `insurance_supplementary_id`.
|
||||
- `status` follows the same transition rules as `PATCH /appointment/{uuid}/status`. A transition to `cancelled_by_doctor`/`cancelled_by_user` records a cancellation event (Timeline) + `app_log` warning; an optional `cancel_reason` body field is stored on the event. An inline cancellation is gated on `appointments.cancel` exactly like the dedicated status endpoint, so it cannot be used to bypass a secretary's missing cancel permission.
|
||||
- Optimistic lock via `version` → `409` on concurrent edit.
|
||||
|
||||
|
||||
+51
-21
@@ -12,20 +12,43 @@
|
||||
- قانون پوشش از قرارداد بیمهی tenant (`TenantInsurance`) + override خدمت (`TenantServiceCoverage`).
|
||||
- درصد پوشش به تفکیک **نوع خدمت** و از زنجیرهٔ resolve توضیحدادهشده در [insurance.md](insurance.md#قاعدهٔ-درصد-پوشش-coverage-percent-model) گرفته میشود: هر خدمت با `ServiceItem.service_category` خودش، و **ویزیت** با `PatientSession.insurance_service_category` (نوعی که سرِ پذیرش انتخاب شده؛ در نبودش سرپایی).
|
||||
- `invoices.service_category` همان نوع را snapshot میکند و در `toArray()` بهصورت `service_category` / `service_category_label` برمیگردد.
|
||||
- ترتیب محاسبه: کل → پوشش پایه (با سقف) → باقیمانده → پوشش مکمل (با سقف) → فرانشیزِ **تکمیلی** روی سهم بیمار.
|
||||
|
||||
**بیمهٔ پایه صرفاً درصدی است:**
|
||||
**محاسبه زنجیرهای است، نه همزمان:** اول بیمهٔ پایه روی کل مبلغ، بعد بیمهٔ تکمیلی روی
|
||||
**باقیماندهٔ سهم بیمار**، نه روی کل.
|
||||
|
||||
```
|
||||
سهم بیمهٔ پایه = round(کل × درصد پوشش پایه ÷ 100)
|
||||
سهم بیمار = کل − سهم بیمهٔ پایه
|
||||
سهم پایه = min(round(کل × درصد پایه ÷ 100), سقف پایه)
|
||||
باقیمانده = کل − سهم پایه
|
||||
سهم تکمیلی = min(max(0, round(باقیمانده × درصد تکمیلی ÷ 100) − round(باقیمانده × فرانشیز ÷ 100)), سقف تکمیلی)
|
||||
سهم بیمار = کل − سهم پایه − سهم تکمیلی
|
||||
```
|
||||
|
||||
`franchise_rials` قرارداد پایه در محاسبه **بیاثر** است (ستون برای سازگاری و قراردادهای تکمیلی میماند).
|
||||
- **فرانشیز درصد است، نه مبلغ**، و از تعهد بیمهٔ تکمیلی **کسر** میشود (نه اینکه روی سهم بیمار
|
||||
اضافه شود). با مدل قبلیِ «افزودن به سهم بیمار»، جمع سهمها از کل بیشتر میشد و مطالبهٔ
|
||||
ارسالی به بیمه بیش از سهم واقعیاش بود.
|
||||
- `franchise_percent` قرارداد **پایه** در محاسبه بیاثر است.
|
||||
- invariant همیشگی: `کل = سهم پایه + سهم تکمیلی + سهم بیمار`.
|
||||
|
||||
نمونهها:
|
||||
- کل ۶۰۰٬۰۰۰ · پایه ۷۰٪ → ۴۲۰٬۰۰۰ · مکمل روی باقیمانده → ۱۲۰٬۰۰۰ · بیمار ۶۰٬۰۰۰.
|
||||
- کل ۱۰٬۰۰۰٬۰۰۰ · پایه ۳۰٪ → ۳٬۰۰۰٬۰۰۰ · تکمیلی ۹۰٪ با فرانشیز ۱۰٪ روی باقیماندهٔ ۷٬۰۰۰٬۰۰۰ → ۵٬۶۰۰٬۰۰۰ · بیمار ۱٬۴۰۰٬۰۰۰.
|
||||
- ویزیت ۵٬۹۵۲٬۰۰۰ ریال · پایهٔ بستری ۳۰٪ → سهم پایه ۱٬۷۸۵٬۶۰۰ · سهم بیمار ۴٬۱۶۶٬۴۰۰.
|
||||
- بدون پایه · تکمیلی ۹۰٪ با فرانشیز ۱۰٪ روی ۱٬۰۰۰٬۰۰۰ → بیمه ۸۰۰٬۰۰۰ · بیمار ۲۰۰٬۰۰۰.
|
||||
|
||||
### مطالبهٔ خودکار
|
||||
|
||||
مطالبهٔ بیمه اثر جانبیِ **نهاییشدن صورتحساب** است، نه کارِ یک endpoint خاص: `InvoiceService::finalize()`
|
||||
رویداد `InvoiceFinalized` میفرستد و `CreateClaimsOnInvoiceFinalized` مطالبات جاافتاده را میسازد
|
||||
(idempotent — مطالبهٔ موجود دستنخورده میماند، و بیمهای که سهمی نبرده مطالبه نمیگیرد).
|
||||
|
||||
هر مراجعهٔ بیمهدار هم — چه از «ثبت مراجعه»، چه از ویرایش مراجعه، چه از **قطعیکردن نوبت** —
|
||||
با `SessionBillingService::ensureFinalizedInvoice()` صورتحساب نهایی میگیرد. پیش از این فقط
|
||||
مسیر «ثبت مراجعه» مطالبه میساخت و بقیهٔ مسیرها بیصدا بدون مطالبه میماندند.
|
||||
|
||||
جبران دادههای قدیمی:
|
||||
|
||||
```bash
|
||||
ddev exec php bin/console app:billing:backfill-claims --dry-run # گزارش
|
||||
ddev exec php bin/console app:billing:backfill-claims # ساخت مطالبات جاافتاده
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -216,9 +239,10 @@
|
||||
| `limit` | int | 20 | حداکثر ۱۰۰ |
|
||||
| `sort` | string | `last_activity_at` | `full_name` \| `claims_count` \| `total_services_rials` \| `total_insurance_rials` \| `last_activity_at` |
|
||||
| `dir` | string | `desc` | `asc` \| `desc` |
|
||||
| `search` | string | — | نام، موبایل یا کد ملی بیمار |
|
||||
| `search` | string | — | نام، موبایل، کد ملی بیمار **یا نام بیمه** |
|
||||
| `status` | string | — | `pending` \| `submitted` \| `approved` \| `rejected` \| `paid` |
|
||||
| `insurance_id` | int | — | شناسه بیمه |
|
||||
| `kind` | string | — | نوع بیمه: `base` \| `supplementary` (واژگان مطالبه `base` است، نه `basic`). مقدار نامعتبر → `422 ERR_VALIDATION_001` با `field: kind` |
|
||||
| `doctor_id` | int | — | پزشکِ نوبتِ مراجعه |
|
||||
| `payment_status` | string | — | `paid` (وصولشده) \| `unpaid` |
|
||||
| `from` / `to` | int | — | بازهی `claims.created_at` (unix ثانیه) |
|
||||
@@ -230,25 +254,31 @@
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"patient_uuid": "45064492-...",
|
||||
"record_uuid": "ad0a3d0e-...",
|
||||
"full_name": "تست جراحی بینی",
|
||||
"mobile": "09370671756",
|
||||
"patient_uuid": "649e24ae-08e2-489d-b502-af07c59dfa2d",
|
||||
"record_uuid": "8e36035c-d234-42aa-858b-2427918e9c4a",
|
||||
"full_name": "تست بیمه ۱",
|
||||
"mobile": "09243243534",
|
||||
"national_code": null,
|
||||
"claims_count": 2,
|
||||
"total_services_rials": 81500000,
|
||||
"total_insurance_rials": 57050000,
|
||||
"total_patient_rials": 24450000,
|
||||
"total_approved_rials": 28000000,
|
||||
"total_paid_rials": 28000000,
|
||||
"overall_status": "mixed",
|
||||
"last_activity_at": 1784404115
|
||||
"claims_count": 3,
|
||||
"total_services_rials": 91900000,
|
||||
"total_insurance_rials": 9877000,
|
||||
"total_patient_rials": 82023000,
|
||||
"total_approved_rials": 0,
|
||||
"total_paid_rials": 0,
|
||||
"overall_status": "pending",
|
||||
"insurances": [
|
||||
{ "insurance_id": 176, "insurance_name": "تامین اجتماعی", "kind": "base" },
|
||||
{ "insurance_id": 182, "insurance_name": "بیمه ایران", "kind": "supplementary" }
|
||||
],
|
||||
"last_activity_at": 1785341593
|
||||
}
|
||||
],
|
||||
"meta": { "totalRecords": 1, "totalPages": 1, "currentPage": 1 }
|
||||
"meta": { "totalRecords": 1, "totalPages": 1, "currentPage": 1, "limit": 1 }
|
||||
}
|
||||
```
|
||||
|
||||
- `insurances`: بیمههایی که این بیمار زیرشان مطالبه دارد — یک بیمار میتواند همزمان پایه و تکمیلی داشته باشد، پس ستون «بیمه» یک لیست است نه یک مقدار.
|
||||
|
||||
- `overall_status`: اگر همهی مطالبات بیمار یک وضعیت داشته باشند همان؛ وگرنه `mixed`.
|
||||
- ثابت: `total_services_rials = total_insurance_rials + total_patient_rials`.
|
||||
- **ضدِ double-counting:** مبالغ خدمات/سهم بیمار از **صورتحسابهای یکتا** جمع میشوند، نه از مطالبات. یک صورتحساب میتواند همزمان مطالبهی پایه و مکمل داشته باشد؛ جمعزدن از سمت مطالبه مبلغ خدمات را دوبار میشمرد.
|
||||
|
||||
+18
-7
@@ -33,7 +33,7 @@ hardcode نمیشود. ویزیت همیشه `outpatient` است.
|
||||
| ۴ | `coverage_percent` قرارداد (سازگاری با ردیفهای قدیمی) | `tenant_insurances` |
|
||||
|
||||
**fallback زنده است، نه کپی:** قراردادی که ردیف سطح ۲ ندارد، با تغییر پیشفرض ادمین
|
||||
خودبهخود بهروز میشود. `franchise_rials` فقط در قراردادهای `supplementary` اثر دارد.
|
||||
خودبهخود بهروز میشود. `franchise_percent` فقط در قراردادهای `supplementary` اثر دارد.
|
||||
|
||||
---
|
||||
|
||||
@@ -527,7 +527,7 @@ tenant از `#[CurrentUser]` با `App\Patient\Security\PatientRecordScopeResolv
|
||||
"version": 1,
|
||||
"is_active": true,
|
||||
"coverage_percent": 70,
|
||||
"franchise_rials": 0,
|
||||
"franchise_percent": 0,
|
||||
"annual_ceiling_rials": null,
|
||||
"kind": "basic",
|
||||
"effective_from": 1718900000,
|
||||
@@ -545,7 +545,7 @@ tenant از `#[CurrentUser]` با `App\Patient\Security\PatientRecordScopeResolv
|
||||
| `category_coverages` | درصد **مؤثر** هر نوع خدمت پس از اجرای زنجیرهٔ resolve |
|
||||
| `category_coverage_source` | منبع هر درصد: `override` (خودِ قرارداد) · `admin_default` (تنظیمات مرکزی) · `contract` (ستون قدیمی `coverage_percent`) |
|
||||
| `coverage_percent` | ستون قدیمی قرارداد؛ فقط آخرین سطح fallback است |
|
||||
| `franchise_rials` | فقط در قرارداد `supplementary` معنا دارد |
|
||||
| `franchise_percent` | فقط در قرارداد `supplementary` معنا دارد |
|
||||
|
||||
### POST `/api/v1/billing/tenant-insurances`
|
||||
فعالسازی/بهروزرسانی قرارداد. اگر قرارداد فعالی برای آن بیمه باشد ویرایش میشود، وگرنه نسخهی جدید.
|
||||
@@ -555,7 +555,7 @@ tenant از `#[CurrentUser]` با `App\Patient\Security\PatientRecordScopeResolv
|
||||
|------|-----|-------|
|
||||
| `insurance_id` | int | الزامی |
|
||||
| `coverage_percent` | float | ستون قدیمی قرارداد (آخرین سطح fallback)؛ پنل آن را با درصد سرپایی همگام میفرستد |
|
||||
| `franchise_rials` | int | فرانشیز — فقط در قرارداد `supplementary` اثر دارد |
|
||||
| `franchise_percent` | float | فرانشیز **درصدی** (۰ تا ۱۰۰) — سهم اجباری بیمار از مبلغ تحت پوشش؛ فقط در قرارداد `supplementary` اثر دارد. خارج از بازه → `422` با `field: franchise_percent` |
|
||||
| `annual_ceiling_rials` | int \| null | سقف تعهد (null = بینهایت) |
|
||||
| `kind` | string \| null | نوع بیمه قرارداد (`basic`/`supplementary`); خالی → پیشفرض نوع کاتالوگ |
|
||||
| `effective_from` | int \| null | تاریخ شروع قرارداد (Unix)؛ null → اکنون |
|
||||
@@ -563,6 +563,17 @@ tenant از `#[CurrentUser]` با `App\Patient\Security\PatientRecordScopeResolv
|
||||
| `category_coverages` | array \| null | اختیاری — override درصد به تفکیک نوع خدمت. **نیامدنش** یعنی قرارداد روی پیشفرض مرکزی ادمین میماند (fallback زنده) |
|
||||
| `category_coverages[].key` | string | یکی از مقادیر `GET /api/v1/service-categories` |
|
||||
| `category_coverages[].coverage_percent` | number \| null | ۰ تا ۱۰۰؛ `null` → override آن نوع حذف و به پیشفرض ادمین برمیگردد |
|
||||
|
||||
**اجبار درصد برای نوع خدمتِ فعال:** با ارسال `category_coverages`، هر نوع خدمتی که در تنظیمات
|
||||
همین tenant فعال است باید درصد مؤثر بزرگتر از صفر داشته باشد — از خود payload، از override
|
||||
قبلی، یا از پیشفرض مرکزی ادمین. ستون قدیمی `coverage_percent` قرارداد اینجا fallback حساب
|
||||
نمیشود، وگرنه نوع خدمتی که درصدش نیامده بیصدا نرخ نوع دیگر را ارث میبرد.
|
||||
|
||||
```json
|
||||
{ "success": false, "errors": [
|
||||
{ "code": "ERR_VALIDATION_001", "field": "category_coverages", "message": "درصد پوشش خدمات بستری الزامی است" }
|
||||
] }
|
||||
```
|
||||
| `doctor_uuid` | string (UUID) \| null | اختیاری — قرارداد را بهازای پزشک هدف ذخیره میکند (نگاه کنید به «تنظیمات per-doctor» بالا) |
|
||||
|
||||
```json
|
||||
@@ -582,7 +593,7 @@ tenant از `#[CurrentUser]` با `App\Patient\Security\PatientRecordScopeResolv
|
||||
### PATCH `/api/v1/billing/tenant-insurances/{uuid}`
|
||||
ویرایش فیلدهای قرارداد (همه اختیاری، فقط کلیدهای موجود اعمال میشوند). فقط قرارداد متعلق به tenant جاری.
|
||||
|
||||
**Body:** `coverage_percent` · `franchise_rials` · `annual_ceiling_rials` · `kind` · `effective_from` · `effective_to` · `is_active` · `category_coverages` (همان ساختار `POST`؛ ارسالش نیازمند مجوز `insurances.update` است وگرنه `403 ERR_FORBIDDEN_001`) · `doctor_uuid` (اختیاری، برای هدفگیری پزشک — نگاه کنید به «تنظیمات per-doctor» بالا).
|
||||
**Body:** `coverage_percent` · `franchise_percent` · `annual_ceiling_rials` · `kind` · `effective_from` · `effective_to` · `is_active` · `category_coverages` (همان ساختار `POST`؛ ارسالش نیازمند مجوز `insurances.update` است وگرنه `403 ERR_FORBIDDEN_001`) · `doctor_uuid` (اختیاری، برای هدفگیری پزشک — نگاه کنید به «تنظیمات per-doctor» بالا).
|
||||
|
||||
- `is_active` (bool): toggle فعال/غیرفعال. برخلاف `DELETE`، مقدار `effective_to`ِ تعیینشدهٔ کاربر را دستنخورده نگه میدارد (برای reactivate).
|
||||
- قرارداد باید به همان موجودیتِ resolveشده (پزشک هدف یا tenant کاربر) تعلق داشته باشد، وگرنه `404`.
|
||||
@@ -623,7 +634,7 @@ override پوشش یک خدمت خاص تحت قرارداد یک بیمه. فی
|
||||
"service_item_uuid": "…",
|
||||
"covered": true,
|
||||
"coverage_percent": 80,
|
||||
"franchise_rials": null,
|
||||
"franchise_percent": null,
|
||||
"ceiling_rials": null
|
||||
}
|
||||
]
|
||||
@@ -641,7 +652,7 @@ override پوشش یک خدمت خاص تحت قرارداد یک بیمه. فی
|
||||
| `service_item_id` | int | جایگزین `service_item_uuid` (id داخلی) — یکی از این دو الزامی |
|
||||
| `covered` | bool | پیشفرض true |
|
||||
| `coverage_percent` | float \| null | null = ارث از قرارداد |
|
||||
| `franchise_rials` | int \| null | null = ارث از قرارداد |
|
||||
| `franchise_percent` | int \| null | null = ارث از قرارداد |
|
||||
| `ceiling_rials` | int \| null | null = ارث از قرارداد |
|
||||
| `doctor_uuid` | string (UUID) \| null | اختیاری — قراردادِ متعلق به پزشک هدف (نگاه کنید به «تنظیمات per-doctor» بالا) |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user