@php use App\Support\Navigation\WorkspaceEmbed; $statutory = $statutory ?? config('payroll_statutory', []); $canEdit = $canEditStatutory ?? false; $effectiveDate = old('effective_date', $statutory['effective_date'] ?? ''); $payeBands = old('paye_bands', collect($statutory['paye']['bands'] ?? [])->map(fn ($band) => [ 'up_to' => $band['up_to'] ?? '', 'rate' => isset($band['rate']) ? round((float) $band['rate'] * 100, 4) : '', ])->all()); if ($payeBands === []) { $payeBands = [['up_to' => '', 'rate' => '']]; } $personalRelief = old('personal_relief_monthly', (float) ($statutory['personal_relief']['monthly'] ?? 0)); $nssf = $statutory['nssf'] ?? []; $shif = $statutory['shif'] ?? []; $housing = $statutory['housing_levy'] ?? []; $nssfRate = old('nssf_employee_rate', round(((float) ($nssf['employee_rate'] ?? 0)) * 100, 4)); $nssfLower = old('nssf_lower_earnings_limit', (float) ($nssf['lower_earnings_limit'] ?? 0)); $nssfUpper = old('nssf_upper_earnings_limit', (float) ($nssf['upper_earnings_limit'] ?? 0)); $shifRate = old('shif_employee_rate', round(((float) ($shif['employee_rate'] ?? 0)) * 100, 4)); $shifMinimum = old('shif_minimum_monthly_contribution', (float) ($shif['minimum_monthly_contribution'] ?? 0)); $housingRate = old('housing_levy_employee_rate', round(((float) ($housing['employee_rate'] ?? 0)) * 100, 4)); $embedded = WorkspaceEmbed::inWorkspaceContext(); @endphp Payroll home Payroll periods @include('loan.accounting.partials.flash') @if ($canEdit)

Super administrator — statutory rates

Changes apply to new payroll generation only. Existing lines, payslips, and posted journals keep the amounts stored at run time.

@if ($statutoryRecord?->updated_at)

Last saved {{ $statutoryRecord->updated_at->format('M j, Y g:i A') }} @if ($statutoryRecord->updatedBy) by {{ $statutoryRecord->updatedBy->name }} @endif

@endif
@csrf @method('put') @if ($embedded) @endif

Effective date

Reference date for the current statutory schedule.

Personal relief

KES

Monthly credit applied against PAYE.

PAYE monthly bands

Applied to taxable pay (gross after NSSF, SHIF, and Housing Levy). Leave the last band ceiling empty.

@foreach ($payeBands as $index => $band) @endforeach
Band ceiling (KES) Rate (%) Remove

NSSF (employee)

Base: pensionable gross, capped at the upper limit. Not a flat KES amount.

SHIF (employee)

Base: gross pay. Then the monthly minimum is applied if the % is lower.

Housing Levy (employee)

Base: gross pay. Taken off before PAYE. No separate floor — the % is the charge.

@else

You can view current statutory rates here. Only a super administrator can edit PAYE bands, NSSF, SHIF, and Housing Levy settings.

@if ($statutoryRecord?->updated_at)

Last updated {{ $statutoryRecord->updated_at->format('M j, Y g:i A') }} @if ($statutoryRecord->updatedBy) by {{ $statutoryRecord->updatedBy->name }} @endif

@endif

Effective date

{{ $effectiveDate ?: '—' }}

Personal relief

KES {{ number_format($personalRelief, 2) }}

PAYE monthly bands

@php $prev = 0; @endphp @foreach ($statutory['paye']['bands'] ?? [] as $band) @php $ceiling = $band['up_to'] ?? null; $rate = ((float) ($band['rate'] ?? 0)) * 100; @endphp @php $prev = $ceiling !== null ? (float) $ceiling : $prev; @endphp @endforeach
Band ceiling (KES) Rate
@if ($ceiling === null) Above {{ number_format($prev, 2) }} @else {{ number_format($prev + 0.01, 2) }} – {{ number_format((float) $ceiling, 2) }} @endif {{ number_format($rate, 2) }}%

NSSF (employee)

Base: pensionable gross (capped).

Rate
{{ number_format($nssfRate, 2) }}%
Lower limit
KES {{ number_format($nssfLower, 2) }}
Upper limit
KES {{ number_format($nssfUpper, 2) }}

SHIF (employee)

Base: gross, then monthly minimum.

Rate
{{ number_format($shifRate, 2) }}%
Minimum monthly
KES {{ number_format($shifMinimum, 2) }}

Housing Levy (employee)

Base: gross pay.

Rate
{{ number_format($housingRate, 2) }}%
@endif @include('loan.accounting.books.payroll.partials.statutory-settings-explain')
@if ($canEdit) @endif