change(cupang): 화면 문구 "박스" → "상자" 통일
템플릿·라우터 메시지·페이지 제목과 seed/DDL 기본값(쿠팡박스→쿠팡상자)까지 표기를 맞췄다. URL(/box-calc)과 코드 식별자(box_name 등)는 그대로. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{% extends "erp_base.html" %}
|
||||
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901n" />{% endblock %}
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901o" />{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="cpg">
|
||||
@@ -16,8 +16,8 @@
|
||||
{% if not box_rules %}
|
||||
<div class="erp-card cpg-form-card">
|
||||
<p class="erp-muted">
|
||||
등록된 박스 입수량 규칙이 없습니다.
|
||||
<a href="/cupang/box-rules">박스 입수량 설정</a>에서 먼저 제품별 입수량을 등록하세요.
|
||||
등록된 상자 입수량 규칙이 없습니다.
|
||||
<a href="/cupang/box-rules">상자 입수량 설정</a>에서 먼저 제품별 입수량을 등록하세요.
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<div class="cpg-calc3">
|
||||
|
||||
<!-- ① 박스 계산 — 제품명 + 수량만 입력 -->
|
||||
<!-- ① 상자 계산 — 제품명 + 수량만 입력 -->
|
||||
<div class="erp-card cpg-form-card cpg-calc-card">
|
||||
<div class="cpg-card-head">
|
||||
<h2>① 쿠팡 발주 업로드</h2>
|
||||
@@ -75,10 +75,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ② 박스 요약 — 센터에 배분하고 남은 수량이 실시간 반영 -->
|
||||
<!-- ② 상자 요약 — 센터에 배분하고 남은 수량이 실시간 반영 -->
|
||||
<div class="erp-card cpg-form-card cpg-calc-sum">
|
||||
<div class="cpg-card-head">
|
||||
<h2>② 박스 요약</h2>
|
||||
<h2>② 상자 요약</h2>
|
||||
<span class="erp-muted">카드를 ③ 센터로 끌어다 놓거나, 카드를 클릭해 담습니다.</span>
|
||||
</div>
|
||||
|
||||
@@ -88,10 +88,10 @@
|
||||
<div class="cpg-sum-kpis" id="cpg-sum-kpis"></div>
|
||||
|
||||
<div class="cpg-sum-scroll">
|
||||
<h3 class="cpg-sum-h3">제품별 박스 <span class="erp-muted">잔여 기준</span></h3>
|
||||
<h3 class="cpg-sum-h3">제품별 상자 <span class="erp-muted">잔여 기준</span></h3>
|
||||
<div class="cpg-sum-prods" id="cpg-sum-prods"></div>
|
||||
|
||||
<h3 class="cpg-sum-h3">자투리 혼합 박스 <span class="erp-muted" id="cpg-sum-mix-note"></span></h3>
|
||||
<h3 class="cpg-sum-h3">자투리 혼합 상자 <span class="erp-muted" id="cpg-sum-mix-note"></span></h3>
|
||||
<div class="cpg-sum-boxes" id="cpg-sum-boxes"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -103,7 +103,7 @@
|
||||
<h2>③ 센터 분배</h2>
|
||||
<span class="erp-muted">담을 센터를 골라 추가하세요.</span>
|
||||
<button type="button" class="erp-btn erp-btn-primary cpg-confirm-btn" id="cpg-confirm" disabled
|
||||
title="모든 박스를 배분하고 센터마다 출고방식을 고르면 활성화됩니다.">분배 확정</button>
|
||||
title="모든 상자를 배분하고 센터마다 출고방식을 고르면 활성화됩니다.">분배 확정</button>
|
||||
</div>
|
||||
|
||||
{% if not centers %}
|
||||
@@ -118,7 +118,7 @@
|
||||
|
||||
</div><!-- /cpg-calc3 -->
|
||||
|
||||
<!-- 담을 박스 수량 입력 대화상자 -->
|
||||
<!-- 담을 상자 수량 입력 대화상자 -->
|
||||
<div class="cpg-modal" id="cpg-dlg" hidden>
|
||||
<div class="cpg-modal-back" data-dlg-close></div>
|
||||
<div class="cpg-modal-box" role="dialog" aria-modal="true" aria-labelledby="cpg-dlg-title">
|
||||
@@ -126,7 +126,7 @@
|
||||
<p class="cpg-dlg-item" id="cpg-dlg-item"></p>
|
||||
<div class="erp-field"><span>센터</span>
|
||||
<div class="cpg-dlg-centers" id="cpg-dlg-centers" role="group" aria-label="담을 센터"></div></div>
|
||||
<label class="erp-field"><span>박스 수량</span>
|
||||
<label class="erp-field"><span>상자 수량</span>
|
||||
<input class="erp-input" type="number" id="cpg-dlg-qty" min="1" step="1" /></label>
|
||||
<p class="erp-muted" id="cpg-dlg-hint"></p>
|
||||
<div class="erp-page-actions cpg-dlg-actions">
|
||||
@@ -195,7 +195,7 @@
|
||||
<script type="application/json" id="cpg-calc-rules">{{ box_rules | tojson }}</script>
|
||||
<script type="application/json" id="cpg-centers">{{ centers | tojson }}</script>
|
||||
<script>
|
||||
// 박스 계산 3열 화면.
|
||||
// 상자 계산 3열 화면.
|
||||
// ① 제품명·수량 입력 → 서버(POST /cupang/api/box-calc)에서 계산
|
||||
// ② 계산 결과 요약 — 드래그(또는 클릭) 소스
|
||||
// ③ 선택한 센터에만 분배. 담은 수량만큼 ② 의 잔여가 즉시 줄어든다.
|
||||
@@ -243,8 +243,8 @@
|
||||
|
||||
// ── 상태 ─────────────────────────────────────────
|
||||
var calc = { results: [], mixes: [] }; // 서버 계산 결과
|
||||
var units = {}; // key -> 박스 1개당 상품 수
|
||||
var contents = {}; // key -> 혼합 박스 내용물 [{product_name, quantity}]
|
||||
var units = {}; // key -> 상자 1개당 상품 수
|
||||
var contents = {}; // key -> 혼합 상자 내용물 [{product_name, quantity}]
|
||||
var labels = {}; // key -> 표시 이름
|
||||
var openCenters = []; // ③ 에 추가한 센터 id (문자열)
|
||||
var alloc = {}; // centerId -> [{id, key, count}]
|
||||
@@ -255,7 +255,7 @@
|
||||
function prodKey(code) { return "p:" + code; }
|
||||
function mixKey(boxName, idx) { return "m:" + boxName + "#" + idx; }
|
||||
|
||||
// 자투리 혼합 박스에 쓸 상자 종류 — 요약 카드에서 고른다(표시용).
|
||||
// 자투리 혼합 상자에 쓸 상자 종류 — 요약 카드에서 고른다(표시용).
|
||||
var MIX_TYPES = ["쿠팡상자", "3호상자", "6호상자"];
|
||||
var mixType = {}; // mixKey -> 고른 상자 종류
|
||||
var mixOwner = {}; // mixKey -> 센터명(업로드로 만들어진 경우)
|
||||
@@ -360,8 +360,8 @@
|
||||
}
|
||||
|
||||
// ── 쿠팡 발주 엑셀 업로드 ─────────────────────────
|
||||
// 업로드 → 센터별 수량 합산(서버) → 센터마다 박스 계산 → ②③ 자동 채움.
|
||||
// 박스는 센터별로 포장하므로 계산도 센터 단위로 한다(자투리 혼합 박스 포함).
|
||||
// 업로드 → 센터별 수량 합산(서버) → 센터마다 상자 계산 → ②③ 자동 채움.
|
||||
// 상자는 센터별로 포장하므로 계산도 센터 단위로 한다(자투리 혼합 상자 포함).
|
||||
var poFile = document.getElementById("cpg-po-file");
|
||||
var poMsg = document.getElementById("cpg-po-msg");
|
||||
var poResult = document.getElementById("cpg-po-result");
|
||||
@@ -412,7 +412,7 @@
|
||||
return '<button type="button" class="cpg-date-tab' + (d === activeDate ? " is-active" : "") + '"' +
|
||||
' data-date="' + esc(d) + '">' +
|
||||
'<strong>' + esc(d || "날짜 미확인") + "</strong>" +
|
||||
'<span>센터 ' + cn + "곳 · " + bx + "박스</span>" +
|
||||
'<span>센터 ' + cn + "곳 · " + bx + "상자</span>" +
|
||||
"</button>";
|
||||
}).join("");
|
||||
}
|
||||
@@ -464,8 +464,8 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 센터별 계산 결과를 하나의 ② 요약으로 합치고, 각 박스를 그 센터에 자동 배분한다.
|
||||
// (한 출고일 안에서만 합친다 — 박스는 센터 단위로 포장)
|
||||
// 센터별 계산 결과를 하나의 ② 요약으로 합치고, 각 상자를 그 센터에 자동 배분한다.
|
||||
// (한 출고일 안에서만 합친다 — 상자는 센터 단위로 포장)
|
||||
function buildDataset(groups, perCenter) {
|
||||
var mergedProds = {}; // code -> 합산 결과
|
||||
var mergedMixes = {}; // box_name -> {box_name, boxes:[]}
|
||||
@@ -603,7 +603,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// 날짜 × 센터 단위로 박스 계산 (박스는 센터별로 포장되므로)
|
||||
// 날짜 × 센터 단위로 상자 계산 (상자는 센터별로 포장되므로)
|
||||
var jobs = [];
|
||||
dateGroups.forEach(function (g) {
|
||||
g.centers.forEach(function (c) {
|
||||
@@ -663,7 +663,7 @@
|
||||
var hit = calc.results.filter(function (r) { return r.product_code === code; })[0];
|
||||
return hit ? hit.full_boxes : 0;
|
||||
}
|
||||
return 1; // 혼합 박스는 1장 = 1박스
|
||||
return 1; // 혼합 상자는 1장 = 1상자
|
||||
}
|
||||
|
||||
function remainFor(key) { return Math.max(0, totalFor(key) - allocatedFor(key)); }
|
||||
@@ -736,7 +736,7 @@
|
||||
});
|
||||
var assigned = (totalProd + totalMix) - (remainProd + remainMix);
|
||||
|
||||
// 모든 박스를 센터에 배분하면 "센터 배분" 칸에 전체 완료 도장을 찍는다.
|
||||
// 모든 상자를 센터에 배분하면 "센터 배분" 칸에 전체 완료 도장을 찍는다.
|
||||
var totalBoxes = totalProd + totalMix;
|
||||
var allDone = totalBoxes > 0 && (remainProd + remainMix) === 0;
|
||||
var allStamp = "";
|
||||
@@ -747,9 +747,9 @@
|
||||
allStamped = allDone;
|
||||
|
||||
sumKpis.innerHTML =
|
||||
kpi("총 박스", totalBoxes + "박스", "제품별 " + totalProd + " + 혼합 " + totalMix) +
|
||||
kpi("센터 배분", assigned + "박스", "③ 에 담긴 수량", allStamp) +
|
||||
kpi("미배분 잔여", (remainProd + remainMix) + "박스", "자투리 " + leftoverUnits + "개 포함");
|
||||
kpi("총 상자", totalBoxes + "상자", "제품별 " + totalProd + " + 혼합 " + totalMix) +
|
||||
kpi("센터 배분", assigned + "상자", "③ 에 담긴 수량", allStamp) +
|
||||
kpi("미배분 잔여", (remainProd + remainMix) + "상자", "자투리 " + leftoverUnits + "개 포함");
|
||||
|
||||
var ph = "";
|
||||
calc.results.forEach(function (r) {
|
||||
@@ -764,8 +764,8 @@
|
||||
(remain ? "" : stampHtml(key)) +
|
||||
"</div>" +
|
||||
'<div class="cpg-sum-prod-nums">' +
|
||||
"<strong>" + remain + "박스</strong>" +
|
||||
'<span class="erp-muted">' + (remain * r.units_per_box) + "개 · 총 " + r.full_boxes + "박스" +
|
||||
"<strong>" + remain + "상자</strong>" +
|
||||
'<span class="erp-muted">' + (remain * r.units_per_box) + "개 · 총 " + r.full_boxes + "상자" +
|
||||
(used ? " · 배분 " + used : "") + "</span>" +
|
||||
(r.remainder_units
|
||||
? '<span class="cpg-sum-left">자투리 ' + r.remainder_units + "개</span>"
|
||||
@@ -779,7 +779,7 @@
|
||||
sumMixNote.textContent = "— 자투리 없음";
|
||||
sumBoxes.innerHTML = '<p class="erp-muted">남는 낱개가 없습니다.</p>';
|
||||
} else {
|
||||
sumMixNote.textContent = "— 1장 = 1박스";
|
||||
sumMixNote.textContent = "— 1장 = 1상자";
|
||||
var bh = "", n = 0;
|
||||
calc.mixes.forEach(function (m) {
|
||||
m.boxes.forEach(function (b, i) {
|
||||
@@ -809,14 +809,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 혼합 박스는 안에 무엇이 몇 개 들어가는지 트리로 펼쳐 보여준다.
|
||||
// 혼합 상자는 안에 무엇이 몇 개 들어가는지 트리로 펼쳐 보여준다.
|
||||
function treeHtml(entry) {
|
||||
var list = contents[entry.key];
|
||||
if (!list || !list.length) return "";
|
||||
return '<ul class="cpg-dist-tree">' + list.map(function (it) {
|
||||
return '<li><span class="cpg-tree-name">' + esc(it.product_name) + "</span>" +
|
||||
'<span class="cpg-tree-qty">' + (it.quantity * entry.count) + "개</span>" +
|
||||
(entry.count > 1 ? '<span class="cpg-tree-per">(' + it.quantity + "개 × " + entry.count + "박스)</span>" : "") +
|
||||
(entry.count > 1 ? '<span class="cpg-tree-per">(' + it.quantity + "개 × " + entry.count + "상자)</span>" : "") +
|
||||
"</li>";
|
||||
}).join("") + "</ul>";
|
||||
}
|
||||
@@ -838,7 +838,7 @@
|
||||
'<div class="cpg-dist-line">' +
|
||||
'<span class="cpg-dist-name">' + esc(labels[a.key] || a.key) + "</span>" +
|
||||
'<input class="erp-input cpg-dist-qty" type="number" min="1" max="999" step="1" inputmode="numeric" value="' + a.count + '" />' +
|
||||
'<span class="cpg-dist-unit">박스 · ' + (a.count * per) + "개</span>" +
|
||||
'<span class="cpg-dist-unit">상자 · ' + (a.count * per) + "개</span>" +
|
||||
'<button type="button" class="erp-btn erp-btn-danger cpg-dist-del" title="빼기" aria-label="빼기">✕</button>' +
|
||||
"</div>" +
|
||||
treeHtml(a) +
|
||||
@@ -855,14 +855,14 @@
|
||||
'<option value="파렛트"' + (method === "파렛트" ? " selected" : "") + '>파렛트</option>' +
|
||||
"</select>" +
|
||||
'<span class="cpg-dist-sum">' +
|
||||
'<span class="erp-badge erp-badge-neutral">' + boxes + "박스</span>" +
|
||||
'<span class="erp-badge erp-badge-neutral">' + boxes + "상자</span>" +
|
||||
'<span class="erp-badge erp-badge-neutral">' + pieces + "개</span>" +
|
||||
'<button type="button" class="erp-btn erp-btn-outline cpg-dist-close" title="센터 빼기" aria-label="센터 빼기">✕</button>' +
|
||||
"</span>" +
|
||||
"</div>" +
|
||||
(rows.length
|
||||
? '<ul class="cpg-dist-items">' + items + "</ul>"
|
||||
: '<p class="cpg-dist-hint">여기로 박스를 끌어다 놓기</p>') +
|
||||
: '<p class="cpg-dist-hint">여기로 상자를 끌어다 놓기</p>') +
|
||||
"</div>";
|
||||
});
|
||||
distList.innerHTML = html;
|
||||
@@ -875,15 +875,15 @@
|
||||
function openDialog(key, centerId) {
|
||||
if (!openCenters.length) { msg.textContent = "먼저 ③ 에서 센터를 추가하세요."; return; }
|
||||
var remain = remainFor(key);
|
||||
if (remain <= 0) { msg.textContent = "남은 박스가 없습니다."; return; }
|
||||
if (remain <= 0) { msg.textContent = "남은 상자가 없습니다."; return; }
|
||||
|
||||
pending = { key: key };
|
||||
dlgItem.textContent = (labels[key] || key) + " — 잔여 " + remain + "박스 (" + (remain * (units[key] || 0)) + "개)";
|
||||
dlgItem.textContent = (labels[key] || key) + " — 잔여 " + remain + "상자 (" + (remain * (units[key] || 0)) + "개)";
|
||||
dlgCenterId = String(centerId != null ? centerId : openCenters[0]);
|
||||
renderDialogCenters();
|
||||
dlgQty.max = remain;
|
||||
dlgQty.value = key.indexOf("m:") === 0 ? 1 : remain;
|
||||
dlgHint.textContent = "1박스 = " + (units[key] || 0) + "개 · 최대 " + remain + "박스";
|
||||
dlgHint.textContent = "1상자 = " + (units[key] || 0) + "개 · 최대 " + remain + "상자";
|
||||
dlg.hidden = false;
|
||||
dlgQty.focus();
|
||||
dlgQty.select();
|
||||
@@ -916,7 +916,7 @@
|
||||
closeDialog();
|
||||
render();
|
||||
msg.textContent = got
|
||||
? centerName(cid) + " ← " + (labels[key] || key) + " " + got + "박스"
|
||||
? centerName(cid) + " ← " + (labels[key] || key) + " " + got + "상자"
|
||||
: "담을 수량이 없습니다.";
|
||||
}
|
||||
|
||||
@@ -1069,7 +1069,7 @@
|
||||
var max = entry.count + remainFor(entry.key);
|
||||
if (want > max) { want = max; e.target.value = max; }
|
||||
entry.count = want;
|
||||
li.querySelector(".cpg-dist-unit").textContent = "박스 · " + (want * (units[entry.key] || 0)) + "개";
|
||||
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();
|
||||
@@ -1105,7 +1105,7 @@
|
||||
pieces += a.count * (units[a.key] || 0);
|
||||
});
|
||||
var badges = zone.querySelectorAll(".cpg-dist-sum .erp-badge");
|
||||
if (badges[0]) badges[0].textContent = boxes + "박스";
|
||||
if (badges[0]) badges[0].textContent = boxes + "상자";
|
||||
if (badges[1]) badges[1].textContent = pieces + "개";
|
||||
}
|
||||
|
||||
@@ -1203,9 +1203,9 @@
|
||||
function confirmBlockReason() {
|
||||
var t = boxTotals();
|
||||
if (!t.total) return "먼저 ① 에서 계산하세요.";
|
||||
if (t.remain) return "아직 " + t.remain + "박스가 남았습니다.";
|
||||
if (t.remain) return "아직 " + t.remain + "상자가 남았습니다.";
|
||||
var cids = filledCenters();
|
||||
if (!cids.length) return "센터에 담긴 박스가 없습니다.";
|
||||
if (!cids.length) return "센터에 담긴 상자가 없습니다.";
|
||||
var missing = cids.filter(function (cid) { return !methods[String(cid)]; });
|
||||
if (missing.length) return "출고방식 미선택: " + missing.map(centerName).join(", ");
|
||||
return "";
|
||||
@@ -1218,7 +1218,7 @@
|
||||
confirmBtn.title = why || "출고일자를 골라 출고 묶음을 만듭니다.";
|
||||
}
|
||||
|
||||
// 센터별 전송 payload — 혼합 박스는 내용물 제품으로 풀어서 담는다.
|
||||
// 센터별 전송 payload — 혼합 상자는 내용물 제품으로 풀어서 담는다.
|
||||
function buildPlans() {
|
||||
return filledCenters().map(function (cid) {
|
||||
var rows = alloc[cid] || [];
|
||||
@@ -1234,7 +1234,7 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
// 출고 엑셀 "출고" 칸 — 상자 종류별 박스 수 (예: "쿠팡상자, 41개")
|
||||
// 출고 엑셀 "출고" 칸 — 상자 종류별 상자 수 (예: "쿠팡상자, 41개")
|
||||
// 종류가 여럿이면 " / " 로 잇는다 (예: "쿠팡상자, 41개 / 3호상자, 2개")
|
||||
var byType = {};
|
||||
var order = [];
|
||||
@@ -1329,7 +1329,7 @@
|
||||
var pieces = pl.items.reduce(function (n, it) { return n + it.quantity; }, 0);
|
||||
return '<div class="cpg-cfm-row">' +
|
||||
'<span class="cpg-cfm-cname">' + esc(centerName(pl.center_id)) + "</span>" +
|
||||
'<span class="cpg-cfm-cmeta">' + esc(pl.ship_method) + " · " + pl.boxes + "박스 · " + pieces + "개</span>" +
|
||||
'<span class="cpg-cfm-cmeta">' + esc(pl.ship_method) + " · " + pl.boxes + "상자 · " + pieces + "개</span>" +
|
||||
"</div>";
|
||||
}).join("");
|
||||
renderCal();
|
||||
@@ -1565,7 +1565,7 @@
|
||||
if (!items.length) addRow("", 0);
|
||||
draftName.value = d.title || "";
|
||||
closeDraft();
|
||||
// 박스 수는 서버에서 다시 계산한 뒤 분배 내역을 얹는다.
|
||||
// 상자 수는 서버에서 다시 계산한 뒤 분배 내역을 얹는다.
|
||||
run(snap);
|
||||
})
|
||||
.catch(function () { draftMsg.textContent = "불러오기 실패 — 다시 시도하세요."; });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "erp_base.html" %}
|
||||
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901n" />{% endblock %}
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901o" />{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="cpg">
|
||||
@@ -14,7 +14,7 @@
|
||||
<!-- 왼쪽: 추가/수정 (product_code UNIQUE → upsert) -->
|
||||
<div class="erp-card cpg-form-card cpg-brule-add">
|
||||
<div class="cpg-card-head">
|
||||
<h2>박스 입수량 추가 / 수정</h2>
|
||||
<h2>상자 입수량 추가 / 수정</h2>
|
||||
<span class="erp-muted">같은 제품코드는 덮어씁니다.</span>
|
||||
</div>
|
||||
<form method="post" action="/cupang/box-rules">
|
||||
@@ -32,9 +32,9 @@
|
||||
<input class="erp-input cpg-brule-code" type="text" name="product_code" id="brule-code" required placeholder="자동" /></label>
|
||||
</div>
|
||||
<div class="cpg-brule-row">
|
||||
<label class="erp-field"><span>박스이름</span>
|
||||
<input class="erp-input cpg-brule-box" type="text" name="box_name" value="쿠팡박스" /></label>
|
||||
<label class="erp-field"><span>박스당 입수량 *</span>
|
||||
<label class="erp-field"><span>상자이름</span>
|
||||
<input class="erp-input cpg-brule-box" type="text" name="box_name" value="쿠팡상자" /></label>
|
||||
<label class="erp-field"><span>상자당 입수량 *</span>
|
||||
<span class="cpg-upb-wrap">
|
||||
<input class="erp-input cpg-brule-upb" type="number" name="units_per_box" min="1" required />
|
||||
<span class="cpg-upb-unit">개</span>
|
||||
@@ -74,7 +74,7 @@
|
||||
<div class="erp-table-wrap">
|
||||
<table class="erp-table">
|
||||
<thead>
|
||||
<tr><th>제품명</th><th>제품코드</th><th>박스명</th><th>입수량</th><th>메모</th><th>동작</th></tr>
|
||||
<tr><th>제품명</th><th>제품코드</th><th>상자명</th><th>입수량</th><th>메모</th><th>동작</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for r in box_rules %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "erp_base.html" %}
|
||||
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901n" />{% endblock %}
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901o" />{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="cpg">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "erp_base.html" %}
|
||||
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901n" />{% endblock %}
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901o" />{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="cpg">
|
||||
@@ -12,7 +12,7 @@
|
||||
<span class="cpg-settings-btns">
|
||||
<a class="erp-btn erp-btn-outline" href="/cupang/products">제품명 설정</a>
|
||||
<a class="erp-btn erp-btn-outline" href="/cupang/centers">입고센터 관리</a>
|
||||
<a class="erp-btn erp-btn-outline" href="/cupang/box-rules">박스 입수량 설정</a>
|
||||
<a class="erp-btn erp-btn-outline" href="/cupang/box-rules">상자 입수량 설정</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="cpg-actions-spacer"></div>
|
||||
@@ -97,7 +97,7 @@
|
||||
<a class="cpg-ship-name" href="/cupang/{{ s.id }}">{{ s.center_name_snapshot or '센터 미지정' }}</a>
|
||||
<span class="erp-badge erp-badge-neutral">{{ s.ship_method }}</span>
|
||||
<span class="cpg-dist-sum">
|
||||
<span class="erp-badge erp-badge-neutral">{{ s.total_boxes }}박스</span>
|
||||
<span class="erp-badge erp-badge-neutral">{{ s.total_boxes }}상자</span>
|
||||
<span class="erp-badge erp-badge-neutral">{{ s.total_qty }}개</span>
|
||||
<button type="button" class="cpg-icon-btn is-danger" title="이 출고 삭제"
|
||||
data-del="{{ s.id }}" data-name="{{ s.center_name_snapshot }}">삭제</button>
|
||||
@@ -110,7 +110,7 @@
|
||||
<li class="cpg-dist-item{% if e.kind == 'mix' %} is-mix{% endif %}">
|
||||
<div class="cpg-dist-line">
|
||||
<span class="cpg-dist-name">{{ e.name }}</span>
|
||||
<span class="cpg-dist-unit">{{ e.count }}박스 · {{ e.quantity }}개</span>
|
||||
<span class="cpg-dist-unit">{{ e.count }}상자 · {{ e.quantity }}개</span>
|
||||
</div>
|
||||
{% if e.kind == 'mix' and e['items'] %}
|
||||
<ul class="cpg-dist-tree">
|
||||
@@ -123,12 +123,12 @@
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{# 예전에 만든 출고(박스 구성 미저장) — 제품 합계만 표시 #}
|
||||
{# 예전에 만든 출고(상자 구성 미저장) — 제품 합계만 표시 #}
|
||||
{% for it in s['items'] %}
|
||||
<li class="cpg-dist-item">
|
||||
<div class="cpg-dist-line">
|
||||
<span class="cpg-dist-name">{{ it.name }}</span>
|
||||
<span class="cpg-dist-unit">{{ it.boxes }}박스 · {{ it.qty }}개</span>
|
||||
<span class="cpg-dist-unit">{{ it.boxes }}상자 · {{ it.qty }}개</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
@@ -141,7 +141,7 @@
|
||||
</ul>
|
||||
{% else %}
|
||||
<p class="erp-muted cpg-empty">선택한 날짜의 출고 묶음이 없습니다.
|
||||
<a href="/cupang/box-calc">박스 계산에서 등록</a></p>
|
||||
<a href="/cupang/box-calc">상자 계산에서 등록</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "erp_base.html" %}
|
||||
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901n" />{% endblock %}
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901o" />{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="cpg">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{% extends "erp_base.html" %}
|
||||
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901n" />{% endblock %}
|
||||
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260901o" />{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{# 출고 묶음 보기 — 박스 계산 화면과 같은 3열 구성. 읽기 전용(수정 없음). #}
|
||||
{# 출고 묶음 보기 — 상자 계산 화면과 같은 3열 구성. 읽기 전용(수정 없음). #}
|
||||
<section class="cpg">
|
||||
|
||||
<div class="erp-page-actions">
|
||||
@@ -44,18 +44,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ② 박스 요약 -->
|
||||
<!-- ② 상자 요약 -->
|
||||
<div class="erp-card cpg-form-card cpg-calc-sum">
|
||||
<div class="cpg-card-head">
|
||||
<h2>② 박스 요약</h2>
|
||||
<h2>② 상자 요약</h2>
|
||||
<span class="erp-muted">확정 당시 수량 기준으로 다시 계산한 값</span>
|
||||
</div>
|
||||
|
||||
<div id="cpg-sum-body">
|
||||
<div class="cpg-sum-kpis">
|
||||
<div class="cpg-kpi">
|
||||
<span class="cpg-kpi-label">총 박스</span>
|
||||
<strong class="cpg-kpi-value">{{ calc.grand_total_boxes }}박스</strong>
|
||||
<span class="cpg-kpi-label">총 상자</span>
|
||||
<strong class="cpg-kpi-value">{{ calc.grand_total_boxes }}상자</strong>
|
||||
<span class="cpg-kpi-hint">제품별 + 혼합</span>
|
||||
</div>
|
||||
<div class="cpg-kpi">
|
||||
@@ -71,7 +71,7 @@
|
||||
</div>
|
||||
|
||||
<div class="cpg-sum-scroll">
|
||||
<h3 class="cpg-sum-h3">제품별 박스</h3>
|
||||
<h3 class="cpg-sum-h3">제품별 상자</h3>
|
||||
<div class="cpg-sum-prods">
|
||||
{% for r in calc.results if r.configured %}
|
||||
<div class="cpg-sum-prod is-done">
|
||||
@@ -79,7 +79,7 @@
|
||||
<span class="cpg-sum-prod-name">{{ r.product_name }}</span>
|
||||
</div>
|
||||
<div class="cpg-sum-prod-nums">
|
||||
<strong>{{ r.full_boxes }}박스</strong>
|
||||
<strong>{{ r.full_boxes }}상자</strong>
|
||||
<span class="erp-muted">{{ r.quantity }}개 · 입수량 {{ r.units_per_box }}</span>
|
||||
{% if r.remainder_units %}
|
||||
<span class="cpg-sum-left">자투리 {{ r.remainder_units }}개</span>
|
||||
@@ -91,14 +91,14 @@
|
||||
{% endfor %}
|
||||
{% set unconfigured = calc.results | rejectattr('configured') | list %}
|
||||
{% if unconfigured %}
|
||||
<p class="erp-muted">박스 입수량 미설정:
|
||||
<p class="erp-muted">상자 입수량 미설정:
|
||||
{% for r in unconfigured %}{{ r.product_name }}{% if not loop.last %}, {% endif %}{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<h3 class="cpg-sum-h3">자투리 혼합 박스
|
||||
<span class="erp-muted">{% if not calc.mixes %}— 자투리 없음{% else %}— 1장 = 1박스{% endif %}</span>
|
||||
<h3 class="cpg-sum-h3">자투리 혼합 상자
|
||||
<span class="erp-muted">{% if not calc.mixes %}— 자투리 없음{% else %}— 1장 = 1상자{% endif %}</span>
|
||||
</h3>
|
||||
<div class="cpg-sum-boxes">
|
||||
{% for m in calc.mixes %}
|
||||
@@ -135,7 +135,7 @@
|
||||
<strong>{{ shipment.center_name_snapshot or '센터 미지정' }}</strong>
|
||||
<span class="erp-badge erp-badge-neutral">{{ shipment.ship_method }}</span>
|
||||
<span class="cpg-dist-sum">
|
||||
<span class="erp-badge erp-badge-neutral">{{ calc.grand_total_boxes }}박스</span>
|
||||
<span class="erp-badge erp-badge-neutral">{{ calc.grand_total_boxes }}상자</span>
|
||||
<span class="erp-badge erp-badge-neutral">{{ total_qty }}개</span>
|
||||
</span>
|
||||
</div>
|
||||
@@ -145,7 +145,7 @@
|
||||
<li class="cpg-dist-item{% if e.kind == 'mix' %} is-mix{% endif %}">
|
||||
<div class="cpg-dist-line">
|
||||
<span class="cpg-dist-name">{{ e.name }}</span>
|
||||
<span class="cpg-dist-unit">{{ e.count }}박스 · {{ e.quantity }}개</span>
|
||||
<span class="cpg-dist-unit">{{ e.count }}상자 · {{ e.quantity }}개</span>
|
||||
</div>
|
||||
{% if e.kind == 'mix' and e['items'] %}
|
||||
<ul class="cpg-dist-tree">
|
||||
|
||||
Reference in New Issue
Block a user