Deploy Ladill Care / deploy (push) Successful in 39s
Shared queue-board is now a Waiting/Called/In care/Done stage board with prominent tickets and Call next; nurses lose queue.manage and canAccessPatientQueue so /queue and queue nav are gated while specialty workspaces stay available. Co-authored-by: Cursor <cursoragent@cursor.com>
126 lines
7.6 KiB
PHP
126 lines
7.6 KiB
PHP
@php $money = fn ($minor) => config('care.billing.currency').' '.number_format($minor / 100, 2); @endphp
|
|
<x-app-layout title="Financial gates">
|
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
<div>
|
|
<h1 class="text-xl font-semibold text-slate-900">Financial gates</h1>
|
|
<p class="mt-1 text-sm text-slate-500">Clear payment or authorization before patients enter gated service queues.</p>
|
|
</div>
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
@if (! empty($canManageQueue) && ! empty($queueIntegration['enabled']))
|
|
<div class="w-full sm:w-auto">
|
|
@include('care.partials.queue-ops', [
|
|
'queueIntegration' => $queueIntegration,
|
|
'queueCallNextRoute' => 'care.bills.call-next',
|
|
'queueCallNextParams' => [],
|
|
'branchId' => $branchId ?? null,
|
|
'variant' => 'button',
|
|
])
|
|
</div>
|
|
@endif
|
|
<a href="{{ route('care.bills.index', ['view' => 'list']) }}" class="rounded-lg border border-slate-200 px-4 py-2 text-sm text-slate-700">Bills & invoices</a>
|
|
</div>
|
|
</div>
|
|
|
|
<form method="GET" class="mt-4 flex flex-wrap gap-3 rounded-2xl border border-slate-200 bg-white p-4">
|
|
<select name="status" class="rounded-lg border-slate-300 text-sm">
|
|
<option value="">All statuses</option>
|
|
@foreach ($statuses as $value => $label)
|
|
<option value="{{ $value }}" @selected(request('status', 'pending') === $value)>{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
<button type="submit" class="btn-primary">Filter</button>
|
|
</form>
|
|
|
|
<div class="mt-4 space-y-3">
|
|
@forelse ($obligations as $obligation)
|
|
<article class="rounded-2xl border border-slate-200 bg-white p-5">
|
|
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
|
<div>
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<h2 class="font-semibold text-slate-900">{{ $obligation->patient?->fullName() ?? 'Patient' }}</h2>
|
|
<span class="rounded-full bg-slate-100 px-2 py-0.5 text-xs text-slate-600">
|
|
{{ $statuses[$obligation->status] ?? ucfirst($obligation->status) }}
|
|
</span>
|
|
</div>
|
|
<p class="mt-1 text-sm text-slate-600">
|
|
{{ $obligation->stage?->name ?? $obligation->stage_code }}
|
|
· {{ $obligation->label ?? 'Workflow charge' }}
|
|
@if ($obligation->branch) · {{ $obligation->branch->name }} @endif
|
|
</p>
|
|
<p class="mt-1 text-xs text-slate-400">
|
|
Created {{ $obligation->created_at->format('d M Y H:i') }}
|
|
@if ($obligation->bill) · Invoice {{ $obligation->bill->invoice_number }} @endif
|
|
@if ($obligation->bill?->queue_ticket_number)
|
|
· Ticket {{ $obligation->bill->queue_ticket_number }}
|
|
@if ($obligation->bill->queue_ticket_status)
|
|
({{ $obligation->bill->queue_ticket_status }})
|
|
@endif
|
|
@endif
|
|
</p>
|
|
</div>
|
|
<p class="text-lg font-semibold text-slate-900">{{ $money($obligation->amount_minor) }}</p>
|
|
</div>
|
|
|
|
@if ($canClear && $obligation->status === \App\Models\FinancialObligation::STATUS_PENDING)
|
|
@php
|
|
$allowedPaymentModes = ! empty($obligation->stage?->payment_modes)
|
|
? array_intersect_key($paymentModes, array_flip($obligation->stage->payment_modes))
|
|
: $paymentModes;
|
|
$availableClearanceMethods = collect($clearanceMethods)->filter(function ($label, $value) use ($obligation, $allowedPaymentModes) {
|
|
return match ($value) {
|
|
'payment' => collect(array_keys($allowedPaymentModes))->intersect(['internal_cashier', 'digital'])->isNotEmpty(),
|
|
'bank_receipt' => array_key_exists('external_bank', $allowedPaymentModes),
|
|
'insurance' => (bool) $obligation->stage?->insurance_eligible,
|
|
'credit' => (bool) $obligation->stage?->credit_allowed,
|
|
'waiver', 'override' => (bool) $obligation->stage?->allow_override,
|
|
default => false,
|
|
};
|
|
});
|
|
@endphp
|
|
<form method="POST" action="{{ route('care.obligations.clear', $obligation) }}" class="mt-4 grid gap-3 border-t border-slate-100 pt-4 md:grid-cols-5">
|
|
@csrf
|
|
<div>
|
|
<label class="block text-xs font-medium text-slate-500">Clearance</label>
|
|
<select name="method" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
@foreach ($availableClearanceMethods as $value => $label)
|
|
<option value="{{ $value }}">{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-slate-500">Payment mode</label>
|
|
<select name="payment_mode" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
<option value="">Not applicable</option>
|
|
@foreach ($allowedPaymentModes as $value => $label)
|
|
<option value="{{ $value }}" @selected($loop->first)>{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-slate-500">Tender</label>
|
|
<select name="payment_method" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
@foreach ($paymentMethods as $value => $label)
|
|
<option value="{{ $value }}">{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-medium text-slate-500">Receipt / authorization ref</label>
|
|
<input name="reference" maxlength="100" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
|
|
</div>
|
|
<div class="flex items-end">
|
|
<button type="submit" class="btn-primary w-full">Clear gate</button>
|
|
</div>
|
|
</form>
|
|
@endif
|
|
</article>
|
|
@empty
|
|
<div class="rounded-2xl border border-slate-200 bg-white px-6 py-12 text-center text-sm text-slate-500">
|
|
No financial obligations match this filter.
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
|
|
<div class="mt-4">{{ $obligations->links() }}</div>
|
|
</x-app-layout>
|