@php // Payslip document. $preview = true renders for an on-screen browser view. $preview = $preview ?? false; $accent = $setting?->primary_color ?: '#124a61'; $ink = '#111827'; $muted = '#6b7280'; $soft = '#9ca3af'; $line = '#e5e7eb'; $wash = '#f8fafc'; $font = $setting?->font_family ? $setting->font_family.', Arial, sans-serif' : 'Arial, Helvetica, sans-serif'; $logoData = null; if ($setting?->logo_path) { try { $logoFull = \Illuminate\Support\Facades\Storage::disk('public')->path($setting->logo_path); if (is_file($logoFull)) { $logoData = 'data:'.(mime_content_type($logoFull) ?: 'image/png').';base64,'.base64_encode(file_get_contents($logoFull)); } } catch (\Throwable $e) { $logoData = null; } } $companyName = $setting?->company_name ?: $line_->team?->name; $money = fn ($v) => trim(($symbol ?: ($baseCode.' ')).number_format((float) $v, 2)); $allowances = $line_->slipRows('allowances'); $benefits = $line_->slipRows('benefits'); $componentDeductions = $line_->slipRows('deductions'); $employerCosts = $line_->slipRows('employer'); $earnings = (array) ($line_->breakdown['earnings'] ?? []); $commissions = (array) ($line_->breakdown['commissions'] ?? []); $otherDeductions = (array) ($line_->breakdown['deductions'] ?? []); $unpaid = (array) ($line_->breakdown['unpaid'] ?? []); $unpaidRows = (array) ($unpaid['rows'] ?? []); $earningLabels = ['overtime' => __('Overtime'), 'leave_cash' => __('Leave cash-out')]; $earningUnits = ['overtime' => __('hrs'), 'leave_cash' => __('days')]; // The name on the ID, snapshotted onto the slip when the run was built, so // a reprint keeps the name the pay was actually made out to. The account // name is only a stand-in for records filled in before full names existed. $employeeName = trim((string) ($line_->breakdown['full_name'] ?? '')) ?: ($profile?->legalName() ?: $line_->user?->name); // The statutory rows carry their own workings ("4.5% of insurable // earnings"), snapshotted at build time, so the slip states the rules it // was actually computed under without a paragraph restating them. $targetNet = $line_->breakdown['target_net'] ?? null; @endphp {{ $line_->payslip_number ?: __('Payslip') }}, {{ $employeeName }}
{{-- ---------------------------------------------------------------- --}}
@if ($logoData) @else
{{ $companyName }}
@endif
@if ($logoData){{ $companyName }}
@endif @if ($setting?->address){{ $setting->address }}
@endif @if ($setting?->phone){{ $setting->phone }}@endif @if ($setting?->email) · {{ $setting->email }}@endif @if ($setting?->tin_number)
{{ __('TIN') }}: {{ $setting->tin_number }}@endif
{{ __('Payslip') }}
{{ __('Pay period') }}: {{ $period->format('F Y') }}
{{ __('Issued') }}: {{ $issuedOn->format('d M Y') }}
@if ($line_->payslip_number)
{{ $line_->payslip_number }}
@endif
{{-- Employee ------------------------------------------------------- --}}
{{ __('Employee') }}
{{ $employeeName ?: __('Unknown') }}
{{ __('Employee no.') }}
{{ $profile?->employee_number ?: '—' }}
{{ __('Job title') }}
{{ $profile?->job_title ?: '—' }}
{{ __('Department') }}
{{ $profile?->department ?: '—' }}
{{ __('Engagement') }}
{{ $profile?->employmentTypeLabel() ?? '—' }}
{{ __('Date joined') }}
{{ $profile?->hired_on?->format('d M Y') ?: '—' }}
{{ __('National ID') }}
{{ $profile?->national_id ?: '—' }}
{{ __('Currency') }}
{{ $baseCode }}
{{-- Earnings vs deductions ----------------------------------------- --}}
@foreach ($unpaidRows as $row) @endforeach @foreach ($allowances as $row) @endforeach @foreach ($earnings as $row) @endforeach @if ((float) $line_->commission_total > 0) @endif
{{ __('Earnings') }}
{{ __('Description') }} {{ __('Amount') }}
{{ __('Basic salary') }} @if ($partMonth_ = $line_->partMonth()) {{ $partMonth_['reason'] === 'left' ? __('Part month: to :date', ['date' => \Illuminate\Support\Carbon::parse($partMonth_['to'])->format('j M')]) : __('Part month: from :date', ['date' => \Illuminate\Support\Carbon::parse($partMonth_['from'])->format('j M')]) }}{{ $partMonth_['reason'] === 'joined_and_left' ? ' '.__('to :date', ['date' => \Illuminate\Support\Carbon::parse($partMonth_['to'])->format('j M')]) : '' }} ({{ __(':d of :of days', ['d' => rtrim(rtrim(number_format((float) $partMonth_['days'], 2), '0'), '.'), 'of' => number_format((float) $partMonth_['of'], 2)]) }}) @endif {{ $money($line_->base_salary) }}
{{ __('Less') }}: {{ $row['label'] }} {{ \Illuminate\Support\Carbon::parse($row['from'])->format('d M') }}{{ $row['from'] !== $row['to'] ? ' – '.\Illuminate\Support\Carbon::parse($row['to'])->format('d M') : '' }} · {{ rtrim(rtrim(number_format((float) $row['days'], 2), '0'), '.') }} {{ __('days') }} × {{ $money($unpaid['rate'] ?? 0) }} -{{ $money(round((float) $row['days'] * (float) ($unpaid['rate'] ?? 0), 2)) }}
{{ $row['label'] }} {{ $row['rule'] }}{{ empty($row['taxable']) ? ' · '.__('non-taxable') : '' }} {{ $money($row['amount']) }}
{{ $earningLabels[$row['type'] ?? ''] ?? __('Earning') }} {{ rtrim(rtrim(number_format((float) ($row['quantity'] ?? 0), 2), '0'), '.') }} {{ $earningUnits[$row['type'] ?? ''] ?? '' }} × {{ $money($row['rate'] ?? 0) }} {{ $money($row['amount'] ?? 0) }}
{{ __('Commission') }} @if ($commissions) {{ trans_choice('{1}:count approved accrual|[2,*]:count approved accruals', count($commissions), ['count' => count($commissions)]) }} @endif {{ $money($line_->commission_total) }}
{{ __('Gross pay') }} {{ $money($line_->gross_pay) }}
@php $hasDeduction = false; @endphp @foreach ($componentDeductions as $row) @php $hasDeduction = true; @endphp @endforeach @foreach ($otherDeductions as $row) @php $hasDeduction = true; @endphp @endforeach @unless ($hasDeduction) @endunless
{{ __('Deductions') }}
{{ __('Description') }} {{ __('Amount') }}
{{ $row['label'] }} {{ $row['rule'] }} {{ $money($row['amount']) }}
@if (isset($row['loan_id'])) {{ __('Staff loan') }}{{ ($row['issued_on'] ?? null) ? ' · '.$row['issued_on'] : '' }} @else {{ $row['label'] ?? __('Loss recovery') }}{{ ($row['reason'] ?? null) ? ' · '.$row['reason'] : '' }} @endif @isset($row['balance_after']) {{ __('Balance after this') }}: {{ $money($row['balance_after']) }} @endisset {{ $money($row['amount'] ?? 0) }}
{{ __('No deductions this period') }}
{{ __('Total deductions') }} {{ $money($line_->deduction_total) }}
@if ($benefits || $employerCosts) @foreach ($benefits as $row) @endforeach @foreach ($employerCosts as $row) @endforeach
{{ __('Benefits & employer contributions') }}
{{ __('Description') }} {{ __('Value') }}
{{ $row['label'] }} {{ __('Non-cash benefit') }} · {{ $row['rule'] }} {{ $money($row['amount']) }}
{{ $row['label'] }} {{ __('Paid by the company') }} · {{ $row['rule'] }} {{ $money($row['amount']) }}
{{ __('Total cost of employment') }} {{ $money($line_->totalEmployerCost()) }}
{{ __('Not part of your net pay.') }}
@endif
{{-- Net pay --------------------------------------------------------- --}}
{{ __('Net pay') }}
{{ $money($line_->net_pay) }}
{{ __('Method') }}
{{ $line_->payMethodLabel() }}
{{ __('Paid by') }}
{{ $companyName }}
{{-- What actually went out: paid now, owed, and any arrears from earlier months paid on this slip (outside this month's tax). --}} @php $arrearsRows_ = $line_->arrearsRows(); $arrearsPaid_ = (float) $line_->arrears_paid; $showSettlement_ = $line_->isPartlyPaid() || $arrearsPaid_ > 0; @endphp @if ($showSettlement_) @if ($arrearsPaid_ > 0) @foreach ($arrearsRows_ as $row) @endforeach @endif @if ($line_->isPartlyPaid()) @endif
{{ $row['label'] }} {{ __('taxed in the month it was earned') }} {{ $money($row['amount']) }}
{{ __('Paid now') }} {{ $money($line_->amountPaidNow() + $arrearsPaid_) }}
{{ __('Owed to you') }} {{ $line_->pay_deferred ? __('deferred to next month') : __('to be paid later') }}{{ $line_->paid_now_reason ? ' · '.$line_->paid_now_reason : '' }} {{ $money($line_->amountOwed()) }}
@endif @if ($line_->pay_method === 'bank' && $profile?->bank_account_number)
{{ __('Credited to') }}: {{ $profile->bank_name }} · {{ $profile->bank_account_name ?: $employeeName }} · {{ __('a/c') }} {{ $profile->bank_account_number }}
@elseif ($line_->pay_method === 'ecocash' && $profile?->mobile_money_number)
{{ __('Sent to') }}: {{ $profile->mobile_money_number }}
@endif @if ($line_->notes)
{{ __('Note') }}: {{ $line_->notes }}
@endif {{-- The deduction rows already carry their own workings, so the only note worth the space is the one thing the figures cannot say for themselves: that the gross was solved backwards from an agreed take-home. --}} @if ($line_->isGrossedUp() && $targetNet !== null)
{{ __('Salary agreed at :net take-home. The gross above is what delivers it after deductions.', ['net' => $money($targetNet)]) }}
@endif
{{ __('Queries within 14 days of issue.') }}
{{ $companyName }} {{ __('Employee signature') }}
{{ __('Private & confidential') }}
{{ $companyName }} · {{ __('Payslip for') }} {{ $period->format('F Y') }} {{ $line_->payslip_number ?: '' }}