Files
accounting_dev_v2/assets/js/receivables-professional.js
T
2026-09-11 16:03:00 +07:00

24 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function($){
'use strict';
var cfg=window.RECEIVABLE_PAGE||{},invoices=[],files=[],sourceIndex=0;
function esc(v){return $('<div>').text(v==null?'':v).html()}
function parseMoney(v){v=String(v==null?'':v).replace(/Rp|\s/g,'');if(v.indexOf(',')>=0)v=v.replace(/\./g,'').replace(',','.');else if(/^\d{1,3}(\.\d{3})+$/.test(v))v=v.replace(/\./g,'');return Number(v)||0}
function money(v){return'Rp '+new Intl.NumberFormat('id-ID',{minimumFractionDigits:2,maximumFractionDigits:2}).format(Number(v)||0)}
function fmt(v){return new Intl.NumberFormat('id-ID',{minimumFractionDigits:0,maximumFractionDigits:2}).format(Number(v)||0)}
function toast(message,icon){if(window.AppAlert)return AppAlert.toast(message,icon||'success');return Swal.fire({toast:true,position:'top-end',icon:icon||'success',title:message,showConfirmButton:false,timer:3200})}
function fail(xhr){var m='Permintaan tidak dapat diproses.';try{var r=xhr.responseJSON||JSON.parse(xhr.responseText);m=r.message||m}catch(e){}toast(m,'error')}
function select2(selector,url,placeholder){$(selector).select2({width:'100%',placeholder:placeholder,allowClear:true,ajax:{url:cfg.base+url,dataType:'json',delay:300,data:function(p){return{q:p.term||'',page:p.page||1}},processResults:function(r){return{results:r.results||[],pagination:r.pagination||{more:false}}},cache:true}})}
function addSource(){sourceIndex++;var row=$('<div class="payment-source-row"><select class="form-select source-account"></select><input class="form-control source-amount" inputmode="decimal" placeholder="Nominal"><button type="button" class="remove-payment-source" aria-label="Hapus sumber"><i class="bi bi-x-lg"></i></button></div>');$('#paymentSources').append(row);select2(row.find('.source-account'),'receivables/lookup_cash_accounts','Pilih akun Aktiva / Passiva');row.find('.source-amount').on('input blur',function(e){if(e.type==='blur')this.value=fmt(parseMoney(this.value));calculate()})}
function renderInvoices(rows){invoices=Array.isArray(rows)?rows:[];if(!invoices.length){$('#invoiceAllocations').html('<div class="ar-empty"><i class="bi bi-receipt-cutoff"></i><span>Customer ini tidak memiliki invoice terbuka.</span></div>');$('#invoiceSelectionHint').text('Tidak ada invoice terbuka.');calculate();return}var today=new Date().toISOString().slice(0,10);$('#invoiceAllocations').html(invoices.map(function(i){var overdue=i.jatuh_tempo<today;return'<article class="invoice-allocation '+(overdue?'is-overdue':'')+'"><div class="invoice-allocation-head"><div><b>'+esc(i.no_invoice)+'</b><small>'+esc(i.invoice_type==='running'?'Berjalan / Akumulasi':'Sekali transaksi')+'</small></div><span class="badge '+(overdue?'bg-danger':'bg-warning text-dark')+'">'+(overdue?'Jatuh tempo':'Belum jatuh tempo')+'</span></div><div class="invoice-allocation-meta"><span>Total '+money(i.total)+'</span><span>Terbayar '+money(i.total_bayar)+'</span></div><div class="invoice-allocation-input"><b>Sisa '+money(i.sisa_piutang)+'</b><input class="form-control allocation-amount" data-id="'+Number(i.id)+'" data-balance="'+Number(i.sisa_piutang)+'" inputmode="decimal" value="0" aria-label="Alokasi '+esc(i.no_invoice)+'"></div></article>'}).join(''));$('#invoiceSelectionHint').text(invoices.length+' invoice belum lunas.');$('.allocation-amount').on('input blur',function(e){var value=Math.min(parseMoney(this.value),Number($(this).data('balance')));if(e.type==='blur')this.value=fmt(value);calculate()});if(cfg.focus&&Number(cfg.focus.customer_id)===Number($('#payCustomer').val())){$('.allocation-amount[data-id="'+Number(cfg.focus.id)+'"]').val(fmt(cfg.focus.sisa_piutang));cfg.focus=null}calculate()}
function loadCustomer(id){$('#paymentCustomerId').val(id||'');if(!id){renderInvoices([]);return}$('#invoiceAllocations').html('<div class="ar-empty"><span class="spinner-border spinner-border-sm"></span><span>Memuat invoice...</span></div>');$.getJSON(cfg.base+'receivables/open_invoices/'+id).done(function(r){if(!r.status)return toast(r.message,'error');renderInvoices(r.invoices)}).fail(fail);$.getJSON(cfg.base+'receivables/payment_history/'+id).done(function(r){renderHistory(r.payments||[])}).fail(fail)}
function renderHistory(rows){if(!rows.length){$('#paymentHistory').html('<div class="ar-empty"><i class="bi bi-clock-history"></i><span>Belum ada riwayat pembayaran customer ini.</span></div>');return}$('#paymentHistory').html('<div class="payment-history-list">'+rows.map(function(p){return'<div class="payment-history-row"><div><b>'+esc(p.payment_no)+'</b><small>'+esc(p.tanggal)+'</small></div><div>'+esc((p.allocations||'Uang muka').replace(/\|\|/g,', '))+'<small>Referensi '+esc(p.reference_no||'-')+' · '+esc(p.creator_name||'-')+'</small></div><b>'+money(p.jumlah)+'</b><button class="btn btn-sm btn-outline-danger preview-receipt" data-url="'+cfg.base+'sales/receipt_pdf/'+p.id+'"><i class="bi bi-file-pdf"></i> Bukti</button></div>'}).join('')+'</div>')}
function calculate(){var allocated=0;$('.allocation-amount').each(function(){allocated+=parseMoney(this.value)});var source=0;$('.source-amount').each(function(){source+=parseMoney(this.value)});var diff=source-allocated;$('#allocatedTotal').text(money(allocated));$('#sourceTotal').text(money(source));$('#paymentDifference').text(money(diff)).toggleClass('is-negative',diff<-.001).toggleClass('is-positive',diff>.001);return{allocated:allocated,source:source,difference:diff}}
function syncFileInput(){var dt=new DataTransfer();files.forEach(function(f){dt.items.add(f)});document.getElementById('paymentAttachments').files=dt.files;renderFiles()}
function renderFiles(){$('#paymentAttachmentGrid .payment-file-tile').remove();var add=$('#addPaymentAttachment');files.forEach(function(f,i){var url=URL.createObjectURL(f),pdf=f.type==='application/pdf';var tile=$('<div class="payment-file-tile" data-index="'+i+'">'+(pdf?'<div class="pdf-icon"><i class="bi bi-file-earmark-pdf"></i></div>':'<img alt="'+esc(f.name)+'" src="'+url+'">')+'<button type="button" class="payment-file-open" aria-label="Pratinjau"></button><small>'+esc(f.name)+'</small><button type="button" class="file-remove" aria-label="Hapus">×</button></div>');tile.data('url',url).data('type',f.type);add.before(tile)})}
function preview(url,type){var modal=$('#paymentPreviewModal'),frame=modal.find('iframe'),img=modal.find('img');frame.hide().attr('src','about:blank');img.hide().attr('src','');if(type==='application/pdf')frame.show().attr('src',url);else img.show().attr('src',url);bootstrap.Modal.getOrCreateInstance(modal[0]).show()}
$(function(){select2('#payCustomer','receivables/lookup_customers','Cari customer');addSource();if(cfg.focus){var option=new Option(cfg.focus.customer_name,cfg.focus.customer_id,true,true);$('#payCustomer').append(option).trigger('change')}else $('#invoiceSelectionHint').text('Pilih customer terlebih dahulu.')});
$('#payCustomer').on('change',function(){loadCustomer(this.value)});$('#addPaymentSource').on('click',addSource);$(document).on('click','.remove-payment-source',function(){if($('.payment-source-row').length===1){$(this).closest('.payment-source-row').find('select').val(null).trigger('change');$(this).closest('.payment-source-row').find('input').val('');calculate();return}$(this).closest('.payment-source-row').remove();calculate()});$('#allocateAll').on('click',function(){$('.allocation-amount').each(function(){this.value=fmt($(this).data('balance'))});calculate()});$('#clearAllocations').on('click',function(){$('.allocation-amount').val('0');calculate()});$('#addPaymentAttachment').on('click',function(){$('#paymentAttachments').trigger('click')});$('#paymentAttachments').on('change',function(){files=files.concat(Array.from(this.files));if(files.length>10){files=files.slice(0,10);toast('Maksimal 10 bukti pembayaran.','warning')}syncFileInput()});$(document).on('click','.file-remove',function(e){e.stopPropagation();files.splice(Number($(this).closest('.payment-file-tile').data('index')),1);syncFileInput()});$(document).on('click','.payment-file-open',function(){var tile=$(this).closest('.payment-file-tile');preview(tile.data('url'),tile.data('type'))});$(document).on('click','.preview-receipt',function(){preview($(this).data('url'),'application/pdf')});
$('#paymentPreviewModal').on('hidden.bs.modal',function(){$(this).find('iframe').attr('src','about:blank');$(this).find('img').attr('src','')});
$('#paymentForm').on('submit',function(e){e.preventDefault();var customer=$('#payCustomer').val(),allocations={},sources=[];$('.allocation-amount').each(function(){var value=parseMoney(this.value);if(value>0)allocations[$(this).data('id')]=value});$('.payment-source-row').each(function(){var account=$(this).find('.source-account').val(),amount=parseMoney($(this).find('.source-amount').val());if(account&&amount>0)sources.push({account_id:Number(account),amount:amount})});var totals=calculate();if(!customer)return toast('Pilih customer.','warning');if(!sources.length)return toast('Tambahkan minimal satu sumber Kas/Bank dan nominal.','warning');if(!files.length)return toast('Bukti pembayaran wajib ditambahkan.','warning');if(totals.difference<-.001)return toast('Sumber penerimaan lebih kecil dari alokasi invoice.','warning');if(totals.difference>.001&&!$('#allowAdvance').is(':checked'))return toast('Terdapat kelebihan. Centang uang muka customer atau sesuaikan nominal.','warning');var form=this,button=$('#postPayment');var confirm=window.AppAlert?AppAlert.confirm({icon:'question',title:'Post pembayaran?',html:'Penerimaan <b>'+money(totals.source)+'</b> akan dialokasikan sebesar <b>'+money(totals.allocated)+'</b>.',confirmButtonText:'Ya, Post'}):Swal.fire({icon:'question',title:'Post pembayaran?',showCancelButton:true,confirmButtonText:'Ya, Post'});confirm.then(function(r){if(!r.isConfirmed)return;var fd=new FormData(form);fd.set('customer_id',customer);fd.set('sources',JSON.stringify(sources));fd.set('allocations_json',JSON.stringify(allocations));button.prop('disabled',true).html('<span class="spinner-border spinner-border-sm"></span> Memproses...');$.ajax({url:form.action,type:'POST',data:fd,dataType:'json',processData:false,contentType:false}).done(function(x){if(!x.status)return toast(x.message,'error');toast(x.message,'success');if(x.result&&x.result.payment_id)preview(cfg.base+'sales/receipt_pdf/'+x.result.payment_id,'application/pdf');loadCustomer(customer);files=[];syncFileInput();$('.source-amount').val('');calculate()}).fail(fail).always(function(){button.prop('disabled',false).html('<i class="bi bi-check-circle"></i> Post Pembayaran')})})});
})(jQuery);