@@ -173,6 +173,7 @@
// ── 상태 ─────────────────────────────────────────
var calc = { results: [], mixes: [] }; // 서버 계산 결과
var units = {}; // key -> 박스 1개당 상품 수
+ var contents = {}; // key -> 혼합 박스 내용물 [{product_name, quantity}]
var labels = {}; // key -> 표시 이름
var openCenters = []; // ③ 에 추가한 센터 id (문자열)
var alloc = {}; // centerId -> [{id, key, count}]
@@ -230,6 +231,7 @@
calc.mixes = (data && data.mixes) || [];
units = {};
labels = {};
+ contents = {};
calc.results.forEach(function (r) {
units[prodKey(r.product_code)] = r.units_per_box;
labels[prodKey(r.product_code)] = r.product_name;
@@ -240,6 +242,9 @@
b.items.forEach(function (it) { n += it.quantity; });
units[mixKey(m.box_name, i)] = n;
labels[mixKey(m.box_name, i)] = m.box_name + " 혼합 #" + (i + 1);
+ contents[mixKey(m.box_name, i)] = b.items.map(function (it) {
+ return { product_name: it.product_name, quantity: it.quantity };
+ });
});
});
var had = Object.keys(alloc).some(function (k) { return alloc[k].length; });
@@ -388,6 +393,18 @@
}
}
+ // 혼합 박스는 안에 무엇이 몇 개 들어가는지 트리로 펼쳐 보여준다.
+ function treeHtml(entry) {
+ var list = contents[entry.key];
+ if (!list || !list.length) return "";
+ return '' + list.map(function (it) {
+ return '- ' + esc(it.product_name) + "" +
+ '' + (it.quantity * entry.count) + "개" +
+ (entry.count > 1 ? '(' + it.quantity + "개 × " + entry.count + "박스)" : "") +
+ "
";
+ }).join("") + "
";
+ }
+
// ── ③ 센터 분배 렌더 ──────────────────────────────
function renderDist() {
if (!distList) return;
@@ -402,10 +419,13 @@
boxes += a.count;
pieces += a.count * per;
items += '' +
- '' + esc(labels[a.key] || a.key) + "" +
- '' +
- '박스 · ' + (a.count * per) + "개" +
- '' +
+ '' +
+ '' + esc(labels[a.key] || a.key) + "" +
+ '' +
+ '박스 · ' + (a.count * per) + "개" +
+ '' +
+ "
" +
+ treeHtml(a) +
"";
});
html += '' +
@@ -608,6 +628,8 @@
if (want > max) { want = max; e.target.value = max; }
entry.count = want;
li.querySelector(".cpg-dist-unit").textContent = "박스 · " + (want * (units[entry.key] || 0)) + "개";
+ var tree = li.querySelector(".cpg-dist-tree");
+ if (tree) tree.outerHTML = treeHtml(entry);
renderSummary();
updateCenterTotals(cid);
});
diff --git a/app/modules/cupang/templates/cupang/box_rules.html b/app/modules/cupang/templates/cupang/box_rules.html
index 1e490bd..10a19d4 100644
--- a/app/modules/cupang/templates/cupang/box_rules.html
+++ b/app/modules/cupang/templates/cupang/box_rules.html
@@ -1,6 +1,6 @@
{% extends "erp_base.html" %}
-{% block head_extra %}{% endblock %}
+{% block head_extra %}{% endblock %}
{% block content %}
diff --git a/app/modules/cupang/templates/cupang/centers.html b/app/modules/cupang/templates/cupang/centers.html
index 3e37b6e..9adb085 100644
--- a/app/modules/cupang/templates/cupang/centers.html
+++ b/app/modules/cupang/templates/cupang/centers.html
@@ -1,6 +1,6 @@
{% extends "erp_base.html" %}
-{% block head_extra %}{% endblock %}
+{% block head_extra %}{% endblock %}
{% block content %}
diff --git a/app/modules/cupang/templates/cupang/detail.html b/app/modules/cupang/templates/cupang/detail.html
index 7a61f1c..4c15487 100644
--- a/app/modules/cupang/templates/cupang/detail.html
+++ b/app/modules/cupang/templates/cupang/detail.html
@@ -1,6 +1,6 @@
{% extends "erp_base.html" %}
-{% block head_extra %}{% endblock %}
+{% block head_extra %}{% endblock %}
{% block content %}
diff --git a/app/modules/cupang/templates/cupang/form.html b/app/modules/cupang/templates/cupang/form.html
index 922ef2c..350ce19 100644
--- a/app/modules/cupang/templates/cupang/form.html
+++ b/app/modules/cupang/templates/cupang/form.html
@@ -1,6 +1,6 @@
{% extends "erp_base.html" %}
-{% block head_extra %}{% endblock %}
+{% block head_extra %}{% endblock %}
{% block content %}
diff --git a/app/modules/cupang/templates/cupang/index.html b/app/modules/cupang/templates/cupang/index.html
index fdaddc7..2f001a6 100644
--- a/app/modules/cupang/templates/cupang/index.html
+++ b/app/modules/cupang/templates/cupang/index.html
@@ -1,6 +1,6 @@
{% extends "erp_base.html" %}
-{% block head_extra %}{% endblock %}
+{% block head_extra %}{% endblock %}
{% block content %}
diff --git a/app/modules/cupang/templates/cupang/products.html b/app/modules/cupang/templates/cupang/products.html
index c351249..18ba2e3 100644
--- a/app/modules/cupang/templates/cupang/products.html
+++ b/app/modules/cupang/templates/cupang/products.html
@@ -1,6 +1,6 @@
{% extends "erp_base.html" %}
-{% block head_extra %}{% endblock %}
+{% block head_extra %}{% endblock %}
{% block content %}
diff --git a/app/static/cupang.css b/app/static/cupang.css
index 094f18d..e08bdc4 100644
--- a/app/static/cupang.css
+++ b/app/static/cupang.css
@@ -705,3 +705,28 @@ body.cpg-dragging { cursor: grabbing; user-select: none; }
overflow-y: auto;
}
.cpg-dlg-center-btn { padding: 4px 12px; }
+
+/* 센터에 담긴 혼합 박스의 내용물 트리 */
+.cpg-dist-item { display: block; }
+.cpg-dist-line { display: flex; align-items: center; gap: 6px; }
+.cpg-dist-tree {
+ list-style: none;
+ margin: 4px 0 2px;
+ padding: 0 0 0 10px;
+ border-left: 1px solid var(--color-subtle-ash);
+}
+.cpg-dist-tree li {
+ display: flex;
+ align-items: baseline;
+ gap: 6px;
+ padding: 1px 0;
+ font-size: 12px;
+ color: var(--color-midtone-gray);
+}
+.cpg-dist-tree li::before {
+ content: "└";
+ color: var(--color-subtle-ash);
+}
+.cpg-tree-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.cpg-tree-qty { font-weight: 600; color: var(--color-rich-black); }
+.cpg-tree-per { font-size: 11px; }
diff --git a/tests/js/box_calc_ui.test.js b/tests/js/box_calc_ui.test.js
index 419ed3c..569d426 100644
--- a/tests/js/box_calc_ui.test.js
+++ b/tests/js/box_calc_ui.test.js
@@ -143,6 +143,12 @@ function dragCardTo(card, target) {
$("#cpg-dlg-ok").click();
check("혼합 박스가 센터에 담긴다", $$(".cpg-dist-item").length === 2);
check("혼합 담은 뒤 배분됨 표시", $(".cpg-box-card").className.includes("is-done"));
+ check("혼합 박스 아래 내용물 트리", $$(".cpg-dist-tree li").length === 2,
+ String($$(".cpg-dist-tree li").length));
+ check("트리에 제품명·개수", text(".cpg-dist-tree li").includes("미라네 4호 세트") &&
+ text(".cpg-dist-tree li").includes("4개"), text(".cpg-dist-tree li"));
+ check("단일 제품 항목에는 트리 없음",
+ !$$(".cpg-dist-item")[0].querySelector(".cpg-dist-tree"));
// ── 항목 빼기 / 센터 빼기 ─────────────────────────
$$(".cpg-dist-del")[1].click();