// ── Inline Code128-B barcode SVG generator (matches barcode.php exactly) ── function genBarcodeSvg(text) { var cs = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.split(''); var P = ['11011001100','11001101100','11001100110','10010011000','10010001100','10001001100','10011001000','10011000100','10001100100','11001001000','11001000100','11000100100','10110011100','10011011100','10011001110','10111001100','10011101100','10011100110','11001110010','11001011100','11001001110','11011100100','11001110100','11100101100','11100100110','11101100100','11100110100','11100110010','11011011000','11011000110','11000110110','10100011000','10001011000','10001000110','10110001000','10001101000','10001100010','11010001000','11000101000','11000100010','10110111000','10110001110','10001101110','10111011000','10111000110','10001110110','11101110110','11010001110','11000101110','11011101000','11011100010','11011101110','11101011000','11101000110','11100010110','11101101000','11101100010','11100011010','11101111010','11001000010','11110001010','10100110000','10100001100','10010110000','10010000110','10000101100','10000100110','10110010000','10110000100','10011010000','10011000010','10000110100','10000110010','11000010010','11001010000','11110111010','11000010100','10001111010','10100111100','10010111100','10010011110','10111100100','10011110100','10011110010','11110100100','11110010100','11110010010','11011011110','11011110110','11110110110','10101111000','10100011110','10001011110','10111101000','10111100010','11110101000','11110100010','10111011110','10111101110','11101011110','11110101110','11010000100','11010010000','11010011100','1100011101011']; var ck=104, bars=P[104]; for(var i=0;i'; svg+=''; var x=pad; for(var i=0;i';x+=sc;} svg+=''+text.replace(/&/g,'&').replace(/'; svg+=''; return svg; } function printSaleInvoice(s, items, payments) { var tpl = invoiceTemplate; var sz; if (tpl === 'thermal') sz = posSlipWidth; else if (tpl === 'a5') sz = 'a5'; else sz = 'a4'; var w = window.open('', '_blank'); w.document.write(buildFullInvoice(s, items, payments, sz)); w.document.close(); } function invoiceItemLabel(it) { var label = it.name || ''; var imei = it.imei_display || (it.imeis && it.imeis.length ? it.imeis.join(', ') : ''); if (imei) { label += '
IMEI: ' + String(imei).replace(/&/g,'&').replace(/'; } return label; } function buildFullInvoice(s, items, payments, size) { var isPos = (size === '58mm' || size === '80mm'); var isA5 = (size === 'a5'); var isA4 = (size === 'a4'); var slipPx = size === '80mm' ? '302px' : '219px'; var slipMm = size === '80mm' ? '80mm' : '58mm'; var barcodeSvg = invOpt.barcode ? genBarcodeSvg(s.invoice_no) : ''; var isPaid = Number(s.due_total) <= 0; var sealColor = isPaid ? '#0a7c42' : '#d32f2f'; var sealText = isPaid ? 'PAID' : 'DUE'; var h = 'Invoice '+s.invoice_no+''; h += '
'; // PAID / DUE seal watermark h += '
'+sealText+'
'; // Header h += '
'; if (invOpt.logo && shopSettings.business_logo_url) { h += ''; } h += '

'+(shopSettings.business_name||'')+'

'; if(invOpt.address && shopSettings.business_address) h += '

'+shopSettings.business_address+'

'; if(invOpt.phone && shopSettings.business_phone) h += '

Phone: '+shopSettings.business_phone+'

'; if(invOpt.branch) h += '

Branch: '+s.branch_name+'

'; h += '
'; // Barcode if(invOpt.barcode) { h += '
'; h += '
Invoice#'+s.invoice_no+'
'; h += barcodeSvg; h += '
Scan this code to search by invoice no in Sales
'; h += '
'; } // Info if (isPos) { h += '
'; if(!invOpt.barcode) h += '
Invoice'+s.invoice_no+'
'; h += '
Date'+s.sale_date+'
'; if(invOpt.customer) h += '
Customer'+(s.customer_name||'Walk-in')+'
'; if(invOpt.customer && s.customer_phone) h += '
Phone'+s.customer_phone+'
'; h += '
Cashier'+s.created_by_name+'
'; h += '
'; } else { h += '
'; if(!invOpt.barcode) h += '
Invoice: '+s.invoice_no+'
'; h += '
Date: '+s.sale_date+'
'; if(invOpt.customer) h += '
Customer: '+(s.customer_name||'Walk-in')+'
'; h += '
'; h += '
Cashier: '+s.created_by_name+'
'; h += '
Status: '+(isPaid?'Paid':'Due')+'
'; h += '
'; } // Items if (isPos) { h += ''; items.forEach(function(it){ h += ''; }); h += '
ItemQAmt
'+invoiceItemLabel(it)+''+Number(it.quantity).toFixed(0)+''+Number(it.line_total).toFixed(2)+'
'; } else { h += ''; h += ''; h += ''; items.forEach(function(it,idx){ h += ''; }); h += '
#ProductQtyPriceDisc.Total
'+(idx+1)+''+invoiceItemLabel(it)+''+Number(it.quantity).toFixed(2)+''+Number(it.unit_price).toFixed(2)+''+Number(it.discount).toFixed(2)+''+Number(it.line_total).toFixed(2)+'
'; } // Summary h += ''; h += ''; if(Number(s.discount_total)>0) h += ''; if(Number(s.membership_discount)>0) h += ''; h += ''; h += ''; if(!isPaid) h += ''; h += ''; h += '
Subtotal'+Number(s.subtotal).toFixed(2)+'
Discount-'+Number(s.discount_total).toFixed(2)+'
Membership-'+Number(s.membership_discount).toFixed(2)+'
Grand Total'+Number(s.grand_total).toFixed(2)+'
Paid'+Number(s.paid_total).toFixed(2)+'
Due'+Number(s.due_total).toFixed(2)+'
Status'+(isPaid?'Paid':'Due')+'
'; // Payments if(invOpt.payments && payments && payments.length) { h += '

Payments

'; payments.forEach(function(p){ h += ''; }); h += '
'+p.method_name+''+Number(p.amount).toFixed(2)+'
'; } // Footer h += '
'; h += '
Thank you for visiting!
'; if(shopSettings.copyright) h += '

'+shopSettings.copyright+'

'; if(shopSettings.powered_by) h += '

'+shopSettings.powered_by+'

'; h += '
'; h += '
'; // .wrap // Print and Close buttons h += '
'; h += ''; h += ''; h += '
'; h += '