Files
2026-07-30 09:49:00 +07:00

576 lines
15 KiB
PHP

<div class="container mt-4">
<div class="card modern-card shadow-sm border-0 rounded-4">
<div class="card-body p-4">
<div class="d-flex justify-content-between mb-3">
<h5>
<?php if($active_menu == 'invoice_unpaid') echo 'Invoice Berjalan'; ?>
<?php if($active_menu == 'invoice_paid') echo 'Riwayat Invoice'; ?>
<?php if($active_menu == 'invoice_draft') echo 'Draft Invoice'; ?>
</h5>
<?php if($active_menu == 'invoice_draft') : ?>
<button class="btn btn-warning btn-add">Buat Invoice</button>
<?php endif; ?>
</div>
<div class="table-responsive">
<table class="table modern-table align-middle w-100" id="tableInvoice">
<!-- <table id="tableInvoice" class="table table-bordered"> -->
<thead>
<tr>
<th>No</th>
<th>No Invoice</th>
<th>Tanggal</th>
<th>Jatuh Tempo</th>
<th>Customer</th>
<th>Total</th>
<th>Terbayar</th>
<th>Sisa</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
</table>
</table>
</div>
</div>
</div>
<!-- MODAL -->
<div class="modal fade" id="modalInvoice">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header bg-warning text-white">
<h5>Buat Invoice</h5>
</div>
<div class="modal-body">
<div class="form-group mt-2">
<label for="customer_id">Customer</label>
<select id="customer_id" class="form-control mb-2"></select>
</div>
<div class="form-group mt-2">
<label for="tanggal">Tanggal</label>
<input type="date" id="tanggal" class="form-control mb-2">
</div>
<div class="form-group mt-2">
<label for="jatuh_tempo">Jatuh Tempo</label>
<input type="date" id="jatuh_tempo" class="form-control mb-3">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-warning" id="btnSimpan">Simpan</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="modalBayar">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header bg-warning text-white">
<h5>
Bayar Invoice -
<span id="customerName"></span>
</h5>
</div>
<div class="modal-body">
<input type="hidden" id="bayar_invoice_id">
<!-- INFO BOX -->
<div class="row mb-3">
<div class="col-md-4">
<div class="p-2 border rounded">
<small>Total Invoice</small>
<h5 id="invoiceTotal">0</h5>
</div>
</div>
<div class="col-md-4">
<div class="p-2 border rounded">
<small>Total Bayar</small>
<h5 id="totalBayar">0</h5>
</div>
</div>
<div class="col-md-4">
<div class="p-2 border rounded">
<small>Sisa (Balance)</small>
<h5 id="balance">0</h5>
</div>
</div>
</div>
<label>Tanggal Bayar</label>
<input type="date" id="tanggal_bayar" class="form-control mb-2">
<table class="table" id="tableBayar">
<thead>
<tr>
<th>Account</th>
<th>Debit</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
<button class="btn btn-sm btn-primary btn-add-bayar">
+ Tambah Pembayaran
</button>
</div>
<div class="modal-footer">
<button class="btn btn-warning" id="btnProsesBayar">
Proses Bayar
</button>
</div>
</div>
</div>
</div>
<script>
$(function(){
let url = "";
let accountOptions = '';
let accountOptionsAssets = '';
// =========================
// URL BY MENU
// =========================
<?php if($active_menu == 'invoice_unpaid'): ?>
url = "<?= base_url('invoices/get_data/unpaid'); ?>";
<?php elseif($active_menu == 'invoice_paid'): ?>
url = "<?= base_url('invoices/get_data/paid'); ?>";
<?php elseif($active_menu == 'invoice_draft'): ?>
url = "<?= base_url('invoices/get_data/draft'); ?>";
<?php endif; ?>
// =========================
// LOAD CUSTOMER
// =========================
$.get("<?= base_url('invoices/get_customers'); ?>", res => {
let opt = '<option value="">Pilih Customer</option>';
res.forEach(c => opt += `<option value="${c.id}">${c.nama}</option>`);
$('#customer_id').html(opt);
}, 'json');
// =========================
// LOAD ACCOUNT (PENDAPATAN)
// =========================
$.get("<?= base_url('invoices/get_accounts'); ?>", res => {
accountOptions = '<option value="">Pilih Akun</option>';
res.forEach(a => {
accountOptions += `<option value="${a.id}">${a.kode_akun} - ${a.nama_akun}</option>`;
});
}, 'json');
// =========================
// LOAD ACCOUNT (ASSET / KAS)
// =========================
$.get("<?= base_url('invoices/get_accounts_assets'); ?>", res => {
accountOptionsAssets = '<option value="">Pilih Akun</option>';
res.forEach(a => {
accountOptionsAssets += `<option value="${a.id}">${a.kode_akun} - ${a.nama_akun}</option>`;
});
}, 'json');
// =========================
// DATATABLE
// =========================
let table = $('#tableInvoice').DataTable({
ajax:{
url: url,
type:"POST"
},
columnDefs:[
{ targets:[3], className:'text-end' }
]
});
// =========================
// ADD ITEM ROW
// =========================
$('.btn-add-row').click(function(){
if(!accountOptions){
Swal.fire('Warning','Account belum siap, tunggu sebentar','warning');
return;
}
$('#tableDetail tbody').append(`
<tr>
<td>
<select class="form-control account_id">${accountOptions}</select>
</td>
<td><input type="text" class="form-control nama_item"></td>
<td><input type="number" class="form-control qty" value="1"></td>
<td><input type="text" class="form-control harga format-rupiah"></td>
<td class="subtotal text-end">0</td>
<td><button class="btn btn-danger btn-remove">X</button></td>
</tr>
`);
});
// =========================
// HITUNG SUBTOTAL
// =========================
$(document).on('input','.qty,.harga',function(){
let tr = $(this).closest('tr');
let qty = parseFloat(tr.find('.qty').val()) || 0;
let harga = parseFloat(tr.find('.harga').val()) || 0;
let sub = qty * harga;
tr.find('.subtotal').text(sub.toLocaleString('id-ID'));
calcTotal();
});
// =========================
// TOTAL
// =========================
function calcTotal(){
let total = 0;
$('.subtotal').each(function(){
total += parseFloat($(this).text().replace(/\./g,'')) || 0;
});
$('#grandTotal').text(total.toLocaleString('id-ID'));
}
// =========================
// REMOVE ROW (GLOBAL)
// =========================
$(document).on('click','.btn-remove',function(){
$(this).closest('tr').remove();
calcTotal();
hitungBayar();
});
// =========================
// OPEN MODAL INVOICE
// =========================
$('.btn-add').click(function(){
$('#modalInvoice').modal('show');
$('#tableDetail tbody').html('');
$('#grandTotal').text('0');
});
// =========================
// SIMPAN INVOICE
// =========================
$('#btnSimpan').click(function(){
let nama_item=[], qty=[], harga=[], account_id=[];
$('#tableDetail tbody tr').each(function(){
nama_item.push($(this).find('.nama_item').val());
qty.push($(this).find('.qty').val());
harga.push($(this).find('.harga').val());
account_id.push($(this).find('.account_id').val());
});
$.post("<?= base_url('invoices/save'); ?>",{
customer_id: $('#customer_id').val(),
tanggal: $('#tanggal').val(),
jatuh_tempo: $('#jatuh_tempo').val()
}, function(res){
if(res.status){
Swal.fire({
icon:'success',
title:'Berhasil',
text:'Invoice berhasil disimpan',
timer:1500,
showConfirmButton:false
}).then(()=>{
window.location.href = "<?= base_url('invoices/detail/'); ?>" + res.invoice_id;
});
}else{
Swal.fire('Error', res.message || 'Gagal simpan', 'error');
}
},'json');
});
// =========================
// DETAIL
// =========================
$(document).on('click','.btn-detail',function(){
let id = $(this).data('id');
window.location.href = "<?= base_url('invoices/detail/'); ?>" + id;
});
// =========================
// OPEN MODAL BAYAR
// =========================
$(document).on('click','.btn-bayar',function(){
let id = $(this).data('id');
let total = parseFloat($(this).data('total') - $(this).data('terbayar')) || 0;
let customer = $(this).data('customer');
$('#bayar_invoice_id').val(id);
$('#customerName').text(customer);
$('#invoiceTotal').text(total.toLocaleString('id-ID'));
$('#tableBayar tbody').html('');
$('#totalBayar').text('0');
$('#balance').text(total.toLocaleString('id-ID'));
$('#modalBayar').modal('show');
});
// =========================
// ADD ROW BAYAR
// =========================
$('.btn-add-bayar').click(function(){
if(!accountOptionsAssets){
Swal.fire('Warning','Account belum siap','warning');
return;
}
$('#tableBayar tbody').append(`
<tr>
<td style="width: 60%;"><select class="form-control account_id select-search">${accountOptionsAssets}</select></td>
<td><input type="text" class="form-control debit text-end format-rupiah"></td>
<td><button class="btn btn-danger btn-remove">X</button></td>
</tr>
`);
});
// =========================
// HITUNG BAYAR
// =========================
$(document).on('input','.debit',function(){
hitungBayar();
});
function hitungBayar(){
let totalBayar = 0;
$('#tableBayar .debit').each(function(){
totalBayar += parseFloat($(this).val()) || 0;
});
let invoiceTotal = parseFloat($('#invoiceTotal').text().replace(/\./g,'')) || 0;
let balance = invoiceTotal - totalBayar;
$('#totalBayar').text(totalBayar.toLocaleString('id-ID'));
$('#balance').text(balance.toLocaleString('id-ID'));
if(balance < 0){
$('#balance').css('color','red');
}else if(balance === 0){
$('#balance').css('color','green');
}else{
$('#balance').css('color','orange');
}
}
// =========================
// PROSES BAYAR
// =========================
$('#btnProsesBayar').click(function(){
let id = $('#bayar_invoice_id').val();
let tanggal_bayar = $('#tanggal_bayar').val();
if(!tanggal_bayar){
Swal.fire('Warning','Tanggal bayar wajib diisi','warning');
return;
}
let detail = [];
let totalBayar = 0;
$('#tableBayar tbody tr').each(function(){
let account_id = $(this).find('.account_id').val();
let debit = parseFloat($(this).find('.debit').val()) || 0;
if(account_id && debit > 0){
detail.push({ account_id, amount: debit });
totalBayar += debit;
}
});
if(detail.length === 0){
Swal.fire('Warning','Isi minimal 1 pembayaran','warning');
return;
}
let invoiceTotal = parseFloat($('#invoiceTotal').text().replace(/\./g,'')) || 0;
if(totalBayar > invoiceTotal){
Swal.fire('Error','Pembayaran melebihi total invoice','error');
return;
}
Swal.fire({
title:'Memproses...',
allowOutsideClick:false,
didOpen:()=>Swal.showLoading()
});
$.post("<?= base_url('invoices/bayar'); ?>", {
invoice_id: id,
tanggal_bayar,
detail
}, function(res){
if(res.status){
Swal.fire('Success','Pembayaran sukses','success');
$('#modalBayar').modal('hide');
table.ajax.reload(null,false);
}else{
Swal.fire('Error', res.message || 'Gagal', 'error');
}
}, 'json');
});
// =========================
// POSTING
// =========================
$(document).on('click','.btn-posting',function(){
let id = $(this).data('id');
Swal.fire({
title:'Posting Invoice?',
text:'Akan masuk ke piutang',
icon:'warning',
showCancelButton:true
}).then(result=>{
if(result.isConfirmed){
Swal.fire({
title:'Processing...',
allowOutsideClick:false,
didOpen:()=>Swal.showLoading()
});
$.post("<?= base_url('invoices/posting'); ?>",{invoice_id:id},function(){
Swal.fire('Success','Berhasil diposting','success');
table.ajax.reload(null,false);
},'json');
}
});
});
// =========================
// DELETE
// =========================
$(document).on('click', '.btn-delete', function () {
let id = $(this).data('id');
Swal.fire({
title: 'Hapus Invoice?',
text: 'Data tidak bisa dikembalikan',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#dc3545',
confirmButtonText: 'Ya, Hapus',
cancelButtonText: 'Batal'
}).then((result) => {
if (result.isConfirmed) {
Swal.fire({
title: 'Menghapus...',
allowOutsideClick: false,
didOpen: () => Swal.showLoading()
});
$.ajax({
url: "<?= base_url('invoices/delete/'); ?>" + id,
type: "GET",
dataType: "json"
})
.done(function (res) {
if (res.status) {
Swal.fire({
icon: 'success',
title: 'Berhasil',
text: 'Invoice berhasil dihapus'
});
// reload datatable
if (typeof table !== 'undefined') {
table.ajax.reload(null, false);
}
} else {
Swal.fire({
icon: 'error',
title: 'Gagal',
text: res.message || 'Tidak bisa dihapus'
});
}
})
.fail(function () {
Swal.fire({
icon: 'error',
title: 'Error',
text: 'Terjadi kesalahan koneksi'
});
});
}
});
});
});
</script>