feat(claims): implement automatic claim creation for insurance sessions

This commit is contained in:
hamed
2026-06-24 02:08:12 +03:30
parent 14c6dd6456
commit f7eb1ebd91
5 changed files with 56 additions and 1 deletions
@@ -67,6 +67,21 @@ class ClaimRepository extends ServiceEntityRepository
}, $rows);
}
/** آیا برای این صورتحساب از قبل مطالبه‌ای ساخته شده؟ (از طریق آیتم‌های صورتحساب) */
public function existsForInvoice(int $invoiceId): bool
{
$count = (int) $this->createQueryBuilder('c')
->select('COUNT(c.id)')
->join('c.items', 'ci')
->join('App\Billing\Entity\InvoiceItem', 'ii', 'WITH', 'ii.id = ci.invoiceItemId')
->where('IDENTITY(ii.invoice) = :invoiceId')
->setParameter('invoiceId', $invoiceId)
->getQuery()
->getSingleScalarResult();
return $count > 0;
}
public function save(Claim $entity, bool $flush = true): void
{
$this->getEntityManager()->persist($entity);
+4
View File
@@ -28,6 +28,10 @@ class ClaimService
throw new AppException(ErrorCodes::ERR_VALIDATION_001, 'فقط از صورتحساب نهایی‌شده می‌توان مطالبه ساخت', 422);
}
if ($invoice->getId() !== null && $this->claimRepo->existsForInvoice($invoice->getId())) {
throw new AppException(ErrorCodes::ERR_VALIDATION_001, 'برای این صورتحساب قبلاً مطالبه ثبت شده است', 422);
}
$claims = [];
$baseId = $invoice->getBaseInsuranceId();
@@ -5,6 +5,9 @@ namespace App\Patient\Controller;
use App\Auth\Entity\User;
use App\Auth\Repository\UserActiveContextRepository;
use App\Auth\Repository\UserRepository;
use App\Billing\Service\ClaimService;
use App\Billing\Service\InvoiceService;
use Psr\Log\LoggerInterface;
use App\Clinic\Repository\ClinicRepository;
use App\Doctor\Repository\DoctorRepository;
use App\Patient\Entity\PatientRecord;
@@ -39,6 +42,9 @@ class PatientController extends BaseController
private readonly UserActiveContextRepository $contextRepo,
private readonly \App\UserProfile\Repository\UserProfileRepository $profileRepo,
private readonly \App\Insurance\Repository\InsuranceRepository $insuranceRepo,
private readonly InvoiceService $invoiceService,
private readonly ClaimService $claimService,
private readonly LoggerInterface $logger,
) {}
private function buildPatientProfile(User $patient): array
@@ -221,9 +227,35 @@ class PatientController extends BaseController
$data = json_decode($request->getContent(), true) ?? [];
$session = $this->patientService->createSession($record, $data, $entityType, $entityId);
$this->autoCreateClaim($session, $entityType, $entityId);
return $this->success($session->toArray(), 201);
}
/**
* اتصال خودکار مطالبه‌ی بیمه: اگر session بیمه‌ی پایه یا مکمل داشته باشد،
* صورتحساب ساخته و نهایی می‌شود و مطالبه (در وضعیت pending) ایجاد می‌گردد.
* ارسال مطالبه دستی از صفحه‌ی مطالبات انجام می‌شود.
* خطا در این مرحله نباید ثبت session را خراب کند.
*/
private function autoCreateClaim(\App\Patient\Entity\PatientSession $session, string $entityType, int $entityId): void
{
if ($session->getInsuranceBaseId() === null && $session->getInsuranceSupplementaryId() === null) {
return;
}
try {
$invoice = $this->invoiceService->createFromSession($session, $entityType, $entityId);
$this->invoiceService->finalize($invoice);
$this->claimService->createFromInvoice($invoice);
} catch (\App\Shared\Exception\AppException $e) {
// سهم بیمه‌ای صفر بود یا صورتحساب از قبل وجود داشت — قابل چشم‌پوشی.
$this->logger->info('auto claim skipped', ['session' => $session->getUuid(), 'reason' => $e->getMessage()]);
} catch (\Throwable $e) {
$this->logger->error('auto claim failed', ['session' => $session->getUuid(), 'error' => $e->getMessage()]);
}
}
#[Route('/api/v1/session/{uuid}', methods: ['PATCH'])]
public function updateSession(string $uuid, Request $request, #[CurrentUser] User $user): JsonResponse
{