fbpx

🌸 ระบบ POS

เลือกสินค้า

รายการขาย

฿
ยังไม่มีสินค้าในรายการ
จำนวนรายการ: 0
ยอดรวมสินค้า: 0.00 ฿
ยอดต้องชำระทั้งสิ้น: 0.00 ฿

ระบุรายละเอียดและราคา

รหัส:
฿

ร้านดอกไม้กลิ่นมาลี

บริษัท ฟลาวเวอส์ ฟอร์ ยู จำกัด
เลขทะเบียน 0105569038310
1511/69 ถ.พหลโยธิน แขวงพญาไท เขตพญาไท กทม. 10400
โทร: 063-7194998 | LINE: @klinmalee | www.klinmaleeflorist.com
ใบเสร็จรับเงิน
เลขที่บิล:
วันที่: เวลา:
รายการสินค้า
ยอดรวมสินค้า (Subtotal)0.00
ยอดที่ชำระ 0.00 ฿

ร้านดอกไม้กลิ่นมาลี

บริษัท ฟลาวเวอส์ ฟอร์ ยู จำกัด
เลขทะเบียน 0105569038310
1511/69 ถ.พหลโยธิน แขวงพญาไท เขตพญาไท กทม. 10400
โทร: 063-7194998 | LINE: @klinmalee | www.klinmaleeflorist.com
INVOICE / ใบแจ้งหนี้
อ้างอิง:
วันที่:
รายการสินค้า
ยอดรวมสินค้า (Subtotal)0.00
ยอดที่ต้องชำระ 0.00 ฿
* หากชำระแล้วให้ส่งสลิป หากส่งแล้วแอดมินตอบช้าให้ทักซ้ำได้เลยครับ/ค่ะ

📊 สรุปยอดขาย

ถึง
1. ยอดขายรวมสินค้า
0.00
2. ภาษีขาย (VAT)
0.00
3. หักต้นทุนแฝง (ค่าส่ง+พัดลม)
0.00
4. ยอดขายสุทธิ (1-3)
0.00
รับเงินสดช่อธนบัตร (ไม่นับยอดขาย)
0.00
รายละเอียดบิล 0 บิล

ร้านดอกไม้กลิ่นมาลี

บริษัท ฟลาวเวอส์ ฟอร์ ยู จำกัด
เลขทะเบียน 0105569038310
1511/69 ถ.พหลโยธิน แขวงพญาไท เขตพญาไท กทม. 10400
โทร: 063-7194998 | LINE: @klinmalee | www.klinmaleeflorist.com
ใบเสร็จรับเงิน
เลขที่บิล:
วันที่:
รายการสินค้า
ยอดรวมสินค้า (Subtotal)0.00
ยอดที่ชำระ 0.00 ฿
ลายเซ็นผู้ขาย / ผู้รับเงิน
ประทับตรา (ถ้ามี)

ร้านดอกไม้กลิ่นมาลี

บริษัท ฟลาวเวอส์ ฟอร์ ยู จำกัด
เลขทะเบียน 0105569038310
1511/69 ถ.พหลโยธิน แขวงพญาไท เขตพญาไท กทม. 10400
โทร: 063-7194998 | LINE: @klinmalee | www.klinmaleeflorist.com
ใบส่งสินค้า
เลขที่บิล:
วันที่:
รายการสินค้า
ขอบพระคุณที่ท่านให้เราส่งความรู้สึกแทนท่าน
หวังว่าครั้งหน้าเราคงมีโอกาสได้รับใช้ท่านอีกครั้งนะครับ/ค่ะ

แก้ไขเลขที่เอกสาร

แก้ไขรายละเอียด

แก้ไขข้อมูลลูกค้า / จัดส่ง

[แจ้งเตือน]

ยกเลิกบิล

กรุณากรอกรหัสผ่านเพื่อยืนยันการยกเลิก
(บิลนี้จะถูกต่อท้ายด้วยเลข -01)

🗑️

ลบบิลถาวร

ข้อมูลบิลนี้จะหายไปจากระบบทันที
กรุณากรอกรหัสผ่านเพื่อยืนยัน

[แจ้งเตือน]

เลขซ้ำ!

เลขที่เอกสารนี้มีในระบบแล้ว
กรุณากรอกรหัสผ่านเพื่อรัน -01 ต่อท้าย

🚨

อันตราย! ล้างข้อมูล

ข้อมูลบิลทั้งหมดจะหายไปและกู้คืนไม่ได้!

ห้ามกดเล่นเด็ดขาด สงวนสิทธิ์เฉพาะแอดมินสูงสุดหรือ CEO เท่านั้น

0 + 0 =

ร้านดอกไม้กลิ่นมาลี

สรุปยอดขาย:
จำนวนบิลรวม
1. ยอดขายรวมสินค้า
2. ภาษีขาย (VAT)
3. หักต้นทุนแฝง(ส่ง+พัดลม)
4. ยอดขายสุทธิ
ยอดรับเงินฝากช่อธนบัตร (ไม่รวมในยอดขาย)
พิมพ์เมื่อ/บันทึกข้อมูลเมื่อ:
'); win.document.close(); } } catch(err) { console.error(err); alert("เกิดข้อผิดพลาดในการสร้างรูปภาพ กรุณาลองใหม่อีกครั้ง"); } if(btn) { btn.innerHTML = originalText; btn.disabled = false; } } function kmpFormatNumber(num) { return Number(num || 0).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2}); } function kmpThaiBaht(amount) { let bahtText = ""; let amount_string = parseFloat(amount || 0).toFixed(2).toString(); let split_amount = amount_string.split("."); let baht = split_amount[0]; let satang = split_amount[1]; const t = ["ศูนย์", "หนึ่ง", "สอง", "สาม", "สี่", "ห้า", "หก", "เจ็ด", "แปด", "เก้า"]; const p = ["", "สิบ", "ร้อย", "พัน", "หมื่น", "แสน", "ล้าน"]; function convert(number_string) { let text = ""; let len = number_string.length; for (let i = 0; i < len; i++) { let n = parseInt(number_string.charAt(i)); if (n !== 0) { if (i === len - 1 && n === 1 && len > 1 && number_string.charAt(i-1) !== '0') { text += "เอ็ด"; } else if (i === len - 2 && n === 2) { text += "ยี่"; } else if (i === len - 2 && n === 1) { text += ""; } else { text += t[n]; } text += p[len - i - 1]; } } return text; } if (baht === "0") { bahtText += "ศูนย์บาท"; } else { let mil_part = ""; let left_baht = baht; while(left_baht.length > 6) { mil_part = left_baht.substring(0, left_baht.length - 6); left_baht = left_baht.substring(left_baht.length - 6); bahtText += convert(mil_part) + "ล้าน"; } bahtText += convert(left_baht) + "บาท"; } if (satang === "00") { bahtText += "ถ้วน"; } else { bahtText += convert(satang) + "สตางค์"; } return "(" + bahtText + ")"; } async function kmpSaveDataToStorage() { try { const dataToSave = { history: kmpSalesHistory, counter: kmpReceiptCounter, counterBackup: kmpReceiptCounterBackup, counterCash: kmpReceiptCounterCash, counterTax: kmpReceiptCounterTax }; const formData = new FormData(); formData.append('action', 'kmp_save_data'); formData.append('kmp_data', JSON.stringify(dataToSave)); await fetch(kmp_ajax_url, { method: 'POST', body: formData }); } catch (e) { console.error(e); } } function kmpLoadDataFromStorage() { try { let jsonStr = kmp_initial_db_data; if (jsonStr && jsonStr !== 'null') { const parsed = JSON.parse(jsonStr); const data = typeof parsed === 'string' ? JSON.parse(parsed) : parsed; kmpSalesHistory = data.history || []; kmpReceiptCounter = data.counter || 1; kmpReceiptCounterBackup = data.counterBackup || 1; kmpReceiptCounterCash = data.counterCash || 1; kmpReceiptCounterTax = data.counterTax || 1; } } catch (e) { console.error(e); } } function kmpRenderProducts() { const grid = document.getElementById('kmp-product-grid'); if(!grid) return; grid.innerHTML = ''; grid.className = "grid grid-cols-3 xl:grid-cols-4 gap-2 md:gap-4"; products.forEach(product => { const card = document.createElement('div'); card.className = 'bg-white p-2 md:p-3 rounded-xl shadow cursor-pointer hover:shadow-md hover:border-pink-300 border border-transparent transition text-center flex flex-col items-center justify-center min-h-[4rem] md:h-32 active:scale-95'; card.onclick = () => kmpOpenAddItemModal(product); card.innerHTML = `
${product.name}
${product.sku}
`; grid.appendChild(card); }); } function kmpOpenAddItemModal(product) { kmpCurrentEditingProduct = product; document.getElementById('kmp-modal-item-sku').innerText = product.sku; document.getElementById('kmp-modal-item-name').innerText = product.name; document.getElementById('kmp-modal-item-detail').value = ''; document.getElementById('kmp-modal-item-price').value = ''; document.getElementById('kmp-modal-item-discount').value = ''; document.getElementById('kmp-modal-special-cost').value = ''; const spContainer = document.getElementById('kmp-special-cost-container'); const spLabel = document.getElementById('kmp-special-cost-label'); const priceLabel = document.getElementById('kmp-main-price-label'); const spDesc = document.getElementById('kmp-special-cost-desc'); if (product.sku === 'WRT-FAN') { spContainer.classList.remove('hidden'); spLabel.innerText = 'ราคาต้นทุนพัดลม (฿):'; spDesc.innerText = '*ยอดนี้จะไม่ถูกบวกเข้าใบเสร็จ (เก็บข้อมูลเพื่อดูรายงานต้นทุน/วางแผนจัดซื้อเท่านั้น)'; priceLabel.innerHTML = 'ราคาขายรวมที่เก็บลูกค้า * :'; } else if (product.sku === 'BQT-CSH') { spContainer.classList.remove('hidden'); spLabel.innerText = 'จำนวนเงินสดที่ใส่ในช่อ (฿):'; spDesc.innerText = '*ยอดนี้จะบวกเพิ่มในบิลเพื่อเก็บเงินลูกค้า แต่ "ไม่ถูกนับเป็นยอดขายรวมของร้าน"'; priceLabel.innerHTML = 'ค่าจัด/ค่าดอกไม้ * :'; } else { spContainer.classList.add('hidden'); priceLabel.innerHTML = 'ราคาขาย * :'; } kmpOpenPane('pane-add-item'); if (product.sku === 'WRT-FAN' || product.sku === 'BQT-CSH') { setTimeout(() => document.getElementById('kmp-modal-special-cost').focus(), 100); } else { setTimeout(() => document.getElementById('kmp-modal-item-price').focus(), 100); } } function kmpCloseAddItemModal() { kmpClosePane('pane-add-item'); } function kmpHandleModalKeyPress(e) { if (e.key === 'Enter') { e.preventDefault(); kmpConfirmAddItem(); } } function kmpConfirmAddItem() { const priceVal = parseFloat(document.getElementById('kmp-modal-item-price').value); let detailVal = document.getElementById('kmp-modal-item-detail').value.trim(); const discountVal = parseFloat(document.getElementById('kmp-modal-item-discount').value); const dType = document.getElementById('kmp-modal-item-discount-type').value; let specialCost = parseFloat(document.getElementById('kmp-modal-special-cost').value); if (isNaN(specialCost) || specialCost < 0) specialCost = 0; if (isNaN(priceVal) || priceVal < 0) return alert('กรุณากรอกราคาขาย(ค่าจัด/ดอกไม้)ให้ถูกต้องครับ'); let revenuePrice = priceVal; let passThroughPrice = 0; let hiddenCost = 0; let autoDetail = ''; // แยกลอจิกพัดลม (ไม่บวกในยอดขาย) กับ ธนบัตร (บวกยอดเก็บเงินลูกค้าแต่ไม่รวมในยอดขาย) if (kmpCurrentEditingProduct.sku === 'WRT-FAN') { revenuePrice = priceVal; // ยอดขายคือยอดที่กรอกเลย ไม่บวกพัดลมเพิ่ม hiddenCost = specialCost; // บันทึกเป็น hiddenCost เพื่อดูรายงานการจัดซื้อ // ไม่ต้องใส่ autoDetail เพื่อไม่ให้ไปโชว์ในใบเสร็จลูกค้า } else if (kmpCurrentEditingProduct.sku === 'BQT-CSH') { revenuePrice = priceVal; // ยอดขายร้านคือค่าจัดเท่านั้น passThroughPrice = specialCost; // เงินฝากช่อ ไม่นับเป็นยอดขาย if (specialCost > 0) autoDetail = `(บวกเงินสดในช่อ ${specialCost}฿)`; } // คำนวณส่วนลด (หักออกจาก revenuePrice) if (discountVal > 0) { if (dType === 'PERCENT') { revenuePrice -= revenuePrice * (discountVal / 100); detailVal += ` [ลด ${discountVal}%]`; } else { revenuePrice -= discountVal; detailVal += ` [ลด ${discountVal}฿]`; } } if (revenuePrice < 0) revenuePrice = 0; let finalDetail = detailVal; if(autoDetail) finalDetail = finalDetail ? `${finalDetail} ${autoDetail}` : autoDetail; const uid = kmpCurrentEditingProduct.sku + '_' + Date.now(); kmpCart.push({ ...kmpCurrentEditingProduct, detail: finalDetail, price: revenuePrice, // ส่วนที่นับเป็นรายได้ (Gross Sales) hiddenCost: hiddenCost, // ต้นทุนแฝง (เช่น พัดลม) ต่อ 1 ชิ้น passThrough: passThroughPrice, // เงินสดฝากช่อ (Pass-through) ต่อ 1 ชิ้น id: uid, qty: 1 }); kmpCloseAddItemModal(); kmpRenderCart(); } function kmpRemoveFromCart(id) { kmpCart = kmpCart.filter(i => i.id !== id); kmpRenderCart(); } function kmpRenderCart() { const cont = document.getElementById('kmp-cart-items'); cont.innerHTML = ''; let tQty = 0; let sumRevenue = 0; // ยอดขายสินค้า let sumPassThrough = 0; // เงินสดฝากช่อ if (kmpCart.length === 0) { cont.innerHTML = '
ยังไม่มีสินค้าในรายการ
'; } else { kmpCart.forEach(item => { tQty += item.qty; const itemRev = item.price * item.qty; sumRevenue += itemRev; sumPassThrough += ((item.passThrough || 0) * item.qty); const div = document.createElement('div'); div.className = 'flex justify-between items-center bg-gray-50 p-3 rounded border border-gray-200'; div.innerHTML = `
${item.name}
${item.detail ? `
↳ ${item.detail}
` : ''}
${kmpFormatNumber(item.price)} ฿ x ${item.qty}
${kmpFormatNumber(itemRev)}
`; cont.appendChild(div); }); } // ระบบคำนวณภาษี const taxType = document.querySelector('input[name="kmp_vat_type"]:checked').value; let subtotal = sumRevenue; let vatAmount = 0; let totalToPay = 0; if (taxType === 'include') { vatAmount = subtotal - (subtotal / 1.07); totalToPay = subtotal + sumPassThrough; } else if (taxType === 'exclude') { let exactVat = subtotal * 0.07; let exactTotal = subtotal + exactVat + sumPassThrough; totalToPay = Math.ceil(exactTotal); // ปัดเศษขึ้นให้เป็นหลักหน่วยเสมอ vatAmount = totalToPay - subtotal - sumPassThrough; // ปรับเศษ VAT ให้ตรงกับยอดที่ปัดแล้ว } else { vatAmount = 0; totalToPay = subtotal + sumPassThrough; } // Update UI Elements document.getElementById('kmp-total-items').innerText = tQty; document.getElementById('kmp-subtotal-price').innerText = kmpFormatNumber(subtotal) + ' ฿'; const vatRow = document.getElementById('kmp-vat-display-row'); if (vatAmount > 0) { vatRow.classList.remove('hidden'); document.getElementById('kmp-vat-price').innerText = kmpFormatNumber(vatAmount) + ' ฿'; vatRow.querySelector('span').innerText = taxType === 'include' ? 'ภาษีมูลค่าเพิ่ม (รวมในยอด):' : 'ภาษีมูลค่าเพิ่ม (บวกเพิ่ม):'; } else { vatRow.classList.add('hidden'); } const passRow = document.getElementById('kmp-passthrough-display-row'); const hasCashBouquet = kmpCart.some(item => item.sku === 'BQT-CSH'); if (sumPassThrough > 0 && hasCashBouquet) { passRow.classList.remove('hidden'); document.getElementById('kmp-passthrough-price').innerText = kmpFormatNumber(sumPassThrough) + ' ฿'; } else { passRow.classList.add('hidden'); } document.getElementById('kmp-total-price').innerText = kmpFormatNumber(totalToPay) + ' ฿'; } function kmpGetLocalIsoDate(d) { return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`; } function kmpPreviewInvoice() { if (kmpCart.length === 0) return alert('กรุณาเลือกสินค้าก่อนครับ'); const pMethod = document.getElementById('kmp-payment-method').value; const d = new Date(); const cusName = document.getElementById('kmp-customer-name').value.trim(); const cusCont = document.getElementById('kmp-customer-contact').value.trim(); const cusPh = document.getElementById('kmp-customer-phone').value.trim(); const dLoc = document.getElementById('kmp-delivery-location').value.trim(); const rPhone = document.getElementById('kmp-recipient-phone').value.trim(); const dDateTimeText = document.getElementById('kmp-delivery-datetime-text').value.trim(); // ใช้เวลาเป็นรหัสอ้างอิงชั่วคราว ไม่กระทบเลขที่บิลหลัก const refNo = 'INV-' + Date.now().toString().slice(-6); const dateStr = kmpGetLocalIsoDate(d); const timeStr = String(d.getHours()).padStart(2,'0')+':'+String(d.getMinutes()).padStart(2,'0'); document.getElementById('kmp-invoice-no').innerText = refNo; document.getElementById('kmp-invoice-time').innerText = `${new Date(dateStr).toLocaleDateString('th-TH',{year:'numeric',month:'short',day:'numeric'})} ${timeStr} น.`; document.getElementById('kmp-invoice-cus-name').innerText = cusName || '-'; document.getElementById('kmp-invoice-cus-contact').innerText = cusCont || '-'; document.getElementById('kmp-invoice-cus-phone').innerText = cusPh || '-'; let dText = dLoc ? dLoc+' ' : ''; if(rPhone) dText += `(โทรผู้รับ: ${rPhone}) `; if(dDateTimeText) dText += `${dDateTimeText}`; document.getElementById('kmp-invoice-delivery-info').innerText = dText.trim(); document.getElementById('kmp-invoice-delivery-wrap').style.display = dText.trim() ? 'block' : 'none'; document.getElementById('kmp-invoice-customer-info').style.display = (cusName || cusCont || cusPh || dText.trim()) ? 'block' : 'none'; let html=''; let sumRevenue = 0; let sumPassThrough = 0; kmpCart.forEach(i => { sumRevenue += i.price * i.qty; sumPassThrough += (i.passThrough || 0) * i.qty; html += `
${i.name} (x${i.qty})${kmpFormatNumber(i.price*i.qty)}
${i.detail?`
- ${i.detail}
`:''}
`; }); document.getElementById('kmp-invoice-items').innerHTML = html; const paymentDetails = document.getElementById('kmp-invoice-payment-details'); if (pMethod === 'โอน กสิกร FLOWERFORYOU') { paymentDetails.innerHTML = `
โอนเงินเข้าบัญชี
ธนาคารกสิกรไทย
บจก. ฟลาวเวอส์ ฟอร์ ยู
229-1-92619-6
`; } else { paymentDetails.innerHTML = `
รายละเอียดช่องทางการชำระเงิน แอดมินจะแจ้งให้ทราบทาง LINE ภายหลัง
`; } const taxType = document.querySelector('input[name="kmp_vat_type"]:checked').value; let subtotal = sumRevenue; let vatAmount = 0; let totalToPay = 0; if (taxType === 'include') { vatAmount = subtotal - (subtotal / 1.07); totalToPay = subtotal + sumPassThrough; } else if (taxType === 'exclude') { let exactVat = subtotal * 0.07; let exactTotal = subtotal + exactVat + sumPassThrough; totalToPay = Math.ceil(exactTotal); // ปัดเศษขึ้นให้เป็นหลักหน่วยเสมอ vatAmount = totalToPay - subtotal - sumPassThrough; // ปรับเศษ VAT ให้ตรงกับยอดที่ปัดแล้ว } else { totalToPay = subtotal + sumPassThrough; } document.getElementById('kmp-invoice-subtotal').innerText = kmpFormatNumber(subtotal); const vatRow = document.getElementById('kmp-invoice-vat-row'); if(vatAmount > 0) { vatRow.classList.remove('hidden'); document.getElementById('kmp-invoice-vat-label').innerText = taxType === 'include' ? 'ภาษีมูลค่าเพิ่ม (รวมแล้ว) 7%' : 'บวกภาษีมูลค่าเพิ่ม 7%'; document.getElementById('kmp-invoice-vat').innerText = kmpFormatNumber(vatAmount); } else { vatRow.classList.add('hidden'); } const passRow = document.getElementById('kmp-invoice-pass-row'); const hasCashBouquet = kmpCart.some(item => item.sku === 'BQT-CSH'); if(sumPassThrough > 0 && hasCashBouquet) { passRow.classList.remove('hidden'); document.getElementById('kmp-invoice-pass').innerText = kmpFormatNumber(sumPassThrough); } else { passRow.classList.add('hidden'); } document.getElementById('kmp-invoice-total').innerText = kmpFormatNumber(totalToPay) + ' ฿'; document.getElementById('kmp-invoice-text-amount').innerText = kmpThaiBaht(totalToPay); kmpOpenPane('pane-invoice'); } function kmpExecuteInvoice() { document.body.classList.add('print-mode-invoice'); window.print(); document.body.classList.remove('print-mode-invoice'); } function kmpProcessCheckout() { if (kmpCart.length === 0) return alert('กรุณาเลือกสินค้าก่อนครับ'); const pMethod = document.getElementById('kmp-payment-method').value; const d = new Date(); const isTax = document.getElementById('kmp-request-tax').checked; let pfix = 'RV', rNoVal = kmpReceiptCounter; if (isTax) { pfix = 'TAX'; rNoVal = kmpReceiptCounterTax; } else if (pMethod.includes('สำรองรับ')) { pfix = 'SR'; rNoVal = kmpReceiptCounterBackup; } else if (pMethod === 'เงินสด') { pfix = 'CS'; rNoVal = kmpReceiptCounterCash; } const cusName = document.getElementById('kmp-customer-name').value.trim(), cusCont = document.getElementById('kmp-customer-contact').value.trim(); const cusPh = document.getElementById('kmp-customer-phone').value.trim(), dLoc = document.getElementById('kmp-delivery-location').value.trim(); const rPhone = document.getElementById('kmp-recipient-phone').value.trim(); const dDateTimeText = document.getElementById('kmp-delivery-datetime-text').value.trim(); const customRDate = document.getElementById('kmp-receipt-custom-date').value; const customRTime = document.getElementById('kmp-receipt-custom-time').value; let receiptDateObj = customRDate ? new Date(customRDate) : d; const yy = String(receiptDateObj.getFullYear()).slice(-2); const mm = String(receiptDateObj.getMonth() + 1).padStart(2, '0'); const dd = String(receiptDateObj.getDate()).padStart(2, '0'); let generatedReceiptNo = ""; if (!isTax && pMethod === 'โอน กสิกร FLOWERFORYOU') { let nextSeq = 1; const prefixToMatch = `RV-${yy}${mm}${dd}-`; // ค้นหาในประวัติบิลว่าวันนี้มีการออกบิลไปแล้วกี่บิล เพื่อรันลำดับ 001 ใหม่ทุกวัน kmpSalesHistory.forEach(s => { if (s.receiptNo && s.receiptNo.startsWith(prefixToMatch)) { const parts = s.receiptNo.split('-'); if (parts.length >= 3) { const seq = parseInt(parts[2], 10); if (!isNaN(seq) && seq >= nextSeq) { nextSeq = seq + 1; } } } }); const rNoStr = String(nextSeq).padStart(3, '0'); generatedReceiptNo = `${prefixToMatch}${rNoStr}`; } else { const rNoStr = String(rNoVal).padStart(3, '0'); generatedReceiptNo = `${pfix}-${yy}${mm}-${rNoStr}`; } document.getElementById('kmp-receipt-no-input').value = generatedReceiptNo; document.getElementById('kmp-receipt-date-input').value = customRDate ? customRDate : kmpGetLocalIsoDate(d); document.getElementById('kmp-receipt-time-input').value = customRTime ? customRTime : String(d.getHours()).padStart(2,'0')+':'+String(d.getMinutes()).padStart(2,'0'); document.getElementById('kmp-receipt-cus-name').innerText = cusName || '-'; document.getElementById('kmp-receipt-cus-contact').innerText = cusCont || '-'; document.getElementById('kmp-receipt-cus-phone').innerText = cusPh || '-'; document.getElementById('kmp-receipt-customer-info').style.display = (cusName || cusCont || cusPh || dLoc || dDateTimeText || rPhone) ? 'block' : 'none'; let dText = dLoc ? dLoc+' ' : ''; if(rPhone) dText += `(โทรผู้รับ: ${rPhone}) `; if(dDateTimeText) dText += `${dDateTimeText}`; document.getElementById('kmp-receipt-delivery-info').innerText = dText.trim(); document.getElementById('kmp-receipt-delivery-wrap').style.display = dText.trim() ? 'block' : 'none'; // จัดเตรียมรายการในบิล let html=''; let sumRevenue = 0; let sumPassThrough = 0; kmpCart.forEach(i => { sumRevenue += i.price * i.qty; sumPassThrough += (i.passThrough || 0) * i.qty; html += `
${i.name} (x${i.qty})${kmpFormatNumber(i.price*i.qty)}
${i.detail?`
- ${i.detail}
`:''}
`; }); document.getElementById('kmp-receipt-items').innerHTML = html; document.getElementById('kmp-receipt-payment-method').innerText = pMethod; // คำนวณยอดต่างๆ ลงบิล const taxType = document.querySelector('input[name="kmp_vat_type"]:checked').value; let subtotal = sumRevenue; let vatAmount = 0; let totalToPay = 0; if (taxType === 'include') { vatAmount = subtotal - (subtotal / 1.07); totalToPay = subtotal + sumPassThrough; } else if (taxType === 'exclude') { let exactVat = subtotal * 0.07; let exactTotal = subtotal + exactVat + sumPassThrough; totalToPay = Math.ceil(exactTotal); // ปัดเศษขึ้นให้เป็นหลักหน่วยเสมอ vatAmount = totalToPay - subtotal - sumPassThrough; // ปรับเศษ VAT ให้ตรงกับยอดที่ปัดแล้ว } else { totalToPay = subtotal + sumPassThrough; } document.getElementById('kmp-receipt-subtotal').innerText = kmpFormatNumber(subtotal); const vatRow = document.getElementById('kmp-receipt-vat-row'); if(vatAmount > 0) { vatRow.classList.remove('hidden'); document.getElementById('kmp-receipt-vat-label').innerText = taxType === 'include' ? 'ภาษีมูลค่าเพิ่ม (รวมแล้ว) 7%' : 'บวกภาษีมูลค่าเพิ่ม 7%'; document.getElementById('kmp-receipt-vat').innerText = kmpFormatNumber(vatAmount); } else { vatRow.classList.add('hidden'); } const passRow = document.getElementById('kmp-receipt-pass-row'); const hasCashBouquet = kmpCart.some(item => item.sku === 'BQT-CSH'); if(sumPassThrough > 0 && hasCashBouquet) { passRow.classList.remove('hidden'); document.getElementById('kmp-receipt-pass').innerText = kmpFormatNumber(sumPassThrough); } else { passRow.classList.add('hidden'); } document.getElementById('kmp-receipt-total').innerText = kmpFormatNumber(totalToPay) + ' ฿'; document.getElementById('kmp-receipt-text-amount').innerText = kmpThaiBaht(totalToPay); // ค่าส่ง (ต้นทุน) const ship = parseFloat(document.getElementById('kmp-actual-shipping-cost').value)||0; document.getElementById('kmp-receipt-actual-shipping').innerText = kmpFormatNumber(ship)+' ฿'; document.getElementById('kmp-receipt-shipping-box').style.display = ship>0 ? 'inline-block' : 'none'; document.getElementById('kmp-receipt-title').innerText = isTax ? 'ใบกำกับภาษี / ใบเสร็จรับเงิน' : 'ใบเสร็จรับเงิน'; kmpOpenPane('pane-receipt'); } function kmpValidateAndProcessReceipt(act, btn = null) { let no = document.getElementById('kmp-receipt-no-input').value.trim(); if(kmpSalesHistory.some(s=>s.receiptNo===no) && no !== '') { kmpPendingSaveAction = act; kmpOpenPane('pane-override-pin'); } else kmpExecuteReceiptAction(act, btn); } function kmpCloseOverridePinModal() { kmpClosePane('pane-override-pin'); } function kmpConfirmOverridePin() { if(document.getElementById('kmp-override-pin').value === '0916983062') { const no = document.getElementById('kmp-receipt-no-input').value.trim(); const old = kmpSalesHistory.find(s=>s.receiptNo===no); if(old) { let max=0; kmpSalesHistory.forEach(s=>{ if(s.receiptNo.startsWith(no+'-')) max = Math.max(max, parseInt(s.receiptNo.split('-').pop())||0); }); old.receiptNo = `${no}-${String(max+1).padStart(2,'0')}`; } kmpCloseOverridePinModal(); kmpExecuteReceiptAction(kmpPendingSaveAction, null); } else alert('รหัสผ่านไม่ถูกต้อง'); document.getElementById('kmp-override-pin').value = ''; } let kmpCaptchaExpected = 0; function kmpRequestClearData() { // สุ่มตัวเลข 1-20 สองตัวเพื่อใช้เป็น CAPTCHA const num1 = Math.floor(Math.random() * 20) + 1; const num2 = Math.floor(Math.random() * 20) + 1; kmpCaptchaExpected = num1 + num2; document.getElementById('kmp-captcha-num1').innerText = num1; document.getElementById('kmp-captcha-num2').innerText = num2; document.getElementById('kmp-captcha-answer').value = ''; document.getElementById('kmp-clear-data-pin-input').value = ''; kmpOpenPane('pane-clear-data-pin'); setTimeout(() => document.getElementById('kmp-clear-data-pin-input').focus(), 100); } function kmpCloseClearDataModal() { kmpClosePane('pane-clear-data-pin'); document.getElementById('kmp-clear-data-pin-input').value = ''; document.getElementById('kmp-captcha-answer').value = ''; } function kmpConfirmClearData() { const pin = document.getElementById('kmp-clear-data-pin-input').value; const captchaAnswer = parseInt(document.getElementById('kmp-captcha-answer').value); if (isNaN(captchaAnswer) || captchaAnswer !== kmpCaptchaExpected) { alert('ผลบวกป้องกันบอทไม่ถูกต้อง กรุณาลองใหม่'); return; } if (pin === '1349900334677') { if (confirm('คุณแน่ใจหรือไม่ว่าต้องการล้างข้อมูลทั้งหมด? การกระทำนี้จะไม่สามารถย้อนกลับได้')) { kmpSalesHistory = []; kmpReceiptCounter = 1; kmpReceiptCounterBackup = 1; kmpReceiptCounterCash = 1; kmpReceiptCounterTax = 1; kmpSaveDataToStorage(); kmpCloseClearDataModal(); kmpGenerateReport(); alert('ล้างข้อมูลและรีเซ็ตลำดับบิลเรียบร้อยแล้วครับ'); } } else { alert('รหัสผ่านไม่ถูกต้อง'); } } async function kmpExecuteReceiptAction(act, btn = null) { const rNo = document.getElementById('kmp-receipt-no-input').value.trim(), dStr = document.getElementById('kmp-receipt-date-input').value; const tStr = document.getElementById('kmp-receipt-time-input').value, pMeth = document.getElementById('kmp-payment-method').value; const ship = parseFloat(document.getElementById('kmp-actual-shipping-cost').value)||0; const isTax = document.getElementById('kmp-request-tax').checked; const taxType = document.querySelector('input[name="kmp_vat_type"]:checked').value; // คำนวณสรุปก้อนสุดท้ายที่จะเซฟลงฐานข้อมูล let sumRevenue = 0; let sumHiddenCost = 0; let sumPassThrough = 0; kmpCart.forEach(i => { sumRevenue += (i.price * i.qty); sumHiddenCost += ((i.hiddenCost || 0) * i.qty); sumPassThrough += ((i.passThrough || 0) * i.qty); }); let vatAmount = 0; let grandTotal = 0; if (taxType === 'include') { vatAmount = sumRevenue - (sumRevenue / 1.07); grandTotal = sumRevenue + sumPassThrough; } else if (taxType === 'exclude') { let exactVat = sumRevenue * 0.07; let exactTotal = sumRevenue + exactVat + sumPassThrough; grandTotal = Math.ceil(exactTotal); // ปัดเศษขึ้นให้เป็นหลักหน่วยเสมอ vatAmount = grandTotal - sumRevenue - sumPassThrough; // ปรับเศษ VAT ให้ตรงกับยอดที่ปัดแล้ว } else { grandTotal = sumRevenue + sumPassThrough; } let staffName = document.getElementById('kmp-staff-name').value; if (staffName === 'other') { staffName = document.getElementById('kmp-staff-custom-name').value.trim() || 'พนักงานทั่วไป'; } kmpSalesHistory.push({ id: 'BILL_'+Date.now(), receiptNo: rNo, dateIso: dStr, timeStr: tStr, monthIso: dStr.slice(0,7), yearIso: dStr.slice(0,4), displayDateTime: `${new Date(dStr).toLocaleDateString('th-TH',{year:'numeric',month:'short',day:'numeric'})}
${tStr} น.`, customerName: document.getElementById('kmp-customer-name').value.trim() || 'ทั่วไป', customerContact: [document.getElementById('kmp-customer-contact').value.trim(), document.getElementById('kmp-customer-phone').value.trim()].filter(Boolean).join(' | ') || '-', deliveryLocation: document.getElementById('kmp-delivery-location').value.trim(), recipientPhone: document.getElementById('kmp-recipient-phone').value.trim(), deliveryDateText: document.getElementById('kmp-delivery-datetime-text').value.trim(), deliveryDate: '', deliveryTime: '', itemsSummary: kmpCart.map(i=>`${i.name} ${i.detail?`(${i.detail})`:''} x${i.qty}`).join('
'), cartItems: JSON.parse(JSON.stringify(kmpCart)), // โครงสร้างตัวเลขบัญชีแบบใหม่ total: grandTotal, // ยอดเรียกเก็บลูกค้าทั้งหมด cartSubtotal: sumRevenue, // ยอดขายสินค้า (Gross Sales) ก่อนบวก VAT vatType: taxType, // ชนิดภาษี vatAmount: vatAmount, // มูลค่าภาษีขาย totalHiddenCost: sumHiddenCost, // รวมต้นทุนแฝง (เช่น พัดลม) passThroughTotal: sumPassThrough, // เงินสดธนบัตร actualShippingCost: ship, // ต้นทุนค่าขนส่ง paymentMethod: pMeth, isCancelled: false, createdBy: staffName, isTaxInvoice: isTax }); ['kmp-customer-name','kmp-customer-contact','kmp-customer-phone','kmp-delivery-location','kmp-recipient-phone','kmp-delivery-datetime-text','kmp-receipt-custom-date','kmp-receipt-custom-time','kmp-actual-shipping-cost'].forEach(id=> { if(document.getElementById(id)) document.getElementById(id).value=''; }); kmpCart = []; document.getElementById('kmp-request-tax').checked = false; document.querySelector('input[name="kmp_vat_type"][value="none"]').checked = true; // reset tax if (isTax) kmpReceiptCounterTax++; else if (pMeth.includes('สำรองรับ')) kmpReceiptCounterBackup++; else if (pMeth === 'เงินสด') kmpReceiptCounterCash++; else kmpReceiptCounter++; kmpRenderCart(); await kmpSaveDataToStorage(); if(act === 'print') { document.getElementById('kmp-receipt-no-input').setAttribute('value', rNo); document.getElementById('kmp-receipt-date-input').setAttribute('value', dStr); document.getElementById('kmp-receipt-time-input').setAttribute('value', tStr); document.body.classList.add('print-mode-receipt'); window.print(); document.body.classList.remove('print-mode-receipt'); kmpCloseReceipt(); } else if (act === 'image') { document.getElementById('kmp-receipt-no-input').setAttribute('value', rNo); document.getElementById('kmp-receipt-date-input').setAttribute('value', dStr); document.getElementById('kmp-receipt-time-input').setAttribute('value', tStr); await kmpExportAsImage('kmp-receipt-print-area', btn); kmpCloseReceipt(); } else { kmpCloseReceipt(); } } function kmpCloseReceipt() { kmpClosePane('pane-receipt'); } function kmpOpenReport() { kmpGenerateReport(); kmpOpenPane('pane-report'); } function kmpCloseReport() { kmpClosePane('pane-report'); } function kmpGenerateReport() { const startVal = document.getElementById('kmp-report-start').value; const endVal = document.getElementById('kmp-report-end').value; if(!startVal || !endVal) return alert('กรุณาเลือกช่วงเวลาให้ครบถ้วน'); const sDate = new Date(startVal); const eDate = new Date(endVal); if((eDate - sDate) / (1000 * 60 * 60 * 24) > 365) { alert("กรุณาเลือกช่วงเวลาไม่เกิน 1 ปี"); return; } const sBody = document.getElementById('kmp-sku-summary-body'); sBody.innerHTML = ''; // กรองเอาบิลตามช่วงวันที่ (รวมบิลที่ยกเลิกด้วยเพื่อให้โชว์ในตาราง) let hist = kmpSalesHistory.filter(s => { return s.dateIso >= startVal && s.dateIso <= endVal; }); kmpCurrentReportBills = [...hist].reverse(); kmpReportCurrentPage = 1; let gGross = 0; // 1. ยอดขายรวมสินค้า let gVat = 0; // 2. ภาษีขาย let gHidden = 0; // 3. ต้นทุนแฝงพัดลม let gShip = 0; // 3. ค่าส่ง let gPass = 0; // เงินช่อธนบัตร (ไม่นับเป็นยอดขาย) let bCount = 0; let skuSum = {}; if(hist.length===0) { sBody.innerHTML = 'ไม่มีข้อมูล'; document.getElementById('kmp-sku-total-qty').innerText='0'; } else { kmpCurrentReportBills.forEach(s => { // หากยกเลิก ไม่ต้องเอาตัวเลขมาบวกในกล่องสรุป if (!s.isCancelled) { bCount++; // รองรับ Database เก่าที่ไม่มีฟิลด์ใหม่ let bGross = s.cartSubtotal !== undefined ? s.cartSubtotal : s.total; let bVat = s.vatAmount || 0; let bHidden = s.totalHiddenCost || 0; let bShip = s.actualShippingCost || 0; let bPass = s.passThroughTotal || 0; gGross += bGross; gVat += bVat; gHidden += bHidden; gShip += bShip; gPass += bPass; s.cartItems.forEach(i => { if(!skuSum[i.sku]) skuSum[i.sku] = {name:i.name, qty:0, tot:0}; skuSum[i.sku].qty += i.qty; skuSum[i.sku].tot += i.price * i.qty; }); } }); let tQty=0; Object.keys(skuSum).sort((a,b)=>skuSum[b].qty-skuSum[a].qty).forEach(k => { tQty+=skuSum[k].qty; sBody.innerHTML += `${skuSum[k].name}
${k}
${skuSum[k].qty}${kmpFormatNumber(skuSum[k].tot)}`; }); document.getElementById('kmp-sku-total-qty').innerText = tQty + ' ชิ้น'; } // อัปเดตกล่องสรุปยอดแบบใหม่ document.getElementById('kmp-report-gross').innerText = kmpFormatNumber(gGross); document.getElementById('kmp-report-vat').innerText = kmpFormatNumber(gVat); const totalDeductions = gShip + gHidden; let deductionText = `${kmpFormatNumber(totalDeductions)}`; if(totalDeductions > 0) deductionText += `
(ค่าส่ง ${kmpFormatNumber(gShip)} + พัดลม ${kmpFormatNumber(gHidden)})`; document.getElementById('kmp-report-hidden').innerHTML = deductionText; // ยอดขายสุทธิ = ยอดขายรวมสินค้า - ภาษี(ถ้าเป็นแบบรวมใน) - ต้นทุนแฝง // *หมายเหตุ* ภาษีในที่นี้เราแยกให้ดูเฉยๆ แต่รายได้สุทธิจริงๆ ต้องหักภาษีที่ต้องส่งรัฐออก let netSales = gGross - gVat - gShip - gHidden; document.getElementById('kmp-report-net').innerText = kmpFormatNumber(netSales); // ยอดธนบัตร document.getElementById('kmp-report-pass').innerText = kmpFormatNumber(gPass); document.getElementById('kmp-report-total-bills').innerText = `${bCount} บิล`; kmpRenderReportTable(); } function kmpRenderReportTable() { const tBody = document.getElementById('kmp-report-table-body'), pControl = document.getElementById('kmp-pagination-controls'); tBody.innerHTML = ''; pControl.innerHTML = ''; const totalBills = kmpCurrentReportBills.length; if(totalBills === 0) { tBody.innerHTML = 'ไม่มีข้อมูลบิลในช่องเวลานี้'; return; } const totalPages = Math.ceil(totalBills / kmpBillsPerPage); if(kmpReportCurrentPage > totalPages) kmpReportCurrentPage = totalPages; if(kmpReportCurrentPage < 1) kmpReportCurrentPage = 1; const startIdx = (kmpReportCurrentPage - 1) * kmpBillsPerPage, endIdx = startIdx + kmpBillsPerPage, billsToShow = kmpCurrentReportBills.slice(startIdx, endIdx); billsToShow.forEach(s => { let bGross = s.cartSubtotal !== undefined ? s.cartSubtotal : s.total; let bVat = s.vatAmount || 0; let bHidden = s.totalHiddenCost || 0; let bShip = s.actualShippingCost || 0; let bPass = s.passThroughTotal || 0; let hiddenCostHtml = ''; if(bHidden > 0) hiddenCostHtml += `
- ต้นทุนแฝง: ${kmpFormatNumber(bHidden)}
`; if(bShip > 0) hiddenCostHtml += `
- ส่ง: ${kmpFormatNumber(bShip)}
`; let passThroughHtml = ''; if(bPass > 0) passThroughHtml = `
+ เงินสดฝากช่อ: ${kmpFormatNumber(bPass)}
`; let vatHtml = ''; if(bVat > 0) vatHtml = `
ภาษี(VAT): ${kmpFormatNumber(bVat)}
`; let rowClass = s.isCancelled ? 'bg-red-50 opacity-60' : ''; let textStrike = s.isCancelled ? 'line-through text-red-500' : ''; let statusTag = s.isCancelled ? `ยกเลิกแล้ว` : ''; let cancelBtn = s.isCancelled ? `CANCELLED ` : ``; let itemsListHtml = ''; let cusEditBtn = s.isCancelled ? '' : ``; tBody.innerHTML += ` ${s.displayDateTime}
ผู้ทำรายการ: ${s.createdBy || 'ทั่วไป'}
${s.receiptNo} ${statusTag}
${s.customerName || 'ทั่วไป'}${cusEditBtn}
${itemsListHtml}
ยอดขายสินค้า: ${kmpFormatNumber(bGross)}
${vatHtml} ${hiddenCostHtml}
สุทธิ: ${kmpFormatNumber(bGross - bVat - bHidden - bShip)} ฿
${passThroughHtml}
ยอดเรียกเก็บ: ${kmpFormatNumber(s.total)} ฿
${s.paymentMethod}
${cancelBtn} `; }); if (totalPages > 1) { pControl.innerHTML = ` หน้า ${kmpReportCurrentPage} / ${totalPages} `; } } function kmpChangePage(newPage) { kmpReportCurrentPage = newPage; kmpRenderReportTable(); } function kmpPrintSummary() { const sd = new Date(document.getElementById('kmp-report-start').value).toLocaleDateString('th-TH',{day:'numeric',month:'short',year:'numeric'}); const ed = new Date(document.getElementById('kmp-report-end').value).toLocaleDateString('th-TH',{day:'numeric',month:'short',year:'numeric'}); document.getElementById('kmp-summary-print-date').innerText = (sd === ed) ? sd : `${sd} ถึง ${ed}`; document.getElementById('kmp-summary-print-count').innerText = document.getElementById('kmp-report-total-bills').innerText; document.getElementById('kmp-summary-print-gross').innerText = document.getElementById('kmp-report-gross').innerText + ' ฿'; document.getElementById('kmp-summary-print-vat').innerText = document.getElementById('kmp-report-vat').innerText + ' ฿'; const shipHtml = document.getElementById('kmp-report-hidden').innerHTML; document.getElementById('kmp-summary-print-hidden').innerHTML = shipHtml.replace('block', 'inline-block ml-2'); document.getElementById('kmp-summary-print-net').innerText = document.getElementById('kmp-report-net').innerText + ' ฿'; document.getElementById('kmp-summary-print-pass').innerText = document.getElementById('kmp-report-pass').innerText + ' ฿'; const now = new Date(); document.getElementById('kmp-summary-print-timestamp').innerText = now.toLocaleDateString('th-TH') + ' ' + String(now.getHours()).padStart(2,'0') + ':' + String(now.getMinutes()).padStart(2,'0') + ' น.'; document.body.classList.add('print-mode-summary'); window.print(); document.body.classList.remove('print-mode-summary'); } function kmpRequestCancelBill(id) { kmpBillToCancelId=id; kmpOpenPane('pane-pin-cancel'); } function kmpClosePinModal() { kmpClosePane('pane-pin-cancel'); } function kmpConfirmCancelBill() { if(document.getElementById('kmp-cancel-pin').value==='0916983062') { let b = kmpSalesHistory.find(s=>s.id===kmpBillToCancelId); b.isCancelled = true; b.receiptNo = b.receiptNo + '-01'; // ลงท้ายด้วย -01 ตามที่ระบุ kmpSaveDataToStorage(); kmpClosePinModal(); kmpGenerateReport(); } else alert('รหัสผ่านผิด'); document.getElementById('kmp-cancel-pin').value=''; } function kmpRequestHardDelete(id) { kmpBillToHardDeleteId = id; document.getElementById('kmp-hard-delete-pin').value = ''; kmpOpenPane('pane-pin-hard-delete'); setTimeout(() => document.getElementById('kmp-hard-delete-pin').focus(), 100); } function kmpCloseHardDeletePinModal() { kmpClosePane('pane-pin-hard-delete'); document.getElementById('kmp-hard-delete-pin').value = ''; } function kmpConfirmHardDeleteBill() { if(document.getElementById('kmp-hard-delete-pin').value === '0916983062') { if(confirm('คุณแน่ใจหรือไม่ที่จะลบบิลนี้ถาวร? ข้อมูลจะถูกลบออกจากระบบและไม่สามารถกู้คืนได้')) { kmpSalesHistory = kmpSalesHistory.filter(s => s.id !== kmpBillToHardDeleteId); kmpSaveDataToStorage(); kmpCloseHardDeletePinModal(); kmpGenerateReport(); } } else { alert('รหัสผ่านผิด'); } document.getElementById('kmp-hard-delete-pin').value = ''; } function kmpOpenEditReceiptModal(id) { kmpCurrentEditSaleId=id; document.getElementById('kmp-edit-receipt-new-no').value=kmpSalesHistory.find(s=>s.id===id).receiptNo; kmpOpenPane('pane-edit-receipt'); } function kmpCloseEditReceiptModal() { kmpClosePane('pane-edit-receipt'); } function kmpConfirmEditReceiptNo() { const no=document.getElementById('kmp-edit-receipt-new-no').value.trim(); if(no){ kmpSalesHistory.find(s=>s.id===kmpCurrentEditSaleId).receiptNo=no; kmpSaveDataToStorage(); kmpGenerateReport(); kmpCloseEditReceiptModal(); } } function kmpOpenEditDetailModal(billId, itemId) { const bill = kmpSalesHistory.find(b => b.id === billId); if (!bill) return; const item = bill.cartItems.find(i => i.id === itemId); if (!item) return; kmpEditDetailContext = 'history'; kmpCurrentEditBillIdForDetail = billId; kmpCurrentEditItemIdForDetail = itemId; document.getElementById('kmp-edit-detail-name').innerText = item.name; document.getElementById('kmp-edit-detail-input').value = item.detail || ''; kmpOpenPane('pane-edit-detail'); } function kmpOpenEditCartDetailModal(itemId) { const item = kmpCart.find(i => i.id === itemId); if (!item) return; kmpEditDetailContext = 'cart'; kmpCurrentEditCartItemId = itemId; document.getElementById('kmp-edit-detail-name').innerText = item.name; document.getElementById('kmp-edit-detail-input').value = item.detail || ''; kmpOpenPane('pane-edit-detail'); } function kmpCloseEditDetailModal() { kmpClosePane('pane-edit-detail'); } function kmpConfirmEditDetail() { const newDetail = document.getElementById('kmp-edit-detail-input').value.trim(); if (kmpEditDetailContext === 'cart') { const item = kmpCart.find(i => i.id === kmpCurrentEditCartItemId); if (item) { item.detail = newDetail; kmpRenderCart(); // อัปเดตตะกร้าทันที } } else if (kmpEditDetailContext === 'history') { const bill = kmpSalesHistory.find(b => b.id === kmpCurrentEditBillIdForDetail); if (bill) { const item = bill.cartItems.find(i => i.id === kmpCurrentEditItemIdForDetail); if (item) { item.detail = newDetail; // อัปเดต text สำหรับ CSV ให้ตรงกันด้วย bill.itemsSummary = bill.cartItems.map(i => `${i.name} ${i.detail ? `(${i.detail})` : ''} x${i.qty}`).join('
'); kmpSaveDataToStorage(); kmpGenerateReport(); } } } kmpCloseEditDetailModal(); } function kmpOpenEditCustomerModal(id) { const bill = kmpSalesHistory.find(s => s.id === id); if(!bill) return; kmpCurrentEditBillIdForCustomer = id; let name = bill.customerName === 'ทั่วไป' ? '' : bill.customerName; let line = '', phone = ''; if (bill.customerContact && bill.customerContact !== '-') { let parts = bill.customerContact.split(' | '); if(parts.length === 2) { line = parts[0].trim(); phone = parts[1].trim(); } else if (parts.length === 1) { if(/^[\d\-\s]+$/.test(parts[0])) phone = parts[0].trim(); else line = parts[0].trim(); } } document.getElementById('kmp-edit-cus-name').value = name; document.getElementById('kmp-edit-cus-line').value = line; document.getElementById('kmp-edit-cus-phone').value = phone; document.getElementById('kmp-edit-cus-address').value = bill.deliveryLocation || ''; document.getElementById('kmp-edit-cus-recphone').value = bill.recipientPhone || ''; document.getElementById('kmp-edit-cus-deldate').value = bill.deliveryDateText || ''; kmpOpenPane('pane-edit-customer'); } function kmpCloseEditCustomerModal() { kmpClosePane('pane-edit-customer'); } function kmpConfirmEditCustomer() { const bill = kmpSalesHistory.find(s => s.id === kmpCurrentEditBillIdForCustomer); if(bill) { bill.customerName = document.getElementById('kmp-edit-cus-name').value.trim() || 'ทั่วไป'; const line = document.getElementById('kmp-edit-cus-line').value.trim(); const phone = document.getElementById('kmp-edit-cus-phone').value.trim(); bill.customerContact = [line, phone].filter(Boolean).join(' | ') || '-'; bill.deliveryLocation = document.getElementById('kmp-edit-cus-address').value.trim(); bill.recipientPhone = document.getElementById('kmp-edit-cus-recphone').value.trim(); bill.deliveryDateText = document.getElementById('kmp-edit-cus-deldate').value.trim(); kmpSaveDataToStorage(); kmpGenerateReport(); } kmpCloseEditCustomerModal(); } function kmpOpenReprintModal(id) { const s = kmpSalesHistory.find(x=>x.id===id); if(!s) return; document.getElementById('kmp-reprint-no').innerText = s.receiptNo; document.getElementById('kmp-reprint-time').innerText = `${new Date(s.dateIso).toLocaleDateString('th-TH',{year:'numeric',month:'short',day:'numeric'})} ${s.timeStr} น.`; document.getElementById('kmp-reprint-cus-name').innerText = s.customerName; document.getElementById('kmp-reprint-cus-contact').innerText = s.customerContact.split(' | ')[0]||'-'; document.getElementById('kmp-reprint-cus-phone').innerText = s.customerContact.split(' | ')[1]||'-'; let dText = s.deliveryLocation ? s.deliveryLocation + ' ' : ''; if(s.recipientPhone) dText += `(โทรผู้รับ: ${s.recipientPhone}) `; if(s.deliveryDate) dText += `วันที่ ${new Date(s.deliveryDate).toLocaleDateString('th-TH', {day:'numeric',month:'short'})} `; if(s.deliveryTime) dText += `เวลา ${s.deliveryTime} น. `; if(s.deliveryDateText) dText += s.deliveryDateText; document.getElementById('kmp-reprint-delivery-info').innerText = dText.trim(); document.getElementById('kmp-reprint-delivery-wrap').style.display = dText.trim() ? 'block' : 'none'; document.getElementById('kmp-reprint-customer-info').style.display = (s.customerName!=='ทั่วไป'||s.customerContact!=='-' || dText.trim()) ? 'block' : 'none'; let html=''; s.cartItems.forEach(i=>{ html+=`
${i.name} (x${i.qty})${kmpFormatNumber(i.price*i.qty)}
${i.detail?`
- ${i.detail}
`:''}
`; }); document.getElementById('kmp-reprint-items').innerHTML = html; let bGross = s.cartSubtotal !== undefined ? s.cartSubtotal : s.total; let bVat = s.vatAmount || 0; let bPass = s.passThroughTotal || 0; document.getElementById('kmp-reprint-subtotal').innerText = kmpFormatNumber(bGross); const vatRow = document.getElementById('kmp-reprint-vat-row'); if(bVat > 0) { vatRow.classList.remove('hidden'); document.getElementById('kmp-reprint-vat-label').innerText = s.vatType === 'include' ? 'ภาษีมูลค่าเพิ่ม (รวมแล้ว) 7%' : 'บวกภาษีมูลค่าเพิ่ม 7%'; document.getElementById('kmp-reprint-vat').innerText = kmpFormatNumber(bVat); } else { vatRow.classList.add('hidden'); } const passRow = document.getElementById('kmp-reprint-pass-row'); const hasCashBouquet = s.cartItems.some(item => item.sku === 'BQT-CSH'); if(bPass > 0 && hasCashBouquet) { passRow.classList.remove('hidden'); document.getElementById('kmp-reprint-pass').innerText = kmpFormatNumber(bPass); } else { passRow.classList.add('hidden'); } document.getElementById('kmp-reprint-total').innerText = kmpFormatNumber(s.total) + ' ฿'; document.getElementById('kmp-reprint-text-amount').innerText = kmpThaiBaht(s.total); document.getElementById('kmp-reprint-title').innerText = s.isTaxInvoice ? 'ใบกำกับภาษี / ใบเสร็จรับเงิน' : 'ใบเสร็จรับเงิน'; kmpOpenPane('pane-reprint'); } function kmpCloseReprintModal() { kmpClosePane('pane-reprint'); } function kmpExecuteReprint() { document.body.classList.add('print-mode-reprint'); window.print(); document.body.classList.remove('print-mode-reprint'); } function kmpOpenDeliveryNoteModal(id) { const s = kmpSalesHistory.find(x=>x.id===id); if(!s) return; const dDate = new Date(s.dateIso); const yy = String(dDate.getFullYear()).slice(-2); const mm = String(dDate.getMonth() + 1).padStart(2, '0'); const dd = String(dDate.getDate()).padStart(2, '0'); const seq = s.receiptNo.split('-').pop() || '001'; document.getElementById('kmp-delivery-no').innerText = `${yy}${mm}${dd}-${seq}`; document.getElementById('kmp-delivery-time').innerText = `${dDate.toLocaleDateString('th-TH',{year:'numeric',month:'short',day:'numeric'})} ${s.timeStr} น.`; document.getElementById('kmp-delivery-cus-name').innerText = s.customerName; document.getElementById('kmp-delivery-cus-contact').innerText = s.customerContact.split(' | ')[0]||'-'; document.getElementById('kmp-delivery-cus-phone').innerText = s.customerContact.split(' | ')[1]||'-'; let dText = s.deliveryLocation ? s.deliveryLocation + ' ' : ''; if(s.recipientPhone) dText += `(โทรผู้รับ: ${s.recipientPhone}) `; if(s.deliveryDate) dText += `วันที่ ${new Date(s.deliveryDate).toLocaleDateString('th-TH', {day:'numeric',month:'short'})} `; if(s.deliveryTime) dText += `เวลา ${s.deliveryTime} น. `; if(s.deliveryDateText) dText += s.deliveryDateText; document.getElementById('kmp-delivery-delivery-info').innerText = dText.trim(); document.getElementById('kmp-delivery-delivery-wrap').style.display = dText.trim() ? 'block' : 'none'; document.getElementById('kmp-delivery-customer-info').style.display = (s.customerName!=='ทั่วไป'||s.customerContact!=='-' || dText.trim()) ? 'block' : 'none'; let html=''; s.cartItems.forEach(i=>{ html+=`
${i.name}x${i.qty}
${i.detail?`
- ${i.detail}
`:''}
`; }); document.getElementById('kmp-delivery-items').innerHTML = html; kmpOpenPane('pane-delivery-note'); } function kmpCloseDeliveryNoteModal() { kmpClosePane('pane-delivery-note'); } function kmpExecuteDeliveryNote() { document.body.classList.add('print-mode-delivery'); window.print(); document.body.classList.remove('print-mode-delivery'); } function kmpExportToCSV() { if(kmpCurrentReportBills.length === 0) return alert('ไม่มีข้อมูลสำหรับดาวน์โหลด'); let csvContent = "data:text/csv;charset=utf-8,\uFEFF"; csvContent += "วันที่,เวลา,สถานะ,ผู้ทำรายการ,เลขที่บิล,ชื่อลูกค้า,การติดต่อ,รายการสินค้า,ยอดขายรวม(ก่อนแฝง),ภาษี(VAT),หักค่าส่ง,หักพัดลม,ยอดสุทธิร้าน,ฝากเงินช่อ,ยอดเรียกเก็บลูดค้า,ช่องทางรับเงิน\n"; kmpCurrentReportBills.forEach(s => { const date = s.dateIso; const time = s.timeStr; const status = s.isCancelled ? 'ยกเลิก' : 'ปกติ'; const staff = s.createdBy || 'ทั่วไป'; const no = s.receiptNo; const cusName = `"${s.customerName.replace(/"/g, '""')}"`; const contact = `"${s.customerContact.replace(/"/g, '""')}"`; const items = `"${s.itemsSummary.replace(/<[^>]*>?/gm, ' ').replace(/"/g, '""')}"`; let bGross = s.cartSubtotal !== undefined ? s.cartSubtotal : s.total; let bVat = s.vatAmount || 0; let bHidden = s.totalHiddenCost || 0; let bShip = s.actualShippingCost || 0; let bPass = s.passThroughTotal || 0; let netSales = bGross - bVat - bHidden - bShip; // ถ้ายกเลิก ให้ตัวเลขในตารางเป็น 0 เพื่อไม่ให้รวมตอนเปิดใน Excel (ยกเว้นยอดรวมเพื่อให้เห็นว่าเคยเก็บไปเท่าไหร่) let strGross = s.isCancelled ? "0" : bGross.toFixed(2); let strVat = s.isCancelled ? "0" : bVat.toFixed(2); let strShip = s.isCancelled ? "0" : bShip.toFixed(2); let strHidden = s.isCancelled ? "0" : bHidden.toFixed(2); let strNet = s.isCancelled ? "0" : netSales.toFixed(2); let strPass = s.isCancelled ? "0" : bPass.toFixed(2); const totalToPay = s.total.toFixed(2); const method = s.paymentMethod; csvContent += `${date},${time},${status},${staff},${no},${cusName},${contact},${items},${strGross},${strVat},${strShip},${strHidden},${strNet},${strPass},${totalToPay},${method}\n`; }); const encodedUri = encodeURI(csvContent); const link = document.createElement("a"); const dStr = document.getElementById('kmp-report-start').value + "_to_" + document.getElementById('kmp-report-end').value; link.setAttribute("href", encodedUri); link.setAttribute("download", `POS_KlinMali_${dStr}.csv`); document.body.appendChild(link); link.click(); document.body.removeChild(link); } function kmpExportCustomerCSV() { if(kmpSalesHistory.length === 0) return alert('ไม่มีข้อมูลในระบบ'); let csvContent = "data:text/csv;charset=utf-8,\uFEFF"; // เพิ่มคอลัมน์ รายการสินค้า csvContent += "วันที่ซื้อ,ชื่อลูกค้า,Line/FB,เบอร์โทรลูกค้า,สถานที่จัดส่ง,เบอร์โทรผู้รับ,ยอดซื้อ(บาท),รายการสินค้า\n"; kmpSalesHistory.forEach(s => { // ข้ามบิลที่ยกเลิก if (s.isCancelled) return; let name = s.customerName === 'ทั่วไป' ? '' : s.customerName; let line = '', phone = ''; if (s.customerContact && s.customerContact !== '-') { let parts = s.customerContact.split(' | '); if(parts.length === 2) { line = parts[0].trim(); phone = parts[1].trim(); } else if (parts.length === 1) { if(/^[\d\-\s]+$/.test(parts[0])) phone = parts[0].trim(); else line = parts[0].trim(); } } let address = s.deliveryLocation || ''; let recPhone = s.recipientPhone || ''; // ดึงรายการสินค้า และแปลงเป็นข้อความ (เช่น ช่อดอกกุหลาบ x1, ลูกโป่ง x2) let itemsBought = s.cartItems.map(i => `${i.name} x${i.qty}`).join(', '); // เอาเฉพาะที่มีข้อมูลติดต่ออย่างใดอย่างหนึ่ง (ไม่เอาบิลลูกค้าหน้าร้านที่ไม่ได้ระบุชื่อ) if (name || line || phone || address || recPhone) { csvContent += `"${s.dateIso}","${name.replace(/"/g, '""')}","${line.replace(/"/g, '""')}","${phone.replace(/"/g, '""')}","${address.replace(/"/g, '""')}","${recPhone.replace(/"/g, '""')}","${s.total.toFixed(2)}","${itemsBought.replace(/"/g, '""')}"\n`; } }); const encodedUri = encodeURI(csvContent); const link = document.createElement("a"); const dateStr = kmpGetLocalIsoDate(new Date()); link.setAttribute("href", encodedUri); link.setAttribute("download", `KlinMali_CustomerDB_${dateStr}.csv`); document.body.appendChild(link); link.click(); document.body.removeChild(link); } kmpRenderProducts();
Message us