Initial commit
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,575 @@
|
||||
<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><select class="form-control account_id">${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>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user