7.4 KiB
یکپارچهسازی قراردادهای بیمه، select یکدست، و تعداد خدمت در مراجعه
پروژه
clinicpro (admin frontend + کمی backend برای quantity)
زمینه
چهار مورد بههممرتبط در پنل ادمین:
- صفحهی
/admin/insurance-pricingدو بخش دارد که همپوشانی دارند → باید یکی شود. - select listها در کل پنل یکشکل نیستند (بعضی
<select className="input">بومی، بعضیSearchableSelect). - در «ثبت مراجعه جدید» هر خدمت فقط یکبار اضافه میشود؛ تعداد (مثلاً سرُم ۲ عدد) ممکن نیست.
- select بیمهی پایه/تکمیلی در فرم مراجعه باید فقط بیمههایی را نشان دهد که tenant در
insurance-pricingقیمتگذاری/قرارداد کرده، و درصد تخفیف خودکار اعمال شود.
وضعیت فعلی
صفحهی insurance-pricing (دو بخش همپوشان)
assets/admin/pages/InsurancePricingPage.tsx:
<TenantInsuranceContracts /> {/* قراردادها: بیمه + درصد پوشش + فرانشیز + سقف */}
<InsurancePricingSection /> {/* قیمتگذاری: قیمت ویزیت آزاد + سهم هر بیمهی پایه */}
TenantInsuranceContracts(assets/admin/components/TenantInsuranceContracts.tsx): per (tenant, insurance) قرارداد باcoverage_percent,franchise_rials,annual_ceiling_rials؛ افزودن/ویرایش/حذف. هم basic هم supplementary. API:/api/v1/billing/tenant-insurances(GET/POST/PATCH/DELETE).InsurancePricingSection(assets/admin/components/InsurancePricingSection.tsx): «قیمت ویزیت آزاد» + سهم بیمار به ازای هر بیمهی پایه. API:GET/PUT /api/v1/insurance-pricing(جدولentity_insurance_pricing).
این دو منطق موازیاند و کاربر را گیج میکنند. قرارداد با coverage_percent کافی است؛ بخش «قیمتگذاری» زیرش بیمعنی است.
select listها
نمونهی بومی پراکنده (NewSessionPage.tsx, MyPatientsPage.tsx, SmsPage.tsx, ClaimsPage.tsx, SettingsPage.tsx, …):
<select className="input" value={...} onChange={...}>
<option value="">...</option>
{opts.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
</select>
و در کنارش کامپوننت SearchableSelect (assets/admin/components/ui/SearchableSelect.tsx) برای بخش خدمات استفاده میشود. ظاهر این دو فرق دارد.
تعداد خدمت
src/Patient/Entity/SessionService.php — فیلد quantity ندارد:
private ServiceItem $serviceItem;
private ?ClinicStaff $staff = null;
private int $priceRials; // = serviceItem price، بدون ضرب در تعداد
PatientService::createSession services را تکواحدی جمع میزند:
$servicesTotal = array_sum(array_column($serviceItems, 'price_rials'));
فرانت (NewSessionPage.tsx) هم هر خدمت را یکبار اضافه میکند (chip بدون تعداد).
select بیمه در فرم مراجعه
NewSessionPage.tsx گزینههای بیمه را از GET /api/v1/insurance-pricing میگیرد (pricing.insurances)، ولی آن endpoint همهی بیمههای فعال را برمیگرداند (نه فقط قراردادهای tenant). درصد هم از patient_share_rials همان endpoint محاسبه میشود — که بعد از حذف بخش قیمتگذاری دیگر منبع درستی نیست.
وظایف
۱. ادغام صفحهی insurance-pricing
InsurancePricingSectionو endpoint/جدولentity_insurance_pricingرا کنار بگذار (ازInsurancePricingPageحذف کن). قرارداد (TenantInsuranceContracts) تنها منبع باشد.TenantInsuranceContractsباید واضح هم basic هم supplementary را پشتیبانی کند (الان هم میکند؛ متن/گروهبندی را شفاف کن: دو دسته «بیمه پایه» و «بیمه تکمیلی»).- اگر «قیمت ویزیت آزاد» جایی لازم است، آن را بهصورت یک فیلد ساده در همان صفحه/پروفایل نگهدار یا حذف کن (تصمیم را در پیادهسازی مستند کن). مسیر
/admin/insurance-pricingو آیتم سایدبار باقی بماند. InsurancePricingSection.tsxحذف یا خالی شود؛ importها پاکسازی.
۲. یک کامپوننت select یکدست
- یک کامپوننت
Selectدرassets/admin/components/ui/بساز (یاSearchableSelectرا بهعنوان استاندارد واحد بپذیر) با ظاهر یکسان: همان استایل، RTL، chevron، حالت focus/disabled، placeholder. - همهی
<select className="input">های پنل را با این کامپوننت جایگزین کن (صفحات بالا). رفتار/داده تغییر نکند، فقط ظاهر یکدست شود. - نمونهی مرجع ظاهر: select خدمات (
SearchableSelect) در فرم مراجعه.
۳. تعداد (quantity) برای خدمات
Backend:
- به
SessionServiceفیلدquantity(int, پیشفرض 1) اضافه کن + getter/setter + درtoArray(). migration. PatientService::createSession: body هر service میتواندquantityداشته باشد؛line_total = price × quantity؛services_total_rialsوfinal_price_rialsبا احتساب تعداد محاسبه شوند.docs/api/patient.md(یا فایل session مربوط) بهروز شود.
Frontend (NewSessionPage.tsx):
- chip خدمت دارای ورودی/استپر تعداد باشد (۱،۲،…)؛ نمایش
price × qty. - body ارسالی:
services: [{ service_item_uuid, quantity }]. - خلاصهی قیمت با تعداد محاسبه شود.
۴. select بیمه فقط از قراردادها + درصد خودکار
- در
NewSessionPage.tsx، گزینههای «بیمه پایه» و «بیمه تکمیلی» از قراردادهای tenant بیایند (GET /api/v1/billing/tenant-insurances)، نه ازinsurance-pricing. - هر گزینه
coverage_percentخودش را دارد؛ با انتخاب بیمه، درصد تخفیف خودکار ازcoverage_percentقرارداد ست شود (نه ازpatient_share_rials). - فقط بیمههای فعال قرارداد نمایش داده شوند؛ تفکیک basic/supplementary بر اساس
insurance_kind.
نکات مهم
- backend فقط برای
quantityتغییر میکند؛ بقیه frontend است. - بعد از تغییر Entity:
doctrine:migrations:diff+migrate. - پاسخها/الگوها:
BaseController،formatRial/formatNumber، RTL، Vazirmatn، CSS variables موجود. - چون
insurance-pricing(entity_insurance_pricing) حذف میشود، هر مصرفکنندهی دیگرش را پیدا و پاکسازی کن (جستجویinsurance-pricingوEntityInsurancePricingدرsrc/وassets/). اگرBillingCalculator/InvoiceServiceبه آن وابسته است، بهcoverage_percentقرارداد سوییچ کن. - tsc +
yarn devبدون خطا؛ هر بخش جدا commit.