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; } }