BẢNG BÁO GIÁ TEM NHÃN IN BẢO MINH
Báo giá bán hàng + Thông số sản xuất | Xuất PDF hóa đơn
// ---------- DỮ LIỆU CHI PHÍ SẢN XUẤT ---------- const BASE_COST = { PP_CO_CAN_43: 10290, PP_CO_CAN_39: 9490, PP_KHONG_CAN_43: 9290, PP_KHONG_CAN_39: 8490, OJ_CO_CAN_NHIET_43: 10140, OJ_CO_CAN_NHIET_39: 9540, OJ_CO_CAN_NHIET_27x52: 10140, OJ_CO_CAN_HOLOGRAM_43: 10640, OJ_CO_CAN_HOLOGRAM_39: 9540, OJ_CO_CAN_HOLOGRAM_27x52: 10640, OJ_KHONG_CAN_43: 9090, OJ_KHONG_CAN_39: 8540, OJ_KHONG_CAN_27x52: 9090, MAU_7_43: 13390, MAU_7_39: 12490, TRONG_43: 13390, TRONG_39: 12490, XIBAC_43: 13390, XIBAC_39: 12490, VO_DAI: 13090, VO_DON: 19090, VO_7MAU: 24190 }; const PRICE_RULES = [ { min: 1, max: 50, heso: 1.3 }, { min: 51, max: 100, heso: 1.2 }, { min: 101, max: 200, heso: 1.15 }, { min: 201, max: 300, heso: 1.12 }, { min: 301, max: 999999, heso: 1.12 } ]; const PRICE_RULES_VO = [ { min: 1, max: 50, heso: 1.3 }, { min: 51, max: 100, heso: 1.25 }, { min: 101, max: 200, heso: 1.2 }, { min: 201, max: 300, heso: 1.15 }, { min: 301, max: 999999, heso: 1.15 } ]; function getMinCost(sheets) { if (sheets <= 10) return 60000; if (sheets <= 20) return 50000; if (sheets <= 30) return 40000; if (sheets <= 40) return 30000; if (sheets <= 50) return 20000; if (sheets <= 60) return 10000; return 0; } function getShippingCost(totalAmount) { if (totalAmount <= 1000000) return 5000; if (totalAmount <= 2000000) return 10000; if (totalAmount <= 5000000) return 15000; if (totalAmount <= 10000000) return 30000; return 0; } function getPriceRule(sheets, decalKey) { const isVo = decalKey.startsWith('VO_'); const rules = isVo ? PRICE_RULES_VO : PRICE_RULES; for (let r of rules) { if (sheets >= r.min && sheets <= r.max) return r; } return rules[rules.length - 1]; } function getBeCost(shapeType) { return shapeType === 'tron' ? 15 : 10; } function maxLabelsPerSheet(paperW, paperH, labelW, labelH, gapMM, marginTop, marginBottom, marginLeft, marginRight) { const gapCm = gapMM / 10; const availW = paperW - marginLeft - marginRight; const availH = paperH - marginTop - marginBottom; if (availW < labelW && availW < labelH) return 0; if (availH < labelW && availH < labelH) return 0; function calcCount(wDir, hDir) { if (availW < wDir || availH < hDir) return 0; let cols = 0, x = 0; while (x + wDir <= availW) { cols++; x += wDir + gapCm; } let rows = 0, y = 0; while (y + hDir <= availH) { rows++; y += hDir + gapCm; } return cols * rows; } return Math.max(calcCount(labelW, labelH), calcCount(labelH, labelW)); } function formatVND(amount) { return Math.round(amount).toLocaleString('vi-VN') + ' ₫'; } function getBaseCost(decalKey, paperSize) { const map = { 'PP_CO_CAN': { '32x43': 'PP_CO_CAN_43', '32x39': 'PP_CO_CAN_39' }, 'PP_KHONG_CAN': { '32x43': 'PP_KHONG_CAN_43', '32x39': 'PP_KHONG_CAN_39' }, 'OJ_CO_CAN_NHIET': { '32x43': 'OJ_CO_CAN_NHIET_43', '32x39': 'OJ_CO_CAN_NHIET_39', '27x52': 'OJ_CO_CAN_NHIET_27x52' }, 'OJ_CO_CAN_HOLOGRAM': { '32x43': 'OJ_CO_CAN_HOLOGRAM_43', '32x39': 'OJ_CO_CAN_HOLOGRAM_39', '27x52': 'OJ_CO_CAN_HOLOGRAM_27x52' }, 'OJ_KHONG_CAN': { '32x43': 'OJ_KHONG_CAN_43', '32x39': 'OJ_KHONG_CAN_39', '27x52': 'OJ_KHONG_CAN_27x52' }, 'MAU_7': { '32x43': 'MAU_7_43', '32x39': 'MAU_7_39' }, 'TRONG': { '32x43': 'TRONG_43', '32x39': 'TRONG_39' }, 'XIBAC': { '32x43': 'XIBAC_43', '32x39': 'XIBAC_39' }, 'VO_DAI': { '26.5x32': 'VO_DAI' }, 'VO_DON': { '26.5x32': 'VO_DON' }, 'VO_7MAU': { '26.5x32': 'VO_7MAU' } }; return BASE_COST[map[decalKey]?.[paperSize] || decalKey] || 0; } function getPaperOptions(decalKey) { const isVo = decalKey.startsWith('VO_'); const isPP = decalKey === 'PP_CO_CAN' || decalKey === 'PP_KHONG_CAN'; const isOJ = decalKey.startsWith('OJ_'); const is7Mau = decalKey === 'MAU_7' || decalKey === 'TRONG' || decalKey === 'XIBAC'; if (isVo) return [{ name: "26.5x32 cm", w: 26.5, h: 32, size: "26.5x32" }]; if (isPP || is7Mau) return [ { name: "32x43 cm", w: 32, h: 43, size: "32x43" }, { name: "32x39 cm", w: 32, h: 39, size: "32x39" } ]; if (isOJ) return [ { name: "32x43 cm", w: 32, h: 43, size: "32x43" }, { name: "32x39 cm", w: 32, h: 39, size: "32x39" }, { name: "27x52 cm", w: 27, h: 52, size: "27x52" } ]; return [{ name: "32x43 cm", w: 32, h: 43, size: "32x43" }]; } function getBaoHaoSheets(baseSheets) { if (baseSheets <= 20) return 1; return 2; } function computePrice(decalKey, labelW, labelH, gapMM, marginTB, marginLR, qty, paper, shapeType) { const perSheet = maxLabelsPerSheet(paper.w, paper.h, labelW, labelH, gapMM, marginTB, marginTB, marginLR, marginLR); if (perSheet === 0) { return { ok: false, error: `Không thể bố trí tem trên khổ ${paper.w}x${paper.h}cm`, paperName: paper.name }; } const baseSheets = Math.ceil(qty / perSheet); const baoHaoSheets = getBaoHaoSheets(baseSheets); const totalSheets = baseSheets + baoHaoSheets; const rule = getPriceRule(totalSheets, decalKey); const base = getBaseCost(decalKey, paper.size); if (base === 0) { return { ok: false, error: `Không tìm thấy giá gốc`, paperName: paper.name }; } const beCost = getBeCost(shapeType); const totalBeCost = qty * beCost; const minCost = getMinCost(totalSheets); const priceBeforeVAT = (base * totalSheets + minCost) * rule.heso; const vat = priceBeforeVAT * 0.08; const totalWithVAT = Math.round(priceBeforeVAT + vat + totalBeCost); const unitPriceVAT = Math.round(totalWithVAT / qty); return { ok: true, paperName: paper.name, paperDim: `${paper.w}x${paper.h} cm`, perSheet, baseSheets: baseSheets, baoHaoSheets: baoHaoSheets, totalSheets: totalSheets, multiplier: rule.heso, minCost: minCost, baseCost: base, beCost: beCost, totalBeCost: totalBeCost, priceBeforeVAT: Math.round(priceBeforeVAT), vat: Math.round(vat), totalWithVAT: totalWithVAT, unitPriceVAT: unitPriceVAT }; } // ---------- BIẾN LƯU TRẠNG THÁI MỞ KHÓA TS_IBM ---------- let isTSIBMUnlocked = false; function checkTSIBMPassword() { const passwordInput = document.getElementById('tsIbmPassword'); const errorMsg = document.getElementById('tsIbmError'); const content = document.getElementById('tsIbmContent'); const locked = document.getElementById('tsIbmLocked'); if (passwordInput.value === 'inbaominh@666') { isTSIBMUnlocked = true; errorMsg.classList.remove('show'); locked.style.display = 'none'; content.classList.add('show'); // Lưu trạng thái vào sessionStorage để giữ khi reload sessionStorage.setItem('tsIbmUnlocked', 'true'); } else { errorMsg.classList.add('show'); errorMsg.textContent = '❌ Mật khẩu không đúng. Vui lòng thử lại!'; passwordInput.value = ''; passwordInput.focus(); } } function render() { const decalType = document.getElementById('decalType').value; let w = parseFloat(document.getElementById('labelW').value); let h = parseFloat(document.getElementById('labelH').value); let gap = parseFloat(document.getElementById('gap').value); let qty = parseInt(document.getElementById('quantity').value, 10); let tb = parseFloat(document.getElementById('marginTB').value); let lr = parseFloat(document.getElementById('marginLR').value); let shapeType = document.getElementById('shapeType').value; let depositPercent = parseInt(document.getElementById('depositPercent').value); let customerName = document.getElementById('customerName').value.trim() || "Khách hàng"; let customerPhone = document.getElementById('customerPhone').value.trim() || "---"; const beCost = getBeCost(shapeType); document.getElementById('beCostDisplay').value = beCost + ' đ/tem'; if (isNaN(w) || isNaN(h) || w <= 0 || h <= 0) { document.getElementById('resultArea').innerHTML = '
'; return; } if (isNaN(qty) || qty < 1) { document.getElementById('resultArea').innerHTML = '
'; return; } if (isNaN(tb)) tb = 1.0; if (isNaN(lr)) lr = 1.0; if (isNaN(gap)) gap = 1.5; tb = Math.min(5, Math.max(0.5, tb)); lr = Math.min(3, Math.max(0.5, lr)); const papers = getPaperOptions(decalType); const results = papers.map(p => computePrice(decalType, w, h, gap, tb, lr, qty, p, shapeType)); const validResults = results.filter(r => r.ok); if (validResults.length === 0) { document.getElementById('resultArea').innerHTML = '
'; return; } let bestPaper = validResults.reduce((a, b) => a.unitPriceVAT < b.unitPriceVAT ? a : b); const decalText = document.getElementById('decalType').options[document.getElementById('decalType').selectedIndex] ?.text; // Tính chi phí đóng hàng và tổng const shippingCost = getShippingCost(bestPaper.totalWithVAT); const totalWithShipping = bestPaper.totalWithVAT + shippingCost; const depositAmount = Math.round(totalWithShipping * depositPercent / 100); const depositText = depositPercent === 100 ? 'Thanh toán hết' : depositPercent + '% tạm ứng'; const isLargeOrder = bestPaper.totalSheets >= 300; // Bảng báo giá bán hàng const customerHtml = `
`; // Bảng TS_IBM (Thông số sản xuất - có mật khẩu) let prodHtml = `
`; document.getElementById('resultArea').innerHTML = customerHtml + prodHtml; // Kiểm tra nếu đã mở khóa trước đó (sessionStorage) if (sessionStorage.getItem('tsIbmUnlocked') === 'true') { isTSIBMUnlocked = true; const content = document.getElementById('tsIbmContent'); const locked = document.getElementById('tsIbmLocked'); if (content && locked) { locked.style.display = 'none'; content.classList.add('show'); } } } function escapeHtml(str) { return str.replace(/[&<>]/g, function(m) { if (m === '&') return '&'; if (m === '<') return '<'; if (m === '>') return '>'; return m; }); } function printInvoice() { const invoiceElem = document.querySelector('#resultArea .quote-card:first-child').cloneNode(true); const customerName = document.getElementById('customerName').value.trim() || "Khách hàng"; const customerPhone = document.getElementById('customerPhone').value.trim() || "---"; const decalText = document.getElementById('decalType').options[document.getElementById('decalType').selectedIndex] ?.text; const w = document.getElementById('labelW').value; const h = document.getElementById('labelH').value; const gap = document.getElementById('gap').value; const tb = document.getElementById('marginTB').value; const lr = document.getElementById('marginLR').value; const shapeType = document.getElementById('shapeType').value; const depositPercent = document.getElementById('depositPercent').value; let invoiceHTML = invoiceElem.innerHTML; invoiceHTML = invoiceHTML.replace( 'TỔNG TIỀN HÀNG (đã VAT + phí đóng hàng):', 'TỔNG TIỀN HÀNG (đã VAT):' ); const printWindow = window.open('', '_blank'); printWindow.document.write(`
BẢNG BÁO GIÁ TEM NHÃN IN BẢO MINH
HÓA ĐƠN BÁN LẺ
${invoiceHTML}
`); printWindow.document.close(); printWindow.print(); } document.getElementById('calcBtn').addEventListener('click', render); document.getElementById('printBtn').addEventListener('click', printInvoice); const inputs = ['decalType', 'labelW', 'labelH', 'gap', 'quantity', 'marginTB', 'marginLR', 'shapeType', 'depositPercent', 'customerName', 'customerPhone' ]; inputs.forEach(id => { const el = document.getElementById(id); if (el) { el.addEventListener('input', render); el.addEventListener('change', render); } }); render(); // Cho phép nhấn Enter để mở khóa document.addEventListener('keydown', function(e) { if (e.key === 'Enter') { const passwordInput = document.getElementById('tsIbmPassword'); if (passwordInput && document.activeElement === passwordInput) { checkTSIBMPassword(); } } });


0123456789
0123456789

