input->get('step')?:'order';if(!in_array($step,array('order','payment','receipt','invoice'),true))$step='order'; $paymentAccounts=$this->db->where(array('is_active'=>1,'allow_posting'=>1))->group_start()->like('nama_akun','kas')->or_like('nama_akun','bank')->group_end()->order_by('kode_akun')->get('accounts')->result(); $bankChargeMapping=$this->db->get_where('system_account_mappings',array('mapping_key'=>'bank_charge_expense','is_active'=>1))->row();$bankChargeAccountId=$bankChargeMapping?(int)$bankChargeMapping->account_id:0; $bankChargeAccounts=$this->db->where(array('is_active'=>1,'allow_posting'=>1,'tipe'=>'expense'))->order_by('kode_akun')->get('accounts')->result(); $payments=$this->db->select('sp.*,po.po_no,s.name supplier_name')->from('supplier_payments sp')->join('purchase_orders po','po.id=sp.purchase_order_id','left')->join('suppliers s','s.id=sp.supplier_id')->order_by('sp.id','DESC')->limit(200)->get()->result(); $invoiceReceipts=$this->db->select('gr.*,po.po_no,s.name')->from('goods_receipts gr')->join('purchase_orders po','po.id=gr.purchase_order_id')->join('suppliers s','s.id=gr.supplier_id')->where('gr.status','posted')->where_in('po.status',array('partially_received','received'))->where("EXISTS(SELECT 1 FROM goods_receipt_lines grl WHERE grl.goods_receipt_id=gr.id AND grl.qty-COALESCE((SELECT SUM(prl.shipped_qty) FROM purchase_return_lines prl JOIN purchase_returns pr ON pr.id=prl.purchase_return_id WHERE prl.receipt_line_id=grl.id AND pr.status IN('shipped','waiting_supplier','partially_resolved','resolved')),0)>COALESCE((SELECT SUM(sil.qty) FROM supplier_invoice_lines sil WHERE sil.receipt_line_id=grl.id),0))",null,false)->order_by('gr.id','DESC')->get()->result(); $paymentItems=array();$paymentItemRows=$this->db->select('pol.purchase_order_id,pol.description,pol.qty,pol.unit_price,pol.tax_amount,pol.line_total,pol.tracking_type,k.kode_barang,k.nama nama_barang')->from('purchase_order_lines pol')->join('kode_barang k','k.id=pol.kode_barang_id','left')->order_by('pol.purchase_order_id')->order_by('pol.id')->get()->result();foreach($paymentItemRows as$paymentItem)$paymentItems[$paymentItem->purchase_order_id][]=$paymentItem; $returnBarcodes=$this->db->select('ib.id,ib.barcode,ib.serial_number,ib.qty_sisa,ib.source_receipt_line_id,pol.tracking_type')->from('item_barcodes ib')->join('goods_receipt_lines grl','grl.id=ib.source_receipt_line_id')->join('purchase_order_lines pol','pol.id=grl.po_line_id')->where('ib.qty_sisa >',0)->order_by('ib.barcode')->get()->result_array(); $budgetCompanyId=(int)$this->session->userdata('company_id');$poBudgetAccounts=$this->db->select('id,kode_akun,nama_akun')->where(array('company_id'=>$budgetCompanyId,'tipe'=>'expense','is_active'=>1,'allow_posting'=>1))->order_by('kode_akun')->get('accounts')->result_array(); function p_action($route,$id,$label,$ci,$step,$class='outline-primary'){return'
';} function p_docs($type,$id,$status=null){$ci=&get_instance();$master=$ci->session->userdata('role')==='Admin';$canReturnView=$master||check_permission('purchase_returns','can_view');$canReturnCreate=$master||check_permission('purchase_returns','can_create');$canRefundView=$master||check_permission('purchase_refunds','can_view');$canRefundCreate=$master||check_permission('purchase_refunds','can_create');$canDebitView=$master||check_permission('supplier_debit_notes','can_view');$canDebitCreate=$master||check_permission('supplier_debit_notes','can_create');$detailClass=$type==='purchase_order'?'purchase-order-detail':($type==='supplier_payment'?'purchase-payment-detail':($type==='goods_receipt'?'purchase-receipt-detail':($type==='supplier_invoice'?'purchase-invoice-detail':'purchase-detail')));$pdfUrl=$type==='supplier_payment'?'purchasedocuments/payment_bank_pdf/'.$id:($type==='goods_receipt'?'purchasedocuments/receipt_pdf/'.$id:($type==='supplier_invoice'?'purchasedocuments/invoice_pdf/'.$id:'purchasedocuments/pdf/'.$type.'/'.$id));$links=array();if($type==='purchase_order'&&in_array($status,array('approved','partially_received','received'),true)){if($canReturnCreate)$links[]=array('Ajukan Retur','return&po_id='.$id);if($canRefundCreate)$links[]=array('Ajukan Refund','refund&po_id='.$id);if($canReturnView||$canRefundView)$links[]=array('Lihat Retur/Refund Terkait','history&po_id='.$id);}elseif($type==='goods_receipt'&&$status==='posted'){if($canReturnCreate){$links[]=array('Retur Barang','return&receipt_id='.$id);$links[]=array('Laporkan Kekurangan','return&category=specification&receipt_id='.$id);$links[]=array('Laporkan Barang Rusak','return&category=damaged&receipt_id='.$id);}if($canReturnView){$links[]=array('Catat Barang Pengganti','replacement&receipt_id='.$id);$links[]=array('Lihat Retur Terkait','history&receipt_id='.$id);}}elseif($type==='supplier_invoice'&&in_array($status,array('partial','paid'),true)){if($canDebitCreate)$links[]=array('Buat Debit Note','debit_note&invoice_id='.$id);if($canRefundCreate)$links[]=array('Ajukan Refund','refund&invoice_id='.$id);if($canDebitView||$canRefundView)$links[]=array('Lihat Penyesuaian Tagihan','history&invoice_id='.$id);}elseif($type==='supplier_payment'&&$status==='posted'){if($canRefundCreate)$links[]=array('Ajukan Refund','refund&payment_id='.$id);if($canRefundView)$links[]=array('Lihat Refund Terkait','history&payment_id='.$id);}$context='';if($links){$context=' ';foreach($links as$link)$context.=''.$link[0].'';$context.='';}$pdf=$master||check_permission('purchases','can_export')?' PDF':'';return''.$pdf.$context;} ?>

Workflow Pembelian

Alur normal dari permintaan sampai finalisasi Invoice Supplier.

Retur & Refund
'success','error'=>'error')as$key=>$icon)if($this->session->flashdata($key)):?>
array('bi-file-earmark-plus','Permintaan','Kebutuhan barang'),'order'=>array('bi-cart-check','Purchase Order','Pesanan disetujui'),'payment'=>array('bi-wallet2','Pembayaran Awal/DP','Jika disyaratkan'),'receipt'=>array('bi-box-arrow-in-down','Penerimaan','Pemeriksaan gudang'),'invoice'=>array('bi-receipt','Invoice Supplier','Final matching'));?>
Buat PO dari PR DisetujuiIsi data order di kiri dan periksa rincian serta total PO di kanan.
Data Purchase Order
Contoh total Rp600.000 tanpa DP dan 3 cicilan = Rp200.000 per bulan.
Hanya DP ini yang muncul di Menu Pembayaran.
'Ongkos Kirim','insurance_cost'=>'Asuransi','service_fee'=>'Biaya Layanan','discount_amount'=>'Diskon/Voucher','cashback_amount'=>'Cashback')as$n=>$label):?>

Unggah penawaran, konfirmasi order, atau dokumen kesepakatan supplier.

Maksimal 10 file, masing-masing 5 MB.
Detail PemesananHarga dan pajak dapat disesuaikan sebelum PO disimpan.
Pilih PR untuk memuat semua barang.
Subtotal barangRp 0,00
PajakRp 0,00
Biaya tambahanRp 0,00
Diskon & cashback- Rp 0,00
Total PORp 0,00
Daftar Purchase Order
POSupplierMetodePembayaranTotalStatusAksi
po_no)?>name)?>procurement_method)?>payment_timing)?> · payment_status)?>total,2,',','.')?>status?>id,$o->status)?> status==='draft')echo p_action('submit_order',$o->id,'Ajukan',$this,'order');elseif($o->status==='submitted'&&($this->session->userdata('role')==='Admin'||check_permission('purchases','can_approve')))echo p_action('approve_order',$o->id,'Approve',$this,'order','success');?>
Pembayaran sebelum barang diterima dicatat ke Barang Dalam Perjalanan. Stok baru bertambah saat Penerimaan Gudang.
payment_timing==='prepaid';$isRequiredDp=$o->payment_timing==='installment'&&(int)($o->down_payment_required??0)===1;$paymentTarget=$isRequiredDp?(float)$o->down_payment_amount:(float)$o->total;if(!in_array($o->status,array('approved','partially_received'),true)||(!$isPrepaid&&!$isRequiredDp)||(float)$o->paid_amount>=$paymentTarget-.001)continue;$requiredPayment=round($paymentTarget-$o->paid_amount,2);$paymentLabel=$isRequiredDp?'DP wajib dibayar':'Wajib dibayar';$poPaymentItems=$paymentItems[$o->id]??array();?>
po_no.' · '.$o->name)?>procurement_method==='online'?'Pesanan online '.($o->marketplace?:''):'Pembelian '.$o->procurement_method)?>
Rp
Form Pembayaran
Isi nominal yang benar-benar keluar dari akun Kas/Bank.
Tidak mengurangi saldo PO.
(pokok)Rp
Admin bankRp 0,00
Total wajib keluarRp
Total sumber Kas/BankRp 0,00
Kekurangan sumber danaRp
Nominal pembayaran belum sesuai.
Wajib. Maksimal 10 file, masing-masing 5 MB.
Detail PemesananPeriksa barang dan nilai PO sebelum pembayaran.
Kode - BarangSpesifikasiQtyHargaTotal
kode_barang?:'-').' - '.($item->nama_barang?:'-'))?>tracking_type?:'-')?>description?:'-')?>qty,0,',','.')?>Rp unit_price,2,',','.')?>Rp line_total,2,',','.')?>
SubtotalRp subtotal,2,',','.')?>
PajakRp tax_total,2,',','.')?>
Ongkir, asuransi & layananRp shipping_cost+$o->insurance_cost+$o->service_fee,2,',','.')?>
Diskon & cashback- Rp discount_amount+$o->cashback_amount,2,',','.')?>
Total PORp total,2,',','.')?>
Sudah dibayarRp paid_amount,2,',','.')?>
Wajib dibayarRp
Riwayat Pembayaran Pembelian
No.POSupplierTanggalJenisPokokAdmin BankTotal KeluarDokumen
payment_no)?>po_no?:'-')?>supplier_name)?>payment_date?>payment_kind?>amount,2,',','.')?>bank_charge_amount??0,2,',','.')?>total_cash_out??0)>0?$p->total_cash_out:($p->amount+($p->bank_charge_amount??0)),2,',','.')?>id,$p->status)?>
Penerimaan Barang ke Gudang

Periksa barang fisik, catat surat jalan, kuantitas aktual, dan bukti penerimaan.

Petugas Gudang
status,array('approved','partially_received'),true))continue;$availableReceipt=true;$lines=$this->db->where('purchase_order_id',$o->id)->get('purchase_order_lines')->result();?>
po_no)?>name)?>
Kurir / Resicourier?:'-').' / '.($o->tracking_no?:'-'))?>
qty-$l->received_qty;?>
BarangDipesanSudah DiterimaDiterima Sekarang
description)?>qty,2,',','.')?>received_qty,2,',','.')?>

Unggah foto kondisi paket/barang, surat jalan bertanda tangan, atau dokumen penerimaan. Bisa memilih beberapa file sekaligus.

Wajib. Maksimal 10 file, masing-masing 5 MB.
Tidak ada Purchase Order yang siap diterima.
Riwayat Penerimaan
No.POSupplierTanggalSurat Jalan/ResiDokumen
receipt_no?>po_no?>name)?>receipt_date?>supplier_delivery_no?:'-')?>id,$r->status)?>
Finalisasi Dokumen Invoice SupplierPilih penerimaan untuk memeriksa final hubungan PO, pembayaran, penerimaan, dan invoice supplier.

Unggah invoice/nota final dan faktur pajak bila ada. Dokumen pendukung PO tidak perlu diunggah ulang.

Wajib. Maksimal 10 file, masing-masing 5 MB.
Ringkasan Dokumen Sumber
Pilih penerimaan untuk melihat PO, supplier, dan barang.
Daftar Invoice SupplierPemeriksaan final matching → Parsial atau Lunas. Tidak memerlukan approval ulang.
total;$displayPaid=max((float)($b->po_paid_amount??0),(float)$b->paid_amount);$displayBalance=max(0,$displayTotal-$displayPaid);?>
InvoiceSupplierJatuh TempoTotal InvoiceTotal Sudah DibayarSisa TagihanStatusAksi
internal_no?>supplier_invoice_no)?>name)?>due_date?>'PERLU FINALISASI','partial'=>'PARSIAL','paid'=>'LUNAS')[$b->status]??strtoupper($b->status))?>id,$b->status)?> status==='verified'){$prepaidReconcile=in_array($b->po_payment_timing,array('prepaid','on_receipt'),true)&&(float)$b->po_paid_amount>=(float)$b->total-.001;echo '';}?>
Retur Barang
Debit Note
Refund Pesanan
Riwayat Retur, Refund & Debit Note
JenisNomorTanggalNilaiDokumen
Retur Barangreturn_no?>return_date?>amount,2,',','.')?>id)?>
Refundrefund_no?>refund_date?>amount,2,',','.')?>id)?>
Debit Notedebit_note_no?>note_date?>amount,2,',','.')?>id)?>