db_lab = $this->load->database('onedev', true); $this->load->library('ibl_patient_decrypt'); } public function index() { $this->sys_ok(['message' => 'Use /tools/kartu_kontrol/pdf?PID=&username=']); } public function pdf() { try { $pid = intval($this->input->get('PID', true)); $username = trim((string) $this->input->get('username', true)); if ($pid <= 0) { $this->sys_error('PID mandatory'); return; } $rows = $this->get_data($pid); if (empty($rows)) { $this->sys_error('Data not found for PID ' . $pid); return; } $first = $rows[0]; $printDate = date('M j, Y g:i A'); require_once APPPATH . 'third_party/fpdf/fpdf.php'; $pdf = new FPDF('P', 'mm', 'A4'); $pdf->SetAutoPageBreak(false); $pdf->SetMargins(10, 35, 10); $pdf->AddPage(); $this->render_page($pdf, $first, $rows, $username, $printDate); header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="kartu_kontrol_' . $pid . '.pdf"'); echo $pdf->Output('S'); } catch (Exception $e) { $this->sys_error($e->getMessage()); } } private function get_data($pid) { // Populate decrypt cache sebelum call SP $cache_id = $this->ibl_patient_decrypt->populate_cache_by_order($pid); $qry = $this->db_lab->query("CALL sp_rpt_fo_001(?, 'fpdf')", [$pid]); // Hapus cache setelah SP selesai $this->ibl_patient_decrypt->delete_cache($cache_id); if (!$qry) return []; return $qry->result_array(); } private function render_page($pdf, $first, $rows, $printBy, $printDate) { $formRev = $first['form_rev'] ?: 'YAN.01-FRM-CR-01.1/04'; $pageW = 190; // usable width (210 - 20 margin) $photoW = 25; $photoH = 30; $photoX = 10 + $pageW - $photoW; // right-aligned $topY = 35; // 3.5cm top margin — space for pre-printed logo header // --- Header --- $pdf->SetFont('Arial', 'B', 12); $pdf->SetXY(10, $topY); $pdf->Cell($pageW - 70, 8, 'KARTU KONTROL PELAYANAN', 0, 0, 'L'); $pdf->SetFont('Arial', '', 8); $pdf->Cell(70, 8, $this->s($formRev), 0, 1, 'R'); // --- Photo (right side, below form rev) --- $photoY = $topY + 10; $photoPath = $this->resolve_photo($first['Photo']); if ($photoPath !== null) { $pdf->Image($photoPath, $photoX, $photoY, $photoW, $photoH); } else { $pdf->SetDrawColor(180, 180, 180); $pdf->Rect($photoX, $photoY, $photoW, $photoH); } // --- Patient Info --- $infoY = $topY + 10; $infoW = $pageW - $photoW - 5; $lblW = 38; $sepW = 5; $valW = $infoW - $lblW - $sepW; $rowH = 7; $fields = [ ['Nama Pasien', $this->s($first['M_PatientName'])], ['Umur / Jns Kelamin', $first['M_PatientDOB']], ['PID/No. Reg', $first['PIiiD']], ['Pengirim', $this->s($first['M_CompanyName'] ?? '')], ['Kel. Pelanggan', $this->s($first['Nat_BahanName'] ?? '')], ['Tanggal', $first['noreg']], ['Perkiraan Hasil', $this->s($first['M_PatientAddressDescription'] ?? '')], ]; $pdf->SetFont('Arial', '', 9); foreach ($fields as $f) { $pdf->SetXY(10, $infoY); $pdf->Cell($lblW, $rowH, $this->s($f[0]), 0, 0, 'L'); $pdf->Cell($sepW, $rowH, ':', 0, 0, 'C'); $pdf->Cell($valW, $rowH, $this->s($f[1]), 0, 1, 'L'); $infoY += $rowH; } // --- Test Table --- $tableY = max($infoY + 3, $photoY + $photoH + 3); $col1W = 90; $col2W = 50; $col3W = $pageW - $col1W - $col2W; $thH = 7; $pdf->SetXY(10, $tableY); $pdf->SetFont('Arial', 'B', 9); $pdf->SetFillColor(220, 220, 220); $pdf->Cell($col1W, $thH, 'JENIS PEMERIKSAAN', 1, 0, 'C', true); $pdf->Cell($col2W, $thH, 'PETUGAS', 1, 0, 'C', true); $pdf->Cell($col3W, $thH, 'CATATAN', 1, 1, 'C', true); $pdf->SetFont('Arial', '', 9); foreach ($rows as $row) { $pdf->SetX(10); $pdf->Cell($col1W, $thH, $this->s($row['Nat_BahanCode']), 1, 0, 'L'); $pdf->Cell($col2W, $thH, '', 1, 0, 'L'); $pdf->Cell($col3W, $thH, '', 1, 1, 'L'); } // --- Consent Section --- $consentY = $pdf->GetY() + 4; $pdf->SetXY(10, $consentY); $pdf->SetFont('Arial', '', 9); $pdf->Cell(0, 6, 'Catatan :', 0, 1, 'L'); $consentText = 'Dengan ini saya menyatakan bahwa informasi yang saya berikan adalah benar ,' . 'dan saya memahami serta menyetujui tindakan medis yang dilakukan oleh Lab. IBL ' . 'untuk menunjang pemeriksaan saya'; $consentY = $pdf->GetY(); $pdf->SetXY(10, $consentY); $pdf->SetFont('Arial', '', 8); $pdf->MultiCell(100, 5, $this->s($consentText), 0, 'L'); $pdf->SetFont('Arial', 'B', 9); $pdf->SetXY(130, $consentY); $pdf->Cell(70, 5, 'TTD', 0, 1, 'C'); $afterConsent = $pdf->GetY() + 18; $pdf->SetXY(130, $afterConsent); $pdf->SetFont('Arial', '', 9); $pdf->Cell(70, 5, $this->s($first['PIiiD']), 0, 1, 'C'); // --- Page Footer --- $footerY = 286; $pdf->SetFont('Times', '', 7); $pdf->SetXY(10, $footerY); $pdf->Cell(60, 4, 'Print Oleh : ' . $this->s($printBy), 0, 0, 'L'); $pdf->SetXY(85, $footerY); $pdf->Cell(20, 4, '1', 0, 0, 'C'); $pdf->Cell(5, 4, '/', 0, 0, 'C'); $pdf->Cell(20, 4, '1', 0, 0, 'C'); $pdf->SetXY(130, $footerY); $pdf->Cell(70, 4, $printDate, 0, 1, 'R'); } private function resolve_photo($photoUrl) { $url = trim((string) $photoUrl); if ($url === '') { return null; } // SP returns file:///home/one/project/one/... — strip file:// to get absolute path if (strpos($url, 'file://') === 0) { $abs = substr($url, 7); return is_file($abs) ? $abs : null; } // fallback: prepend mediaBase for relative paths $abs = $this->mediaBase . '/' . ltrim($url, '/'); return is_file($abs) ? $abs : null; } private function s($text) { return iconv('UTF-8', 'windows-1252//TRANSLIT', (string) $text); } }