feat(insurance): add insurance coverage flag to selected services and update coverage logic
This commit is contained in:
@@ -61,7 +61,7 @@ export default function NewSessionPage() {
|
||||
const nav = useNavigate();
|
||||
const qc = useQueryClient();
|
||||
|
||||
const [selectedServices, setSelectedServices] = useState<{ uuid: string; name: string; price: number; qty: number }[]>([]);
|
||||
const [selectedServices, setSelectedServices] = useState<{ uuid: string; name: string; price: number; qty: number; insured: boolean }[]>([]);
|
||||
const [sectionUuid, setSectionUuid] = useState('');
|
||||
const [itemUuid, setItemUuid] = useState('');
|
||||
const [baseId, setBaseId] = useState('');
|
||||
@@ -154,7 +154,7 @@ export default function NewSessionPage() {
|
||||
if (!itemUuid) return;
|
||||
const found = itemsData?.data?.find(i => i.uuid === itemUuid);
|
||||
if (!found || selectedServices.some(s => s.uuid === found.uuid)) return;
|
||||
setSelectedServices(p => [...p, { uuid: found.uuid, name: found.name, price: found.price_rials, qty: 1 }]);
|
||||
setSelectedServices(p => [...p, { uuid: found.uuid, name: found.name, price: found.price_rials, qty: 1, insured: !!found.insurance_covered }]);
|
||||
setItemUuid('');
|
||||
};
|
||||
|
||||
@@ -168,6 +168,8 @@ export default function NewSessionPage() {
|
||||
const servicesPatient = useMemo(
|
||||
() => selectedServices.reduce((sum, x) => {
|
||||
const total = x.price * x.qty;
|
||||
// پرچم سرویس gate نهایی: اگر «شامل بیمه» نباشد، کامل سهم بیمار است.
|
||||
if (!x.insured) return sum + total;
|
||||
return sum + patientShareOf(
|
||||
total,
|
||||
ruleFor(baseContract, baseCoverage, x.uuid),
|
||||
|
||||
@@ -455,4 +455,4 @@ override پوشش یک خدمت خاص تحت قرارداد یک بیمه. فی
|
||||
پاسخ `200`: `{ success, data: { message } }`.
|
||||
خطاها: `404 ERR_NOT_FOUND_001` قرارداد یافت نشد · `422 ERR_VALIDATION_001` سرویس یافت نشد · `403 ERR_FORBIDDEN_001` سرویس متعلق به شما نیست.
|
||||
|
||||
> منطق resolve: `TenantInsuranceService::coverageRuleForService()` ابتدا override خدمت را بررسی میکند؛ اگر `covered=false` → `CoverageRule::notCovered()`؛ در غیر این صورت فیلدهای null از قرارداد پر میشوند. این `CoverageRule` ورودی `BillingCalculator` است و سهم بیمهی هر `InvoiceItem` را تعیین میکند؛ همان سهمها در `ClaimService::createFromInvoice()` به `ClaimItem` (مطالبات بیمه) تبدیل میشوند. پنل ادمین این endpoint را از مودال «پوشش بیمه» در صفحه سرویسهای کلینیک فراخوانی میکند.
|
||||
> منطق resolve: `TenantInsuranceService::coverageRuleForService()` ابتدا **پرچم `ServiceItem.insurance_covered`** را چک میکند؛ اگر این خدمت «شامل بیمه» نباشد، بدون توجه به override یا قرارداد، `CoverageRule::notCovered()` برمیگردد (gate نهایی). سپس override خدمت بررسی میشود؛ اگر `covered=false` → `notCovered()`؛ در غیر این صورت فیلدهای null از قرارداد پر میشوند. این `CoverageRule` ورودی `BillingCalculator` است و سهم بیمهی هر `InvoiceItem` را تعیین میکند؛ همان سهمها در `ClaimService::createFromInvoice()` به `ClaimItem` (مطالبات بیمه) تبدیل میشوند. پنل ادمین این endpoint را از مودال «پوشش بیمه» در صفحه سرویسهای کلینیک فراخوانی میکند.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Insurance\Service;
|
||||
|
||||
use App\ClinicService\Repository\ServiceItemRepository;
|
||||
use App\Insurance\Entity\TenantInsurance;
|
||||
use App\Insurance\Repository\InsuranceRepository;
|
||||
use App\Insurance\Repository\TenantInsuranceRepository;
|
||||
@@ -16,6 +17,7 @@ class TenantInsuranceService
|
||||
private readonly TenantInsuranceRepository $repo,
|
||||
private readonly InsuranceRepository $insuranceRepo,
|
||||
private readonly TenantServiceCoverageRepository $coverageRepo,
|
||||
private readonly ServiceItemRepository $serviceItemRepo,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -101,6 +103,12 @@ class TenantInsuranceService
|
||||
return CoverageRule::notCovered();
|
||||
}
|
||||
|
||||
// پرچم سرویس gate نهایی است: اگر «این خدمت شامل بیمه میشود» غیرفعال باشد، هیچ پوششی محاسبه نمیشود.
|
||||
$service = $this->serviceItemRepo->find($serviceItemId);
|
||||
if ($service === null || !$service->isInsuranceCovered()) {
|
||||
return CoverageRule::notCovered();
|
||||
}
|
||||
|
||||
$contract = $this->repo->findActiveContract($entityType, $entityId, $insuranceId);
|
||||
if ($contract === null) {
|
||||
return CoverageRule::notCovered();
|
||||
|
||||
Reference in New Issue
Block a user