@php
use App\Support\InvoiceDisplayFormatter as F;
// ── Resolve the company logo as a base64 data URI so Dompdf, browser
// print and email attachments all render the same image. Prefer the
// canonical circular emblem shipped with the app over any wordmark
// saved in Settings (which is the sidebar asset). --}
$logoSrc = null;
$tryEncode = function ($path) {
if (!$path || !is_file($path) || !is_readable($path)) return null;
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
$mime = $ext === 'jpg' || $ext === 'jpeg' ? 'image/jpeg'
: ($ext === 'gif' ? 'image/gif'
: ($ext === 'svg' ? 'image/svg+xml' : 'image/png'));
return 'data:' . $mime . ';base64,' . base64_encode(file_get_contents($path));
};
foreach ([
public_path('images/stepup-circular-logo.png'),
public_path('images/step-up-logo.png'),
public_path('images/logo-round.png'),
] as $candidate) {
if ($encoded = $tryEncode($candidate)) { $logoSrc = $encoded; break; }
}
$s = null;
try { $s = \App\Models\Setting::find(1); } catch (\Throwable $e) { $s = null; }
// White-label: use Company Settings + config('company.*'), no whitelisting.
$rawCompanyName = trim((string) ($s->companyName ?? ''));
$companyName = $rawCompanyName !== ''
? F::titleCase($rawCompanyName)
: trim((string) (config('company.legal') ?: config('company.name', '')));
$companyAddress = $s->companyAddress ?? trim((string) (config('company.address.line1', '') . ' ' . config('company.address.line2', '')));
$companyPhone = $s->companyPhone ?? (string) config('company.phone', '');
$companyEmail = trim((string) ($s->companyEmail ?? config('company.email', '')));
$companyWebsite = $s->companyWebsite ?? (string) config('company.website', '');
// ── Money & date helpers (Dompdf: no closures in view scope). --}
$fmtMoney = fn ($v) => '$' . number_format((float) $v, 2);
$fmtDate = fn ($d) => $d ? \Carbon\Carbon::parse($d)->format('M j, Y') : '—';
// ── Student / parent bill-to block. --}
$studentFirst = trim((string) ($invoice->student->first_name ?? ''));
$studentLast = trim((string) ($invoice->student->last_name ?? ''));
$studentName = F::titleCase(trim("$studentFirst $studentLast")) ?: '—';
$parentName = F::titleCase(trim((string) ($parent['name'] ?? ''))) ?: null;
$parentEmail = $parent['email'] ?? null;
$addressParts = array_filter([
$invoice->student->unit_number ?? null,
$invoice->student->street ?? null,
$invoice->student->city ?? null,
$invoice->student->province ?? null,
$invoice->student->postal_code ?? null,
]);
$addressLine = $addressParts ? F::titleCase(implode(', ', $addressParts)) : '—';
$phone = $parent['phone'] ?? ($invoice->student->phone ?? null);
$studentEmail = $invoice->student->email ?? null;
$locationName = F::titleCase((string) ($invoice->student->location->location_name ?? '')) ?: null;
// ── Billing period — prefer the invoice's own billing_period (YYYY-MM
// added by the 2026_07_23 migration) so it reflects the CANONICAL
// invoice month, not the accidental issueDate month. Fall back to
// the first line's period, then to the issueDate month. --}
$rawPeriod = $invoice->billing_period ?? null;
$firstItem = ($items instanceof \Illuminate\Support\Collection) ? $items->first() : ($items[0] ?? null);
if (!$rawPeriod && $firstItem && !empty($firstItem->billing_period)) {
$rawPeriod = $firstItem->billing_period;
}
if (!$rawPeriod && $invoice->issueDate) {
$rawPeriod = \Carbon\Carbon::parse($invoice->issueDate)->format('Y-m');
}
$periodLabel = F::billingPeriodLabel($rawPeriod, $firstItem->billing_period_label ?? null);
$statusRaw = strtolower((string) ($effective_status ?? $invoice->status ?? 'draft'));
$statusLabel = F::statusLabel($statusRaw);
@endphp
@php
// Watermark lives OUTSIDE .invoice-page so its `position: fixed`
// containing block is the page/viewport itself — Dompdf then
// repeats it on every generated PDF page. Placing it inside a
// positioned ancestor would render it only once. The Print List
// wrapper emits its own top-level watermark and passes
// $skipWatermark=true so we don't double-stack them.
$suppressWatermark = !empty($skipWatermark);
@endphp
@if($logoSrc && !$suppressWatermark)
@endif
|
{{-- Single-invoice variant: status badge (list report uses
title + date + prepared-by here instead). --}}
Status
{{ $statusLabel }}
|
|
Bill To
Student{{ $studentName }}
@if($parentName)
Parent / Guardian{{ $parentName }}
@endif
Address{{ $addressLine }}
@if($phone)
Phone{{ $phone }}
@endif
@if($parentEmail || $studentEmail)
Email{{ $parentEmail ?: $studentEmail }}
@endif
@if($locationName)
Location{{ $locationName }}
@endif
|
Invoice Details
Invoice Number{{ $invoice->invoiceNumber }}
Billing Period{{ $periodLabel }}
Issue Date{{ $fmtDate($invoice->issueDate) }}
Due Date{{ $fmtDate($invoice->dueDate) }}
Status{{ $statusLabel }}
|
| Class Details | Fee Type | Rate | Amount |
|---|---|---|---|
|
{{-- Subject (bold) + grade on the same line. Subject already
passes through F::titleCase() which preserves canonical
acronyms (ICT, ABA, STEM, ESL) and title-cases the
rest — so "SCIENCE / ICT" becomes "Science / ICT". --}}
{{ $head }}@if($grade !== '') — {{ $grade }}@endif
@if($staff !== '')
Staff: {{ $staff }}
@endif
@if($chip !== '')
{{ $chip }}
@endif
@if($itemPeriod !== '—')
{{ $itemPeriod }} {{ $isPerClass ? 'Per Class Fee' : 'Monthly Fee' }}
@endif
@if($subject === '' && $staff === '' && !empty($it->description))
{{-- Legacy / manual line — no structured data, keep description. --}}
{{ $it->description }}
@endif
|
{{ $feeTypeLabel }}
@if($isPerClass && $qtyInt > 0)
{{ $qtyInt }} {{ $qtyInt === 1 ? 'class' : 'classes' }}
@endif
|
{{ $fmtMoney($it->unitPrice) }} | {{ $fmtMoney($it->totalPrice) }} |
| No line items. | |||
| Subtotal | {{ $fmtMoney($invoice->subtotal) }} |
| Discount | −{{ $fmtMoney($invoice->discountAmount) }} |
| Tax | {{ $fmtMoney($invoice->taxAmount) }} |
| Total | {{ $fmtMoney($invoice->totalAmount) }} |
| Paid | {{ $fmtMoney($paid_amount) }} |
| Balance Due | {{ $fmtMoney($balance_due) }} |
| Date | Receipt # | Method | Reference | Amount | Status |
|---|---|---|---|---|---|
| {{ $p->paymentDate ? \Carbon\Carbon::parse($p->paymentDate)->format('M j, Y') : '—' }} | {{ $p->receipt_number ?? ('REC-' . $p->id) }} | {{ $p->paymentMethod ?: '—' }} | {{ $p->transactionId ?? '—' }} | {{ $fmtMoney($p->amount) }} | {{ $pStatusLbl }} |
| TOTAL PAID | {{ $fmtMoney($paid_amount) }} | ||||
|
Thank you for choosing {{ $companyName }}.
For questions regarding this invoice, contact {{ $companyEmail }} or {{ $companyPhone }}.
|