AddFont('Arial_Narrow', '', 'Arial_Narrow.php'); // regular $this->AddFont('Arial_Narrow', 'B', 'Arial_Narrow_B.php'); // bold } public function Footer() { $pageW = $this->GetPageWidth() - 30; // 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_penyerahan_mutasi extends MY_Controller { // ── Properti bersama antar fungsi PDF ───────────────────────────────────── /** @var MutasiHandoverFpdf */ private $_pdf; private $_pageW; private $_header_data; private $_username; public function __construct() { parent::__construct(); } public function index() { echo "Mutasi Handover (Penyerahan Mutasi) Report API"; } // ========================================================================= // ENDPOINT: pdf // GET/POST: id (MutasiHandoverID), 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 MutasiHandoverFpdf('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 = 'PH_' . str_replace('/', '-', $header['MutasiHandoverNumber']) . '.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 mh.*, mr.MutasiRequestNumber, ic.itemCategoryID, ic.itemCategoryName, a.M_BranchID AS branch_asal_id, a.M_BranchCode AS branch_asal_code, a.M_BranchName AS branch_asal_name, b.M_BranchID AS branch_tujuan_id, b.M_BranchCode AS branch_tujuan_code, b.M_BranchName AS branch_tujuan_name, IFNULL(u.M_UserUsername, '') AS CreatedByName, IFNULL(ur.M_UserUsername, '') AS ReceiveByName, CASE WHEN wh.WarehouseType = 'B' THEN CONCAT(wh.WarehouseCode, ' ', wh.WarehouseName, ' - ', b.M_BranchName) ELSE wh.WarehouseName END AS WarehouseName, r.M_RuanganName FROM mutasi_handover mh LEFT JOIN mutasi_request mr ON mr.MutasiRequestID = mh.MutasiHandoverMutasiRequestID JOIN item_category ic ON ic.itemCategoryID = mh.MutasiHandoverItemCategoryID AND ic.itemCategoryIsActive = 'Y' JOIN m_branch a ON a.M_BranchID = mh.MutasiHandoverFromBranchID AND a.M_BranchIsActive = 'Y' JOIN m_branch b ON b.M_BranchID = mh.MutasiHandoverToBranchID AND b.M_BranchIsActive = 'Y' LEFT JOIN m_user u ON u.M_UserID = mh.MutasiHandoverUserID LEFT JOIN m_user ur ON ur.M_UserID = mh.MutasiHandoverReceiveUserID LEFT JOIN warehouse wh ON wh.WarehouseID = mh.MutasiHandoverReceiveWarehouseID AND wh.WarehouseIsActive = 'Y' LEFT JOIN m_ruangan r ON r.M_RuanganID = mh.MutasiHandoverReceiveM_RuanganID AND r.M_RuanganIsActive = 'Y' WHERE mh.MutasiHandoverID = ? AND mh.MutasiHandoverIsActive = 'Y' LIMIT 1 "; $qry = $this->db->query($sql, array($id)); if (!$qry || $qry->num_rows() === 0) { $this->sys_error("Data Penyerahan Mutasi tidak ditemukan"); exit; } return $qry->row_array(); } // ========================================================================= // DATABASE: Ambil data detail // ========================================================================= private function _get_detail($id) { $sql = " SELECT mhd.*, i.M_ItemCode, i.M_ItemDesc, iu.ItemUnitName, iu.ItemUnitCode FROM mutasi_handover_detail mhd LEFT JOIN m_item i ON i.M_ItemID = mhd.MutasiHandoverDetailM_ItemID LEFT JOIN itemunit iu ON iu.ItemUnitID = mhd.MutasiHandoverDetailItemUnitID WHERE mhd.MutasiHandoverDetailMutasiHandoverID = ? AND mhd.MutasiHandoverDetailIsActive = 'Y' ORDER BY mhd.MutasiHandoverDetailID 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, 'PENYERAHAN MUTASI (HANDOVER)', 0, 1, 'L'); $pdf->SetDrawColor(0, 0, 0); $pdf->SetLineWidth(0.5); $pdf->Line(15, $pdf->GetY(), 15 + $pageW, $pdf->GetY()); $pdf->Ln(2); $startY = $pdf->GetY(); $halfW = $pageW / 2; $lblW = 30; $valW = $halfW - $lblW - 4; // ── Kolom Kiri ──────────────────────────────────────────────────────── $pdf->SetY($startY); $leftItems = array( array('Nomor Handover', $header['MutasiHandoverNumber'], true), array('No. Request', $header['MutasiRequestNumber'] ?: '-', false), array('Tanggal', $this->_fmt_date($header['MutasiHandoverDate']), false), array('Status', $header['MutasiHandoverStatus'], false), array('Kategori', $header['itemCategoryName'], false), ); foreach ($leftItems as $item) { $pdf->SetX(15); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lblW, 5, $item[0], 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); if ($item[2]) { $pdf->SetFont('Arial_Narrow', 'B', 9); } else { $pdf->SetFont('Arial_Narrow', '', 9); } $pdf->Cell($valW, 5, $item[1], 0, 1, 'L'); } // Keterangan (Note) langsung di bawah Status if (!empty($header['MutasiHandoverNote'])) { $pdf->SetX(15); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lblW, 5, 'Keterangan', 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); $pdf->MultiCell($valW, 5, $header['MutasiHandoverNote'], 0, 'L'); } $leftY = $pdf->GetY(); // ── Kolom Kanan ─────────────────────────────────────────────────────── $pdf->SetY($startY); $rightX = 15 + $halfW; $rightItems = array( array('Cabang Asal', $header['branch_asal_name']), array('Cabang Tujuan', $header['branch_tujuan_name']), array('Warehouse Tujuan', $header['WarehouseName'] ?: '-'), array('Ruangan Tujuan', $header['M_RuanganName'] ?: '-'), array('Dibuat Oleh', $header['CreatedByName']), ); foreach ($rightItems as $item) { $pdf->SetX($rightX); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lblW, 5, $item[0], 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($valW, 5, $item[1], 0, 1, 'L'); } // Tanggal terima di kolom kanan $pdf->SetX($rightX); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lblW, 5, 'Tgl Terima', 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($valW, 5, $this->_fmt_date($header['MutasiHandoverReceiveDate']), 0, 1, 'L'); // Penerima di kolom kanan if ($header['MutasiHandoverStatus'] === 'Received') { $pdf->SetX($rightX); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($lblW, 5, 'Diterima Oleh', 0, 0, 'L'); $pdf->Cell(4, 5, ':', 0, 0, 'C'); $pdf->SetFont('Arial_Narrow', '', 9); $pdf->Cell($valW, 5, $header['ReceiveByName'] ?: '-', 0, 1, 'L'); } $rightY = $pdf->GetY(); // Posisikan Y ke yang paling bawah + margin $pdf->SetY(max($leftY, $rightY) + 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 + 80 + 20 + 20 + 25 + 27 = 180 $cols = array( array('No', 8, 'C'), array('Nama Item', 80, 'L'), array('Unit', 20, 'C'), array('Qty', 20, 'R'), array('Nilai Buku', 25, 'R'), array('Total', 27, 'R'), ); // Header kolom $pdf->SetLineWidth(0.3); $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); $pdf->SetFont('Arial_Narrow', '', 8); $pdf->SetFillColor(255, 255, 255); $no = 1; $total_val = 0; foreach ($details as $d) { $bookValue = floatval($d['MutasiHandoverDetailBookValue'] ?? 0); $qty = floatval($d['MutasiHandoverDetailQty'] ?? 0); $lineTotal = $qty * $bookValue; $pdf->Cell($cols[0][1], 6, $no, 1, 0, 'C'); $pdf->Cell($cols[1][1], 6, $d['M_ItemDesc'] ?: ($d['M_ItemCode'] ?: '-'), 1, 0, 'L'); $pdf->Cell($cols[2][1], 6, $d['ItemUnitName'] ?: ($d['ItemUnitCode'] ?: '-'), 1, 0, 'C'); $pdf->Cell($cols[3][1], 6, $this->_fmt_qty($qty), 1, 0, 'R'); $pdf->Cell($cols[4][1], 6, $this->_fmt_rp($bookValue), 1, 0, 'R'); $pdf->Cell($cols[5][1], 6, $this->_fmt_rp($lineTotal), 1, 0, 'R'); $pdf->Ln(); $total_val += $lineTotal; $no++; } // Baris TOTAL $span = array_sum(array_column(array_slice($cols, 0, 5), 1)); $pdf->SetLineWidth(0.3); $pdf->SetFont('Arial_Narrow', 'B', 9); $pdf->SetFillColor(220, 220, 220); $pdf->Cell($span, 7, 'TOTAL', 1, 0, 'R', true); $pdf->Cell($cols[5][1], 7, $this->_fmt_rp($total_val), 1, 0, 'R', true); $pdf->Ln(); // ── Ringkasan nilai (rata kanan) ────────────────────────────────────── $pdf->Ln(3); $summary = array( array('Total Nilai Penyerahan', $this->_fmt_rp($header['MutasiHandoverTotalValue'])), ); $cW1 = 50; $cW2 = 40; $offsetX = 15 + $this->_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( 'Penyerahan mutasi ini dilakukan berdasarkan dokumen mutasi yang telah disetujui sebelumnya.', 'Barang yang diserahkan harus sesuai dengan jumlah dan spesifikasi yang tercantum dalam dokumen ini.', 'Penerima barang wajib memeriksa dan memverifikasi kesesuaian barang sebelum menerima.', 'Dokumen ini bersifat internal dan hanya digunakan untuk keperluan proses mutasi barang.', ); $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, ',', '.'); } private function _fmt_qty($n) { return number_format(floatval($n), 0, ',', '.'); } private function _fmt_rp($n) { return 'Rp ' . number_format(floatval($n), 2, ',', '.'); } }