{{-- Shared Payment Section - used by OPD, Dental, IPD, ANC Requires: $visit (with invoice.items, invoice.payments.receipt loaded) Optional: $readOnly (bool) Styled to match the encounter theme (.enc-page). Falls back to neutral styling when used outside an .enc-page wrapper (e.g. IPD, if not wrapped). --}} @php $invoice = $visit->invoice ?? null; $readOnly = $readOnly ?? in_array($visit->status, ['completed','cancelled','discharged']); $payments = $invoice ? $invoice->payments : collect(); if ($invoice) { $freshTotal = $invoice->items()->sum(\DB::raw('quantity * unit_price')); $freshPaid = $invoice->payments()->where('status', 'completed')->sum('amount'); $balance = max(0, $freshTotal - $freshPaid); } else { $balance = 0; } $sectionId = 'pay-' . $visit->id; // SHA detection — the JS-side toggle compares the insurance_provider // option value (which is the company NAME) to this string. We expose // the SHA company name once here so we don't have to hard-code it in // JS, and so renaming the SHA insurer in admin propagates correctly. // Falls back to the canonical seed name if the row is missing. $shaCompany = \App\Models\InsuranceCompany::where('code', 'SHA')->first(); $shaName = $shaCompany?->name ?? 'SHA (Social Health Authority)'; // Prefill from this patient's existing SHA cover, if any. The // patient_insurances table is the source of truth — written by // BillingController::recordPayment() on first SHA capture, and kept // in sync on subsequent payments. Auth reference is intentionally // NOT prefilled (it's per-episode, see controller comment). $shaCover = null; if ($shaCompany && ($visit->patient_id ?? null)) { $shaCover = \App\Models\PatientInsurance::where('patient_id', $visit->patient_id) ->where('insurance_company_id', $shaCompany->id) ->where('is_active', true) ->latest() ->first(); } @endphp @once @endonce @if($invoice)
@if(!($readOnly ?? false))@endif @foreach($payments as $pay) @if(!($readOnly ?? false)) @endif @endforeach {{-- Payment form row --}} @if(!$readOnly && $balance > 0 && auth()->user()->hasAnyRole('Receptionist','Clinician','Nurse','Triage Nurse','Dental User','Super Admin','Hospital Admin')) @elseif($balance <= 0 && !$readOnly) @endif
Method Details Amount Reference
@if($pay->payment_type === 'copay') Co-pay ({{ str_replace('_',' ',$pay->payment_method) }}) @else {{ str_replace('_',' ',$pay->payment_method) }} @endif {{ $pay->description ?? '' }} · {{ $pay->created_at?->format('d M H:i') ?? '' }} @if(!empty($pay->sha_number))
SHA: {{ $pay->sha_number }} · {{ $pay->sha_member_name }} · {{ $pay->sha_relationship }} @if(!empty($pay->sha_auth_reference)) · Auth {{ $pay->sha_auth_reference }} @endif
@endif
KES {{ number_format($pay->amount) }} {{ $pay->reference_number ?? $pay->mpesa_code ?? '' }} @if(auth()->user()->hasAnyRole('Super Admin','Hospital Admin','Receptionist','Clinician','Nurse','Triage Nurse'))
@csrf @method('DELETE')
@endif
@csrf
{{-- Co-pay sub-rail. When the cashier picks Co-pay, they --}} {{-- still need to specify HOW it was actually paid (cash --}} {{-- in hand vs M-Pesa). This sub-select shadows --}} {{-- payment_method on submit via JS so the row gets --}} {{-- payment_type='copay' + payment_method='cash'|'mpesa'. --}} {{-- When the rail = mpesa, the M-Pesa channel sub-select --}} {{-- (Direct / KCB / Bingwa) reveals as well — same --}} {{-- channel field that regular M-Pesa uses, so the back- --}} {{-- end's existing channel-label logic kicks in unchanged.--}}
{{-- ── SHA member-identity panel ───────────────────────── Reveals only when the cashier picks Insurance → SHA (Social Health Authority). SHA receipts/claims require the principal's SHA Number, the member name (which may differ from the patient — e.g. a child dependent), and the patient's relationship to that principal. Auth Reference is optional and only applies when SHA has pre-authorised the episode. Server-side validation enforces the three mandatory fields when payment_method is insurance AND insurance_provider resolves to the insurer whose code is 'SHA'. --}}
✓ Bill fully paid
Total Paid KES {{ number_format($invoice->amount_paid ?? 0) }}
Balance Due KES {{ number_format($balance) }} {{ $visit->visit_number }}
{{-- Print buttons: Invoice | Receipt | Final Receipt | Case Summary --}} @php // Case Summary button: enabled only when a diagnosis is recorded // on the visit's consultation. Both the structured ICD-10 entries // and the legacy free-text array count. Same check the controller // enforces on submit. $_csConsult = $visit->consultation ?? null; $_hasDiagnosis = $_csConsult && ( ($_csConsult->relationLoaded('diagnoses') ? $_csConsult->diagnoses->isNotEmpty() : $_csConsult->diagnoses()->exists()) || !empty(array_filter($_csConsult->diagnosis ?? [])) ); @endphp
Print Invoice @if($payments->count()) @php $lastReceipt = $payments->last()?->receipt; @endphp @if($lastReceipt) Interim Receipt @endif @endif Final Receipt {{-- Case Summary — clinical-financial summary for SHA / insurer claims. Receptionist hands the printed page to the patient at end of visit. Disabled (greyed out, tooltip explains) until a diagnosis is recorded on the consultation. The controller also enforces this server-side so a hand-typed URL can't bypass the gate. --}} @if($_hasDiagnosis) Case Summary @else Case Summary — needs diagnosis @endif
@endif