From 58ebf1c232fcffaff0bbd64310096830b64bf698 Mon Sep 17 00:00:00 2001 From: king Date: Tue, 1 Sep 2026 16:33:32 +0900 Subject: [PATCH] =?UTF-8?q?change(cupang):=20=EB=AF=B8=EB=B0=B0=EC=B9=98?= =?UTF-8?q?=20=EC=9E=90=ED=88=AC=EB=A6=AC=20=EC=A0=9C=EA=B1=B0=20=E2=80=94?= =?UTF-8?q?=20=EC=83=81=EC=9E=90=20=EA=B0=84=20=EC=A7=81=EC=A0=91=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=EB=A7=8C,=20=E2=91=A2=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A1=A4=20=EB=B3=B4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - "미배치로 빼기" 옵션과 미배치 풀 UI/상태 삭제 - [−] 는 자리가 있는 다른 상자로 1개 이동(없으면 새 상자 자동 생성), [+] 는 같은 제품이 있는 다른 상자에서 1개 가져오기 → 총량 항상 보존 - 혼합 상자 ✕ 는 내용물을 다른 상자로 옮긴 뒤 상자를 없앤다 - 3열이 2열/1열로 접히는 폭에서 카드 max-height 를 줘서 ③ 목록이 카드 안에서 스크롤되도록 수정(편집으로 줄이 늘어나도 페이지가 안 밀림) Co-Authored-By: Claude Opus 5 --- .../cupang/templates/cupang/box_calc.html | 274 +++++++----------- .../cupang/templates/cupang/box_rules.html | 2 +- .../cupang/templates/cupang/centers.html | 2 +- .../cupang/templates/cupang/index.html | 2 +- .../cupang/templates/cupang/products.html | 2 +- app/modules/cupang/templates/cupang/view.html | 2 +- app/static/cupang.css | 27 +- 7 files changed, 117 insertions(+), 194 deletions(-) diff --git a/app/modules/cupang/templates/cupang/box_calc.html b/app/modules/cupang/templates/cupang/box_calc.html index 133f701..00ae37b 100644 --- a/app/modules/cupang/templates/cupang/box_calc.html +++ b/app/modules/cupang/templates/cupang/box_calc.html @@ -1,6 +1,6 @@ {% extends "erp_base.html" %} -{% block head_extra %}{% endblock %} +{% block head_extra %}{% endblock %} {% block content %}
@@ -351,7 +351,6 @@ var had = Object.keys(alloc).some(function (k) { return alloc[k].length; }); alloc = {}; stamped = {}; - pool = {}; allStamped = false; // 계산이 바뀌면 이전 배분은 근거가 사라지므로 비운다. var skipped = restore ? applyRestore(restore) : 0; render(); @@ -433,7 +432,7 @@ units: units, labels: labels, contents: contents, openCenters: openCenters.slice(), alloc: alloc, methods: methods, stamped: stamped, allStamped: allStamped, - mixType: mixType, mixOwner: mixOwner, pool: pool + mixType: mixType, mixOwner: mixOwner }; } @@ -450,7 +449,6 @@ alloc = st.alloc; methods = st.methods; stamped = st.stamped; allStamped = st.allStamped; mixType = st.mixType || {}; mixOwner = st.mixOwner || {}; - pool = st.pool || {}; tbody.innerHTML = ""; (st.items || []).forEach(function (it) { addRow(it.product_code, it.quantity); }); @@ -482,7 +480,7 @@ units: {}, labels: {}, contents: {}, openCenters: [], alloc: {}, methods: {}, stamped: {}, allStamped: false, - mixType: {}, mixOwner: {}, pool: {} + mixType: {}, mixOwner: {} }; function put(cid, key, count) { @@ -691,8 +689,6 @@ // ── 혼합 상자 편집 ──────────────────────────────── // 상자 용량은 부피 합으로 본다: 제품 1개 = 1/입수량 상자. // 빼낸 수량은 센터별 "미배치 자투리" 풀에 남고, 거기서 다시 담는다. - var pool = {}; // centerId -> [{product_code, product_name, quantity}] - function upbOf(code) { var hit = calc.results.filter(function (r) { return r.product_code === code; })[0]; return hit ? (hit.units_per_box || 0) : 0; @@ -766,36 +762,6 @@ .map(function (a) { return a.key; }); } - function poolOf(cid) { - cid = String(cid); - if (!pool[cid]) pool[cid] = []; - return pool[cid]; - } - - function poolAdd(cid, code, name, qty) { - if (qty <= 0) return; - var list = poolOf(cid); - var hit = list.filter(function (it) { return it.product_code === code; })[0]; - if (hit) { hit.quantity += qty; return; } - list.push({ product_code: code, product_name: name, quantity: qty }); - } - - function poolTake(cid, code, qty) { - var list = poolOf(cid); - var hit = list.filter(function (it) { return it.product_code === code; })[0]; - if (!hit) return 0; - var take = Math.min(hit.quantity, qty); - hit.quantity -= take; - pool[String(cid)] = list.filter(function (it) { return it.quantity > 0; }); - return take; - } - - function poolTotal(cid) { - var n = 0; - poolOf(cid).forEach(function (it) { n += it.quantity; }); - return n; - } - function mixItem(key, code) { return (contents[key] || []).filter(function (it) { return it.product_code === code; })[0]; } @@ -812,19 +778,48 @@ return put; } - // 상자에서 빼기 — 뺀 수량은 그 센터의 미배치 풀로. - function mixTake(key, code, qty) { + // 상자에서 덜어내기(내부용) — 호출한 쪽이 곧바로 다른 상자에 담는다. + function mixPull(key, code, qty) { var hit = mixItem(key, code); if (!hit) return 0; var take = Math.min(hit.quantity, qty); if (take <= 0) return 0; - var cid = centerOfKey(key); hit.quantity -= take; syncMix(key); - if (cid) poolAdd(cid, code, hit.product_name, take); return take; } + // 자리가 있는 다른 상자 찾기 (없으면 "") + function boxWithRoom(cid, code, exceptKey) { + var found = ""; + mixKeysOf(cid).forEach(function (k) { + if (found || k === exceptKey) return; + if (mixRoomFor(k, code) > 0) found = k; + }); + return found; + } + + // 그 제품이 담겨 있는 다른 상자 찾기 (없으면 "") + function boxHaving(cid, code, exceptKey) { + var found = ""; + mixKeysOf(cid).forEach(function (k) { + if (found || k === exceptKey) return; + if (mixItem(k, code)) found = k; + }); + return found; + } + + // 상자 → 상자 이동. 실제로 옮긴 수량을 돌려준다(자리만큼만). + function moveUnits(fromKey, toKey, code, name, qty) { + var room = mixRoomFor(toKey, code); + var move = Math.min(qty, room); + if (move <= 0) return 0; + var pulled = mixPull(fromKey, code, move); + if (!pulled) return 0; + mixPut(toKey, code, name, pulled); + return pulled; + } + // 새 혼합 상자 (같은 센터, 비어 있는 상태로 추가) function newMixBox(cid, boxName) { var name = boxName || (calc.mixes[0] && calc.mixes[0].box_name) || MIX_TYPES[0]; @@ -983,7 +978,6 @@ esc(labels[k] || k) + (room ? " (여유 " + room + "개)" : " (가득)") + ""; }); opts += ''; - opts += ''; return opts; } @@ -1000,15 +994,16 @@ (entry.count > 1 ? '(' + it.quantity + "개 × " + entry.count + "상자)" : "") + ""; } - var canAdd = mixRoomFor(entry.key, it.product_code) > 0; + var canAdd = mixRoomFor(entry.key, it.product_code) > 0 && + !!boxHaving(cid, it.product_code, entry.key); return '
  • ' + esc(it.product_name) + "" + '' + '' + + '" data-code="' + esc(it.product_code) + '" title="다른 상자로 1개 옮기기">−' + '' + qty + "개" + '' + + ' title="다른 상자에서 1개 가져오기">+' + '' + opts + "" + - "
  • "; - }).join(""); - return '
    ' + - '
    미배치 자투리 ' + poolTotal(cid) + "개" + - '' + - "
    " + - '
      ' + rows + "
    " + - "
    "; - } - // ── ③ 센터 분배 렌더 ────────────────────────────── function renderDist() { if (!distList) return; @@ -1090,7 +1057,6 @@ (rows.length ? '
      ' + items + "
    " : '

    여기로 상자를 끌어다 놓기

    ') + - poolHtml(cid) + (rows.length ? '
    ' + '