• استعلام قیمت و ثبت سفارش
`;var iframe = document.createElement('iframe'); iframe.style.position = 'fixed'; iframe.style.right = '0'; iframe.style.bottom = '0'; iframe.style.width = '0'; iframe.style.height = '0'; iframe.style.border = '0'; document.body.appendChild(iframe);var doc = iframe.contentWindow.document; doc.open(); doc.write(html); doc.close();// صبر کوتاه برای رندر فونت‌ها setTimeout(function(){ iframe.contentWindow.focus(); iframe.contentWindow.print(); setTimeout(function(){ document.body.removeChild(iframe); }, 500); }, 100); });const DIGITS_EN = ['0','1','2','3','4','5','6','7','8','9']; const DIGITS_FA = ['۰','۱','۲','۳','۴','۵','۶','۷','۸','۹'];function toFaDigits(s){ return (''+s).replace(/[0-9]/g, d => DIGITS_FA[d]); } function formatToman(n){ n = parseFloat(n||0) || 0; let s = Math.round(n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, "٬"); s = toFaDigits(s); return s + ' تومان'; } function parseMoneyFa(s){ if(typeof s==='number') return s; s = (s||'').toString().replace(/[\s,]/g,'').replace(/تومان/g,'').trim(); for(let i=0;i<10;i++){ s = s.split(DIGITS_FA[i]).join(DIGITS_EN[i]); } s = s.replace(/٬/g,''); const v = parseFloat(s); return isNaN(v)?0:v; }// Row template function newRow(){ const tr = $('').append( $('').append( $(''), $('').append(''), $('').append(''), $('').append(''), $('').append(''), $('').append('') ); return tr; }// state: sum of existing payments from customer (loaded), to show with prepayment let loadedCustomerPaid = 0;function recalc(){ let items_total=0, discount_total=0; $('#jmbj-items tbody tr').each(function(){ const type = $('.line-type', this).val(); const qty = parseFloat($('.qty', this).val()||0); const unit = parseMoneyFa($('.unit', this).val()); let lt = qty * unit; if(type==='discount') lt = -Math.abs(lt); $('.ltotal', this).val(formatToman(lt)); if(type==='discount') discount_total += Math.abs(lt); else items_total += lt; }); const gross = items_total - discount_total; const prepayment = parseMoneyFa($('input[name="prepayment"]').val()); const flow = $('input[name="payment_flow"]:checked').val(); const totalInvoicesSum = parseFloat($('#jmbj_total_invoices_sum').val() ?? 0);const customer_payable = Math.max(0, gross - prepayment);// (1) مبلغ پرداختی مشتری = prepayment + existing from_customer payments //const customer_paid_total = prepayment + loadedCustomerPaid; const customer_paid_total = prepayment; let commission_input = $('#jmbj_commission_percent'); let commission_rate = 0; if(commission_input.length){ commission_rate = parseFloat(commission_input.val()||0); } let invoice_commission = customer_payable * (commission_rate/100); let total_commission = Math.max(0, gross) * (commission_rate/100);// We don't have commission client-side; server sends back post-save $('[data-key="items_total"]').text(formatToman(items_total)); $('[data-key="discount_total"]').text(formatToman(discount_total)); $('[data-key="customer_payable"]').text(formatToman(customer_payable)); $('[data-key="provider_income"]').text(formatToman(Math.max(0, gross) - total_commission)); // temp $('[data-key="customer_paid_total"]').text(formatToman(customer_paid_total)); $('[data-key="commission_total"]').text(formatToman(total_commission)); }function gatherItems(){ const items=[]; $('#jmbj-items tbody tr').each(function(){ if($('.title', this).val() !== ''){ items.push({ line_type: $('.line-type', this).val(), title: $('.title', this).val(), description: $('.desc', this).val(), qty: parseFloat($('.qty', this).val()||0), unit_price: parseMoneyFa($('.unit', this).val()) }); } }); return items; }function toggleMiniPay(){ const flow = $('input[name="payment_flow"]:checked').val(); $('#jmbj-mini-pay').css('display', flow==='indirect' ? '' : 'none'); }function hydrate(inv, items, pays, paidSum,totalSum){ // paid sum loadedCustomerPaid = parseFloat(paidSum||0) || 0; //loadedCustomerPaid += inv.prepayment || 0; // header $('input[name="invoice_number"]').val(inv.invoice_number || ''); $('select[name="status"]').val(inv.status || 'sent'); $('input[name="prepayment"]').val(formatToman(inv.prepayment || 0)); $('#jmbj_total_invoices_sum').val(totalSum||0); if (inv.payment_flow) $('input[name="payment_flow"][value="'+inv.payment_flow+'"]').prop('checked', true);// rows const tb = $('#jmbj-items tbody').empty(); if(items && items.length){ items.forEach(it=>{ const tr = newRow(); $('.line-type', tr).val(it.line_type); $('.title', tr).val(it.title); $('.desc', tr).val(it.description); $('.qty', tr).val(it.qty); $('.unit', tr).val(formatToman(it.unit_price)); tb.append(tr); }); } else { tb.append(newRow()); }toggleMiniPay(); recalc(); }function loadInvoice() { const wrap = $('.jmbj-invoice'); if(!wrap.length) return; const invoice_id = wrap.data('invoice')||''; const appointment_id = wrap.data('appointment')||''; $.get(JMBJ_INV.ajaxUrl, { action:'jmbj_get_invoice', nonce: JMBJ_INV.nonce, invoice_id, appointment_id }).done(res=>{ if(res.ok) hydrate(res.invoice, res.items, res.payments, res.customer_paid_total,res.total_invoices_sum); }); }// Suggest box let suggestFor = null; $(document) .on('input', '#jmbj-items .title', function(){ const q = $(this).val().trim(); suggestFor = $(this).closest('tr'); if(q.length < 2) { $('#jmbj-suggest').attr('hidden', true); return; } $.get(JMBJ_INV.ajaxUrl, { action:'jmbj_search_service_prices', nonce:JMBJ_INV.nonce, q }) .done(res=>{ const box = $('#jmbj-suggest'), list = $('.jmbj-suggest-list', box).empty(); if(!res.ok || !res.items.length){ box.attr('hidden', true); return; } res.items.forEach(it=>{ const li = $('
  • ').append( $('
    ').text(it.title || ''), $('').text((it.type === 'fixed' ? 'ثابت' : 'متغیر') + (it.price? (' | '+formatToman(it.price)) : '')) ).data('it', it); list.append(li); }); box.removeAttr('hidden'); }); }) .on('click', '#jmbj-suggest li', function(){ const it = $(this).data('it'); if(!suggestFor || !it) return; $('.title', suggestFor).val(it.title||''); $('.desc', suggestFor).val(it.description||''); $('.qty', suggestFor).val(1); $('.unit', suggestFor).val(formatToman(it.price||0)).prop('readonly', (it.type==='fixed')); $('#jmbj-suggest').attr('hidden', true); recalc(); });// Buttons and events $(document) .on('click', '#jmbj-add-row', function(){ $('#jmbj-items tbody').append(newRow()); }) .on('click', '.jmbj-del', function(){ $(this).closest('tr').remove(); recalc(); }) .on('input change', '#jmbj-items input, #jmbj-items select, input[name="payment_flow"], input[name="prepayment"]', function(){ toggleMiniPay(); recalc(); });// format .jmbj-money on focus/blur $(document).on('focus', '.jmbj-money', function(){ this.select(); }); $(document).on('blur', '.jmbj-money', function(){ $(this).val(formatToman(parseMoneyFa($(this).val()))); });function fgiga_notification(type = 'success', message = '') { if(type === 'success'){ $('body').append('
    موفق
    '+message+'
    '); setTimeout(function (){ $('.fgiga_notification').addClass('fgiga_notification_show'); },100); setTimeout(function (){ $('.fgiga_notification').removeClass('fgiga_notification_show'); },5000); setTimeout(function (){ $('.fgiga_notification').remove(); },5100); let i = 0; let intervalID = setInterval(function () { $('.fgiga_notification').find('.fgiga_notification_timeline').css('width',i+'%'); i += 1; if(i > 100) clearInterval(intervalID); },50); } else{ $('body').append('
    ناموفق
    '+message+'
    '); setTimeout(function (){ $('.fgiga_notification').addClass('fgiga_notification_show'); },100); setTimeout(function (){ $('.fgiga_notification').removeClass('fgiga_notification_show'); },5000); setTimeout(function (){ $('.fgiga_notification').remove(); },5100); let i = 0; let intervalID = setInterval(function () { $('.fgiga_notification').find('.fgiga_notification_timeline').css('width',i+'%'); i += 1; if(i > 100) clearInterval(intervalID); },50); } } // Save invoice $(document).on('click', '#jmbj-save-invoice', function(){ let button = $(this); let beforehtml = button.html(); if(!gatherItems().length){ fgiga_notification('danger', 'حداقل یک مورد باید وارد کنید!'); return; } const wrap = $('.jmbj-invoice'); const flow = $('input[name="payment_flow"]:checked').val(); const payload = { appointment_id: wrap.data('appointment')||'', invoice_id: wrap.data('invoice')||'', order_id: wrap.data('order')||'', payment_flow: flow, status: $('select[name="status"]').val(), invoice_number: $('input[name="invoice_number"]').val(), prepayment: $('input[name="prepayment"]').val(), items: gatherItems() };if (flow==='indirect') { payload.mini_amount = $('#mini-amount').val(); payload.mini_method = $('#mini-method').val(); payload.mini_ref = $('#mini-ref').val(); payload.mini_bank = $('#mini-bank').val(); payload.mini_at = $('#mini-at').val(); }$.ajax({ url:JMBJ_INV.ajaxUrl+'?action=jmbj_save_invoice&nonce='+JMBJ_INV.nonce, method:'POST', data: JSON.stringify(payload), contentType:'application/json', beforeSend: function (response) { button.html('...'); button.attr('disabled', 'disabled'); }, complete: function (response) { button.html(beforehtml); button.removeAttr('disabled'); }, }).done(res=>{ if(!res.ok) { $('#jmbj-result').css('color','#dc2626').text(res.error||'خطا'); return; } $('#jmbj-result').css('color','#059669').html(res.message || 'ذخیره شد'); if(res.invoice_id){ wrap.attr('data-invoice', res.invoice_id); }// reflect totals from server if(res.calc){ $('[data-key="commission_total"]').text(formatToman(res.calc.commission_total || 0)); $('[data-key="provider_income"]').text(formatToman(res.calc.provider_income || 0)); $('[data-key="customer_payable"]').text(formatToman(res.calc.customer_payable || 0)); }// Direct flow: show pay link (order created automatically) if (res.pay_url) { $('#jmbj-result').append(' — لینک پرداخت مشتری'); }// refresh to update "مبلغ پرداختی مشتری" (prepayment + new payments) loadInvoice(); }); });// -------- INVOICE LIST (modal) -------- $(document) .on('click', '.jmbj-view-inv', function(){ let button = $(this); let beforehtml = button.html(); const id = $(this).data('id'); const user_panel = $(this).data('user_panel') === 'true'; button.html('...'); button.attr('disabled', 'disabled'); $.get(JMBJ_INV.ajaxUrl, { action:'jmbj_render_invoice', nonce:JMBJ_INV.nonce, invoice_id:id,user_panel:user_panel }) .always(function (response) { button.html(beforehtml); button.removeAttr('disabled'); }) .done(res=>{ if(!res.ok) return alert(res.error||'خطا'); $('#jmbj-modal-content').html(res.html); // if indirect enable pay box const flow = $('tr[data-inv="'+id+'"]').data('flow'); const status = $('tr[data-inv="'+id+'"]').data('status'); $('#jmbj-modal-pay').toggle(flow==='indirect' && status !== 'paid').attr('data-id', id); /*$('#jmbj-modal').removeAttr('hidden');*/ $('#view_invoice_popup').addClass('fgiga_popup_show'); }); }) .on('click', '.jmbj-modal-close', function(){ $('#jmbj-modal').attr('hidden', true); }) .on('click', '#mod-addpay', function(){ const invoice_id = $('#jmbj-modal-pay').attr('data-id'); const payload = { invoice_id, direction:'from_customer', method: $('#mod-method').val(), amount: $('#mod-amount').val(), reference: $('#mod-ref').val(), bank_name: $('#mod-bank').val(), paid_at: $('#mod-at').val() }; $.ajax({ url:JMBJ_INV.ajaxUrl+'?action=jmbj_add_payment&nonce='+JMBJ_INV.nonce, method:'POST', data: JSON.stringify(payload), contentType:'application/json' }).done(res=>{ if(!res.ok) return $('#mod-result').css('color','#dc2626').text(res.error||'خطا'); $('#mod-result').css('color','#059669').text('پرداخت ثبت شد.'); // refresh invoice HTML in modal $('.jmbj-view-inv[data-id="'+invoice_id+'"]').trigger('click'); }); });$(function(){ loadInvoice(); toggleMiniPay(); });})(jQuery); //# sourceURL=jmbj-invoice-js-js-after