Files
BE_IBL/application/controllers/tools/Medical_checkup_report.php
2026-05-21 12:08:34 +07:00

569 lines
21 KiB
PHP

<?php
require_once APPPATH . 'third_party/fpdf/fpdf.php';
class MedicalCheckupReportPdf extends FPDF
{
public $printBy = 'ADMIN';
public $branchAddress = '-';
public $watermarkPath = '';
public function Header()
{
if ($this->watermarkPath === '' || !file_exists($this->watermarkPath)) {
return;
}
// Draw watermark background per page.
$this->Image($this->watermarkPath, 23, 102, 164, 102, '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=<id>&username=<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 <kesimpulan> (<standart_tensi>)
$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();
}
}
private function safe_text($text)
{
$text = (string)$text;
if ($text === '') {
return '';
}
return iconv('UTF-8', 'windows-1252//TRANSLIT//IGNORE', $text);
}
}