feat: insurance & medical billing system (6 phases)

Multi-tenant insurance contracts, service coverage, versioned tariffs,
invoice calculation, and insurance claims with debt reporting.

- TenantInsurance: per-tenant insurance contracts (coverage/franchise/ceiling,
  versioning, soft-deactivate) + active guard
- ServiceItem.insuranceCovered + TenantServiceCoverage per-service overrides
- Tariff: versioned yearly tariffs with fallback to ServiceItem price
- Billing domain: Money/ShareBreakdown VOs, BillingCalculator (unit-tested),
  Invoice/InvoiceItem aggregate, InvoiceService.createFromSession
- Claim/ClaimItem with state machine (pending->submitted->approved/rejected->paid),
  ClaimService, insurance-debt report
- ClaimSubmitterInterface + ManualClaimSubmitter (future insurance API ready)
- Admin UI: insurance-pricing page, claims page, service tariff modal,
  service insurance toggle; routes + sidebar entries
- Architecture doc + billing/insurance/clinic-services API docs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-06-23 15:05:24 +03:30
co-authored by Claude Opus 4.8
parent 5b1dfe9b40
commit 89191eee57
54 changed files with 4233 additions and 10 deletions
@@ -0,0 +1,98 @@
# مشخص‌کردن شمول بیمه برای هر خدمت
## پروژه
`clinicpro` (backend + admin frontend)
## زمینه
هر خدمت کلینیک با موجودیت `ServiceItem` نگه‌داری می‌شود. در حال حاضر هیچ فیلدی ندارد که بگوید این خدمت **شامل بیمه می‌شود یا نه**.
## مشکل / هدف
افزودن قابلیت تعیین «شمول بیمه» به هر `ServiceItem`:
- یک پرچم: آیا این خدمت شامل بیمه می‌شود؟
- اگر شامل می‌شود، اطلاعات لازم برای محاسبه‌ی درست (مثلاً سهم بیمار / درصد پوشش / لیست بیمه‌های پذیرفته‌شده) ذخیره و نمایش داده شود.
## فایل‌های مرتبط
| فایل | نقش |
|------|-----|
| `src/ClinicService/Entity/ServiceItem.php` | موجودیت خدمت |
| `src/ClinicService/Controller/ClinicServiceController.php` | CRUD خدمات/بخش‌ها |
| `src/ClinicService/Repository/ServiceItemRepository.php` | کوئری‌ها |
| `assets/admin/pages/ClinicServicesPage.tsx` | صفحه‌ی مدیریت خدمات در پنل |
| `src/Patient/Service/PatientService.php` | محاسبه‌ی قیمت مراجعه (مصرف‌کننده‌ی خدمت) |
| `docs/api/clinic-services.md` | مستندات API خدمات |
## وضعیت فعلی
`ServiceItem` فیلدهای موجود:
```php
private string $name;
#[ORM\Column(name: 'price_rials', type: 'integer')]
private int $priceRials = 0;
#[ORM\Column(type: 'boolean')]
private bool $active = true;
```
`toArray()`:
```php
return [
'uuid' => $this->uuid,
'section_uuid' => $this->section->getUuid(),
'staff_uuid' => $this->staff?->getUuid(),
'staff_name' => $this->staff?->getFullName(),
'name' => $this->name,
'price_rials' => $this->priceRials,
'active' => $this->active,
'created_at' => $this->createdAt,
'updated_at' => $this->updatedAt,
];
```
هیچ مفهوم بیمه‌ای ندارد.
## وظایف
### ۱. طراحی فیلد شمول بیمه
تصمیم بگیر مدل داده چه باشد:
- ساده: یک `bool $insuranceCovered = false`.
- کامل‌تر: `bool $insuranceCovered` + `?int $patientShareRials` (سهم بیمار وقتی بیمه اعمال شود) یا `?float $coveragePercent`.
> توصیه: `insuranceCovered` (bool) + `?int $insurancePriceRials` (قیمت/سهم بیمار با بیمه). اگر `insuranceCovered=false`، فیلد دوم نادیده گرفته شود.
طرح را قبل از پیاده‌سازی توضیح بده.
### ۲. Entity + Migration
- فیلد(ها) را به `ServiceItem` اضافه کن + getter/setter.
- در `toArray()` اضافه کن.
- `doctrine:migrations:diff` سپس `migrate`.
### ۳. API
`ClinicServiceController` (create/update خدمت) باید فیلدهای جدید را از body بپذیرد و ذخیره کند. validation مناسب (اگر `insurance_covered=true` و قیمت بیمه خالی، خطا یا صفر منطقی).
### ۴. Admin Frontend
در `ClinicServicesPage.tsx` فرم خدمت:
- یک toggle/checkbox «شامل بیمه می‌شود»
- وقتی روشن شد، ورودی «قیمت با بیمه (ریال)» نمایش داده شود
- در لیست خدمات، یک badge نشان دهد خدمت شامل بیمه است یا خیر
### ۵. مستندات
`docs/api/clinic-services.md` را با فیلدهای جدید در request/response به‌روز کن.
## نکات مهم
- قیمت‌ها integer ریال.
- این فیلد بعداً در محاسبه‌ی قیمت مراجعه (`PatientService::createSession`) قابل استفاده است؛ در این پرامپت فقط ذخیره/نمایش کافی است مگر اینکه ساده باشد همان‌جا هم اعمال شود.
- الگوی frontend خدمات موجود را رعایت کن (همان فرم/modal فعلی).