/* 쿠팡 밀크런 — 출고 폼 동적 라인. 제품명 드롭다운(설정에서 등록한 카탈로그) 선택 → 제품코드 자동 입력. 수량 입력 시 박스 수 미리보기(서버가 저장 시 store.compute_boxes 로 재계산). */ (function () { "use strict"; var CFG = window.CPG || {}; var body = document.getElementById("cpg-lines-body"); var form = document.getElementById("cpg-form"); if (!body || !form) return; // 입수량 규칙: product_code -> units_per_box var ruleMap = {}; try { var rules = JSON.parse(document.getElementById("cpg-box-rules").textContent || "[]"); rules.forEach(function (r) { if (r.active !== false) ruleMap[r.product_code] = r.units_per_box; }); } catch (e) {} // 제품 카탈로그: [{product_code, product_name}] var products = []; try { products = JSON.parse(document.getElementById("cpg-products").textContent || "[]"); } catch (e) {} var nameByCode = {}; products.forEach(function (p) { nameByCode[p.product_code] = p.product_name; }); var initLines = []; try { initLines = JSON.parse(document.getElementById("cpg-init-lines").textContent || "[]"); } catch (e) {} function ceilDiv(a, b) { return Math.ceil(a / b); } function recalc(row) { var qty = parseInt(row.querySelector(".cpg-qty").value, 10) || 0; var upb = parseInt(row.querySelector(".cpg-upb").value, 10); var cell = row.querySelector(".cpg-line-calc"); if (!upb || upb <= 0) { cell.textContent = "미설정"; cell.classList.add("cpg-warn"); return; } cell.classList.remove("cpg-warn"); if (qty <= 0) { cell.textContent = "—"; return; } var boxes = ceilDiv(qty, upb), rem = qty % upb; cell.textContent = boxes + "박스" + (rem ? " +" + rem : " (딱맞음)"); } function buildNameSelect(selectedCode) { var sel = document.createElement("select"); sel.className = "erp-select cpg-name-sel"; var opt0 = document.createElement("option"); opt0.value = ""; opt0.textContent = "— 제품명 선택 —"; sel.appendChild(opt0); var found = false; products.forEach(function (p) { var o = document.createElement("option"); o.value = p.product_code; o.textContent = p.product_name; o.setAttribute("data-name", p.product_name); if (p.product_code === selectedCode) { o.selected = true; found = true; } sel.appendChild(o); }); // 카탈로그에 없는 기존 라인 코드 → 임시 옵션으로 표시 if (selectedCode && !found) { var o = document.createElement("option"); o.value = selectedCode; o.textContent = (nameByCode[selectedCode] || selectedCode) + " (미등록)"; o.setAttribute("data-name", nameByCode[selectedCode] || selectedCode); o.selected = true; sel.appendChild(o); } return sel; } function makeRow(data) { data = data || {}; var tr = document.createElement("tr"); // 컬럼: 체크 / 제품명(select) / 제품코드 / 수량 / 입수량 / 박스계산 / 라인메모 tr.innerHTML = '' + '' + '' + '' + '' + '' + ''; var code = data.product_code || ""; var nameSel = buildNameSelect(code); tr.querySelector(".cpg-cell-name").appendChild(nameSel); var codeInput = tr.querySelector(".cpg-code"); codeInput.value = code; tr.querySelector(".cpg-qty").value = data.quantity || ""; var upb = data.units_per_box; if (upb == null && code && ruleMap[code] != null) upb = ruleMap[code]; tr.querySelector(".cpg-upb").value = (upb != null ? upb : ""); // 제품명 선택 → 코드 자동 입력 + 입수량 자동 nameSel.addEventListener("change", function () { var c = nameSel.value; codeInput.value = c; if (c && ruleMap[c] != null) tr.querySelector(".cpg-upb").value = ruleMap[c]; recalc(tr); }); // 코드 직접 입력 시 입수량 규칙 자동 codeInput.addEventListener("input", function () { var c = codeInput.value.trim(); if (c && ruleMap[c] != null && !tr.querySelector(".cpg-upb").value) { tr.querySelector(".cpg-upb").value = ruleMap[c]; } }); tr.querySelector(".cpg-qty").addEventListener("input", function () { recalc(tr); }); tr.querySelector(".cpg-upb").addEventListener("input", function () { recalc(tr); }); body.appendChild(tr); recalc(tr); syncCheckAll(); return tr; } // 전체 선택 체크박스 상태 동기화 var checkAll = document.getElementById("cpg-check-all"); function syncCheckAll() { if (!checkAll) return; var checks = body.querySelectorAll(".cpg-row-check"); var total = checks.length; var on = 0; Array.prototype.forEach.call(checks, function (c) { if (c.checked) on++; }); checkAll.checked = total > 0 && on === total; checkAll.indeterminate = on > 0 && on < total; } if (checkAll) { checkAll.addEventListener("change", function () { Array.prototype.forEach.call(body.querySelectorAll(".cpg-row-check"), function (c) { c.checked = checkAll.checked; }); }); } body.addEventListener("change", function (e) { if (e.target && e.target.classList.contains("cpg-row-check")) syncCheckAll(); }); // 초기 라인 if (initLines.length) { initLines.forEach(makeRow); } else { makeRow(); } document.getElementById("cpg-add-line").addEventListener("click", function () { makeRow(); }); // 선택 라인 삭제 (체크된 행 삭제, 최소 1줄 유지) var delBtn = document.getElementById("cpg-del-line"); if (delBtn) { delBtn.addEventListener("click", function () { var checked = body.querySelectorAll(".cpg-row-check:checked"); if (!checked.length) { alert("삭제할 라인을 선택하세요."); return; } Array.prototype.forEach.call(checked, function (c) { var tr = c.closest("tr"); if (tr) tr.remove(); }); if (!body.querySelectorAll("tr").length) makeRow(); // 최소 1줄 if (checkAll) { checkAll.checked = false; checkAll.indeterminate = false; } syncCheckAll(); }); } // 제출: 라인 직렬화 form.addEventListener("submit", function (e) { var lines = []; Array.prototype.forEach.call(body.querySelectorAll("tr"), function (tr) { var code = tr.querySelector(".cpg-code").value.trim(); var qty = parseInt(tr.querySelector(".cpg-qty").value, 10) || 0; if (!code || qty <= 0) return; var upb = parseInt(tr.querySelector(".cpg-upb").value, 10); var sel = tr.querySelector(".cpg-name-sel"); var name = ""; if (sel && sel.selectedIndex >= 0) { var opt = sel.options[sel.selectedIndex]; name = opt ? (opt.getAttribute("data-name") || "") : ""; } if (!name) name = nameByCode[code] || code; lines.push({ product_code: code, product_name_snapshot: name, quantity: qty, units_per_box: (upb > 0 ? upb : null), memo: tr.querySelector(".cpg-memo").value.trim() }); }); if (!lines.length) { e.preventDefault(); alert("품목 라인을 최소 1개 입력하세요 (제품명/코드 + 수량)."); return; } document.getElementById("cpg-lines-json").value = JSON.stringify(lines); }); // 입고센터 select → 스냅샷 hidden 동기화 var centerSel = document.getElementById("cpg-center-select"); var centerName = document.getElementById("cpg-center-name"); if (centerSel && centerName) { function syncCenter() { var opt = centerSel.options[centerSel.selectedIndex]; if (opt && opt.value) centerName.value = opt.getAttribute("data-name") || opt.text; } centerSel.addEventListener("change", syncCenter); if (!centerName.value) syncCenter(); } })();