Files
accounting_dev_v2/application/views/professional_reports/index.php
T
2026-09-17 00:51:53 +07:00

64 lines
19 KiB
PHP

<?php
$reportNames=array('trial_balance'=>'Neraca Saldo','general_ledger'=>'Buku Besar','profit_loss'=>'Laporan Laba Rugi','balance_sheet'=>'Laporan Neraca','cash_flow'=>'Laporan Arus Kas','bank_account_balances'=>'Rekening Bank & Saldo','changes_equity'=>'Perubahan Ekuitas','journal_register'=>'Register Jurnal','account_detail'=>'Detail Transaksi Akun','actual_budget'=>'Aktual vs Budget','sales_summary'=>'Rekap Penjualan','sales_by_customer'=>'Penjualan per Customer','sales_by_item'=>'Penjualan per Barang','sales_by_barcode'=>'Penjualan per Barcode','running_invoices'=>'Invoice Berjalan Belum Final','sales_returns'=>'Retur Penjualan','revenue_recognition'=>'Pendapatan Diakui vs Ditangguhkan','unbilled_deliveries'=>'Surat Jalan Belum Ditagihkan','receivable_reconciliation'=>'Rekonsiliasi Piutang','purchase_returns'=>'Laporan Retur Pembelian','supplier_refunds'=>'Laporan Refund Supplier','outstanding_supplier_refunds'=>'Outstanding Refund Supplier','supplier_debit_notes'=>'Laporan Debit Note Supplier');
$money=function($value){return number_format((float)$value,2,',','.');};
$accountCode=function($value){return preg_replace('/(?:[\.,]0+)$/','',(string)$value);};
?>
<div class="container-fluid py-3 professional-report-page">
<div class="d-flex flex-wrap justify-content-between align-items-start gap-2">
<div><h4><?=html_escape(isset($reportNames[$report])?$reportNames[$report]:'Laporan Profesional')?></h4><small><?=html_escape($company->name)?> · <?=in_array($report,array('balance_sheet','bank_account_balances'),true)?'posisi per '.$filters['to']:'periode '.$filters['from'].' s.d. '.$filters['to']?></small></div>
<div><a class="btn btn-success" href="<?=base_url('professionalreports/export/'.$report.'?'.http_build_query($filters))?>">Export Excel/CSV</a> <button class="btn btn-outline-dark" onclick="print()">PDF/Print</button></div>
</div>
<form class="card card-body my-3"><div class="row g-2">
<div class="col-md-3"><label class="form-label">Tipe Laporan</label><select class="form-select" name="report"><?php foreach($reportNames as$k=>$v):?><option value="<?=$k?>" <?=$report===$k?'selected':''?>><?=$v?></option><?php endforeach?></select></div>
<?php if(!in_array($report,array('balance_sheet','bank_account_balances'),true)):?><div class="col-md-2"><label class="form-label">Dari tanggal</label><input class="form-control" type="date" name="from" value="<?=$filters['from']?>"></div><?php else:?><input type="hidden" name="from" value="1900-01-01"><?php endif?>
<div class="col-md-2"><label class="form-label">Sampai tanggal</label><input class="form-control" type="date" name="to" value="<?=$filters['to']?>"></div>
<div class="col-md-3"><label class="form-label">Akun</label><select class="form-select" name="account_id"><option value="">Semua akun</option><?php foreach($accounts as$a):?><option value="<?=$a->id?>" <?=$filters['account_id']==$a->id?'selected':''?>><?=html_escape($a->kode_akun.' '.$a->nama_akun)?></option><?php endforeach?></select></div>
<div class="col-md-2 d-flex align-items-end"><button class="btn btn-primary w-100">Tampilkan</button></div>
</div></form>
<?php if($report==='balance_sheet'):
$assets=array();$liabilities=array();$equities=array();$totalAssets=0;$totalLiabilities=0;$totalEquity=0;
foreach($rows as$r){if($r['tipe']==='asset'){$assets[]=$r;$totalAssets+=(float)$r['amount'];}elseif($r['tipe']==='liability'){$liabilities[]=$r;$totalLiabilities+=(float)$r['amount'];}elseif($r['tipe']==='equity'){$equities[]=$r;$totalEquity+=(float)$r['amount'];}}
$revenue=0;$expense=0;foreach($profit_loss_rows as$r){if($r['tipe']==='revenue')$revenue+=(float)$r['amount'];elseif($r['tipe']==='expense')$expense+=(float)$r['amount'];}$netProfit=$revenue-$expense;$totalPasiva=$totalLiabilities+$totalEquity+$netProfit;$difference=$totalAssets-$totalPasiva;$balanced=abs($difference)<0.01;
?>
<div class="alert <?=$balanced?'alert-success':'alert-danger'?> d-flex justify-content-between align-items-center"><b><?=$balanced?'NERACA BALANCE':'NERACA TIDAK BALANCE'?></b><span>Selisih: Rp <?=$money($difference)?></span></div>
<div class="row g-3 report-paired-cards">
<div class="col-lg-6"><div class="card h-100"><div class="card-header bg-primary text-white"><b>AKTIVA</b></div><div class="card-body p-0"><table class="table mb-0"><tbody><?php foreach($assets as$r):?><tr><td><?=html_escape($accountCode($r['kode_akun']).' · '.$r['nama_akun'])?></td><td class="text-end"><?=$money($r['amount'])?></td></tr><?php endforeach?></tbody><tfoot><tr class="table-primary"><th>TOTAL AKTIVA</th><th class="text-end">Rp <?=$money($totalAssets)?></th></tr></tfoot></table></div></div></div>
<div class="col-lg-6"><div class="card h-100"><div class="card-header bg-dark text-white"><b>PASIVA</b></div><div class="card-body p-0"><table class="table mb-0"><tbody><tr class="table-light"><th colspan="2">Liabilitas</th></tr><?php foreach($liabilities as$r):?><tr><td><?=html_escape($accountCode($r['kode_akun']).' · '.$r['nama_akun'])?></td><td class="text-end"><?=$money($r['amount'])?></td></tr><?php endforeach?><tr class="table-light"><th colspan="2">Ekuitas</th></tr><?php foreach($equities as$r):?><tr><td><?=html_escape($accountCode($r['kode_akun']).' · '.$r['nama_akun'])?></td><td class="text-end"><?=$money($r['amount'])?></td></tr><?php endforeach?><tr class="table-warning"><th>Laba Bersih Berjalan</th><th class="text-end">Rp <?=$money($netProfit)?></th></tr></tbody><tfoot><tr class="table-dark"><th>TOTAL PASIVA</th><th class="text-end">Rp <?=$money($totalPasiva)?></th></tr></tfoot></table></div></div></div>
</div>
<?php elseif($report==='profit_loss'):
$revenues=array();$expenses=array();$totalRevenue=0;$totalExpense=0;foreach($rows as$r){if($r['tipe']==='revenue'){$revenues[]=$r;$totalRevenue+=(float)$r['amount'];}elseif($r['tipe']==='expense'){$expenses[]=$r;$totalExpense+=(float)$r['amount'];}}$netProfit=$totalRevenue-$totalExpense;
?>
<div class="row g-3 report-paired-cards">
<div class="col-lg-6"><div class="card h-100"><div class="card-header bg-success text-white"><b>PENDAPATAN</b></div><div class="card-body p-0"><table class="table mb-0"><tbody><?php foreach($revenues as$r):?><tr><td><?=html_escape($accountCode($r['kode_akun']).' · '.$r['nama_akun'])?></td><td class="text-end"><?=$money($r['amount'])?></td></tr><?php endforeach?></tbody><tfoot><tr class="table-success"><th>TOTAL PENDAPATAN</th><th class="text-end">Rp <?=$money($totalRevenue)?></th></tr></tfoot></table></div></div></div>
<div class="col-lg-6"><div class="card h-100"><div class="card-header bg-danger text-white"><b>BEBAN</b></div><div class="card-body p-0"><table class="table mb-0"><tbody><?php foreach($expenses as$r):?><tr><td><?=html_escape($accountCode($r['kode_akun']).' · '.$r['nama_akun'])?></td><td class="text-end"><?=$money($r['amount'])?></td></tr><?php endforeach?></tbody><tfoot><tr class="table-danger"><th>TOTAL BEBAN</th><th class="text-end">Rp <?=$money($totalExpense)?></th></tr></tfoot></table></div></div></div>
</div>
<div class="card mt-3"><div class="card-body d-flex justify-content-between align-items-center"><h5 class="mb-0"><?=$netProfit>=0?'LABA BERSIH':'RUGI BERSIH'?></h5><h4 class="mb-0 <?=$netProfit>=0?'text-success':'text-danger'?>">Rp <?=$money(abs($netProfit))?></h4></div></div>
<?php elseif($report==='cash_flow'): ?>
<div class="row g-2 mb-3">
<?php foreach(array('opening_balance'=>'Saldo Awal Kas','operating'=>'Aktivitas Operasi','investing'=>'Aktivitas Investasi','financing'=>'Aktivitas Pendanaan','increase_decrease'=>'Kenaikan / Penurunan Kas','closing_balance'=>'Saldo Akhir Kas')as$key=>$label):?>
<div class="col-md-4 col-xl-2"><div class="card h-100"><div class="card-body"><small class="text-muted"><?=$label?></small><strong class="d-block mt-1 <?=((float)($report_summary[$key]??0))<0?'text-danger':''?>">Rp <?=$money($report_summary[$key]??0)?></strong></div></div></div>
<?php endforeach?>
</div>
<div class="card"><div class="card-header"><b>Detail Transaksi Pembentuk Arus Kas</b><small class="d-block text-muted">Saldo berjalan mencakup seluruh akun kas/bank yang dipilih.</small></div><div class="table-responsive"><table class="table table-sm align-middle mb-0"><thead><tr><th>Tanggal</th><th>Referensi</th><th>Keterangan</th><th>Akun</th><th>Aktivitas</th><th class="text-end">Kas Masuk</th><th class="text-end">Kas Keluar</th><th class="text-end">Saldo</th></tr></thead><tbody><?php foreach($rows as$r):?><tr><td><?=html_escape($r['tanggal'])?></td><td><a href="<?=base_url('jurnal?focus='.$r['journal_id'])?>"><?=html_escape($r['no_ref']?:'#'.$r['journal_id'])?></a></td><td><?=html_escape($r['keterangan'])?></td><td><?=html_escape($r['akun'])?></td><td><?=html_escape($r['aktivitas'])?></td><td class="text-end text-success"><?=$money($r['kas_masuk'])?></td><td class="text-end text-danger"><?=$money($r['kas_keluar'])?></td><td class="text-end fw-semibold"><?=$money($r['saldo_berjalan'])?></td></tr><?php endforeach?><?php if(!$rows):?><tr><td colspan="8" class="text-center text-muted py-4">Tidak ada transaksi kas pada periode ini.</td></tr><?php endif?></tbody><tfoot><tr><th colspan="5">Total Mutasi</th><th class="text-end"><?=$money($report_summary['cash_in']??0)?></th><th class="text-end"><?=$money($report_summary['cash_out']??0)?></th><th class="text-end"><?=$money($report_summary['closing_balance']??0)?></th></tr></tfoot></table></div></div>
<?php elseif($report==='bank_account_balances'):
$mapped=0;$unmapped=0;$uniqueBalances=array();foreach($rows as$r){if(empty($r['gl_account_id']))$unmapped++;else{$mapped++;$uniqueBalances[(int)$r['gl_account_id']]=(float)$r['closing_balance'];}}$totalBankBalance=array_sum($uniqueBalances);
?>
<div class="row g-2 mb-3">
<div class="col-md-4"><div class="card h-100"><div class="card-body"><small class="text-muted">Seluruh Rekening</small><strong class="d-block mt-1"><?=count($rows)?></strong><span class="small text-muted">Aktif maupun nonaktif</span></div></div></div>
<div class="col-md-4"><div class="card h-100"><div class="card-body"><small class="text-muted">Terhubung ke COA</small><strong class="d-block mt-1 text-success"><?=$mapped?></strong><span class="small text-muted"><?=$unmapped?> rekening belum terhubung</span></div></div></div>
<div class="col-md-4"><div class="card h-100"><div class="card-body"><small class="text-muted">Total Saldo COA Unik</small><strong class="d-block mt-1"><?=html_escape($company->base_currency?:'IDR')?> <?=$money($totalBankBalance)?></strong><span class="small text-muted">Tidak menggandakan COA yang dipakai bersama</span></div></div></div>
</div>
<div class="card"><div class="card-header"><b>Daftar Rekening dan Saldo Buku Besar</b><small class="d-block text-muted">Saldo berasal dari jurnal posted/reversed sampai <?=html_escape($filters['to'])?> dalam mata uang dasar perusahaan. Seluruh rekening tetap ditampilkan; pilihan PDF Invoice hanya bersifat informasi.</small></div><div class="table-responsive"><table class="table table-sm align-middle mb-0"><thead><tr><th>Bank / Rekening</th><th>Produk</th><th>Mata Uang</th><th>Akun COA</th><th>Status</th><th>PDF Invoice</th><th class="text-end">Saldo Akhir COA</th></tr></thead><tbody><?php foreach($rows as$r):?><tr><td><b><?=html_escape($r['bank_name'])?></b><small class="d-block text-muted"><?=html_escape($r['account_number'].' · a.n. '.$r['account_holder'])?></small></td><td><?=html_escape($r['account_type_label'])?><small class="d-block text-muted"><?=html_escape($r['product_name']?:'-')?></small></td><td><?=html_escape($r['currency'])?></td><td><?php if(!empty($r['gl_account_id'])):?><b><?=html_escape($accountCode($r['kode_akun']))?></b><small class="d-block text-muted"><?=html_escape($r['nama_akun'])?></small><?php if((int)$r['linked_account_count']>1):?><span class="badge bg-warning text-dark mt-1"><?=html_escape($r['mapping_status'])?></span><?php endif?><?php else:?><span class="text-warning">Belum terhubung</span><?php endif?></td><td><span class="badge <?=$r['is_active']?'bg-success':'bg-secondary'?>"><?=html_escape($r['account_status'])?></span><?=$r['is_primary']?'<span class="badge bg-primary ms-1">Utama</span>':''?></td><td><span class="badge <?=$r['show_on_invoice']?'bg-info text-dark':'bg-light text-dark'?>"><?=html_escape($r['invoice_status'])?></span></td><td class="text-end fw-bold"><?=html_escape($company->base_currency?:'IDR')?> <?=$money($r['closing_balance'])?></td></tr><?php endforeach?><?php if(!$rows):?><tr><td colspan="7" class="text-center text-muted py-4">Belum ada rekening perusahaan.</td></tr><?php endif?></tbody></table></div></div>
<?php elseif($report==='general_ledger'): ?>
<div class="card mb-3"><div class="card-header"><b>Ringkasan Saldo per Akun</b><small class="d-block text-muted">Saldo awal berasal dari seluruh jurnal sebelum periode, bukan dari pagination tampilan.</small></div><div class="table-responsive"><table class="table table-sm mb-0"><thead><tr><th>Akun</th><th class="text-end">Saldo Awal</th><th class="text-end">Total Debit</th><th class="text-end">Total Kredit</th><th class="text-end">Saldo Akhir</th></tr></thead><tbody><?php foreach($report_summary as$r):?><tr><td><?=html_escape($accountCode($r['kode_akun']).' - '.$r['nama_akun'])?></td><td class="text-end"><?=$money($r['saldo_awal'])?></td><td class="text-end"><?=$money($r['total_debit'])?></td><td class="text-end"><?=$money($r['total_kredit'])?></td><td class="text-end fw-bold"><?=$money($r['saldo_akhir'])?></td></tr><?php endforeach?><?php if(!$report_summary):?><tr><td colspan="5" class="text-center text-muted py-4">Tidak ada saldo atau mutasi akun.</td></tr><?php endif?></tbody></table></div></div>
<div class="card"><div class="card-header"><b>Rincian Buku Besar</b></div><div class="table-responsive"><table class="table table-sm align-middle mb-0"><thead><tr><th>Akun</th><th>Tanggal</th><th>Referensi</th><th>Keterangan</th><th class="text-end">Debit</th><th class="text-end">Kredit</th><th class="text-end">Saldo Berjalan</th></tr></thead><tbody><?php foreach($rows as$r):?><tr><td><?=html_escape($accountCode($r['kode_akun']).' - '.$r['nama_akun'])?></td><td><?=html_escape($r['tanggal'])?></td><td><a href="<?=base_url('jurnal?focus='.$r['journal_id'])?>"><?=html_escape($r['no_ref'])?></a></td><td><?=html_escape($r['keterangan'])?></td><td class="text-end"><?=$money($r['debit'])?></td><td class="text-end"><?=$money($r['kredit'])?></td><td class="text-end fw-semibold"><?=$money($r['saldo_berjalan'])?></td></tr><?php endforeach?><?php if(!$rows):?><tr><td colspan="7" class="text-center text-muted py-4">Tidak ada transaksi pada periode ini.</td></tr><?php endif?></tbody></table></div></div>
<?php elseif($report==='receivable_reconciliation'): ?>
<div class="row g-2 mb-3"><div class="col-md-4"><div class="card h-100"><div class="card-body"><small class="text-muted">Subledger Invoice</small><strong class="d-block">Rp <?=$money($report_summary['subledger']??0)?></strong></div></div></div><div class="col-md-4"><div class="card h-100"><div class="card-body"><small class="text-muted">Saldo Buku Besar Piutang</small><strong class="d-block">Rp <?=$money($report_summary['general_ledger']??0)?></strong></div></div></div><div class="col-md-4"><div class="card h-100 border-<?=$report_summary['balanced']?'success':'warning'?>"><div class="card-body"><small class="text-muted">Selisih Belum Terpetakan</small><strong class="d-block <?=$report_summary['balanced']?'text-success':'text-warning'?>">Rp <?=$money($report_summary['difference']??0)?></strong></div></div></div></div>
<div class="card"><div class="card-header"><b>Piutang per Invoice sampai <?=html_escape($filters['to'])?></b><small class="d-block text-muted">Pembayaran, credit note, dan write-off ditelusuri sampai tanggal laporan. Selisih data lama tetap ditampilkan untuk kebutuhan koreksi.</small></div><div class="table-responsive"><table class="table table-sm align-middle mb-0"><thead><tr><th>Customer</th><th>Invoice</th><th>Tanggal</th><th>Jatuh Tempo</th><th class="text-end">Nilai Piutang</th><th class="text-end">Pembayaran</th><th class="text-end">Credit Note</th><th class="text-end">Write-off</th><th class="text-end">Sisa</th><th>Status</th><th>Referensi</th></tr></thead><tbody><?php foreach($rows as$r):?><tr class="<?=!empty($r['reconciliation_adjustment'])?'table-warning':''?>"><td><?=html_escape($r['customer'])?></td><td><?php if(!empty($r['record_id'])):?><a href="<?=base_url('invoices/detail/'.$r['record_id'])?>"><?=html_escape($r['no_invoice'])?></a><?php else:?><?=html_escape($r['no_invoice'])?><?php endif?></td><td><?=html_escape($r['invoice_date']?:'-')?></td><td><?=html_escape($r['due_date']?:'-')?></td><td class="text-end"><?=$money($r['receivable_amount'])?></td><td class="text-end"><?=$money($r['payments'])?></td><td class="text-end"><?=$money($r['credit_notes'])?></td><td class="text-end"><?=$money($r['writeoffs'])?></td><td class="text-end fw-bold"><?=$money($r['remaining_receivable'])?></td><td><?=html_escape($r['status'])?></td><td><?=html_escape($r['transaction_references']?:'-')?></td></tr><?php endforeach?></tbody><tfoot><tr><th colspan="8">Total setelah rekonsiliasi</th><th class="text-end">Rp <?=$money($report_summary['general_ledger']??0)?></th><th colspan="2"></th></tr></tfoot></table></div></div>
<?php else: ?>
<?php $visibleColumns=$rows?array_values(array_filter(array_keys($rows[0]),function($key){return$key!=='record_id';})):array();$documentTypes=array('return_no'=>'purchase_return','refund_no'=>'supplier_refund','debit_note_no'=>'supplier_debit_note'); ?>
<div class="card"><div class="table-responsive"><table class="table table-sm mb-0"><thead><?php if($rows):?><tr><?php foreach($visibleColumns as$h):?><th><?=html_escape(ucwords(str_replace('_',' ',$h)))?></th><?php endforeach?></tr><?php endif?></thead><tbody><?php foreach($rows as$r):?><tr><?php foreach($visibleColumns as$k):$v=$r[$k];?><td class="<?=is_numeric($v)&&!preg_match('/(^id$|_id$|kode_akun$)/',$k)?'text-end':''?>"><?php if($k==='journal_id'&&$v):?><a href="<?=base_url('jurnal?focus='.$v)?>">#<?=$v?></a><?php elseif(isset($documentTypes[$k])&&!empty($r['record_id'])):?><a href="<?=base_url('purchases/returns?action=history&focus_type='.$documentTypes[$k].'&focus='.$r['record_id'])?>"><?=html_escape($v)?></a><?php elseif($k==='kode_akun'):?><?=html_escape($accountCode($v))?><?php elseif(is_numeric($v)&&!preg_match('/(^id$|_id$|kode_akun$)/',$k)):?><?=$money($v)?><?php else:?><?=html_escape($v===null?'-':$v)?><?php endif?></td><?php endforeach?></tr><?php endforeach?></tbody></table></div></div>
<?php endif; ?>
<div class="mt-3"><b>Subledger:</b> <a href="<?=base_url('receivables')?>">Aging Piutang</a> · <a href="<?=base_url('payables')?>">Aging Hutang</a> · <a href="<?=base_url('inventoryprofessional')?>">Persediaan</a> · <a href="<?=base_url('fixedassets')?>">Aset</a> · <a href="<?=base_url('hrpayroll')?>">Payroll</a> · <a href="<?=base_url('purchases/returns')?>">Retur &amp; Refund</a></div>
</div>