feat(claims): add insurance_name field to claims and update API responses

This commit is contained in:
hamed
2026-06-24 02:11:16 +03:30
parent f7eb1ebd91
commit fbfe25c3c6
3 changed files with 26 additions and 8 deletions
+4 -2
View File
@@ -17,6 +17,7 @@ interface ClaimItem {
interface Claim {
uuid: string;
insurance_id: number;
insurance_name: string | null;
insurance_kind: string;
total_claimed_rials: number;
total_approved_rials: number | null;
@@ -28,6 +29,7 @@ interface Claim {
interface DebtRow {
insurance_id: number;
insurance_name: string | null;
claimed: number;
approved: number;
paid: number;
@@ -94,7 +96,7 @@ export default function ClaimsPage() {
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
{debt.map((d: DebtRow) => (
<div key={d.insurance_id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 12px', borderRadius: 8, border: '1px solid var(--border)', fontSize: 13 }}>
<span style={{ fontWeight: 600 }}>بیمه #{formatNumber(d.insurance_id)}</span>
<span style={{ fontWeight: 600 }}>{d.insurance_name ?? `بیمه #${formatNumber(d.insurance_id)}`}</span>
<span style={{ color: 'var(--text-3)' }}>ادعا {formatRial(d.claimed)} · پرداخت {formatRial(d.paid)}</span>
<span style={{ fontWeight: 700, color: d.debt > 0 ? 'var(--danger)' : 'var(--success, #16a34a)' }}>بدهی {formatRial(d.debt)}</span>
</div>
@@ -129,7 +131,7 @@ export default function ClaimsPage() {
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 10 }}>
<div>
<div style={{ fontWeight: 600, fontSize: 13.5 }}>
بیمه #{formatNumber(c.insurance_id)}
{c.insurance_name ?? `بیمه #${formatNumber(c.insurance_id)}`}
<span className="badge gray" style={{ fontSize: 10, marginInlineStart: 6 }}>{KIND_LABEL[c.insurance_kind] ?? c.insurance_kind}</span>
<span className={`badge ${meta.cls}`} style={{ fontSize: 10, marginInlineStart: 4 }}><span className="bdot" />{meta.label}</span>
</div>
+4 -2
View File
@@ -108,8 +108,10 @@
**Response 201:** `{ success, data: [ …claims ] }` (یک یا دو مطالبه: پایه/مکمل).
**Errors:** `422` صورتحساب نهایی نشده / سهم بیمه ندارد / مطالبه از قبل ثبت شده · `404` صورتحساب یافت نشد.
هر مطالبه در پاسخ علاوه بر `insurance_id`، فیلد `insurance_name` (نام بیمه، یا `null` اگر بیمه حذف شده باشد) را نیز دارد. در `POST` و `transition` و `GET` یکسان است.
## GET /api/v1/billing/claims?status=
لیست مطالبات tenant. فیلتر اختیاری `status` (`pending|submitted|approved|rejected|paid`).
لیست مطالبات tenant. فیلتر اختیاری `status` (`pending|submitted|approved|rejected|paid`). هر آیتم شامل `insurance_name` است.
## POST /api/v1/billing/claims/{uuid}/{action}
انتقال وضعیت. `action``submit|approve|reject|pay`.
@@ -132,7 +134,7 @@
"success": true,
"data": {
"data": [
{ "insurance_id": 3, "claimed": 840000, "approved": 800000, "paid": 500000, "debt": 340000 }
{ "insurance_id": 3, "insurance_name": "تأمین اجتماعی", "claimed": 840000, "approved": 800000, "paid": 500000, "debt": 340000 }
]
}
}
+18 -4
View File
@@ -10,6 +10,7 @@ use App\Billing\Service\ClaimService;
use App\Billing\Service\InvoiceService;
use App\Clinic\Repository\ClinicRepository;
use App\Doctor\Repository\DoctorRepository;
use App\Insurance\Repository\InsuranceRepository;
use App\Patient\Repository\PatientSessionRepository;
use App\Shared\Constant\ErrorCodes;
use App\Shared\Controller\BaseController;
@@ -32,8 +33,16 @@ class BillingController extends BaseController
private readonly PatientSessionRepository $sessionRepo,
private readonly DoctorRepository $doctorRepo,
private readonly ClinicRepository $clinicRepo,
private readonly InsuranceRepository $insuranceRepo,
) {}
private function claimArray(Claim $claim): array
{
$data = $claim->toArray();
$data['insurance_name'] = $this->insuranceRepo->find($claim->getInsuranceId())?->getName();
return $data;
}
#[Route('/api/v1/billing/invoices', methods: ['POST'])]
public function create(Request $request, #[CurrentUser] User $user): JsonResponse
{
@@ -107,7 +116,7 @@ class BillingController extends BaseController
$claims = $this->claimService->createFromInvoice($invoice);
return $this->success(['data' => array_map(fn(Claim $c) => $c->toArray(), $claims)], 201);
return $this->success(['data' => array_map(fn(Claim $c) => $this->claimArray($c), $claims)], 201);
}
#[Route('/api/v1/billing/claims', methods: ['GET'])]
@@ -121,7 +130,7 @@ class BillingController extends BaseController
$status = $request->query->get('status') ?: null;
$claims = $this->claimRepo->findByTenant($entityType, $entityId, $status);
return $this->success(['data' => array_map(fn(Claim $c) => $c->toArray(), $claims)]);
return $this->success(['data' => array_map(fn(Claim $c) => $this->claimArray($c), $claims)]);
}
#[Route('/api/v1/billing/claims/{uuid}/{action}', methods: ['POST'], requirements: ['action' => 'submit|approve|reject|pay'])]
@@ -151,7 +160,7 @@ class BillingController extends BaseController
'reason' => trim($data['reason'] ?? ''),
]);
return $this->success(['data' => $claim->toArray()]);
return $this->success(['data' => $this->claimArray($claim)]);
}
#[Route('/api/v1/billing/reports/insurance-debt', methods: ['GET'])]
@@ -162,7 +171,12 @@ class BillingController extends BaseController
return $this->error(ErrorCodes::ERR_FORBIDDEN_001, 'پروفایل یافت نشد', 403);
}
return $this->success(['data' => $this->claimRepo->debtReport($entityType, $entityId)]);
$rows = array_map(function (array $row) {
$row['insurance_name'] = $this->insuranceRepo->find($row['insurance_id'])?->getName();
return $row;
}, $this->claimRepo->debtReport($entityType, $entityId));
return $this->success(['data' => $rows]);
}
private function ownsSession($session, string $entityType, int $entityId): bool