@php // Every tab this page has. Which of them get drawn is the component's call // ($visibleTabs), so the bar can never offer a tab that 403s on click. // An employee is looking at their OWN pay here, so the labels say so. $tabMeta = [ 'overview' => ['label' => __('Overview'), 'icon' => 'squares-2x2'], 'commissions' => ['label' => $isPayrollAdmin ? __('Commissions') : __('My Commissions'), 'icon' => 'sparkles'], 'profit_share' => ['label' => __('Profit Share'), 'icon' => 'scale'], 'staff' => ['label' => __('Staff'), 'icon' => 'identification'], 'components' => ['label' => __('Benefits'), 'icon' => 'gift'], 'statutory' => ['label' => __('Statutory'), 'icon' => 'scale-balance'], 'liabilities' => ['label' => $isPayrollAdmin ? __('Losses') : __('Loss Recovery'), 'icon' => 'exclamation-triangle'], 'runs' => ['label' => $isPayrollAdmin ? __('Pay Runs') : __('My Payslips'), 'icon' => 'credit-card'], 'plans' => ['label' => __('Plans'), 'icon' => 'adjustments-horizontal'], ]; $tabs = array_intersect_key($tabMeta, array_flip($visibleTabs)); $componentKindBadge = [ 'allowance' => 'emerald', 'benefit' => 'sky', 'deduction' => 'rose', 'employer_cost' => 'violet', ]; $accrualBadge = [ 'pending' => 'amber', 'approved' => 'sky', 'paid' => 'emerald', 'forfeited' => 'slate', 'cancelled' => 'rose', ]; $liabilityBadge = ['active' => 'amber', 'settled' => 'emerald', 'waived' => 'slate', 'cancelled' => 'rose']; $runBadge = ['draft' => 'amber', 'finalized' => 'emerald', 'cancelled' => 'slate']; $gpRunBadge = ['not_eligible' => 'slate', 'pending' => 'amber', 'approved' => 'sky', 'paid' => 'emerald']; $planBadge = ['sales' => 'indigo', 'production' => 'sky', 'gp_hurdle' => 'emerald']; $planLabel = ['sales' => __('Sales'), 'production' => __('Production'), 'gp_hurdle' => __('GP-Hurdle')]; @endphp
{{-- The same page serves two very different people: the payroll admin running the month, and the employee checking their own slip. Say which one this is, rather than promising a payroll they cannot run. --}} @if ($tab === 'plans' && ($canManage ?? false)) {{ __('New Plan') }} @elseif ($tab === 'liabilities' && ($canManage ?? false)) {{ __('Record Loss') }} @elseif ($tab === 'statutory' && ($canManagePay ?? false)) {{ __('New Tax Table') }} @elseif ($tab === 'components' && ($canManagePay ?? false)) {{ __('New Benefit') }} @elseif ($tab === 'runs' && $canProcessPayroll) {{ __('Build Pay Run') }} @elseif ($tab === 'commissions' && $isManager) {{ __('Recalculate') }} @elseif ($tab === 'profit_share' && ($canManageCommissions ?? false)) {{ __('Build Pool') }} @endif @if ($commissionPauses->isNotEmpty())

{{ __('Commission paused') }}

    @foreach ($commissionPauses as $pause)
  • {{ $pause->user?->name ?? __('Former team member') }}: {{ $pause->ends_on ? __('from :from to :to', ['from' => $pause->starts_on->format('j M Y'), 'to' => $pause->ends_on->format('j M Y')]) : __('from :from until a director ends it', ['from' => $pause->starts_on->format('j M Y')]) }}. {{ $pause->reason }}
  • @endforeach

{{ __('No commission is earned while paused, and the paused period is not paid later.') }}

@endif
count($tabs) < 2, ])> @foreach ($tabs as $key => $meta) @endforeach
@foreach ($kpis as $kpi) @php $pill = ['up' => 'bg-emerald-50 text-emerald-700', 'down' => 'bg-rose-50 text-rose-700', 'muted' => 'bg-slate-100 text-slate-500'][$kpi['sub']['tone']] ?? 'bg-slate-100 text-slate-500'; @endphp

{{ $kpi['label'] }}

{{ $kpi['value'] }}

{{ $kpi['sub']['text'] }}
@endforeach
{{-- ============================================================ --}} {{-- OVERVIEW --}} {{-- ============================================================ --}} @if ($tab === 'overview')

{{ __('Commission Split') }}

{{ __('Sales vs production this month, in :base.', ['base' => $baseCode]) }}

@if ($split['total'] > 0)
@foreach ($split['segments'] as $seg)
{{ $seg['label'] }} {{ $baseCode }} {{ number_format($seg['value'], 2) }}
@endforeach
@else

{{ __('No commission earned this month yet.') }}

@endif

{{ __('Commission Trend') }}

{{ __('Earned over the last 6 months, in :base.', ['base' => $baseCode]) }}

{{-- Scoped to the viewer for a non-admin, so a one-row "league table" would just be them. Name it honestly. --}}

{{ $isPayrollAdmin ? __('Top Earners') : __('Earned by me') }}

{{ __('This month') }}

@if (! empty($topEarners))
@foreach ($topEarners as $earner)
{{ $earner['name'] }} {{ $earner['total'] }}
@endforeach
@else

{{ __('No earners yet.') }}

@endif

{{ __('How commissions work here') }}

{{ __('Sales, tiered by target') }}

{{ __('A % of each job\'s gross profit, with the rate rising as the salesperson approaches and beats their monthly revenue target. Only payable once the target is met and the invoice is paid.') }}

{{ __('Production, profit-share pool') }}

{{ __('A % of gross profit pooled and split among the crew by hours logged, paid only on clean runs: on time, within budget, no reprints.') }}

{{ __('Losses, recovered from pay') }}

{{ __('Mistakes that cost money are charged to the responsible person and recovered over 3 months, capped so a paycheck is never zeroed.') }}

@endif {{-- ============================================================ --}} {{-- COMMISSIONS --}} {{-- ============================================================ --}} @if ($tab === 'commissions')

{{ __('Commission Ledger') }}

@if ($isManager)@endif @forelse ($accruals as $a) @if ($isManager) @endif @empty @endforelse
{{ __('Beneficiary') }} {{ __('Job / Invoice') }} {{ __('Type') }} {{ __('Period') }} {{ __('Base · Rate') }} {{ __('Amount') }} {{ __('Status') }}{{ __('Actions') }}
{{ $a->user?->name ?? '—' }} {{ $a->job?->job_number ?? '—' }} @if ($a->invoice){{ $a->invoice->invoice_number }}@endif {{ ucfirst($a->type) }} {{ $a->period?->format('M Y') }} {{ $baseCode }} {{ number_format((float) $a->base_amount, 0) }} {{ rtrim(rtrim(number_format((float) $a->rate, 2), '0'), '.') }}%{{ $a->hours ? ' · ' . rtrim(rtrim(number_format((float)$a->hours,2),'0'),'.') . 'h' : '' }} {{ $baseCode }} {{ number_format((float) $a->amount, 2) }} {{ ucfirst($a->status) }} @if ($a->status === 'pending' && $a->blocked_reason) {{ $reasonLabels[$a->blocked_reason] ?? $a->blocked_reason }} @endif @if (! in_array($a->status, ['paid', 'cancelled'], true))
@if ($a->status !== 'approved') @endif
@else — @endif
{{ __('No commission lines yet. They appear automatically when a job is completed and invoiced.') }}
{{ $accruals->links() }}
@endif {{-- ============================================================ --}} {{-- PROFIT SHARE, GP-Hurdle Profit Share pool (spec §9 / §20) --}} {{-- ============================================================ --}} @if ($tab === 'profit_share') @unless ($gpModelActive)

{{ __('GP-Hurdle Profit Share is not the workspace\'s active commission model. You can still build pools to preview, but they won\'t drive the Profitability eligibility column until you switch the active model in Settings → Profit & Commission.') }}

@endunless @unless ($gpPlan)

{{ __('No active GP-Hurdle plan, pools use the workspace defaults (hurdle multiplier, pool rate, splits). Create a GP-Hurdle plan in the Plans tab to override them.') }}

@endunless

{{ __('Profit-Share Pools') }}

@if ($canManageCommissions)
{{ __('Build') }}
@endif
@forelse ($gpRuns as $run) @empty
@if ($canManageCommissions){{ __('Build Pool') }}@endif
@endforelse
{{ $gpRuns->links() }}
@if ($viewGpRun) @php $stat = fn ($label, $val, $accent = 'text-slate-900') => ['label' => $label, 'val' => $val, 'accent' => $accent]; $entry = [ $stat(__('Actual GP'), $viewGpRun->actual_gp), $stat(__('Overheads'), $viewGpRun->overheads), $stat(__('Break-even GP'), $viewGpRun->break_even_gp), $stat(__('GP Hurdle'), $viewGpRun->gp_hurdle, 'text-sky-700'), $stat(__('Excess GP'), $viewGpRun->excess_gp, (float) $viewGpRun->excess_gp > 0 ? 'text-emerald-700' : 'text-slate-400'), $stat(__('Commission Pool'), $viewGpRun->commission_pool, 'text-indigo-700'), ]; @endphp

{{ $viewGpRun->period->format('F Y') }} · {{ __('Profit Share') }}

{{ ucfirst(str_replace('_', ' ', $viewGpRun->status)) }} {{ __('hurdle = overheads × :m', ['m' => rtrim(rtrim(number_format((float) $viewGpRun->multiplier, 2), '0'), '.')]) }} · {{ __('pool @ :r%', ['r' => rtrim(rtrim(number_format((float) $viewGpRun->pool_rate * 100, 2), '0'), '.')]) }}

@if ($viewGpRun->status === 'pending' && $canManageCommissions) {{ __('Approve Pool') }} @endif
@if (! $viewGpRun->isEligible())
{{ $viewGpRun->blocked_reason === 'below_hurdle' ? __('Gross profit (:gp) did not clear the GP hurdle (:h) for this period, no commission accrues.', ['gp' => $baseCode.' '.number_format((float) $viewGpRun->actual_gp, 2), 'h' => $baseCode.' '.number_format((float) $viewGpRun->gp_hurdle, 2)]) : __('No eligible staff to share the pool, set a commission group on staff profiles.') }}
@endif {{-- §20 commission entry: the frozen figures the pool was built from --}}
@foreach ($entry as $cell)

{{ $cell['label'] }}

{{ $baseCode }} {{ number_format((float) $cell['val'], 2) }}

@endforeach
@if ($viewGpRun->isEligible())

{{ __('Sales / Admin Pool') }} · {{ rtrim(rtrim(number_format((float) $viewGpRun->sales_split * 100, 2), '0'), '.') }}%

{{ $baseCode }} {{ number_format((float) $viewGpRun->sales_pool, 2) }}

{{ __('Production Pool') }} · {{ rtrim(rtrim(number_format((float) $viewGpRun->production_split * 100, 2), '0'), '.') }}%

{{ $baseCode }} {{ number_format((float) $viewGpRun->production_pool, 2) }}

@foreach ($viewGpRun->accruals as $share) @endforeach
{{ __('Employee') }} {{ __('Group') }} {{ __('Share') }} {{ __('Status') }} {{ __('Amount') }}
{{ $share->user?->name ?? '—' }} {{ $planLabel[$share->pool_group] ?? ucfirst((string) $share->pool_group) }} {{ rtrim(rtrim(number_format((float) $share->rate, 2), '0'), '.') }}%@if ($share->pool_group === 'production' && $share->hours !== null) · {{ rtrim(rtrim(number_format((float) $share->hours, 2), '0'), '.') }}h@endif {{ ucfirst($share->status) }} {{ $baseCode }} {{ number_format((float) $share->amount, 2) }}
{{ __('Total shared') }} {{ $baseCode }} {{ number_format((float) $viewGpRun->accruals->sum('amount'), 2) }}
@endif @else

{{ __('Select a pool to see the §20 entry and employee shares, or build one for a month.') }}

@endif
@endif {{-- ============================================================ --}} {{-- STAFF --}} {{-- ============================================================ --}} @if ($tab === 'staff')
@if ($canManage)@endif @forelse ($profiles as $p) @if ($canManage) @endif @empty @endforelse
{{ __('Staff') }} {{ __('Salary / mo') }} {{ __('Daily') }} {{ __('Hourly') }} {{ __('Revenue Target') }} {{ __('Plans') }} {{ __('Loss Cap') }} {{ __('Status') }}{{ __('Actions') }}

{{ $p->user?->name ?? '—' }}

{{ $p->user?->email }}

{{ $p->salary_currency_code ?: $baseCode }} {{ number_format((float) $p->monthly_salary, 2) }} {{ $baseCode }} {{ number_format((float) ($staffRates[$p->id]['daily'] ?? 0), 2) }} {{ $baseCode }} {{ number_format((float) ($staffRates[$p->id]['hourly'] ?? 0), 2) }} {{ $p->monthly_revenue_target !== null ? $baseCode . ' ' . number_format((float) $p->monthly_revenue_target, 2) : '—' }} @if ($p->salesPlan){{ $p->salesPlan->name }}@endif @if ($p->productionPlan){{ $p->productionPlan->name }}@endif @if (! $p->salesPlan && ! $p->productionPlan){{ __('Team default') }}@endif {{ rtrim(rtrim(number_format((float) $p->loss_recovery_cap_pct, 2), '0'), '.') }}% {{ $p->is_active ? __('Active') : __('Inactive') }} {{-- Why somebody's slip shows no PAYE or NSSA, visible without opening the record, because a silent exemption is how a deduction goes missing for a month before anyone notices. --}} @if ($p->is_consultant) {{ __('Consultant') }} @elseif ($p->paye_exempt || $p->nssa_exempt) {{ $p->paye_exempt && $p->nssa_exempt ? __('No PAYE / NSSA') : ($p->paye_exempt ? __('No PAYE') : __('No NSSA')) }} @endif
@endif {{-- ============================================================ --}} {{-- BENEFITS, ALLOWANCES & DEDUCTIONS --}} {{-- ============================================================ --}} @if ($tab === 'statutory' && ($canManagePay ?? false)) @if (! $activeTaxTable)

{{ __('No tax table is in force this month') }}

{{ __('Payroll will pay everyone their full gross with no NSSA or PAYE deducted. Add a table covering this month before you finalize a run.') }}

@endif

{{ __('PAYE & NSSA tables') }}

{{ __('What the law takes off pay. Tables are dated rather than edited: when ZIMRA re-issues them, add a new one from that month and old payslips keep being computed under the rules they were earned under.') }}

@forelse ($taxTables as $taxTable) @empty @endforelse
{{ __('Table') }} {{ __('In force') }} {{ __('NSSA') }} {{ __('Actions') }}
{{ $taxTable->name }} @if ($activeTaxTable && $activeTaxTable->id === $taxTable->id) {{ __('In force') }} @endif {{ trans_choice('{1}:count band|[2,*]:count bands', count($taxTable->normalisedBands()), ['count' => count($taxTable->normalisedBands())]) }} · {{ __(':pct% AIDS levy', ['pct' => rtrim(rtrim(number_format((float) $taxTable->aids_levy_pct, 2), '0'), '.')]) }} · {{ $taxTable->currency_code ?: $baseCode }} {{ $taxTable->windowLabel() }} {{ rtrim(rtrim(number_format((float) $taxTable->nssa_employee_pct, 2), '0'), '.') }}% + {{ rtrim(rtrim(number_format((float) $taxTable->nssa_employer_pct, 2), '0'), '.') }}% @if ($taxTable->nssa_insurable_ceiling !== null) {{ __('capped at :v insurable', ['v' => number_format((float) $taxTable->nssa_insurable_ceiling, 2)]) }} @else {{ __('no ceiling') }} @endif
{{ __('New Tax Table') }}
{{-- Check the system against a slip you already trust. --}}

{{ __('Try a figure') }}

{{ __('Work a salary through the table in force this month, and see exactly how the deductions were arrived at.') }}

{{ __('Work it out') }} @if ($taxPreview)
@if (isset($taxPreview['grossed_up_from']))
{{ __('Take-home promised') }}
{{ number_format((float) $taxPreview['grossed_up_from'], 2) }}
@endif
{{ __('Gross pay') }}
{{ number_format((float) $taxPreview['gross'], 2) }}
{{ __('Insurable earnings') }}
{{ number_format((float) $taxPreview['insurable_earnings'], 2) }}
{{ __('Employee NSSA') }}
−{{ number_format((float) $taxPreview['nssa_employee'], 2) }}
{{ __('Taxable pay') }}
{{ number_format((float) $taxPreview['taxable_pay'], 2) }}
{{ __('PAYE incl. AIDS levy') }} {{ __('tax :tax + levy :levy', [ 'tax' => number_format((float) $taxPreview['income_tax'], 2), 'levy' => number_format((float) $taxPreview['aids_levy'], 2), ]) }}
−{{ number_format((float) $taxPreview['paye_total'], 2) }}
{{ __('Net pay') }}
{{ number_format((float) $taxPreview['net_of_statutory'], 2) }}
{{ __('Employer NSSA') }}
{{ number_format((float) $taxPreview['nssa_employer'], 2) }}
{{ __('Total employer cost') }}
{{ number_format((float) $taxPreview['gross'] + (float) $taxPreview['nssa_employer'], 2) }}
@endif
@endif @if ($tab === 'components' && ($canManagePay ?? false))

{{ __('Benefits, allowances & deductions') }}

{{ __('Payroll works these out for every payslip automatically. Change a rule once and every future slip follows; finalized slips keep what they actually paid.') }}

{{-- $benefit, not $component: Blade reserves $component inside tags. --}} @forelse ($components as $benefit) @empty @endforelse
{{ __('Name') }} {{ __('Kind') }} {{ __('How it is worked out') }} {{ __('Who gets it') }} {{ __('Status') }} {{ __('Actions') }}
{{ $benefit->name }} @if ($benefit->code) {{ $benefit->code }} @endif @if ($benefit->description) {{ $benefit->description }} @endif {{ $benefit->kindLabel() }} {{ $benefit->ruleLabel($baseCode) }} @if ($benefit->min_amount !== null || $benefit->max_amount !== null) @if ($benefit->min_amount !== null){{ __('min :v', ['v' => number_format((float) $benefit->min_amount, 2)]) }}@endif @if ($benefit->min_amount !== null && $benefit->max_amount !== null) · @endif @if ($benefit->max_amount !== null){{ __('capped at :v', ['v' => number_format((float) $benefit->max_amount, 2)]) }}@endif @endif @if ($benefit->kind === 'allowance' && ! $benefit->is_taxable) {{ __('Not counted in gross for %-of-gross rules') }} @endif @if ($benefit->applies_to === 'all') {{ __('Everyone') }} @else {{ trans_choice('{0}Nobody yet|{1}:count employee|[2,*]:count employees', $benefit->staff_profiles_count, ['count' => $benefit->staff_profiles_count]) }} @endif @if (($statutoryInForce ?? false) && $benefit->duplicatesStatutory()) {{ __('Handled by tax tables') }} {{ __('Payroll deducts this itself under the statutory tables, so this row is not charged as well.') }} @else {{ $benefit->is_active ? __('Active') : __('Paused') }} @endif
@endif {{-- ============================================================ --}} {{-- LIABILITIES --}} {{-- ============================================================ --}} @if ($tab === 'liabilities')
@if ($canManage)@endif @forelse ($liabilities as $l) @if ($canManage) @endif @empty @endforelse
{{ __('Staff') }} {{ __('Reason') }} {{ __('Job') }} {{ __('Total') }} {{ __('Recovered') }} {{ __('Plan') }} {{ __('Status') }}{{ __('Actions') }}
{{ $l->user?->name ?? '—' }} {{ \Illuminate\Support\Str::limit($l->reason, 48) }} {{ $l->job?->job_number ?? '—' }} {{ $baseCode }} {{ number_format((float) $l->total_amount, 2) }} {{ $baseCode }} {{ number_format((float) $l->recovered_amount, 2) }} {{ __('left :amt', ['amt' => $baseCode . ' ' . number_format($l->outstanding, 2)]) }} {{ __(':n mo', ['n' => $l->recover_months]) }}{{ $l->monthly_cap_pct !== null ? ' · ' . rtrim(rtrim(number_format((float)$l->monthly_cap_pct,2),'0'),'.') . '%' : '' }} {{ ucfirst($l->status) }}
@if ($l->signedUrl()) @endif {{ __('Ack') }} @if ($l->status === 'active') @endif
@if ($canManage){{ __('Record Loss') }}@endif
{{ $liabilities->links() }}
@endif {{-- ============================================================ --}} {{-- PAY RUNS --}} {{-- ============================================================ --}} @if ($tab === 'runs') @if (! ($activeTaxTable ?? null) && ($canManagePay ?? false))

{{ __('No PAYE or NSSA will be deducted') }}

{{ __('There is no tax table in force for this period, so everyone is paid their full gross. Set one up before you finalize, or the deductions will have to be corrected later.') }}

@endif

{{ __('Payroll Runs') }}

@forelse ($runs as $run) @empty
@if ($canProcessPayroll){{ __('Build Pay Run') }}@endif
@endforelse
{{ $runs->links() }}
@if ($viewRun)

{{ $viewRun->period->format('F Y') }}

{{ ucfirst($viewRun->status) }} @if ($viewRun->isFinalized() && $viewRun->fundAccount){{ __('paid from :acct', ['acct' => $viewRun->fundAccount->name]) }}@endif

@if ($viewRun->isFinalized() && $canProcessPayroll)
{{-- Payroll goes out for everybody at once, so the slips do too. Each one lands at the address that person gave for it. --}} {{ __('Email slips') }} {{-- Correcting a finalized month is deliberate work, so it asks plainly what it is about to reverse before doing any of it. --}} {{ __('Reopen') }}
@endif @if (! $viewRun->isFinalized() && $canProcessPayroll)
{{ __('Recompute') }} {{ __('Finalize') }}
@endif
@forelse ($viewRun->lines as $line) @php $otherDeductions = round((float) $line->deduction_total - (float) $line->statutory_total, 2); @endphp @empty @endforelse @if ($viewRun->lines->isNotEmpty()) @endif
{{ __('Staff') }} {{ __('Gross Pay') }} {{ __('Employee NSSA') }} {{ __('PAYE incl. Levy') }} {{ __('Other Ded.') }} {{ __('Net Pay') }} {{ __('Employer NSSA') }} {{ __('Employer Cost') }} {{ __('Document') }}
{{ $line->user?->name ?? '—' }} @if ($line->isConsultantFee()) {{ __('Fee') }} @endif {{ $line->payMethodLabel() }}@if ($line->fundAccount) · {{ $line->fundAccount->name }}@endif {{ number_format((float) $line->gross_pay, 2) }} @if ($line->isGrossedUp()) {{ __('grossed up') }} @endif {{ $line->nssa_employee > 0 ? '−' . number_format((float) $line->nssa_employee, 2) : '—' }} {{ $line->paye_total > 0 ? '−' . number_format((float) $line->paye_total, 2) : '—' }} {{ $otherDeductions > 0 ? '−' . number_format($otherDeductions, 2) : '—' }} {{ $baseCode }} {{ number_format((float) $line->net_pay, 2) }} @if ($line->partMonth()) {{ __('part month: :d of :of days', ['d' => rtrim(rtrim(number_format($line->partMonth()['days'], 2), '0'), '.'), 'of' => number_format($line->partMonth()['of'], 2)]) }} @endif @if ($line->pay_deferred) {{ __('deferred to next month') }} @elseif ($line->isPartlyPaid()) {{ __('paid now :a · owed :b', ['a' => number_format($line->amountPaidNow(), 2), 'b' => number_format($line->amountOwed(), 2)]) }} @endif @php $arrearsOnSlip = $viewRun->isFinalized() ? (float) $line->arrears_paid : $line->plannedArrears(); @endphp @if ($arrearsOnSlip > 0) {{ __('+ arrears :a', ['a' => number_format($arrearsOnSlip, 2)]) }} @endif @if (! $viewRun->isFinalized() && $canProcessPayroll) @endif {{ $line->nssa_employer > 0 ? number_format((float) $line->nssa_employer, 2) : '—' }} {{ number_format($line->totalEmployerCost(), 2) }} @if ($viewRun->isFinalized()) {{ __('View') }} @if ($canProcessPayroll) @php $slipEmail = $payslipEmails[$line->user_id] ?? $line->user?->email; @endphp · @if ($line->payslip_emailed_at) {{ __('sent :when', ['when' => $line->payslip_emailed_at->timezone(config('app.display_timezone'))->format('j M, H:i')]) }} @endif @endif @else {{ __('On finalize') }} @endif
{{ __('No staff profiles to pay. Add staff first.') }}
{{ __('Total') }} {{ number_format((float) $viewRun->lines->sum('gross_pay'), 2) }} −{{ number_format((float) $viewRun->lines->sum('nssa_employee'), 2) }} −{{ number_format((float) $viewRun->lines->sum('paye_total'), 2) }} −{{ number_format((float) $viewRun->lines->sum('deduction_total') - (float) $viewRun->lines->sum('statutory_total'), 2) }} {{ $baseCode }} {{ number_format((float) $viewRun->lines->sum('net_pay'), 2) }} {{ number_format((float) $viewRun->lines->sum('nssa_employer'), 2) }} {{ number_format($viewRun->lines->sum(fn ($l) => $l->totalEmployerCost()), 2) }}
@else

{{ __('Select a run to see the slips, or build a new one.') }}

@endif
{{-- Salary owed: what finalized runs did not pay out yet. --}} @if ($owedSalaries->isNotEmpty())

{{ __('Salary owed') }}

{{ __('Pay that was earned and taxed in its month but not yet paid. It is paid on the next run as an arrears row, or here, straight from an account.') }}

@foreach ($owedSalaries as $owed) @endforeach
{{ __('Employee') }} {{ __('Earned in') }} {{ __('Reason') }} {{ __('Owed') }} {{ __('Paid so far') }} {{ __('Still owed') }}
{{ $owed->user?->name }} {{ $owed->periodLabel() }} @if ($owed->deferred){{ __('Deferred') }}@endif {{ $owed->reason ?: '-' }} {{ number_format((float) $owed->amount, 2) }} {{ number_format((float) $owed->settled_amount, 2) }} {{ $baseCode }} {{ number_format($owed->outstanding(), 2) }} @if ($canManagePay) @endif
@endif @endif {{-- ============================================================ --}} {{-- PLANS --}} {{-- ============================================================ --}} @if ($tab === 'plans')
@forelse ($plans as $plan)
{{ $planLabel[$plan->applies_to] ?? ucfirst($plan->applies_to) }}

{{ $plan->name }}

@if ($canManage)
@endif
@if ($plan->applies_to === 'sales')

{{ __('Tiers (% of gross profit)') }}

@foreach ($plan->tiers as $tier)
≥ {{ rtrim(rtrim(number_format($tier['min_attainment'], 1), '0'), '.') }}% {{ __('of target') }} {{ rtrim(rtrim(number_format($tier['rate'], 2), '0'), '.') }}%
@endforeach @elseif ($plan->applies_to === 'gp_hurdle') @php $cfg = $plan->config ?? []; @endphp

{{ __('Company-wide monthly pool') }}

{{ __('Hurdle multiplier') }} {{ isset($cfg['multiplier']) ? '× '.rtrim(rtrim(number_format((float) $cfg['multiplier'], 2), '0'), '.') : __('workspace default') }}
{{ __('Pool rate') }} {{ isset($cfg['pool_rate']) ? rtrim(rtrim(number_format((float) $cfg['pool_rate'] * 100, 2), '0'), '.').'%' : __('workspace default') }}
{{ __('Share method') }} {{ ($cfg['share_method'] ?? 'weighted') === 'equal' ? __('Equal split') : __('By contribution') }}
@else
{{ __('Profit-share pool') }} {{ rtrim(rtrim(number_format((float) $plan->pool_rate, 2), '0'), '.') }}%
@endif
@if ($plan->margin_floor !== null){{ __('Margin ≥ :n%', ['n' => rtrim(rtrim(number_format((float)$plan->margin_floor,2),'0'),'.')]) }}@endif @if ($plan->require_invoice_paid){{ __('Paid invoice') }}@endif @if ($plan->require_target_met){{ __('Target unlock') }}@endif @if ($plan->require_on_time){{ __('On time') }}@endif @if ($plan->require_within_budget){{ __('Within budget') }}@endif @if ($plan->require_no_reprint){{ __('No reprint') }}@endif
@empty
@if ($canManage){{ __('New Plan') }}@endif
@endforelse
@endif
{{-- ================================================================ --}} {{-- MODALS --}} {{-- ================================================================ --}} {{ $planId ? __('Edit Commission Plan') : __('New Commission Plan') }}
@if ($plan_applies_to === 'sales')

{{ __('Tiers') }}

{{ __('Rate rises with % of monthly revenue target reached.') }}

@foreach ($plan_tiers as $i => $tier)
≥ % {{ __('target') }}
→
% {{ __('profit') }}
@endforeach
@elseif ($plan_applies_to === 'gp_hurdle')

{{ __('Pool overrides') }}

{{ __('Leave blank to inherit the workspace defaults (Settings → Profit & Commission). The pool is computed from the finance engine\'s gross profit and overheads.') }}

{{ __('Production = remainder.') }}

@else

{{ __('Pooled per job and split among the crew by hours logged.') }}

@endif
@if ($plan_applies_to !== 'gp_hurdle')

{{ __('No commission on jobs below this margin.') }}

@endif
{{ __('Cancel') }} {{ __('Save Plan') }}
{{ $staffId ? __('Edit Staff Profile') : __('Add Staff Profile') }}

{{ __('Choose take-home when you agreed a round figure "in hand": payroll works back to the gross that delivers it.') }}

{{-- Statutory standing. Defaults keep everyone fully liable. --}}

{{ __('Statutory') }}

{{ __('NSSA and PAYE are deducted for everyone by default. Only switch these off where you can point to the exemption.') }}

@if ($staff_is_consultant)

{{ __('A consultant is already outside both, so these two are moot.') }}

@endif

{{ __('Elderly, blind or disabled credits. Taken off the tax itself, not off taxable income.') }}

{{ __('Which side of the company-wide profit-share pool this person shares in.') }}

{{ __('Cancel') }} {{ __('Save') }}
{{ $liabilityId ? __('Edit Loss') : __('Record a Loss') }}

{{ __('Each payroll run deducts at most the cap % of that month\'s net pay, so recovery can run longer than the months above, never zeroing a paycheck.') }}

{{-- Signed acknowledgement: only available once the loss record exists. --}}

{{ __('Signed acknowledgement') }}

{{ __('Generate the consent form on the company letterhead, have the employee sign it, then upload the scan as proof.') }}

@if ($liabilityId) @endif
@if ($liabilityId)
@if ($existingAckUrl && ! $ackUpload)
{{ __('Signed copy on file') }}@if ($existingAckAt) · {{ $existingAckAt }}@endif {{ __('View') }}
@endif

{{ __('PDF or image, up to 10 MB.') }}

@else

{{ __('Save this loss first, then re-open it to download the acknowledgement and upload the signed copy.') }}

@endif
{{ __('Cancel') }} {{ __('Save') }}
{{ __('Build Payroll Run') }}

{{ __('Builds a draft netting each active staff member\'s salary, approved commissions and any loss installments. You can review and recompute before finalizing.') }}

{{ __('This is the month the pay belongs to, not the day you run it. The wage bill posts dated the last day of the month chosen here, so a run finalized in the following month still lands in the month it paid for.') }}

{{ __('Cancel') }} {{ __('Build Draft') }}
{{ ($viewRun ?? null) ? __('Finalize :month Payroll', ['month' => $viewRun->period->format('F Y')]) : __('Finalize Payroll') }} {{-- Payroll is usually finalized days into the next month, so say out loud which month the money is being booked into. --}} @if ($viewRun ?? null)

{{ __('Paying for :month. The wage bill posts as an expense dated :date, so it falls in that month whatever today\'s date is.', [ 'month' => $viewRun->period->format('F Y'), 'date' => $viewRun->period->copy()->endOfMonth()->format('j M Y'), ]) }}

@endif

{{ __('Staff with their own pay-from account keep it; this covers everyone else.') }}

{{ __('Finalizing locks the run, issues every payslip, marks its commissions paid, advances loss recovery, and deducts the total wage bill from each paying account as a single "Salaries & Wages" expense. This cannot be undone.') }}

{{ __('Cancel') }} {{ __('Finalize & Pay') }}
{{-- Paid now: how much of one slip goes out with the run --}} {{ __('Paid now') }}@if ($paidNowLine ?? null) · {{ $paidNowLine->user?->name }}@endif @if ($paidNowLine ?? null)

{{ __('Net pay this month: :amt', ['amt' => $baseCode.' '.number_format((float) $paidNowLine->net_pay, 2)]) }}

@foreach (['full' => __('Pay in full'), 'part' => __('Pay part now'), 'defer' => __('Defer to next month')] as $mode => $label) @endforeach
@if ($pn_mode === 'part')
@endif @if ($pn_mode !== 'full')

{{ __('The slip is still issued and taxed for this month. What is not paid now becomes salary owed: it counts as this month\'s wage cost and shows as a liability until it is paid.') }}

@endif
@endif
{{ __('Cancel') }} {{ __('Save') }}
{{-- Pay owed salary outside a run --}} {{ __('Pay owed salary') }} @if ($payOwedArrear ?? null)

{{ __(':name, earned in :period. Still owed: :amt', ['name' => $payOwedArrear->user?->name, 'period' => $payOwedArrear->periodLabel(), 'amt' => number_format($payOwedArrear->outstanding(), 2)]) }}

{{ __('Part payments are fine; the rest stays owed. This moves cash only: the cost was already booked in the month it was earned.') }}

@endif
{{ __('Cancel') }} {{ __('Pay') }}
@if ($canManagePay ?? false) {{ $componentId ? __('Edit benefit or deduction') : __('New benefit or deduction') }}
@php $isPercent = in_array($comp_calc, ['percent_basic', 'percent_gross']); @endphp
@if ($isPercent) % @endif
@if ($isPercent)

{{ __('A percentage follows the salary it is worked out from.') }}

@endif

{{ __('Useful for statutory items that cap out at a ceiling.') }}

@if ($comp_kind === 'allowance')
@endif
{{ __('Cancel') }} {{ $componentId ? __('Save changes') : __('Add to catalogue') }} {{ __('Saving…') }}
{{ $taxId ? __('Edit Tax Table') : __('New Tax Table') }}

{{ __('Leave blank while this is the current table.') }}

{{-- NSSA -------------------------------------------------- --}}

{{ __('NSSA') }}

{{ __('Contributions stop counting above the ceiling. The employer share costs the company but never comes off take-home.') }}

{{-- PAYE bands -------------------------------------------- --}}

{{ __('Written the way ZIMRA publishes them: tax = pay × rate − the subtract figure. Bands must run continuously with no gaps.') }}

{{ __('Add band') }}
@foreach ($tax_bands as $i => $band) @endforeach
{{ __('Over') }} {{ __('Up to') }} {{ __('Rate %') }} {{ __('Subtract') }}
{{ __('Cancel') }} {{ $taxId ? __('Save changes') : __('Save table') }} {{ __('Saving…') }}
@endif