144 lines
5.1 KiB
PHP
144 lines
5.1 KiB
PHP
<?php
|
|
ini_set('display_errors', 1);
|
|
error_reporting(E_ALL);
|
|
session_start();
|
|
require_once __DIR__ . '/db/config.php';
|
|
require_once __DIR__ . '/vendor/autoload.php';
|
|
|
|
if (!isset($_SESSION['user_id']) || !isset($_SESSION['company_id'])) {
|
|
http_response_code(403);
|
|
die('Access denied');
|
|
}
|
|
|
|
if (!isset($_GET['payslip_id'])) {
|
|
http_response_code(400);
|
|
die('Payslip ID is required');
|
|
}
|
|
|
|
$company_id = $_SESSION['company_id'];
|
|
$payslip_id = $_GET['payslip_id'];
|
|
|
|
// Fetch data
|
|
try {
|
|
$pdo = db();
|
|
// Fetch Payslip, Employee, Company, and Run info
|
|
$stmt = $pdo->prepare(
|
|
"SELECT ps.*, pr.pay_period_month, pr.pay_period_year, e.first_name, e.last_name, e.position, c.name as company_name
|
|
FROM payslips ps
|
|
JOIN payroll_runs pr ON ps.payroll_run_id = pr.id
|
|
JOIN employees e ON ps.employee_id = e.id
|
|
JOIN companies c ON pr.company_id = c.id
|
|
WHERE ps.id = ? AND c.id = ?"
|
|
);
|
|
$stmt->execute([$payslip_id, $company_id]);
|
|
$payslip = $stmt->fetch();
|
|
|
|
if (!$payslip) {
|
|
http_response_code(404);
|
|
die('Payslip not found or access denied.');
|
|
}
|
|
|
|
// Fetch Payslip Items
|
|
$stmt = $pdo->prepare("SELECT * FROM payslip_items WHERE payslip_id = ? ORDER BY type, description");
|
|
$stmt->execute([$payslip_id]);
|
|
$items = $stmt->fetchAll();
|
|
|
|
} catch (Exception $e) {
|
|
http_response_code(500);
|
|
die('Database error: ' . $e->getMessage());
|
|
}
|
|
|
|
// PDF Generation
|
|
class MYPDF extends TCPDF {
|
|
public function Header() {
|
|
$this->SetFont('helvetica', 'B', 20);
|
|
$this->Cell(0, 15, 'Payslip', 0, false, 'C', 0, '', 0, false, 'M', 'M');
|
|
}
|
|
public function Footer() {
|
|
$this->SetY(-15);
|
|
$this->SetFont('helvetica', 'I', 8);
|
|
$this->Cell(0, 10, 'Page '.$this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
|
|
}
|
|
}
|
|
|
|
$pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
|
|
|
$pdf->SetCreator(PDF_CREATOR);
|
|
$pdf->SetAuthor('GPTPayroll');
|
|
$pdf->SetTitle('Payslip');
|
|
$pdf->SetSubject('Payslip');
|
|
|
|
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
|
|
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
|
|
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
|
|
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
|
|
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
|
|
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
|
|
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
|
|
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
|
|
|
|
$pdf->AddPage();
|
|
|
|
$pdf->SetFont('helvetica', '', 10);
|
|
|
|
// --- Company & Employee Details ---
|
|
$html = '
|
|
<table cellpadding="5" cellspacing="0" border="0" width="100%">
|
|
<tr>
|
|
<td>
|
|
<b>' . htmlspecialchars($payslip['company_name']) . '</b><br>
|
|
Pay Period: ' . htmlspecialchars(date('F Y', mktime(0,0,0, (int)$payslip['pay_period_month'], 1, (int)$payslip['pay_period_year']))) . '<br>
|
|
</td>
|
|
<td align="right">
|
|
<b>Employee:</b> ' . htmlspecialchars($payslip['first_name'] . ' ' . $payslip['last_name']) . '<br>
|
|
<b>Position:</b> ' . htmlspecialchars($payslip['position']) . '<br>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<hr>';
|
|
|
|
$pdf->writeHTML($html, true, false, true, false, '');
|
|
|
|
// --- Earnings, Deductions, Summary ---
|
|
$earnings = array_filter($items, function($i) { return $i['type'] == 'earning'; });
|
|
$deductions = array_filter($items, function($i) { return $i['type'] == 'deduction' || $i['type'] == 'tax'; });
|
|
|
|
$html = '
|
|
<table cellpadding="5" cellspacing="0" border="0" width="100%">
|
|
<tr>
|
|
<td width="50%" valign="top">
|
|
<b style="font-size: 12px;">Earnings</b><br>
|
|
<table cellpadding="2">
|
|
' . implode('', array_map(function($item) {
|
|
return '<tr><td>' . htmlspecialchars($item['description']) . '</td><td align="right">' . number_format((float)$item['amount'], 2) . '</td></tr>';
|
|
}, $earnings)) . '
|
|
</table>
|
|
</td>
|
|
<td width="50%" valign="top">
|
|
<b style="font-size: 12px;">Deductions</b><br>
|
|
<table cellpadding="2">
|
|
' . implode('', array_map(function($item) {
|
|
return '<tr><td>' . htmlspecialchars($item['description']) . '</td><td align="right">' . number_format((float)$item['amount'], 2) . '</td></tr>';
|
|
}, $deductions)) . '
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<br><br>';
|
|
$pdf->writeHTML($html, true, false, true, false, '');
|
|
|
|
// --- Summary ---
|
|
$html = '
|
|
<table cellpadding="5" cellspacing="0" border="1" width="100%" style="background-color:#f0f0f0;">
|
|
<tr>
|
|
<td width="33.3%"><b>Gross Pay:</b><br>ZMW ' . number_format((float)$payslip['gross_pay'], 2) . '</td>
|
|
<td width="33.3%"><b>Total Deductions:</b><br>ZMW ' . number_format((float)$payslip['total_deductions'], 2) . '</td>
|
|
<td width="33.3%"><b>Net Pay:</b><br><b>ZMW ' . number_format((float)$payslip['net_pay'], 2) . '</b></td>
|
|
</tr>
|
|
</table>';
|
|
|
|
$pdf->writeHTML($html, true, false, true, false, '');
|
|
|
|
// --- Output ---
|
|
$pdf->Output('payslip_' . $payslip_id . '.pdf', 'I');
|