83 lines
2.7 KiB
PHP
83 lines
2.7 KiB
PHP
<?php
|
|
|
|
function calculate_payroll(float $basic_salary, array $settings): array
|
|
{
|
|
$result = [
|
|
'gross_pay' => $basic_salary,
|
|
'items' => [],
|
|
'deductions' => [],
|
|
'taxes' => [],
|
|
'net_pay' => 0,
|
|
];
|
|
|
|
// Add Basic Salary as an earning item
|
|
$result['items'][] = ['type' => 'earning', 'description' => 'Basic Salary', 'amount' => $basic_salary];
|
|
|
|
// --- Deductions ---
|
|
|
|
// 1. NAPSA Calculation
|
|
$napsa_rate = (float)($settings['napsa_rate'] ?? 5) / 100;
|
|
$napsa_ceiling = (float)($settings['napsa_ceiling'] ?? 2880);
|
|
$assessable_for_napsa = min($basic_salary, $napsa_ceiling);
|
|
$napsa_contribution = $assessable_for_napsa * $napsa_rate;
|
|
$result['deductions']['napsa'] = $napsa_contribution;
|
|
$result['items'][] = ['type' => 'deduction', 'description' => 'NAPSA', 'amount' => $napsa_contribution];
|
|
|
|
// 2. NHIMA Calculation
|
|
$nhima_rate = (float)($settings['nhima_rate'] ?? 1) / 100;
|
|
$nhima_contribution = $basic_salary * $nhima_rate;
|
|
$result['deductions']['nhima'] = $nhima_contribution;
|
|
$result['items'][] = ['type' => 'deduction', 'description' => 'NHIMA', 'amount' => $nhima_contribution];
|
|
|
|
// --- Taxable Income ---
|
|
$taxable_income = $basic_salary - $napsa_contribution;
|
|
|
|
// --- PAYE Calculation ---
|
|
$paye_brackets = json_decode($settings['paye_brackets'] ?? '[]', true);
|
|
$paye_tax = 0;
|
|
$remaining_income = $taxable_income;
|
|
|
|
// Sort brackets by 'from' value to ensure correct order
|
|
usort($paye_brackets, function($a, $b) {
|
|
return $a['from'] <=> $b['from'];
|
|
});
|
|
|
|
$cumulative_tax = 0;
|
|
$income_in_previous_bands = 0;
|
|
|
|
foreach ($paye_brackets as $bracket) {
|
|
$from = (float)$bracket['from'];
|
|
$to = isset($bracket['to']) ? (float)$bracket['to'] : null;
|
|
$rate = (float)$bracket['rate'] / 100;
|
|
|
|
if ($taxable_income > $from) {
|
|
$taxable_in_this_band = 0;
|
|
if ($to === null) { // Top bracket
|
|
$taxable_in_this_band = $taxable_income - $from;
|
|
} else {
|
|
$taxable_in_this_band = min($taxable_income, $to) - $from;
|
|
}
|
|
|
|
if ($taxable_in_this_band > 0) {
|
|
$cumulative_tax += $taxable_in_this_band * $rate;
|
|
}
|
|
}
|
|
}
|
|
|
|
$paye_tax = $cumulative_tax;
|
|
|
|
if ($paye_tax > 0) {
|
|
$result['taxes']['paye'] = $paye_tax;
|
|
$result['items'][] = ['type' => 'tax', 'description' => 'PAYE', 'amount' => $paye_tax];
|
|
}
|
|
|
|
// --- Final Calculations ---
|
|
$total_deductions = array_sum($result['deductions']) + array_sum($result['taxes']);
|
|
$net_pay = $basic_salary - $total_deductions;
|
|
|
|
$result['total_deductions'] = $total_deductions;
|
|
$result['net_pay'] = $net_pay;
|
|
|
|
return $result;
|
|
}
|