@extends('layouts.app') @section('title', $invoice->reference ?? __('billing::messages.invoices.singular')) @php /* | The status enums name a Bootstrap contextual colour, because that is what | they were written against and the print views still read them. Mapped | here rather than renamed underneath everything that already uses them. */ $pill = static fn (string $bootstrapTone): string => match ($bootstrapTone) { 'success' => 'px-pill--green', 'warning' => 'px-pill--amber', 'danger' => 'px-pill--red', 'info' => 'px-pill--blue', 'primary' => 'px-pill--violet', default => 'px-pill--grey', }; /* | The three figures somebody standing at the counter needs before reading a | single line: what it comes to, what has been handed over, and what is | still owed. The full breakdown stays in the aside — this is the glance. */ $tallies = [ [ 'label' => __('billing::messages.totals.total'), 'value' => $invoice->total->toMajor(), 'icon' => 'bi-receipt', 'tone' => 'violet', ], [ 'label' => __('billing::messages.totals.paid'), 'value' => $invoice->paid_total->toMajor(), 'icon' => 'bi-cash-coin', 'tone' => 'green', ], /* | Three states, not two. A negative balance is the clinic owing the | patient — money taken or credited beyond what was charged — and it | used to read as green with a minus sign in front, which looks like | nothing to do on the one figure that needs doing something about. */ $invoice->balance->isNegative() ? [ 'label' => __('billing::messages.totals.owed_back'), 'value' => $invoice->balance->absolute()->toMajor(), 'icon' => 'bi-arrow-return-left', 'tone' => 'amber', ] : [ 'label' => __('billing::messages.totals.balance'), 'value' => $invoice->balance->toMajor(), 'icon' => 'bi-hourglass-split', 'tone' => $invoice->balance->isPositive() ? 'pink' : 'green', ], ]; @endphp @section('content') {{-- ============================ IDENTITY ============================ --}}

{{ $patient?->name ?? '—' }}

{{ $invoice->reference ?? __('billing::messages.invoice_status.draft') }} @if ($patient) {{ $patient->mrn }} @endif @if ($invoice->issued_on) {{ __('billing::messages.invoices.issued_on') }}: {{ $invoice->issued_on->format('Y-m-d') }} @endif @if ($invoice->print_count > 0) {{ trans_choice('billing::messages.invoices.copies_printed', $invoice->print_count, ['count' => $invoice->print_count]) }} @endif
{{ $invoice->status->label() }} @if (! $invoice->status->isVoid()) {{ $invoice->payment_status->label() }} @endif
@foreach ($tallies as $tally) {{ $tally['value'] }} {{ $tally['label'] }} @endforeach
{{-- This screen's own way back. Breadcrumbs are deliberately absent across the product, so a detail page reached from a listing carries a single explicit return instead. --}} {{ __('billing::messages.invoices.title') }} @can('print', $invoice) {{ __('billing::messages.invoices.print') }} @endcan
{{-- Standing notices, not flash messages: px-advice rather than , which is the dismissible banner the layout uses for session feedback. --}} @if ($invoice->isEditable())
{{ __('billing::messages.invoices.draft_notice') }}
@elseif ($invoice->status->isVoid())
{{ __('billing::messages.invoices.void_notice', ['reason' => $invoice->void_reason]) }}
@else
{{ __('billing::messages.invoices.issued_notice') }}
@if ($invoice->isOverdue())
{{ __('billing::messages.invoices.overdue_notice', ['date' => $invoice->due_on->format('Y-m-d')]) }}
@endif @endif
{{-- Charges ------------------------------------------------------ --}}
@can('update', $invoice)@endcan @forelse ($invoice->items as $item) @can('update', $invoice) @endcan @empty @endforelse
{{ __('billing::messages.items.description') }} {{ __('billing::messages.items.quantity') }} {{ __('billing::messages.items.unit_price') }} {{ __('billing::messages.items.discount') }} {{ __('billing::messages.items.tax') }} {{ __('billing::messages.items.line_total') }}
{{ $item->description }} @if ($item->code) {{ $item->code }} @endif @if (! $item->is_discountable) {{ __('billing::messages.items.not_discountable') }} @endif @foreach ($item->taxes as $tax)
{{ $tax->label() }}
@endforeach
{{ $item->quantityLabel() }} {{ $item->unit_price->toMajor() }} {{ $item->discount_amount->isZero() ? '—' : '−'.$item->discount_amount->toMajor() }} {{ $item->tax_amount->isZero() ? '—' : $item->tax_amount->toMajor() }} {{ $item->line_total->toMajor() }}

{{ __('billing::messages.items.empty') }}

{{ __('billing::messages.items.empty_text') }}

@can('update', $invoice)
@csrf
    {{-- Bill-level discount ---------------------------------------- --}}
    @csrf

    {{ __('billing::messages.discount.hint') }}

    @endcan {{-- Payments ------------------------------------------------------ --}}
    @forelse ($invoice->payments as $payment) @empty @endforelse
    {{ __('billing::messages.payments.reference') }} {{ __('billing::messages.payments.method') }} {{ __('billing::messages.payments.received_at') }} {{ __('billing::messages.payments.amount') }}
    {{ $payment->reference }} @if ($payment->kind->isNegative()) {{ $payment->kind->label() }} @endif @if ($payment->reversal_reason)
    {{ $payment->reversal_reason }}
    @endif
    {{ $payment->method->name }} @if ($payment->external_reference)
    {{ $payment->external_reference }}
    @endif
    {{ $payment->received_at->format('Y-m-d H:i') }} {{ $payment->amount->toMajor() }} {{ __('billing::messages.payments.receipt') }} @can('reverse', $payment) @if (! $payment->kind->isNegative())
    @csrf
    @endif @endcan

    {{ __('billing::messages.payments.empty') }}

    {{ __('billing::messages.payments.empty_text') }}

    {{-- Totals and actions ------------------------------------------------ --}}
    {{-- The arithmetic, in the order it happens. Two rules run through it: a line that is zero is not drawn — an invoice with no discount should not carry a row of dashes — and the two figures that get argued about at the counter, the total and the balance, are set apart from the working above them. --}}
    {{ __('billing::messages.totals.subtotal') }}
    {{ $invoice->subtotal->toMajor() }}
    @if (! $invoice->discount_total->isZero())
    {{ __('billing::messages.totals.discount') }}
    −{{ $invoice->discount_total->toMajor() }}
    @endif @if (! $invoice->tax_total->isZero())
    {{ __('billing::messages.totals.tax') }}
    {{ $invoice->tax_total->toMajor() }}
    @endif
    {{ __('billing::messages.totals.total') }}
    {{ $invoice->total->toMajor() }}
    @if (! $invoice->paid_total->isZero())
    {{ __('billing::messages.totals.paid') }}
    {{ $invoice->paid_total->toMajor() }}
    @endif @if (! $invoice->credited_total->isZero())
    {{ __('billing::messages.totals.credited') }}
    {{ $invoice->credited_total->toMajor() }}
    @endif
    $invoice->balance->isPositive()])>
    {{ __('billing::messages.totals.balance') }}
    {{ $invoice->balance->toMajor() }}
    @can('issue', $invoice)
    @csrf
    @endcan @if ($invoice->status->acceptsPayment() && $invoice->balance->isPositive()) @can('create', \App\Modules\Billing\Models\Payment::class)
    @csrf {{-- Minted server-side per page load. A second submission of the same form carries the same token and finds the first payment instead of taking a second one. --}}
    @endcan @endif @can('void', $invoice)
    @csrf
    @endcan {{-- Credit notes -------------------------------------------------- --}} @if ($invoice->status->acceptsPayment()) @foreach ($invoice->creditNotes as $note)
    {{ $note->reference }} −{{ $note->total->toMajor() }}
    @endforeach @can('create', \App\Modules\Billing\Models\CreditNote::class)
    @csrf

    {{ __('billing::messages.credit_notes.hint') }}

    @endcan
    @endif
    @endsection