Files
2026-09-16 23:20:08 +07:00

428 lines
18 KiB
PHP

<?php
namespace app\Controllers;
use app\Models\PayrollModel;
use app\Models\HrPersonModel;
use app\Models\IncomeMasterModel;
use app\Models\DeductionMasterModel;
use app\Models\OfficerTypeModel;
class ReportController extends Controller {
public function __construct() {
if (empty($_SESSION['user_id'])) {
$_SESSION['error'] = 'กรุณาเข้าสู่ระบบก่อนใช้งาน';
header('Location: ' . BASE_URL . '/login');
exit;
}
}
public function index() {
$payrollModel = new PayrollModel();
// Get filter inputs
$month = $_GET['month'] ?? date('m');
$year = $_GET['year'] ?? date('Y');
// Fetch payroll data for the selected month/year
$payrollData = $payrollModel->getSalariesByPeriod($month, $year);
// Fetch matching HR data
$hrModel = new HrPersonModel();
$nationalIds = array_column($payrollData, 'national_id');
$hrData = $hrModel->getPersonsByNationalIds($nationalIds);
// Combine data
foreach ($payrollData as &$row) {
$nid = $row['national_id'];
if (isset($hrData[$nid])) {
$row['hr_fname'] = $hrData[$nid]['HR_FNAME'];
$row['hr_lname'] = $hrData[$nid]['HR_LNAME'];
$row['hr_position'] = $hrData[$nid]['HR_POSITION_NAME'];
$row['hr_department'] = $hrData[$nid]['HR_DEPARTMENT_SUB_SUB_NAME'];
}
}
$this->view('reports/index', [
'title' => 'ระบบสืบค้นและพิมพ์สลิปเงินเดือน | ' . APP_NAME,
'activeMenu' => 'reports',
'month' => $month,
'year' => $year,
'payrollData' => $payrollData
]);
}
public function printSlip() {
$nationalId = $_GET['national_id'] ?? null;
$month = $_GET['month'] ?? null;
$year = $_GET['year'] ?? null;
if (!$nationalId || !$month || !$year) {
die('ข้อมูลไม่ครบถ้วน');
}
$payrollModel = new PayrollModel();
$salary = $payrollModel->getSalaryByNationalId($nationalId, $month, $year);
if (!$salary) {
die('ไม่พบข้อมูลเงินเดือนของบุคคลนี้ในงวดที่เลือก');
}
$incomes = $payrollModel->getEmployeeIncomes($salary['id']);
$deductions = $payrollModel->getEmployeeDeductions($salary['id']);
$hrModel = new HrPersonModel();
$hrData = $hrModel->getPersonByNationalId($nationalId);
$profileModel = new \app\Models\EmployeeProfileModel();
$bankProfile = $profileModel->getProfile($nationalId);
$settingModel = new \app\Models\SystemSettingModel();
$signatureName = $settingModel->getSetting('signature_name', '( นางณัฐฐิณี เรืองทอง )');
$signaturePosition = $settingModel->getSetting('signature_position', 'นักวิชาการเงินและบัญชี');
$signatureScale = $settingModel->getSetting('signature_scale', '100');
$slipFontSize = $settingModel->getSetting('slip_font_size', '11pt');
$signaturePosX = $settingModel->getSetting('signature_pos_x', '0');
$signaturePosY = $settingModel->getSetting('signature_pos_y', '0');
$this->view('reports/slip', [
'salary' => $salary,
'incomes' => $incomes,
'deductions' => $deductions,
'hrData' => $hrData,
'bankProfile' => $bankProfile,
'signatureName' => $signatureName,
'signaturePosition' => $signaturePosition,
'signatureScale' => $signatureScale,
'slipFontSize' => $slipFontSize,
'signaturePosX' => $signaturePosX,
'signaturePosY' => $signaturePosY,
'month' => $month,
'year' => $year
]);
}
public function printTax() {
$nationalId = $_GET['national_id'] ?? null;
$year = $_GET['year'] ?? null;
if (!$nationalId || !$year) {
die('ข้อมูลไม่ครบถ้วน');
}
$payrollModel = new PayrollModel();
$yearlySummary = $payrollModel->getYearlyTaxSummary($nationalId, $year);
if (!$yearlySummary || $yearlySummary['total_income'] == 0) {
die('ไม่พบข้อมูลรายได้ในปีที่เลือก');
}
$hrModel = new HrPersonModel();
$hrData = $hrModel->getPersonByNationalId($nationalId);
$settingModel = new \app\Models\SystemSettingModel();
$orgTaxId = $settingModel->getSetting('org_tax_id', '');
$taxSignatureName = $settingModel->getSetting('tax_signature_name', '');
$taxSignaturePosition = $settingModel->getSetting('tax_signature_position', '');
$taxSignatureScale = $settingModel->getSetting('tax_signature_scale', '100');
$taxSignaturePosX = $settingModel->getSetting('tax_signature_pos_x', '0');
$taxSignaturePosY = $settingModel->getSetting('tax_signature_pos_y', '0');
$taxFontSize = $settingModel->getSetting('tax_font_size', '11pt');
$orgAddress = $settingModel->getSetting('org_address', 'ต.อ่างทอง อ.เกาะสมุย จ.สุราษฎร์ธานี 84140');
$taxPayeeAddress = $settingModel->getSetting('tax_payee_address', 'ต.อ่างทอง อ.เกาะสมุย จ.สุราษฎร์ธานี 84140');
$this->view('reports/tax', [
'yearlySummary' => $yearlySummary,
'hrData' => $hrData,
'year' => $year,
'nationalId' => $nationalId,
'orgTaxId' => $orgTaxId,
'taxSignatureName' => $taxSignatureName,
'taxSignaturePosition' => $taxSignaturePosition,
'taxSignatureScale' => $taxSignatureScale,
'taxSignaturePosX' => $taxSignaturePosX,
'taxSignaturePosY' => $taxSignaturePosY,
'taxFontSize' => $taxFontSize,
'orgAddress' => $orgAddress,
'taxPayeeAddress' => $taxPayeeAddress
]);
}
public function printTaxBulk() {
$nationalIds = $_POST['national_ids'] ?? [];
$year = $_POST['year'] ?? null;
$groupByLetter = isset($_POST['group_by_letter']) && $_POST['group_by_letter'] == '1';
if (empty($nationalIds) || !$year) {
die('ข้อมูลไม่ครบถ้วน กรุณาเลือกพนักงานอย่างน้อย 1 รายการ');
}
$payrollModel = new PayrollModel();
$hrModel = new HrPersonModel();
$bulkData = [];
foreach ($nationalIds as $nationalId) {
$yearlySummary = $payrollModel->getYearlyTaxSummary($nationalId, $year);
if ($yearlySummary && $yearlySummary['total_income'] > 0) {
$hrData = $hrModel->getPersonByNationalId($nationalId);
$bulkData[] = [
'nationalId' => $nationalId,
'yearlySummary' => $yearlySummary,
'hrData' => $hrData
];
}
}
if (empty($bulkData)) {
die('ไม่พบข้อมูลรายได้ในปีที่เลือกของพนักงานที่เลือกทั้งหมด');
}
// Sort data by First Name if grouping by letter is enabled
if ($groupByLetter) {
usort($bulkData, function($a, $b) {
$nameA = $a['hrData']['HR_FNAME'] ?? '';
$nameB = $b['hrData']['HR_FNAME'] ?? '';
return strcmp($nameA, $nameB);
});
}
$settingModel = new \app\Models\SystemSettingModel();
$orgTaxId = $settingModel->getSetting('org_tax_id', '');
$taxSignatureName = $settingModel->getSetting('tax_signature_name', '');
$taxSignaturePosition = $settingModel->getSetting('tax_signature_position', '');
$taxSignatureScale = $settingModel->getSetting('tax_signature_scale', '100');
$taxSignaturePosX = $settingModel->getSetting('tax_signature_pos_x', '0');
$taxSignaturePosY = $settingModel->getSetting('tax_signature_pos_y', '0');
$taxFontSize = $settingModel->getSetting('tax_font_size', '11pt');
$orgAddress = $settingModel->getSetting('org_address', 'ต.อ่างทอง อ.เกาะสมุย จ.สุราษฎร์ธานี 84140');
$taxPayeeAddress = $settingModel->getSetting('tax_payee_address', 'ต.อ่างทอง อ.เกาะสมุย จ.สุราษฎร์ธานี 84140');
$this->view('reports/tax_bulk', [
'bulkData' => $bulkData,
'year' => $year,
'groupByLetter' => $groupByLetter,
'orgTaxId' => $orgTaxId,
'taxSignatureName' => $taxSignatureName,
'taxSignaturePosition' => $taxSignaturePosition,
'taxSignatureScale' => $taxSignatureScale,
'taxSignaturePosX' => $taxSignaturePosX,
'taxSignaturePosY' => $taxSignaturePosY,
'taxFontSize' => $taxFontSize,
'orgAddress' => $orgAddress,
'taxPayeeAddress' => $taxPayeeAddress
]);
}
public function salaryReport() {
$payrollModel = new PayrollModel();
$hrModel = new HrPersonModel();
$officerTypeModel = new OfficerTypeModel();
$month = $_GET['month'] ?? date('m');
$year = $_GET['year'] ?? date('Y');
$typeId = $_GET['type_id'] ?? '';
$officerTypes = $officerTypeModel->getActive();
$selectedTypeName = '';
if ($typeId) {
foreach ($officerTypes as $type) {
if ($type['id'] == $typeId) {
$selectedTypeName = $type['name'];
break;
}
}
}
$payrollData = $payrollModel->getSalariesByPeriod($month, $year);
$nationalIds = array_column($payrollData, 'national_id');
$hrData = $hrModel->getPersonsByNationalIds($nationalIds);
$reportData = [];
foreach ($payrollData as $row) {
$nid = $row['national_id'];
if (isset($hrData[$nid])) {
$personType = $hrData[$nid]['HR_PERSON_TYPE_NAME'] ?? '';
// Filter by type if selected
if ($typeId && $personType !== $selectedTypeName) {
continue;
}
$row['hr_prefix'] = $hrData[$nid]['HR_PREFIX_NAME'] ?? '';
$row['hr_fname'] = $hrData[$nid]['HR_FNAME'] ?? '';
$row['hr_lname'] = $hrData[$nid]['HR_LNAME'] ?? '';
$row['hr_position'] = $hrData[$nid]['HR_POSITION_NAME'] ?? '';
$row['hr_department'] = $hrData[$nid]['HR_DEPARTMENT_SUB_SUB_NAME'] ?? '';
$row['person_type'] = $personType;
// Fetch incomes and deductions to display sums or details if needed
// But for performance, we can just use the cached totals if available.
// Wait, if we need specific columns for Excel, we should fetch details.
// In this case, we fetch them here or in export mode.
$reportData[] = $row;
}
}
// Sort by first name (ignoring prefix)
usort($reportData, function($a, $b) {
return strcmp($a['hr_fname'], $b['hr_fname']);
});
$this->view('reports/salary_report', [
'title' => 'รายงานเงินเดือน | ' . APP_NAME,
'activeMenu' => 'report_salary',
'month' => $month,
'year' => $year,
'typeId' => $typeId,
'officerTypes' => $officerTypes,
'reportData' => $reportData
]);
}
public function exportExcel() {
require_once APP_ROOT . '/app/Libraries/SimpleXLSXGen.php';
$payrollModel = new PayrollModel();
$hrModel = new HrPersonModel();
$officerTypeModel = new OfficerTypeModel();
$incomeModel = new IncomeMasterModel();
$deductionModel = new DeductionMasterModel();
$month = $_GET['month'] ?? date('m');
$year = $_GET['year'] ?? date('Y');
$typeId = $_GET['type_id'] ?? '';
$officerTypes = $officerTypeModel->getActive();
$selectedTypeName = 'ทั้งหมด';
if ($typeId) {
foreach ($officerTypes as $type) {
if ($type['id'] == $typeId) {
$selectedTypeName = $type['name'];
break;
}
}
}
$payrollData = $payrollModel->getSalariesByPeriod($month, $year);
$nationalIds = array_column($payrollData, 'national_id');
$hrData = $hrModel->getPersonsByNationalIds($nationalIds);
// Fetch all income/deduction codes to build dynamic columns
$allIncomes = $incomeModel->getAllIncomes();
$allDeductions = $deductionModel->getAllDeductions();
$incomeCols = [];
foreach ($allIncomes as $inc) {
$incomeCols[$inc['code']] = $inc['name'];
}
$deductionCols = [];
foreach ($allDeductions as $ded) {
$deductionCols[$ded['code']] = $ded['name'];
}
$reportData = [];
foreach ($payrollData as $row) {
$nid = $row['national_id'];
if (isset($hrData[$nid])) {
$personType = $hrData[$nid]['HR_PERSON_TYPE_NAME'] ?? '';
if ($typeId && $personType !== $selectedTypeName) {
continue;
}
$row['hr_prefix'] = $hrData[$nid]['HR_PREFIX_NAME'] ?? '';
$row['hr_fname'] = $hrData[$nid]['HR_FNAME'] ?? '';
$row['hr_lname'] = $hrData[$nid]['HR_LNAME'] ?? '';
// Fetch details
$incomes = $payrollModel->getEmployeeIncomes($row['id']);
$deductions = $payrollModel->getEmployeeDeductions($row['id']);
$row['incomes_detail'] = [];
foreach ($incomes as $inc) {
$row['incomes_detail'][$inc['income_code']] = $inc['amount'];
}
$row['deductions_detail'] = [];
foreach ($deductions as $ded) {
$row['deductions_detail'][$ded['deduction_code']] = $ded['amount'];
}
$reportData[] = $row;
}
}
usort($reportData, function($a, $b) {
return strcmp($a['hr_fname'], $b['hr_fname']);
});
$monthNames = [
'01' => 'มกราคม', '02' => 'กุมภาพันธ์', '03' => 'มีนาคม', '04' => 'เมษายน',
'05' => 'พฤษภาคม', '06' => 'มิถุนายน', '07' => 'กรกฎาคม', '08' => 'สิงหาคม',
'09' => 'กันยายน', '10' => 'ตุลาคม', '11' => 'พฤศจิกายน', '12' => 'ธันวาคม'
];
$monthName = $monthNames[$month] ?? $month;
$thaiYear = $year + 543;
$excelData = [];
// Header
$excelData[] = ["รายงานเงินเดือนเจ้าหน้าที่โรงพยาบาล"];
$excelData[] = ["ประจำเดือน: $monthName $thaiYear", "", "ประเภท: $selectedTypeName"];
$excelData[] = [];
// Columns
$headerRow = ["ลำดับ", "ชื่อ-สกุล", "เงินเดือนหลัก"];
foreach ($incomeCols as $code => $name) {
$headerRow[] = $name;
}
$headerRow[] = "รวมรายรับ";
foreach ($deductionCols as $code => $name) {
$headerRow[] = $name;
}
$headerRow[] = "รวมรายจ่าย";
$headerRow[] = "รับสุทธิ";
$excelData[] = $headerRow;
// Data Rows
$idx = 1;
foreach ($reportData as $row) {
$fullName = trim($row['hr_prefix']) . trim($row['hr_fname']) . ' ' . trim($row['hr_lname']);
$dataRow = [
$idx++,
$fullName,
$row['base_salary']
];
// Incomes
foreach ($incomeCols as $code => $name) {
$dataRow[] = $row['incomes_detail'][$code] ?? 0;
}
$dataRow[] = $row['total_income'];
// Deductions
foreach ($deductionCols as $code => $name) {
$dataRow[] = $row['deductions_detail'][$code] ?? 0;
}
$dataRow[] = $row['total_deduction'];
$dataRow[] = $row['net_salary'];
$excelData[] = $dataRow;
}
$xlsx = \Shuchkin\SimpleXLSXGen::fromArray($excelData);
$xlsx->freezePanes('A5');
$filename = "รายงานเงินเดือนเจ้าหน้าที่_{$month}_{$year}.xlsx";
$xlsx->downloadAs($filename);
exit;
}
}