feat: integrate insurance coverage management for clinic services

- Updated NewSessionPage to calculate patient share based on insurance coverage rules.
- Refactored billing calculations to utilize new patientShareOf function for service items.
- Enhanced API documentation to reflect changes in service coverage structure.
- Implemented ServiceInsuranceModal for managing insurance coverage per service.
- Added UI components for displaying and editing insurance coverage details.
- Removed obsolete toggle switch styles and adjusted CSS for new components.
- Ensured backend endpoints support both service_item_id and service_item_uuid for flexibility.
This commit is contained in:
hamed
2026-06-24 04:23:50 +03:30
parent 253414ef3e
commit 27840da78d
11 changed files with 878 additions and 258 deletions
+45 -9
View File
@@ -4,8 +4,11 @@ namespace App\Patient\Service;
use App\Appointment\Entity\Appointment;
use App\Auth\Repository\UserRepository;
use App\Billing\Service\BillingCalculator;
use App\Billing\ValueObject\Money;
use App\ClinicService\Repository\ServiceItemRepository;
use App\Clinic\Repository\ClinicRepository;
use App\Insurance\Service\TenantInsuranceService;
use App\Doctor\Repository\DoctorAddressRepository;
use App\Patient\Entity\PatientRecord;
use App\Patient\Entity\PatientSession;
@@ -28,17 +31,46 @@ class PatientService
private readonly SubscriptionService $subscriptionService,
private readonly DoctorAddressRepository $addressRepo,
private readonly ClinicRepository $clinicRepo,
private readonly TenantInsuranceService $tenantInsuranceService,
private readonly BillingCalculator $billingCalculator,
) {}
public function calculateFinalPrice(int $visitPrice, float $baseDiscount, float $suppDiscount, array $serviceItems): array
{
$afterBase = $visitPrice * (1 - $baseDiscount / 100);
$afterSupp = $afterBase * (1 - $suppDiscount / 100);
$servicesTotal = array_sum(array_column($serviceItems, 'price_rials'));
/**
* محاسبه‌ی سهم بیمار.
* ویزیت با درصد تخفیف انتخاب‌شده در فرم؛ هر خدمت با قاعده‌ی پوشش همان بیمه‌گر برای همان خدمت
* (TenantServiceCoverage از طریق BillingCalculator). خدمتی که آن بیمه را پوشش نمی‌دهد، کامل بر عهده‌ی بیمار است.
*
* @param array<array{item_id: int, price_rials: int}> $serviceItems قیمت کل هر ردیف (با احتساب تعداد)
*/
public function calculateFinalPrice(
int $visitPrice,
float $baseDiscount,
float $suppDiscount,
array $serviceItems,
string $entityType = 'doctor',
int $entityId = 0,
?int $baseInsuranceId = null,
?int $suppInsuranceId = null,
): array {
$afterBase = $visitPrice * (1 - $baseDiscount / 100);
$afterSupp = $afterBase * (1 - $suppDiscount / 100);
$visitShare = (int) round($afterSupp);
$servicesTotal = 0;
$servicesPatient = 0;
foreach ($serviceItems as $svc) {
$servicesTotal += $svc['price_rials'];
$baseRule = $this->tenantInsuranceService->coverageRuleForService($entityType, $entityId, $baseInsuranceId, $svc['item_id']);
$suppRule = $this->tenantInsuranceService->coverageRuleForService($entityType, $entityId, $suppInsuranceId, $svc['item_id']);
$breakdown = $this->billingCalculator->calculateItem(new Money($svc['price_rials']), $baseRule, $suppRule);
$servicesPatient += $breakdown->patientRials;
}
return [
'services_total_rials' => (int) $servicesTotal,
'final_price_rials' => (int) round($afterSupp) + (int) $servicesTotal,
'services_total_rials' => $servicesTotal,
'final_price_rials' => $visitShare + $servicesPatient,
];
}
@@ -111,7 +143,7 @@ class PatientService
$item = $this->serviceItemRepo->findByUuid($svc['service_item_uuid'] ?? '');
if ($item !== null) {
$qty = max(1, (int) ($svc['quantity'] ?? 1));
$serviceItemsData[] = ['price_rials' => $item->getPriceRials() * $qty];
$serviceItemsData[] = ['item_id' => $item->getId(), 'price_rials' => $item->getPriceRials() * $qty];
}
}
@@ -119,7 +151,11 @@ class PatientService
$session->getVisitPriceRials(),
$session->getBaseInsuranceDiscountPercent(),
$session->getSupplementaryDiscountPercent(),
$serviceItemsData
$serviceItemsData,
$entityType,
$entityId,
$session->getInsuranceBaseId(),
$session->getInsuranceSupplementaryId(),
);
$session->setServicesTotalRials($priceCalc['services_total_rials']);