Files
BE_IBL/application/controllers/tools/Kartu_kontrol.php
sas.fajri 5c9daffb38 FHM31052601IBL - FPDF controllers: decrypt PII via Ibl_patient_decrypt library
- Ibl_patient_decrypt: helper populate/delete patient_print_cache + decrypt_row
- Inform_consent, Medical_checkup_report: decrypt langsung dari _enc (direct SQL)
- Kartu_kontrol, Rpt_t_002, Rpt_t_002_eng: populate cache sebelum call SP,
  delete cache setelah SP selesai

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 17:49:45 +07:00

205 lines
6.9 KiB
PHP

<?php
defined('BASEPATH') or exit('No direct script access allowed');
class Kartu_kontrol extends MY_Controller
{
private $mediaBase = '/home/one/project/one';
public function __construct()
{
parent::__construct();
$this->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=<id>&username=<name>']);
}
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);
}
}