AddFont('Arial_Narrow', '', 'Arial_Narrow.php'); // regular $this->AddFont('Arial_Narrow', 'B', 'Arial_Narrow_B.php'); // bold (Liberation Sans Narrow Bold) } public function Footer() { $pageW = $this->GetPageWidth() - 30; // sama dengan margin 15+15 // ── Posisi: 20mm dari bawah halaman ────────────────────────────────── $this->SetY(-20); // ── Baris 1: Print Oleh (kiri) | Nomor Halaman (tengah) ─────────────── $colSide = ($pageW - 40) / 2; $colCenter = 40; $this->SetFont('Arial_Narrow', '', 7); $this->Cell($colSide, 4, 'Print Oleh : ' . $this->printUsername, 0, 0, 'L'); $this->Cell($colCenter, 4, $this->PageNo() . ' / {nb}', 0, 0, 'C'); $this->Cell($colSide, 4, '', 0, 1, 'R'); // ── Baris 2: Tgl Print (kiri) ────────────────────────────────────────── $this->SetFont('Arial_Narrow', '', 7); $this->Cell($colSide, 4, 'Tgl Print : ' . $this->printDate, 0, 0, 'L'); $this->Cell($colCenter + $colSide, 4, '', 0, 1, 'L'); } } // ============================================================================= // Controller // ============================================================================= class Rpt_pr_direct extends MY_Controller { // ── Properti bersama antar fungsi PDF ───────────────────────────────────── /** @var PrdFpdf */ private $_pdf; private $_pageW; private $_header_data; private $_username; public function __construct() { parent::__construct(); } public function index() { echo "Purchase Request Direct Report API"; } // ========================================================================= // ENDPOINT: pdf // GET/POST: id (PurchaseRequestDirectID), username (opsional) // ========================================================================= public function pdf() { try { $id = intval($this->input->get_post('id')); $username = trim($this->input->get_post('username') ?? ''); if ($id <= 0) { $this->sys_error("ID tidak valid"); exit; } // ── Ambil data header & detail dari DB ──────────────────────────── $header = $this->_get_header($id); $details = $this->_get_detail($id); // ── Inisialisasi FPDF custom ────────────────────────────────────── $this->_pdf = new PrdFpdf('P', 'mm', 'A4'); $this->_pdf->printUsername = $username !== '' ? $username : '-'; $this->_pdf->printDate = date('d-m-Y H:i:s'); $this->_pageW = $this->_pdf->GetPageWidth() - 30; $this->_header_data = $header; $this->_username = $this->_pdf->printUsername; $this->_pdf->AliasNbPages(); // aktifkan alias total halaman $this->_pdf->SetMargins(15, 15, 15); $this->_pdf->SetAutoPageBreak(true, 22); // 22mm ruang footer di bawah $this->_pdf->AddPage(); // ── Susun isi halaman ───────────────────────────────────────────── $this->_pdf_header(); $this->_pdf_data($details); $this->_pdf_terms(); // ── Output ──────────────────────────────────────────────────────── $filename = 'PRD_' . str_replace('/', '-', $header['PurchaseRequestDirectNumber']) . '.pdf'; header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="' . $filename . '"'); header('Cache-Control: private, max-age=0, must-revalidate'); header('Pragma: public'); echo $this->_pdf->Output('S'); } catch (Exception $exc) { $this->sys_error($exc->getMessage()); } } // ========================================================================= // DATABASE: Ambil data header // ========================================================================= private function _get_header($id) { $sql = " SELECT prd.*, b.M_BranchName, b.M_BranchAddress, r.S_RegionalName, IFNULL(u.M_UserUsername,'') AS CreatedByName, IFNULL(ua.M_UserUsername,'') AS ApprovedByName FROM purchase_request_direct prd LEFT JOIN m_branch b ON b.M_BranchCode = prd.PurchaseRequestDirectM_BranchCode LEFT JOIN s_regional r ON r.S_RegionalID = prd.PurchaseRequestDirectS_RegionalID LEFT JOIN m_user u ON u.M_UserID = prd.PurchaseRequestCreatedUserID LEFT JOIN m_user ua ON ua.M_UserID = prd.PurchaseRequestDirectApprovedBy WHERE prd.PurchaseRequestDirectID = ? LIMIT 1 "; $qry = $this->db->query($sql, array($id)); if (!$qry || $qry->num_rows() === 0) { $this->sys_error("Data Purchase Request Direct tidak ditemukan"); exit; } return $qry->row_array(); } // ========================================================================= // DATABASE: Ambil data detail // ========================================================================= private function _get_detail($id) { $sql = " SELECT prdd.*, iu.ItemUnitName, iu.ItemUnitCode, pdc.PurchaseDirectCategoryName FROM purchase_request_direct_detail prdd LEFT JOIN itemunit iu ON iu.ItemUnitID = prdd.PurchaseRequestDirectDetailItemUnitID LEFT JOIN purchase_direct_category pdc ON pdc.PurchaseDirectCategoryID = prdd.PurchaseRequestDirectDetailPurchaseRequestDirectCategoryID WHERE prdd.PurchaseRequestDirectDetailPurchaseRequestDirectID = ? AND prdd.PurchaseRequestDirectDetailIsActive = 'Y' ORDER BY prdd.PurchaseRequestDirectDetailID ASC "; $qry = $this->db->query($sql, array($id)); return $qry ? $qry->result_array() : array(); } // ========================================================================= // PDF SECTION: Header — Judul + Informasi Dokumen (2 kolom) // ========================================================================= private function _pdf_header() { $pdf = $this->_pdf; $pageW = $this->_pageW; $header = $this->_header_data; // ── Judul utama ─────────────────────────────────────────────────────── $pdf->SetFont('Arial_Narrow', 'B', 14); $pdf->Cell($pageW, 8, 'PURCHASE REQUEST DIRECT (PRD)', 0, 1, 'L'); $pdf->SetDrawColor(0, 0, 0); $pdf->SetLineWidth(0.5); $pdf->Line(15, $pdf->GetY(), 15 + $pageW, $pdf->GetY()); $pdf->Ln(2); // ── Info dokumen: 2 kolom (kiri & kanan) ───────────────────────────── $half = $pageW / 2; $lbl = 30; $val = $half - $lbl - 4; $left = array( array('Nomor', $header['PurchaseRequestDirectNumber']), array('Tanggal', $this->_fmt_date($header['PurchaseRequestDirectDate'])), array('Tanggal Pelaksanaan', $this->_fmt_date($header['PurchaseRequestDirectDateUse'])), array('Status', $header['PurchaseRequestDirectStatus']), ); $right = array( array('Cabang', $header['M_BranchName']), array('Regional', $header['S_RegionalName']), array('Alamat', $header['M_BranchAddress']), ); $maxRow = max(count($left), count($right)); for ($i = 0; $i < $maxRow; $i++) { // kolom kiri if (isset($left[$i])) { $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lbl, 5, $left[$i][0], 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); if ($left[$i][0] === 'Nomor') { $pdf->SetFont('Arial_Narrow', 'B', 9); } else { $pdf->SetFont('Arial_Narrow', '', 9); } $pdf->Cell($val, 5, $left[$i][1], 0, 0, 'L'); } else { $pdf->Cell($half, 5, '', 0, 0); } // kolom kanan if (isset($right[$i])) { $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lbl, 5, $right[$i][0], 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($val, 5, $right[$i][1], 0, 1, 'L'); } else { $pdf->Cell($half, 5, '', 0, 1); } } // Keterangan & Catatan (full width) if (!empty($header['PurchaseRequestDirectDescription'])) { $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lbl, 5, 'Keterangan', 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); $pdf->Cell($pageW - $lbl - 4, 5, $header['PurchaseRequestDirectDescription'], 0, 1, 'L'); } if (!empty($header['PurchaseRequestDirectNote'])) { $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lbl, 5, 'Catatan', 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); $pdf->Cell($pageW - $lbl - 4, 5, $header['PurchaseRequestDirectNote'], 0, 1, 'L'); } $pdf->Ln(4); } // ========================================================================= // PDF SECTION: Data — Tabel detail item + ringkasan nilai // ========================================================================= private function _pdf_data($details) { $pdf = $this->_pdf; $pageW = $this->_pageW; $header = $this->_header_data; // ── Definisi kolom: [label, lebar, align] ───────────────────────────── // Total lebar = 180mm (A4 portrait: 210 - margin 15 kiri - 15 kanan) // 8 + 42 + 25 + 15 + 17 + 18 + 28 + 27 = 180 $cols = array( array('No', 8, 'C'), array('Nama', 42, 'L'), array('Kategori', 25, 'L'), array('Unit', 15, 'C'), array('Qty Request', 17, 'R'), array('Qty Disetujui', 18, 'R'), array('Harga', 28, 'R'), array('Total', 27, 'R'), ); // Header kolom $pdf->SetLineWidth(0.3); // border medium $pdf->SetFont('Arial_Narrow', 'B', 8); $pdf->SetFillColor(220, 220, 220); $pdf->SetDrawColor(0, 0, 0); foreach ($cols as $c) { $pdf->Cell($c[1], 7, $c[0], 1, 0, 'C', true); } $pdf->Ln(); // Baris data $pdf->SetLineWidth(0.2); // border lebih tipis di data $pdf->SetFont('Arial_Narrow', '', 8); $pdf->SetFillColor(255, 255, 255); $no = 1; $total_est = 0; foreach ($details as $d) { $pdf->Cell($cols[0][1], 6, $no, 1, 0, 'C'); $pdf->Cell($cols[1][1], 6, $d['PurchaseRequestDirectDescription'] ?: $d['ItemUnitName'], 1, 0, 'L'); $pdf->Cell($cols[2][1], 6, $d['PurchaseDirectCategoryName'] ?: '-', 1, 0, 'L'); $pdf->Cell($cols[3][1], 6, $d['ItemUnitName'], 1, 0, 'C'); $pdf->Cell($cols[4][1], 6, $this->_fmt_qty($d['PurchaseRequestDirectDetailAmountRequest']), 1, 0, 'R'); $pdf->Cell($cols[5][1], 6, $this->_fmt_qty($d['PurchaseRequestDirectDetailAmount']), 1, 0, 'R'); $pdf->Cell($cols[6][1], 6, $this->_fmt_rp($d['PurchaseRequestDirectDetailEstimationPrice']), 1, 0, 'R'); $pdf->Cell($cols[7][1], 6, $this->_fmt_rp($d['PurchaseRequestDirectDetailTotalEstimationPrice']), 1, 0, 'R'); $pdf->Ln(); $total_est += floatval($d['PurchaseRequestDirectDetailTotalEstimationPrice']); $no++; } // Baris TOTAL $span = array_sum(array_column(array_slice($cols, 0, 7), 1)); $pdf->SetLineWidth(0.3); $pdf->SetFont('Arial_Narrow', 'B', 9); // bold + size 9 agar menonjol $pdf->SetFillColor(220, 220, 220); $pdf->Cell($span, 7, 'TOTAL', 1, 0, 'R', true); $pdf->Cell($cols[7][1], 7, $this->_fmt_rp($total_est), 1, 0, 'R', true); $pdf->Ln(); // ── Ringkasan nilai (rata kanan) ────────────────────────────────────── $pdf->Ln(4); $summary = array( array('Total Estimasi', $this->_fmt_rp($header['PurchaseRequestDirectTotalEstimation'])), array('Adjustment', $this->_fmt_rp($header['PurchaseRequestDirectAdjustment'])), array('Total Realisasi', $this->_fmt_rp($header['PurchaseRequestDirectTotalRealitation'])), array('Total Pembayaran', $this->_fmt_rp($header['PurchaseRequestDirectTotalPaid'])), ); $cW1 = 50; $cW2 = 40; $offsetX = 15 + $pageW - $cW1 - $cW2; foreach ($summary as $s) { $pdf->SetX($offsetX); $pdf->SetFont('Arial_Narrow', '', 8); $pdf->Cell($cW1, 5, $s[0], 0, 0, 'L'); $pdf->SetFont('Arial_Narrow', 'B', 8); $pdf->Cell($cW2, 5, $s[1], 0, 1, 'R'); } $pdf->Ln(4); } // ========================================================================= // PDF SECTION: Syarat & Ketentuan // ========================================================================= private function _pdf_terms() { $pdf = $this->_pdf; $pageW = $this->_pageW; $terms = array( 'Pengajuan pembelian ini harus mendapatkan persetujuan dari pejabat berwenang sebelum proses pembelian dilakukan.', 'Barang/jasa yang dibeli harus sesuai dengan spesifikasi dan kebutuhan yang tercantum dalam dokumen ini.', 'Pembayaran dilakukan setelah barang/jasa diterima dan diverifikasi sesuai pesanan.', 'Dokumen ini bersifat internal dan hanya digunakan untuk keperluan proses pengadaan.', ); $pdf->SetFont('Arial_Narrow', 'B', 9); $pdf->Cell($pageW, 5, 'Syarat & Ketentuan:', 0, 1, 'L'); $pdf->SetFont('Arial_Narrow', '', 8); foreach ($terms as $i => $t) { $pdf->Cell(6, 5, ($i + 1) . '.', 0, 0, 'R'); $pdf->Cell($pageW - 6, 5, $t, 0, 1, 'L'); } } // ========================================================================= // HELPER: Format tampilan // ========================================================================= private function _fmt_date($d) { if (!$d || $d === '0000-00-00') return '-'; return date('d-m-Y', strtotime($d)); } private function _fmt_datetime($d) { if (!$d || $d === '0000-00-00 00:00:00') return '-'; return date('d-m-Y H:i', strtotime($d)); } private function _fmt_num($n) { return number_format(floatval($n), 2, ',', '.'); } // format jumlah/qty: tanpa desimal private function _fmt_qty($n) { return number_format(floatval($n), 0, ',', '.'); } private function _fmt_rp($n) { return 'Rp ' . number_format(floatval($n), 2, ',', '.'); } }