Add Kartu Kontrol Pelayanan FPDF report endpoint
Replaces BIRT rpt_fo_001 which had unresolvable image loading issues. FPDF-based endpoint with 3.5cm top margin for pre-printed letterhead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
198
application/controllers/tools/Kartu_kontrol.php
Normal file
198
application/controllers/tools/Kartu_kontrol.php
Normal file
@@ -0,0 +1,198 @@
|
||||
<?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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
$qry = $this->db_lab->query("CALL sp_rpt_fo_001(?, 'fpdf')", [$pid]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user