feat: update session payment logic to ensure accurate payable amounts and reflect consumables in cost breakdown
- Adjusted the calculation of payable amounts in PaymentStep to align with server logic, ensuring overpayments are handled correctly. - Enhanced DetailsStep to include consumables in the itemized cost breakdown, ensuring consistency with patient share calculations. - Updated tests for SessionPaymentPage to validate new behavior regarding overpayments and consumable listings. - Modified PatientController to register SessionPayment correctly when settling sessions via wallet, preventing double charges. - Refactored WalletService to remove outdated methods and ensure wallet transactions reflect the correct amounts after discounts. - Improved accessibility in SearchableSelect component by adding aria labels and ensuring proper role attributes for screen readers. - Updated styles to ensure minimum touch targets meet WCAG guidelines for mobile usability.
This commit is contained in:
@@ -41,7 +41,9 @@ export default function DetailsStep({ session, recordUuid, onBack, onFinish }: P
|
||||
// زمان مراجعه: زمان واقعی نوبت؛ در نبود آن، زمان ثبت پرونده.
|
||||
const visitAt = session.session_at ?? session.created_at ?? null;
|
||||
|
||||
// آیتمهای هزینهی تفکیکشده: ویزیت + هر سرویس، با جمع کل.
|
||||
// آیتمهای هزینهی تفکیکشده: ویزیت + هر سرویس + کالای مصرفی.
|
||||
// کالای مصرفی هم باید بیاید چون سرور آن را در سهم بیمار میآورد
|
||||
// (PatientService::…$consumablesTotal)؛ نبودش ریز هزینهها را با جمع ناسازگار میکرد.
|
||||
const costItems: Array<{ label: string; rials: number }> = [];
|
||||
if (visitPrice > 0) costItems.push({ label: 'ویزیت', rials: visitPrice });
|
||||
(session.services ?? []).forEach((s) => {
|
||||
@@ -50,6 +52,19 @@ export default function DetailsStep({ session, recordUuid, onBack, onFinish }: P
|
||||
rials: s.line_total_rials ?? (s.price_rials ?? 0) * (s.quantity ?? 1),
|
||||
});
|
||||
});
|
||||
(session.consumables ?? []).forEach((c) => {
|
||||
costItems.push({
|
||||
label: c.item_name ?? 'کالای مصرفی',
|
||||
rials: c.line_total_rials ?? 0,
|
||||
});
|
||||
});
|
||||
|
||||
// خطوط بالا ناخالصاند (پیش از بیمه) ولی finalPrice سهمِ بیمار پس از بیمه است.
|
||||
// پس وقتی بیمه هست، جمعِ خطوط را ناخالص نشان بده و سهم بیمه را جدا کم کن.
|
||||
const grossTotal = session.gross_total_rials ?? finalPrice;
|
||||
const baseInsurance = session.base_insurance_rials ?? 0;
|
||||
const suppInsurance = session.supplementary_insurance_rials ?? 0;
|
||||
const hasInsurance = baseInsurance > 0 || suppInsurance > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -78,8 +93,28 @@ export default function DetailsStep({ session, recordUuid, onBack, onFinish }: P
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 500, color: '#525252' }}>{formatRial(it.rials)}</span>
|
||||
</div>
|
||||
))}
|
||||
{hasInsurance && (
|
||||
<>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0 4px', borderTop: '1px dashed #E0E0E0' }}>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 13, fontWeight: 700, color: '#2f2f2f' }}>جمع کل خدمات</span>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 700, color: '#2f2f2f' }}>{formatRial(grossTotal)}</span>
|
||||
</div>
|
||||
{baseInsurance > 0 && (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '6px 0' }}>
|
||||
<span className="dark:text-[#A1A1A1]" style={{ fontSize: 13, color: '#616161' }}>سهم بیمه پایه</span>
|
||||
<span style={{ fontSize: 14, fontWeight: 500, color: '#2E7D32' }}>{formatRial(baseInsurance)}</span>
|
||||
</div>
|
||||
)}
|
||||
{suppInsurance > 0 && (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '6px 0' }}>
|
||||
<span className="dark:text-[#A1A1A1]" style={{ fontSize: 13, color: '#616161' }}>سهم بیمه تکمیلی</span>
|
||||
<span style={{ fontSize: 14, fontWeight: 500, color: '#2E7D32' }}>{formatRial(suppInsurance)}</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0 4px', borderTop: '1px dashed #E0E0E0' }}>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 13, fontWeight: 700, color: '#2f2f2f' }}>جمع کل</span>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 13, fontWeight: 700, color: '#2f2f2f' }}>{hasInsurance ? 'سهم بیمار' : 'جمع کل'}</span>
|
||||
<span className="dark:text-[#D7D8ED]" style={{ fontSize: 14, fontWeight: 700, color: '#2f2f2f' }}>{formatRial(finalPrice)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -124,9 +124,10 @@ export default function PaymentStep({ recordUuid, session, walletBalance, onCont
|
||||
const baseInsurance = session.base_insurance_rials ?? 0;
|
||||
const suppInsurance = session.supplementary_insurance_rials ?? 0;
|
||||
const hasInsurance = baseInsurance > 0 || suppInsurance > 0;
|
||||
const payable = session.remaining_rials !== undefined
|
||||
? session.remaining_rials + (session.paid_total_rials ?? 0)
|
||||
: Math.max(0, finalPrice - discountRials);
|
||||
// همان فرمول سرور (PatientSession::getPayableRials). بازسازی از روی
|
||||
// `remaining + paid` غلط بود: سرور remaining را در صفر کلمپ میکند، پس در
|
||||
// بیشپرداخت مبلغ نهایی تا اندازهی پرداختی بالا میرفت و اضافهپرداخت پنهان میشد.
|
||||
const payable = Math.max(0, finalPrice - discountRials);
|
||||
const debt = session.remaining_rials ?? session.patient_debt_rials ?? 0;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user