watermarkPath === '' || !file_exists($this->watermarkPath)) { return; } // Keep original image ratio to avoid stretched watermark. $info = @getimagesize($this->watermarkPath); if (!$info || intval($info[0]) <= 0 || intval($info[1]) <= 0) { return; } $imgW = intval($info[0]); $imgH = intval($info[1]); $drawW = 175.0; $drawH = ($imgH / $imgW) * $drawW; // Position tuned to match lab report reference. $x = ($this->GetPageWidth() - $drawW) / 2; $y = 80.0; $this->Image($this->watermarkPath, $x, $y, $drawW, $drawH, 'JPEG'); } public function Footer() { $pageW = $this->GetPageWidth(); $pageH = $this->GetPageHeight(); $left = 14; $right = 14; $this->SetY($pageH - 18); $this->SetFont('Times', '', 8); $this->SetX($left); $this->Cell(20, 4, 'Tgl Print :', 0, 0, 'L'); $this->Cell(32, 4, date('d/m/Y H:i'), 0, 0, 'L'); $pageNoWidth = 24; $branchWidth = $pageW - $left - $right - 20 - 32 - $pageNoWidth - 20; $this->Cell(20, 4, '', 0, 0, 'L'); $this->Cell($pageNoWidth, 4, $this->PageNo() . ' / {nb}', 0, 0, 'C'); $this->Cell($branchWidth, 4, '', 0, 0, 'L'); $this->Cell(0, 4, $this->safeFooterText($this->branchAddress), 0, 1, 'R'); $this->SetX($left); $this->Cell(20, 4, 'Dicetak :', 0, 0, 'L'); $this->Cell(55, 4, $this->safeFooterText($this->printBy), 0, 0, 'L'); $this->Cell(0, 4, 'F / MCU / 032 Rev 00', 0, 1, 'R'); } private function safeFooterText($text) { $text = (string)$text; if ($text === '') { return ''; } return iconv('UTF-8', 'windows-1252//TRANSLIT//IGNORE', $text); } } class Medical_checkup_report extends MY_Controller { public function __construct() { parent::__construct(); $this->db_onedev = $this->load->database('onedev', true); } public function index() { $this->sys_ok([ 'message' => 'Use /tools/medical_checkup_report/pdf?T_OrderHeaderID=&username=' ]); } public function pdf() { try { $orderHeaderId = intval($this->input->get('T_OrderHeaderID', true)); if ($orderHeaderId <= 0) { $this->sys_error('T_OrderHeaderID mandatory'); return; } $printBy = trim((string)$this->input->get('username', true)); if ($printBy === '') { $printBy = 'ADMIN'; } $header = $this->get_header_data($orderHeaderId); if (!$header) { $this->sys_error('Data order tidak ditemukan'); return; } $rows = $this->get_result_rows($orderHeaderId); $saran = $this->get_saran($orderHeaderId); $branch = $this->get_default_branch(); require_once APPPATH . 'third_party/fpdf/fpdf.php'; $pdf = new MedicalCheckupReportPdf('P', 'mm', 'A4'); $pdf->SetAutoPageBreak(true, 22); $pdf->SetMargins(14, 10, 14); $pdf->AliasNbPages(); $pdf->printBy = $printBy; $pdf->branchAddress = (string)$branch['branch_address']; $pdf->watermarkPath = dirname(APPPATH) . '/assets/images/watermark-ibl.jpeg'; $pdf->AddPage(); // Header offset 3.5 cm for pre-printed kop. $pdf->SetY(35); $pageW = $pdf->GetPageWidth(); $left = 14; $right = 14; $contentW = $pageW - $left - $right; $pdf->SetFont('Times', 'B', 11); $pdf->Cell(0, 6, 'MEDICAL CHECK UP REPORT', 0, 1, 'C'); $pdf->Ln(3); $leftLabelW = 28; $rightLabelW = 28; $colonW = 4; $leftValueW = 64; $rightValueW = $contentW - ($leftLabelW + $colonW + $leftValueW + 12 + $rightLabelW + $colonW); $leftRows = [ ['Tgl. Registrasi', $header['tgl_registrasi']], ['No Lab', $header['no_lab']], ['No Medrec', $header['no_medrec']], ['Affiliasi', $header['affiliasi']], ['Departemen / NPK', $header['departemen_npk']] ]; $rightRows = [ ['Nama Pasien', $header['nama_pasien']], ['Jenis Kelamin', $header['jenis_kelamin']], ['Tgl Lahir / Usia', $header['tgl_lahir_usia']], ['Alamat Pasien', $header['alamat_pasien']] ]; $maxRows = max(count($leftRows), count($rightRows)); for ($i = 0; $i < $maxRows; $i++) { $l = isset($leftRows[$i]) ? $leftRows[$i] : ['', '']; $r = isset($rightRows[$i]) ? $rightRows[$i] : ['', '']; $y = $pdf->GetY(); $pdf->SetX($left); $pdf->SetFont('Times', '', 9); $pdf->Cell($leftLabelW, 5, $this->safe_text($l[0]), 0, 0, 'L'); $pdf->Cell($colonW, 5, ':', 0, 0, 'C'); $pdf->Cell($leftValueW, 5, $this->safe_text($l[1]), 0, 0, 'L'); $pdf->SetXY($left + $leftLabelW + $colonW + $leftValueW + 12, $y); $pdf->Cell($rightLabelW, 5, $this->safe_text($r[0]), 0, 0, 'L'); $pdf->Cell($colonW, 5, ':', 0, 0, 'C'); if ($r[0] === 'Alamat Pasien') { $pdf->SetFont('Times', '', 9); $pdf->MultiCell($rightValueW, 5, $this->safe_text($r[1]), 0, 'L'); } else { $fontStyle = ($r[0] === 'Nama Pasien') ? 'B' : ''; $pdf->SetFont('Times', $fontStyle, 9); $pdf->Cell($rightValueW, 5, $this->safe_text($r[1]), 0, 1, 'L'); } } $pdf->Ln(4); $lineY = $pdf->GetY(); $pdf->Line($left, $lineY, $pageW - $right, $lineY); $pdf->SetY($lineY + 3); $pdf->SetFont('Times', 'B', 10); $pdf->Cell(0, 6, 'PEMERIKSAAN', 0, 1, 'L'); $lineY2 = $pdf->GetY(); $pdf->Line($left, $lineY2, $pageW - $right, $lineY2); $pdf->Ln(4); $this->render_result_rows($pdf, $rows, $saran); header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="medical_checkup_report_' . $orderHeaderId . '.pdf"'); echo $pdf->Output('S'); } catch (Exception $exc) { $this->sys_error($exc->getMessage()); } } private function get_header_data($orderHeaderId) { $sql = "SELECT DATE_FORMAT(h.T_OrderHeaderDate, '%d-%m-%Y') AS tgl_registrasi, IFNULL(h.T_OrderHeaderLabNumber, '-') AS no_lab, IFNULL(p.M_PatientNoReg, '-') AS no_medrec, IFNULL(c.M_CompanyName, '-') AS affiliasi, IFNULL( NULLIF(TRIM(IFNULL(p.M_PatientDepartement, '')), ''), IFNULL(NULLIF(TRIM(IFNULL(p.M_PatientDivisi, '')), ''), '-') ) AS departemen_npk, IFNULL(s.M_SexName, '-') AS jenis_kelamin, CONCAT( IF(TRIM(IFNULL(t.M_TitleName, '')) = '', '', CONCAT(TRIM(t.M_TitleName), '. ')), TRIM(IFNULL(p.M_PatientPrefix, '')), ' ', TRIM(IFNULL(p.M_PatientName, '')), ' ', TRIM(IFNULL(p.M_PatientSuffix, '')) ) AS nama_pasien, CONCAT( IFNULL(DATE_FORMAT(p.M_PatientDOB, '%d-%m-%Y'), '-'), ' / ', IFNULL(NULLIF(TRIM(IFNULL(h.T_OrderHeaderM_PatientAge, '')), ''), '-') ) AS tgl_lahir_usia, IFNULL(pa.M_PatientAddressDescription, '-') AS alamat_pasien FROM t_orderheader h JOIN m_patient p ON p.M_PatientID = h.T_OrderHeaderM_PatientID LEFT JOIN m_title t ON t.M_TitleID = p.M_PatientM_TitleID LEFT JOIN m_company c ON c.M_CompanyID = h.T_OrderHeaderM_CompanyID LEFT JOIN m_sex s ON s.M_SexID = p.M_PatientM_SexID LEFT JOIN m_patientaddress pa ON pa.M_PatientAddressM_PatientID = p.M_PatientID AND pa.M_PatientAddressNote = 'Utama' AND pa.M_PatientAddressIsActive = 'Y' WHERE h.T_OrderHeaderID = ? LIMIT 1"; $qry = $this->db_onedev->query($sql, [$orderHeaderId]); if (!$qry) { return false; } return $qry->row_array(); } private function get_result_rows($orderHeaderId) { $sql = "SELECT r.ResultFisikUmumType AS type, IFNULL(a.Result_FisikAliasLabelName, r.ResultFisikUmumLabel) AS label_name, IFNULL(r.ResultFisikUmumValue, '') AS value FROM result_fisik_umum r LEFT JOIN result_fisikaliaslabel a ON a.Result_FisikAliasLabelCode = r.ResultFisikUmumLabel AND a.Result_FisikAliasLabelIsActive = 'Y' WHERE r.ResultFisikUmumT_OrderHeaderID = ? AND r.ResultFisikUmumIsActive = 'Y' AND IFNULL(r.ResultFisikUmumValue, '') <> 'Err' AND IFNULL(r.ResultFisikUmumValue, '') <> '' ORDER BY r.ResultFisikUmumID"; $qry = $this->db_onedev->query($sql, [$orderHeaderId]); if (!$qry) { return []; } return $qry->result_array(); } private function get_default_branch() { $sql = "SELECT IFNULL(M_BranchAddress, '-') AS branch_address FROM m_branch WHERE M_BranchIsDefault = 'Y' AND M_BranchIsActive = 'Y' LIMIT 1"; $qry = $this->db_onedev->query($sql); if (!$qry || !$qry->row_array()) { return ['branch_address' => '-']; } return $qry->row_array(); } private function get_saran($orderHeaderId) { $sql = "SELECT IFNULL(So_ResultEntryFisikUmumAdditionalValue, '') AS saran FROM so_resultentry_fisik_umum_additional WHERE So_ResultEntryFisikUmumAdditionalT_OrderHeaderID = ? AND So_ResultEntryFisikUmumAdditionalType = 'saran' AND So_ResultEntryFisikUmumAdditionalIsActive = 'Y' ORDER BY So_ResultEntryFisikUmumAdditionalID DESC LIMIT 1"; $qry = $this->db_onedev->query($sql, [$orderHeaderId]); if (!$qry) { return ''; } $row = $qry->row_array(); if (!$row) { return ''; } return trim((string)$row['saran']); } private function render_result_rows($pdf, $rows, $saran = '') { $left = 14; $labelW = 55; $valueW = $pdf->GetPageWidth() - $left - 14 - $labelW; $lineH = 6; $detailIndent = 6; $normalRows = []; $k3Rows = []; foreach ($rows as $row) { if (strtoupper((string)$row['type']) === 'K3') { $k3Rows[] = $row; } else { $normalRows[] = $row; } } // Gabungkan tekanan darah: sistole/diastole mmHg () $tdIndex = null; $tdSistole = null; $tdDiastole = null; $tdKesimpulan = null; $tdStandart = null; $skipIndex = []; foreach ($normalRows as $i => $row) { $labelKey = $this->normalize_label($row['label_name']); $val = trim((string)$row['value']); if ($labelKey === 'tekanan darah' && $tdIndex === null) { $tdIndex = $i; continue; } if ($labelKey === 'sistole') { $tdSistole = $val; $skipIndex[$i] = true; if ($tdIndex === null) $tdIndex = $i; continue; } if ($labelKey === 'diastole') { $tdDiastole = $val; $skipIndex[$i] = true; if ($tdIndex === null) $tdIndex = $i; continue; } if ($labelKey === 'kesimpulan tensi') { $tdKesimpulan = $val; $skipIndex[$i] = true; if ($tdIndex === null) $tdIndex = $i; continue; } if ($labelKey === 'standart tensi' || $labelKey === 'standar tensi') { $tdStandart = $val; $skipIndex[$i] = true; if ($tdIndex === null) $tdIndex = $i; continue; } } $tekananDarahValue = ''; if ($tdSistole !== null || $tdDiastole !== null || $tdKesimpulan !== null || $tdStandart !== null) { $sd = trim((string)$tdSistole) . '/' . trim((string)$tdDiastole); $sd = trim($sd, '/'); if ($sd !== '') { $tekananDarahValue = $sd . ' mmHg'; } if (trim((string)$tdKesimpulan) !== '') { $tekananDarahValue .= ($tekananDarahValue === '' ? '' : ' ') . trim((string)$tdKesimpulan); } if (trim((string)$tdStandart) !== '') { $tekananDarahValue .= ' (' . trim((string)$tdStandart) . ')'; } $tekananDarahValue = trim($tekananDarahValue); } $pdf->SetFont('Times', '', 10); $printedSections = []; $doctorValue = ''; $dedupeKeys = [ 'refleks fisiologis', 'refleks pathologis', 'refleks neurologis lainnya' ]; $seenLabelValue = []; $bulletKeys = [ 'riwayat bahaya ling. kerja', 'riwayat bahaya ling kerja', 'riwayat kecelakaan kerja', 'ayah', 'ibu', 'telinga', 'hidung', 'tenggorokan', 'dada', 'jantung', 'paru', 'abdomen', 'ginjal', 'lingkar perut', 'lingkar pinggang', 'lingkar pinggang / panggul' ]; foreach ($normalRows as $i => $row) { if (isset($skipIndex[$i])) { continue; } $label = trim((string)$row['label_name']); $value = trim((string)$row['value']); $labelKey = $this->normalize_label($label); if ($tdIndex !== null && $i === $tdIndex && $tekananDarahValue !== '') { $label = 'Tekanan Darah'; $value = $tekananDarahValue; $labelKey = 'tekanan darah'; } if ($value === '' || strtoupper($value) === 'ERR') { continue; } if ($labelKey === 'dokter pemeriksa') { if ($doctorValue === '') { $doctorValue = $value; } continue; } if (in_array($labelKey, $dedupeKeys, true)) { $dedupeSig = $labelKey . '|' . strtolower($value); if (isset($seenLabelValue[$dedupeSig])) { continue; } $seenLabelValue[$dedupeSig] = true; } if (in_array($labelKey, ['riwayat bahaya ling. kerja', 'riwayat bahaya ling kerja', 'riwayat kecelakaan kerja'], true)) { if (!isset($printedSections['riwayat_pekerjaan'])) { $this->ensure_space($pdf, $lineH * 3); $pdf->SetFont('Times', '', 10); $pdf->SetX($left); $pdf->Cell(0, $lineH, 'Riwayat Pekerjaan', 0, 1, 'L'); $printedSections['riwayat_pekerjaan'] = true; } } if (in_array($labelKey, ['ayah', 'ibu'], true)) { if (!isset($printedSections['riwayat_penyakit_keluarga'])) { $this->ensure_space($pdf, $lineH * 3); $pdf->SetFont('Times', '', 10); $pdf->SetX($left); $pdf->Cell(0, $lineH, 'Riwayat Penyakit Keluarga', 0, 1, 'L'); $printedSections['riwayat_penyakit_keluarga'] = true; } } if (in_array($labelKey, ['telinga', 'hidung', 'tenggorokan'], true)) { if (!isset($printedSections['tht'])) { $this->ensure_space($pdf, $lineH * 3); $pdf->SetFont('Times', 'B', 10); $pdf->SetX($left); $pdf->Cell(0, $lineH, 'Telinga Hidung Tenggorokan', 0, 1, 'L'); $printedSections['tht'] = true; } } if (in_array($labelKey, ['dada', 'jantung', 'paru'], true)) { if (!isset($printedSections['toraks'])) { $this->ensure_space($pdf, $lineH * 3); $pdf->SetFont('Times', 'B', 10); $pdf->SetX($left); $pdf->Cell(0, $lineH, 'Toraks', 0, 1, 'L'); $printedSections['toraks'] = true; } } if (in_array($labelKey, ['abdomen', 'ginjal', 'lingkar perut', 'lingkar pinggang', 'lingkar pinggang / panggul'], true)) { if (!isset($printedSections['abdomen'])) { $this->ensure_space($pdf, $lineH * 3); $pdf->SetFont('Times', 'B', 10); $pdf->SetX($left); $pdf->Cell(0, $lineH, 'Abdomen', 0, 1, 'L'); $printedSections['abdomen'] = true; } } $renderLabel = $label; $rowLeft = $left; $valueX = $left + $labelW; if (in_array($labelKey, $bulletKeys, true)) { $renderLabel = '• ' . $label; $rowLeft = $left + $detailIndent; } $y = $pdf->GetY(); $pdf->SetX($rowLeft); $isBoldLabel = in_array($labelKey, ['rongga mulut dan gigi', 'anogenital'], true); $pdf->SetFont('Times', $isBoldLabel ? 'B' : '', 10); $pdf->Cell($labelW, $lineH, $this->safe_text($renderLabel), 0, 0, 'L'); $pdf->SetXY($valueX, $y); $pdf->SetFont('Times', '', 10); $pdf->MultiCell($valueW, $lineH, $this->safe_text($value), 0, 'L'); } $k3ValidRows = []; foreach ($k3Rows as $row) { $value = trim((string)$row['value']); if ($value === '' || strtoupper($value) === 'ERR') { continue; } $k3ValidRows[] = $row; } if (count($k3ValidRows) > 0) { $pdf->Ln(2); $this->ensure_space($pdf, $lineH * 4); $pdf->SetFont('Times', 'B', 10); $pdf->SetX($left); $pdf->Cell(0, 6, 'Faktor pajanan', 0, 1, 'L'); foreach ($k3ValidRows as $row) { $label = trim((string)$row['label_name']); $value = trim((string)$row['value']); $y = $pdf->GetY(); $pdf->SetX($left + $detailIndent); $pdf->SetFont('Times', '', 10); $pdf->Cell($labelW, $lineH, $this->safe_text('• ' . $label), 0, 0, 'L'); // Keep value column aligned with the main report value column. $pdf->SetXY($left + $labelW, $y); $pdf->SetFont('Times', '', 10); $pdf->MultiCell($valueW, $lineH, $this->safe_text($value), 0, 'L'); } } if (trim((string)$saran) !== '') { $pdf->Ln(2); $y = $pdf->GetY(); $pdf->SetX($left); $pdf->SetFont('Times', 'B', 10); $pdf->Cell($labelW, $lineH, $this->safe_text('Saran'), 0, 0, 'L'); $pdf->SetXY($left + $labelW, $y); $pdf->SetFont('Times', '', 10); $pdf->MultiCell($valueW, $lineH, $this->safe_text($saran), 0, 'L'); } if ($doctorValue !== '') { $pdf->Ln(2); $y = $pdf->GetY(); $pdf->SetX($left); $pdf->SetFont('Times', 'B', 10); $pdf->Cell($labelW, $lineH, $this->safe_text('Dokter Pemeriksa'), 0, 0, 'L'); $pdf->SetXY($left + $labelW, $y); $pdf->SetFont('Times', '', 10); $pdf->MultiCell($valueW, $lineH, $this->safe_text($doctorValue), 0, 'L'); } } private function normalize_label($text) { $text = strtolower(trim((string)$text)); $text = preg_replace('/\s+/', ' ', $text); return $text; } private function ensure_space($pdf, $neededHeight) { $bottomMargin = 22; // sync with SetAutoPageBreak(true, 22) $available = $pdf->GetPageHeight() - $bottomMargin - $pdf->GetY(); if ($available < $neededHeight) { $pdf->AddPage(); // Samakan jarak awal konten di halaman lanjutan. $pdf->SetY(35); } } private function safe_text($text) { $text = (string)$text; if ($text === '') { return ''; } return iconv('UTF-8', 'windows-1252//TRANSLIT//IGNORE', $text); } }