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
@@ -3,6 +3,7 @@
namespace App\Insurance\Controller;
use App\Auth\Entity\User;
use App\ClinicService\Repository\ServiceItemRepository;
use App\Clinic\Repository\ClinicRepository;
use App\Doctor\Repository\DoctorRepository;
use App\Insurance\Entity\DoctorInsurance;
@@ -39,6 +40,7 @@ class InsuranceController extends BaseController
private readonly TenantInsuranceRepository $tenantInsuranceRepo,
private readonly TenantServiceCoverageRepository $serviceCoverageRepo,
private readonly TenantInsuranceService $tenantInsuranceService,
private readonly ServiceItemRepository $serviceItemRepo,
private readonly FileValidatorService $fileValidator,
private readonly string $projectDir,
) {}
@@ -403,7 +405,14 @@ class InsuranceController extends BaseController
$rows = $this->serviceCoverageRepo->findByContract($contract->getId());
return $this->success(['data' => array_map(fn($r) => $r->toArray(), $rows)]);
$data = array_map(function ($r) {
$row = $r->toArray();
$item = $this->serviceItemRepo->find($r->getServiceItemId());
$row['service_item_uuid'] = $item?->getUuid();
return $row;
}, $rows);
return $this->success(['data' => $data]);
}
#[Route('/api/v1/billing/tenant-insurances/{uuid}/service-coverage', methods: ['PUT'])]
@@ -416,12 +425,23 @@ class InsuranceController extends BaseController
return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'قرارداد یافت نشد', 404);
}
$data = json_decode($request->getContent(), true) ?? [];
$serviceItemId = isset($data['service_item_id']) ? (int) $data['service_item_id'] : 0;
if ($serviceItemId <= 0) {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'service_item_id الزامی است', 422);
$data = json_decode($request->getContent(), true) ?? [];
$serviceItem = isset($data['service_item_uuid'])
? $this->serviceItemRepo->findByUuid((string) $data['service_item_uuid'])
: (isset($data['service_item_id']) ? $this->serviceItemRepo->find((int) $data['service_item_id']) : null);
if ($serviceItem === null) {
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'سرویس یافت نشد', 422);
}
$section = $serviceItem->getSection();
if ($section->getEntityType() !== $entityType || $section->getEntityId() !== $entityId) {
return $this->error(ErrorCodes::ERR_FORBIDDEN_001, 'این سرویس متعلق به شما نیست', 403);
}
$serviceItemId = $serviceItem->getId();
$this->tenantInsuranceService->setServiceCoverage(
$contract,
$serviceItemId,