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>
6.3 KiB
قیمتگذاری ویزیت بر اساس بیمه در پروفایل کلینیک/مطب
پروژه
clinicpro (backend + admin frontend)
زمینه
در حال حاضر قیمت ویزیت پزشک نسبت به بیمه فقط با موجودیت DoctorInsurance ذخیره میشود که یک فیلد قیمت تکی (price) دارد:
// src/Insurance/Entity/DoctorInsurance.php
#[ORM\Column(type: 'integer', nullable: true)]
private ?int $price = null;
این کافی نیست. کاربر (کلینیک یا مطب شخصی) باید بتواند در پروفایل خود مشخص کند:
- مبلغ ویزیت آزاد (بدون بیمه) چقدر است
- اگر بیمه پایه اعمال شود، مبلغ نهایی/سهم بیمار چقدر میشود
- اگر علاوه بر آن بیمه مکمل هم اضافه شود، مبلغ نهایی چقدر میشود
مشکل / هدف
افزودن یک ساختار قیمتگذاری ویزیت بر اساس بیمه در پروفایل entity (هم doctor و هم clinic)، با سه لایه:
- قیمت پایه آزاد (free / بدون بیمه)
- سهم/مبلغ با بیمه پایه — به ازای هر بیمه پایهای که entity میپذیرد
- سهم/مبلغ با بیمه مکمل — به ازای هر بیمه مکمل
این مقادیر بعداً در «ثبت مراجعه جدید» (پرامپت new-visit-modal-ux.md) برای پر کردن خودکار قیمت ویزیت و درصد/مبلغ تخفیف استفاده میشوند.
فایلهای مرتبط
| فایل | نقش |
|---|---|
src/Insurance/Entity/DoctorInsurance.php |
رابطه فعلی پزشک↔بیمه با یک قیمت |
src/Insurance/Entity/Insurance.php |
موجودیت بیمه؛ دارای type (enum InsuranceType) |
src/Insurance/Enum/InsuranceType.php |
نوع بیمه (پایه/مکمل) — بخوان و مقادیر را تأیید کن |
src/Insurance/Controller/InsuranceController.php |
CRUD بیمه + DoctorInsurance (از خط ۱۸۶) |
src/Insurance/Repository/DoctorInsuranceRepository.php |
کوئریها |
assets/admin/pages/MyClinicPage.tsx و DoctorProfilePage.tsx |
پروفایل کلینیک/مطب در پنل |
docs/api/insurance.md |
مستندات API بیمه |
وضعیت فعلی
DoctorInsurance.toArray():
return [
'id' => $this->id,
'doctor_id' => $this->doctor->getId(),
'insurance_id' => $this->insurance->getId(),
'insurance_name' => $this->insurance->getName(),
'type' => $this->insurance->getType()->value,
'price' => $this->price,
];
- فقط برای
doctorاست؛ معادلclinicوجود ندارد. - فقط یک
priceتکی دارد؛ تفکیک آزاد/پایه/مکمل ندارد.
وظایف
۱. تحلیل و طراحی مدل قیمتگذاری
ابتدا InsuranceType و DoctorInsurance و InsuranceController (بخش DoctorInsurance) را کامل بخوان. سپس تصمیم بگیر:
- آیا «ویزیت آزاد» یک فیلد روی پروفایل entity است (یک مقدار) و هر
DoctorInsuranceفقط مبلغ سهم بیمار با آن بیمه را نگه میدارد؟ (پیشنهاد: بله) - آیا باید برای
clinicهم معادلDoctorInsuranceساخت (مثلاً عمومیسازی به entity-type/entity-id مثلPatientRecord)، یا یک موجودیت جدیدEntityInsurancePricing(entityType, entityId, insuranceId, patientShareRials)ساخت؟
توصیه: یک موجودیت polymorphic جدید
EntityInsurancePricingبا کلیدهایentity_type(doctor|clinic)،entity_id،insurance_id،patient_share_rialsبساز وDoctorInsuranceرا بهمرور کنار بگذار (اما دادهی فعلی را migrate کن). قیمت ویزیت آزاد را روی پروفایل entity (یک کلید config یا ستون) نگهدار.
طرح نهایی را قبل از پیادهسازی بهصورت یک پاراگراف توضیح بده.
۲. Entity + Migration
- موجودیت/فیلدهای جدید را بساز (طبق طرح مرحله ۱).
- مقدار «ویزیت آزاد» را برای entity ذخیره کن.
doctrine:migrations:diffسپسmigrate.- دادهی موجود
doctor_insurances.priceرا به مدل جدید migrate کن (در همان migration یا یک migration دادهای).
۳. API
Endpointها برای خواندن/ذخیره قیمتگذاری بیمهی entity جاری (از #[CurrentUser] → resolve به doctor یا clinic مثل الگوی PatientController::resolveEntity):
GET /api/v1/insurance-pricing— لیست قیمتگذاری entity جاری + قیمت ویزیت آزادPUT|PATCH /api/v1/insurance-pricing— ذخیرهی قیمت آزاد + آرایهی سهم هر بیمه
از BaseController و helperهای $this->success() / $this->error() استفاده کن.
۴. Admin Frontend
در MyClinicPage.tsx و DoctorProfilePage.tsx یک بخش «قیمتگذاری ویزیت بر اساس بیمه» اضافه کن:
- ورودی «مبلغ ویزیت آزاد (ریال)»
- جدول/لیست بیمههای پایه و مکمل (از
GET /api/v1/insurances) با یک ورودی مبلغ سهم بیمار به ازای هر کدام - پیشنمایش: «آزاد: X — با بیمه پایه Y: Z — با بیمه مکمل W: …»
- ذخیره با TanStack Query
useMutation
۵. مستندات
docs/api/insurance.md را با endpointهای جدید (method/path/permission، body کامل، نمونه پاسخ JSON واقعی، error codeها) بهروز کن.
نکات مهم
- entity جاری از
#[CurrentUser]resolve میشود؛ الگو را ازPatientController::resolveEntityبگیر (نقشROLE_DOCTOR→ doctor،ROLE_CLINIC→ clinic). - تاریخها/قیمتها همه integer ریال هستند.
- این پرامپت پیشنیاز
new-visit-modal-ux.mdاست؛ خروجی قیمتها آنجا مصرف میشود. - مهاجرت دادهی
DoctorInsuranceنباید قیمتهای موجود را از بین ببرد.