Invoices

PT ENOS TOUR MEDAN — Invoice :root{–ink:#122425;–muted:#6c7a7a;–line:#dce7e5;–brand:#0b5d5a;–paper:#fff;–canvas:#f3f7f6;–gold:#d99b38;–shadow:0 14px 40px #0a2b2917}*{box-sizing:border-box}body{margin:0;color:var(–ink);background:var(–canvas);font:14px/1.5 Inter,system-ui,”Segoe UI”,sans-serif}button,input,select,textarea{font:inherit}button{cursor:pointer}.topbar{min-height:72px;display:flex;align-items:center;justify-content:space-between;gap:20px;padding:12px clamp(18px,5vw,72px);background:#fff;border-bottom:1px solid var(–line)}.brand{display:flex;align-items:center;gap:12px;color:var(–ink);text-decoration:none}.brand-logo{width:48px;height:48px;object-fit:contain;border-radius:50%}.brand strong,.brand small{display:block}.brand strong{font-size:15px;letter-spacing:.06em}.brand small{color:var(–muted);font-size:11px}.nav{display:flex;flex-wrap:wrap;gap:13px}.nav a{color:var(–brand);font-size:13px;font-weight:750;text-decoration:none}.lang-select{padding:7px 9px;border:1px solid var(–line);border-radius:8px;background:#fff;color:var(–brand);font-weight:700}main{max-width:1360px;margin:auto;padding:32px clamp(18px,5vw,72px) 55px}.intro{margin-bottom:22px}.eyebrow{color:var(–brand);font-size:12px;font-weight:800;letter-spacing:.12em}h1{margin:5px 0;font-size:clamp(27px,4vw,38px);letter-spacing:-.04em}.intro p{margin:5px 0;color:var(–muted)}.layout{display:grid;grid-template-columns:minmax(280px,.7fr) minmax(0,1.5fr);gap:20px;align-items:start}.card{border:1px solid var(–line);border-radius:15px;background:#fff;box-shadow:var(–shadow)}.form-card{padding:22px;position:sticky;top:16px}.form-card h2,.list-head h2{margin:0 0 16px;font-size:18px}.fields{display:grid;gap:12px}.field{display:grid;gap:5px}.field label{font-size:12px;font-weight:750;color:#485756}.field input,.field select,.field textarea{width:100%;padding:10px 11px;border:1px solid #cbdad7;border-radius:8px;background:#fff;color:var(–ink)}.field textarea{min-height:72px;resize:vertical}.hint{padding:10px;border-radius:8px;color:#48605d;background:#f1f6f5;font-size:12px}.actions,.row-actions{display:flex;gap:8px}.actions{margin-top:16px}.btn{border:0;border-radius:8px;padding:10px 13px;font-weight:750}.primary{flex:1;color:white;background:var(–brand)}.secondary,.smallbtn{color:var(–brand);background:#edf3f2}.content{display:grid;gap:18px}.invoice-wrap{padding:20px;overflow:auto}.invoice{min-width:550px;max-width:850px;margin:auto;padding:30px;border:1px solid var(–line);border-radius:10px;background:white}.invoice-head{display:flex;justify-content:space-between;gap:20px;padding-bottom:19px;border-bottom:2px solid var(–brand)}.invoice-brand{display:flex;align-items:center;gap:11px}.invoice-brand img{width:58px;height:58px;object-fit:contain}.invoice-brand strong,.invoice-brand small{display:block}.invoice-brand small,.muted{color:var(–muted);font-size:12px}.invoice-title{text-align:right}.invoice-title h2{margin:0;color:var(–brand);font-size:26px;letter-spacing:.08em}.billto,.details{display:grid;grid-template-columns:1fr 1fr;gap:15px 20px;padding:19px 0}.details{border-block:1px solid var(–line)}.label{color:var(–muted);font-size:10px;font-weight:800;letter-spacing:.09em}.value{font-weight:700}.table{width:100%;margin-top:16px;border-collapse:collapse}.table th,.table td{padding:10px;border-bottom:1px solid var(–line);text-align:left}.table th{color:var(–muted);font-size:10px}.table td:last-child,.table th:last-child{text-align:right}.total{display:flex;justify-content:flex-end;gap:25px;margin-top:17px;font-size:18px;font-weight:800}.total strong{color:var(–brand)}.notes{margin-top:19px;padding:12px;border-left:3px solid var(–gold);background:#fffaf1;white-space:pre-wrap}.foot{display:flex;justify-content:space-between;gap:18px;margin-top:28px;padding-top:14px;border-top:1px solid var(–line);color:var(–muted);font-size:11px}.empty-preview,.no-data{padding:38px 18px;text-align:center;color:var(–muted)}.list-card{overflow:hidden}.list-head{padding:17px 19px;border-bottom:1px solid var(–line)}.table-scroll{overflow:auto}.records{width:100%;border-collapse:collapse;white-space:nowrap}.records th,.records td{padding:11px 12px;border-bottom:1px solid var(–line);text-align:left}.records th{background:#fafcfb;color:var(–muted);font-size:10px}.records td select{max-width:145px;padding:5px;border:1px solid var(–line);border-radius:6px}.smallbtn{padding:6px 8px;border:1px solid var(–line);border-radius:6px;font-size:11px;font-weight:700}.smallbtn.delete{color:#a32b23;background:#fff0ef}.status{padding:3px 7px;border-radius:99px;background:#fff3df;color:#916100;font-size:11px;font-weight:750}.edit-table{width:100%;min-width:500px;border-collapse:collapse;font-size:12px}.edit-table th,.edit-table td{padding:6px;border:1px solid var(–line);text-align:left}.edit-table input{width:78px;padding:6px;border:1px solid var(–line);border-radius:5px}.edit-table input[data-desc]{width:145px}.line-total{text-align:right;margin-top:8px}.payment{margin-top:20px;padding:14px;border:1px solid var(–line);border-radius:8px;background:#f8fbfa}.payment h3{margin:0 0 7px;color:var(–brand);font-size:12px;letter-spacing:.08em}.words{margin-top:13px;padding:11px;border:1px solid var(–line);background:#f4f8fb;font-style:italic}@media(max-width:930px){.layout{grid-template-columns:1fr}.form-card{position:static}}@media(max-width:650px){.topbar{align-items:flex-start;flex-direction:column}.nav{gap:10px}main{padding:24px 14px 38px}.invoice-wrap,.form-card{padding:14px}.invoice{min-width:520px;padding:19px}.foot{flex-direction:column}}@media print{body{background:white}.topbar,.intro,.form-card,.list-card{display:none!important}main,.layout,.content{display:block;padding:0}.invoice-wrap,.card{padding:0;border:0;box-shadow:none;overflow:visible}.invoice{width:100%;max-width:none;min-width:0;padding:14mm;border:0}}
PT ENOS TOUR MEDANINVOICE MANAGEMENTBahasa IndonesiaEnglish
TAGIHAN PERJALANAN

Invoice

Pilih booking untuk mengisi detail perjalanan secara otomatis.

Preview invoice
Pilih booking dan isi jumlah tagihan.

Invoice Tersimpan

No. InvoiceBookingAgent / TamuTanggalJatuh TempoTotalStatusAksi
(function(){ var BOOKING_KEY=’enos-tour-medan-booking-list-v1′,GUEST_KEY=’enos-tour-medan-guest-list-v1′,INVOICE_KEY=’enos-tour-medan-invoice-list-v1′; var samples=[{id:’b1′,no:1,agent:’Nusantara Holiday’,guestName:’Budi Santoso’,package:’Danau Toba & Samosir’,start:’2026-09-18′,end:’2026-09-20′,adult:4,kid:1,infant:0,partnerItems:[{partner:’Grand Mercure Medan — Hotel’}]},{id:’b2′,no:2,agent:’Wonderful Travel’,guestName:’Siti Nur Aisyah’,package:’Medan – Berastagi – Danau Toba’,start:’2026-09-25′,end:’2026-09-28′,adult:8,kid:2,infant:1,partnerItems:[{partner:’Grand Mercure Medan — Hotel’},{partner:’Restoran Tip Top — Restaurant’}]}]; var $=function(id){return document.getElementById(id)},form=$(‘invoiceForm’),select=$(‘bookingSelect’),lineBody=$(‘lineItems’),bookings=[],invoices=[],editingIndex=-1,editingBooking=null; function esc(v){return String(v==null?”:v).replace(/[&”‘]/g,function(c){return {‘&’:’&’,”:’>’,'”‘:’"’,”‘”:’'’}[c]})} function arr(key,fallback){try{var x=JSON.parse(localStorage.getItem(key));return Array.isArray(x)?x:fallback}catch(e){return fallback}} function persist(){localStorage.setItem(INVOICE_KEY,JSON.stringify(invoices))} function today(){var d=new Date();return d.getFullYear()+’-‘+String(d.getMonth()+1).padStart(2,’0′)+’-‘+String(d.getDate()).padStart(2,’0′)} function plusDays(v,n){var d=new Date(v+’T00:00:00′);d.setDate(d.getDate()+n);return d.getFullYear()+’-‘+String(d.getMonth()+1).padStart(2,’0′)+’-‘+String(d.getDate()).padStart(2,’0’)} var lang=localStorage.getItem(‘mvt-invoice-language’)===’en’?’en’:’id’; var translations={‘INVOICE MANAGEMENT’:’Manajemen Invoice’,’Daftar Agent’:’Agent List’,’Daftar Booking’:’Booking List’,’Daftar Partner’:’Partner List’,’Voucher’:’Voucher’,’TAGIHAN PERJALANAN’:’TRAVEL BILLING’,’Pilih booking untuk mengisi detail perjalanan secara otomatis.’:’Select a booking to fill in trip details automatically.’,’Buat Invoice’:’Create Invoice’,’Edit Invoice’:’Edit Invoice’,’Pilih Booking *’:’Select Booking *’,’Pilih booking’:’Select booking’,’Pilih booking untuk mengambil data agent, tamu, paket, periode, dan peserta.’:’Select a booking to load agent, guest, package, travel dates, and passenger details.’,’Nomor Invoice *’:’Invoice Number *’,’Tanggal Invoice *’:’Invoice Date *’,’Jatuh Tempo *’:’Due Date *’,’Mata Uang’:’Currency’,’Rincian Tagihan’:’Billing Details’,’Deskripsi’:’Description’,’Pax’:’Pax’,’Price’:’Price’,’Amount’:’Amount’,’+ Tambah Baris’:’+ Add Row’,’Total:’:’Total:’,’Status Pembayaran’:’Payment Status’,’Belum dibayar’:’Unpaid’,’DP dibayar’:’Deposit Paid’,’Lunas’:’Paid in Full’,’Terlambat’:’Overdue’,’Dibatalkan’:’Cancelled’,’Catatan / Rincian’:’Notes / Details’,’Instruksi pembayaran atau rincian tambahan’:’Payment instructions or additional details’,’Simpan Invoice’:’Save Invoice’,’Simpan Perubahan’:’Save Changes’,’Reset’:’Reset’,’Batal Edit’:’Cancel Edit’,’Preview invoice’:’Invoice preview’,’Pilih booking dan isi jumlah tagihan.’:’Select a booking and enter the billing amount.’,’Invoice Tersimpan’:’Saved Invoices’,’No. Invoice’:’Invoice No.’,’Booking’:’Booking’,’Agent / Tamu’:’Agent / Guest’,’Tanggal’:’Date’,’Total’:’Total’,’Status’:’Status’,’Aksi’:’Actions’,’Belum ada invoice tersimpan.’:’No invoices saved yet.’,’Lihat / Cetak’:’View / Print’,’Edit’:’Edit’,’Hapus’:’Delete’,’DESCRIPTION’:’DESCRIPTION’,’PRICE’:’PRICE’,’AMOUNT’:’AMOUNT’,’DITAGIHKAN KEPADA’:’BILLED TO’,’STATUS PEMBAYARAN’:’PAYMENT STATUS’,’KODE BOOKING’:’BOOKING CODE’,’PAKET WISATA’:’TOUR PACKAGE’,’PERIODE PERJALANAN’:’TRAVEL DATES’,’JUMLAH PESERTA’:’PASSENGER COUNT’,’Jatuh Tempo’:’Due Date’,’TOTAL’:’TOTAL’,’TERBILANG’:’IN WORDS’,’Invoice perjalanan wisata’:’Travel Invoice’,’Nomor invoice’:’Invoice number’,’PIC Agent:’:’Agent Contact:’,’Phone:’:’Phone:’,’Email:’:’Email:’,’Address:’:’Address:’,’Adult ‘:’Adult ‘,’ · Kid ‘:’ · Child ‘,’ · Infant ‘:’ · Infant ‘,’PAYMENT TO’:’PAYMENT TO’,’Catatan:’:’Notes:’,’Terima kasih telah memilih PT ENOS TOUR MEDAN.’:’Thank you for choosing PT ENOS TOUR MEDAN.’,’Cantumkan nomor invoice saat pembayaran.’:’Please include the invoice number with your payment.’,’ peserta’:’ passengers’,’Nomor invoice sudah digunakan.’:’This invoice number is already in use.’,’Invoice tersimpan. Gunakan Lihat / Cetak untuk mencetak atau menyimpan sebagai PDF.’:’Invoice saved. Use View / Print to print or save as PDF.’,’Hapus invoice ‘:’Delete invoice ‘}; function tr(s){var keys=Object.keys(translations);if(lang===’id’){keys.forEach(function(k){s=s.split(translations[k]).join(k)});return s}keys.forEach(function(k){s=s.split(k).join(translations[k])});return s} function localize(root){if(!root)return;var walker=document.createTreeWalker(root,NodeFilter.SHOW_TEXT),node;while(node=walker.nextNode())node.nodeValue=tr(node.nodeValue);Array.from(root.querySelectorAll(‘[placeholder],[aria-label]’)).forEach(function(el){[‘placeholder’,’aria-label’].forEach(function(a){if(el.hasAttribute(a))el.setAttribute(a,tr(el.getAttribute(a)))})})} function applyLanguage(){lang=$(‘languageSelect’).value===’en’?’en’:’id’;localStorage.setItem(‘mvt-invoice-language’,lang);document.documentElement.lang=lang;localize(document.querySelector(‘main’));localize(document.querySelector(‘.topbar’));localize(lineBody);localize($(‘invoiceRows’));localize($(‘previewWrap’));var statuses=[‘Belum dibayar’,’DP dibayar’,’Lunas’,’Terlambat’,’Dibatalkan’];Array.from($(‘paymentStatus’).options).forEach(function(o,i){o.value=statuses[i]});Array.from($(‘invoiceRows’).querySelectorAll(‘select[data-status]’)).forEach(function(sel){var i=Number(sel.dataset.status);Array.from(sel.options).forEach(function(o,j){o.value=statuses[j];o.selected=statuses[j]===invoices[i].status})})} function date(v){return v?new Intl.DateTimeFormat(lang===’en’?’en-MY’:’id-ID’,{day:’2-digit’,month:’long’,year:’numeric’}).format(new Date(v+’T00:00:00′)):’—’} function currency(){return $(‘currency’).value||’MYR’} function money(v,c){return new Intl.NumberFormat(lang===’en’?’en-MY’:’id-ID’,{style:’currency’,currency:c||currency(),maximumFractionDigits:0}).format(Number(v||0))} function words(n){var a=[‘nol’,’satu’,’dua’,’tiga’,’empat’,’lima’,’enam’,’tujuh’,’delapan’,’sembilan’,’sepuluh’,’sebelas’];n=Math.floor(Math.abs(Number(n)||0));if(n<12)return a[n];if(n<20)return words(n-10)+' belas';if(n<100)return words(Math.floor(n/10))+' puluh'+(n%10?' '+words(n%10):'');if(n<200)return 'seratus'+(n-100?' '+words(n-100):'');if(n<1000)return words(Math.floor(n/100))+' ratus'+(n%100?' '+words(n%100):'');if(n<2000)return 'seribu'+(n-1000?' '+words(n-1000):'');var scales=[[1e12,' triliun'],[1e9,' miliar'],[1e6,' juta'],[1e3,' ribu']];for(var i=0;i=unit){var q=Math.floor(n/unit),r=n%unit;return words(q)+scales[i][1]+(r?’ ‘+words(r):”)}}return String(n)} function wordsEn(n){var a=[‘zero’,’one’,’two’,’three’,’four’,’five’,’six’,’seven’,’eight’,’nine’,’ten’,’eleven’,’twelve’,’thirteen’,’fourteen’,’fifteen’,’sixteen’,’seventeen’,’eighteen’,’nineteen’],t=[”,”,’twenty’,’thirty’,’forty’,’fifty’,’sixty’,’seventy’,’eighty’,’ninety’];n=Math.floor(Math.abs(Number(n)||0));if(n<20)return a[n];if(n<100)return t[Math.floor(n/10)]+(n%10?' '+a[n%10]:'');if(n<1000)return a[Math.floor(n/100)]+' hundred'+(n%100?' '+wordsEn(n%100):'');var s=[[1e9,' billion'],[1e6,' million'],[1e3,' thousand']];for(var i=0;i=s[i][0])return wordsEn(Math.floor(n/s[i][0]))+s[i][1]+(n%s[i][0]?’ ‘+wordsEn(n%s[i][0]):”);return String(n)} function inWords(amount,c){return (lang===’en’?wordsEn(amount)+(c===’IDR’?’ rupiah’:’ Malaysian ringgit’):words(amount)+’ ‘+(c===’IDR’?’rupiah’:’Ringgit Malaysia’))} function booking(){return bookings.find(function(b){return String(b.id)===select.value})||(editingBooking&&String(editingBooking.id)===select.value?editingBooking:null)} function agentContact(name){return arr(GUEST_KEY,[]).find(function(g){return String(g.agent||”).trim().toLowerCase()===String(name||”).trim().toLowerCase()})||{}} function partners(b){var p=Array.isArray(b.partnerItems)?b.partnerItems:[];return p.map(function(x){return x.partner}).filter(Boolean).join(‘, ‘)||b.partner||’—’} function readLines(){return Array.from(lineBody.querySelectorAll(‘tr’)).map(function(row){var desc=row.querySelector(‘[data-desc]’).value.trim(),pax=Number(row.querySelector(‘[data-pax]’).value||0),price=Number(row.querySelector(‘[data-price]’).value||0);return {description:desc,pax:pax,price:price,amount:pax*price}}).filter(function(x){return x.description||x.pax||x.price})} function total(lines){return lines.reduce(function(sum,x){return sum+Number(x.amount||0)},0)} function addLine(item){var row=document.createElement(‘tr’);row.innerHTML=’‘+money(0)+’‘;if(item){row.querySelector(‘[data-desc]’).value=item.description||”;row.querySelector(‘[data-pax]’).value=item.pax==null?1:item.pax;row.querySelector(‘[data-price]’).value=item.price==null?0:item.price}lineBody.appendChild(row);localize(row)} function updateLineAmounts(){Array.from(lineBody.querySelectorAll(‘tr’)).forEach(function(row){var pax=Number(row.querySelector(‘[data-pax]’).value||0),price=Number(row.querySelector(‘[data-price]’).value||0);row.querySelector(‘[data-amount]’).textContent=money(pax*price)});$(‘draftTotal’).textContent=money(total(readLines()));preview()} function refreshBookings(){bookings=arr(BOOKING_KEY,samples);var old=select.value;select.innerHTML=’Pilih booking’+bookings.map(function(b){return ”+String(b.no||”).padStart(3,’0′)+’ — ‘+esc(b.agent)+(b.guestName?’ / ‘+esc(b.guestName):”)+’ — ‘+esc(b.package)+”}).join(”);select.value=old;localize(select);info();preview()} function info(){var b=booking();$(‘bookingInfo’).innerHTML=b?’‘+esc(b.agent)+’‘+(b.guestName?’ · ‘+esc(b.guestName):”)+’
‘+esc(b.package)+’
‘+date(b.start)+’ – ‘+date(b.end)+’ · ‘+(Number(b.adult||0)+Number(b.kid||0)+Number(b.infant||0))+’ peserta’:’Pilih booking untuk mengisi detail perjalanan.’;localize($(‘bookingInfo’))} function draft(){var b=booking();if(!b)return null;var contact=agentContact(b.agent),lines=readLines();return {number:$(‘invoiceNumber’).value.trim(),bookingId:b.id,bookingNo:b.no,agent:b.agent,guestName:b.guestName||”,agentPic:contact.pic||”,agentPhone:contact.phone||”,agentEmail:contact.email||”,agentAddress:contact.country||contact.address||”,package:b.package,start:b.start,end:b.end,adult:Number(b.adult||0),kid:Number(b.kid||0),infant:Number(b.infant||0),date:$(‘invoiceDate’).value,due:$(‘dueDate’).value,currency:currency(),lineItems:lines,amount:total(lines),status:$(‘paymentStatus’).value,notes:$(‘notes’).value.trim()}} function show(data){if(!data)return’
Preview invoice
Pilih booking dan isi rincian tagihan.
‘;var cur=data.currency||’IDR’,lines=Array.isArray(data.lineItems)&&data.lineItems.length?data.lineItems:[{description:data.package||’Paket wisata’,pax:1,price:Number(data.amount||0),amount:Number(data.amount||0)}],sum=total(lines),contact=agentContact(data.agent);return ‘
<img src="” alt=”Logo”>
PT ENOS TOUR MEDANInvoice perjalanan wisata

INVOICE

‘+esc(data.number||’Nomor invoice’)+’‘+date(data.date)+’
DITAGIHKAN KEPADA
‘+esc(data.agent||’—’)+(data.guestName?’ / ‘+esc(data.guestName):”)+’
PIC Agent: ‘+esc(data.agentPic||contact.pic||’—’)+’
Phone: ‘+esc(data.agentPhone||contact.phone||’—’)+’
Email: ‘+esc(data.agentEmail||contact.email||’—’)+’
Address: ‘+esc(data.agentAddress||contact.country||contact.address||’—’)+’
STATUS PEMBAYARAN
‘+esc(data.status||’Belum dibayar’)+’
KODE BOOKING
‘+esc(String(data.bookingNo||”).padStart(3,’0′))+’
JATUH TEMPO
‘+date(data.due)+’
PAKET WISATA
‘+esc(data.package||’—’)+’
PERIODE PERJALANAN
‘+date(data.start)+’ – ‘+date(data.end)+’
JUMLAH PESERTA
Adult ‘+Number(data.adult||0)+’ · Kid ‘+Number(data.kid||0)+’ · Infant ‘+Number(data.infant||0)+’
‘+lines.map(function(x){return ‘‘}).join(”)+’
DESCRIPTIONPAXPRICEAMOUNT
‘+esc(x.description)+’‘+Number(x.pax||0)+’‘+money(x.price,cur)+’‘+money(x.amount,cur)+’
TOTAL‘+money(sum,cur)+’
TERBILANG
‘+esc(inWords(sum,cur))+’

PAYMENT TO

BNI
Acc No : 1938328825
Beneficiary Name : PT MEDAN VACATIONS TRAVEL
‘+(data.notes?’
Catatan:
‘+esc(data.notes)+’
‘:”)+’
Terima kasih telah memilih PT ENOS TOUR MEDAN.PT ENOS TOUR MEDAN
Cantumkan nomor invoice saat pembayaran.
‘} function preview(data){$(‘previewWrap’).innerHTML=show(data===undefined?draft():data);localize($(‘previewWrap’))} function rows(){var el=$(‘invoiceRows’);if(!invoices.length){el.innerHTML=’Belum ada invoice tersimpan.‘;localize(el);return}el.innerHTML=invoices.map(function(x,i){return ‘‘+esc(x.number)+’‘+String(x.bookingNo||”).padStart(3,’0′)+’‘+esc(x.agent)+(x.guestName?’ / ‘+esc(x.guestName):”)+’‘+date(x.date)+’‘+date(x.due)+’‘+money(x.amount,x.currency||’IDR’)+’Belum dibayarDP dibayarLunasTerlambatDibatalkan
‘}).join(”);localize(el);var statuses=[‘Belum dibayar’,’DP dibayar’,’Lunas’,’Terlambat’,’Dibatalkan’];Array.from(el.querySelectorAll(‘select[data-status]’)).forEach(function(sel){var i=Number(sel.dataset.status);Array.from(sel.options).forEach(function(o,j){o.value=statuses[j];o.selected=statuses[j]===invoices[i].status})})} function nextInvoiceNumber(){var max=0;invoices.forEach(function(x){var m=/^MVT-(\d+)$/.exec(String(x.number||”));if(m)max=Math.max(max,Number(m[1]))});return ‘MVT-‘+String(max+1).padStart(3,’0’)} function editInvoice(index){var data=invoices[index];if(!data)return;editingIndex=index;editingBooking=bookings.find(function(b){return String(b.id)===String(data.bookingId)})||{id:data.bookingId,no:data.bookingNo,agent:data.agent,guestName:data.guestName,package:data.package,start:data.start,end:data.end,adult:data.adult,kid:data.kid,infant:data.infant,partnerItems:[{partner:data.partners}]};if(!Array.from(select.options).some(function(o){return o.value===String(data.bookingId)})){var option=document.createElement(‘option’);option.value=String(data.bookingId);option.textContent=String(data.bookingNo||”).padStart(3,’0′)+’ — ‘+(data.agent||”)+(data.guestName?’ / ‘+data.guestName:”)+’ — ‘+(data.package||”);select.appendChild(option)}select.value=String(data.bookingId);$(‘invoiceNumber’).value=data.number||”;$(‘invoiceDate’).value=data.date||today();$(‘dueDate’).value=data.due||plusDays(today(),7);$(‘currency’).value=data.currency||’IDR’;$(‘paymentStatus’).value=data.status||’Belum dibayar’;$(‘notes’).value=data.notes||”;lineBody.innerHTML=”;var lines=Array.isArray(data.lineItems)&&data.lineItems.length?data.lineItems:[{description:data.package||’Paket wisata’,pax:1,price:Number(data.amount||0)}];lines.forEach(addLine);$(‘editorTitle’).textContent=’Edit Invoice’;form.querySelector(‘[type=”submit”]’).textContent=’Simpan Perubahan’;$(‘resetBtn’).textContent=’Batal Edit’;info();updateLineAmounts();localize(document.querySelector(‘.form-card’));form.scrollIntoView({behavior:’smooth’,block:’start’})} function reset(){editingIndex=-1;editingBooking=null;form.reset();$(‘invoiceDate’).value=today();$(‘dueDate’).value=plusDays(today(),7);$(‘invoiceNumber’).value=nextInvoiceNumber();$(‘editorTitle’).textContent=’Buat Invoice’;form.querySelector(‘[type=”submit”]’).textContent=’Simpan Invoice’;$(‘resetBtn’).textContent=’Reset’;select.value=”;lineBody.innerHTML=”;addLine();info();updateLineAmounts();localize(document.querySelector(‘.form-card’))} select.addEventListener(‘change’,function(){info();preview()}); [‘invoiceNumber’,’invoiceDate’,’dueDate’,’paymentStatus’,’notes’,’currency’].forEach(function(id){$(id).addEventListener(‘input’,function(){updateLineAmounts()})}); $(‘currency’).addEventListener(‘change’,updateLineAmounts);lineBody.addEventListener(‘input’,updateLineAmounts); lineBody.addEventListener(‘click’,function(e){if(e.target.hasAttribute(‘data-remove-line’)){e.target.closest(‘tr’).remove();if(!lineBody.children.length)addLine();updateLineAmounts()}}); $(‘addLine’).addEventListener(‘click’,function(){addLine();updateLineAmounts()}); $(‘resetBtn’).addEventListener(‘click’,reset); $(‘languageSelect’).value=lang;$(‘languageSelect’).addEventListener(‘change’,function(){applyLanguage();refreshBookings();rows();updateLineAmounts()}); form.addEventListener(‘submit’,function(e){e.preventDefault();if(!form.reportValidity())return;var data=draft();if(!data)return;if(invoices.some(function(x,i){return i!==editingIndex&&String(x.number||”).toLowerCase()===data.number.toLowerCase()})){alert(tr(‘Nomor invoice sudah digunakan.’));return}if(editingIndex>=0){data.id=invoices[editingIndex].id||String(Date.now());invoices[editingIndex]=data}else{data.id=(crypto.randomUUID?crypto.randomUUID():String(Date.now()));invoices.unshift(data)}persist();rows();reset();preview(data);alert(tr(‘Invoice tersimpan. Gunakan Lihat / Cetak untuk mencetak atau menyimpan sebagai PDF.’))}); $(‘invoiceRows’).addEventListener(‘change’,function(e){if(e.target.dataset.status===undefined)return;invoices[Number(e.target.dataset.status)].status=e.target.value;persist();rows()}); $(‘invoiceRows’).addEventListener(‘click’,function(e){if(e.target.dataset.edit!==undefined){editInvoice(Number(e.target.dataset.edit))}else if(e.target.dataset.print!==undefined){preview(invoices[Number(e.target.dataset.print)]);window.print()}else if(e.target.dataset.delete!==undefined){var n=Number(e.target.dataset.delete);if(confirm(tr(‘Hapus invoice ‘)+invoices[n].number+’?’)){invoices.splice(n,1);persist();rows()}}}); window.addEventListener(‘storage’,function(e){if(e.key===BOOKING_KEY)refreshBookings();if(e.key===GUEST_KEY)preview()}); invoices=arr(INVOICE_KEY,[]);refreshBookings();rows();reset();applyLanguage();refreshBookings();rows();preview() })();

Simple Invoicing

Create clear invoices for tour bookings, partner services, and travel agent transactions—all in one place.
Invoices are clear, vouchers are easy to track, and partner payments stay organized.
John Doe