feat(cupang): 등록 제품명 표 정렬 + 박스 입수량 시드 SQL

제품명/제품코드 헤더 클릭으로 오름·내림차순 토글. Intl.Collator(ko,
numeric) 사용해 "미라네 2호"가 "미라네 10호"보다 앞에 오도록 정렬.
검색 비활성 상태에서도 동작하게 스크립트를 search_enabled 밖에 배치.

박스 입수량 14건(미라네 1~7호, 황토 김치통 1~7호) 시드 SQL 추가.
피킹비 전용 컬럼이 없어 memo 에 기록.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-28 12:13:22 +09:00
parent 55d1c1d6f3
commit 7eb63ff664
8 changed files with 118 additions and 10 deletions
@@ -1,6 +1,6 @@
{% extends "erp_base.html" %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260530p" />{% endblock %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260828s" />{% 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=20260530p" />{% endblock %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260828s" />{% 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=20260530p" />{% endblock %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260828s" />{% 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=20260530p" />{% endblock %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260828s" />{% 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=20260530p" />{% endblock %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260828s" />{% 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=20260530p" />{% endblock %}
{% block head_extra %}<link rel="stylesheet" href="/static/cupang.css?v=20260828s" />{% endblock %}
{% block content %}
<section class="cpg">
@@ -38,10 +38,17 @@
<span class="erp-muted">폼의 제품명 드롭다운에 노출</span></div>
<div class="erp-table-wrap cpg-reg-scroll">
<table class="erp-table">
<thead><tr><th>제품명</th><th>제품코드</th><th>상태</th><th>동작</th></tr></thead>
<tbody>
<thead>
<tr>
<th><button type="button" class="cpg-sort" data-sort-key="name">제품명<span class="cpg-sort-ind" aria-hidden="true"></span></button></th>
<th><button type="button" class="cpg-sort" data-sort-key="code">제품코드<span class="cpg-sort-ind" aria-hidden="true"></span></button></th>
<th>상태</th>
<th>동작</th>
</tr>
</thead>
<tbody id="cpg-prod-tbody">
{% for p in products %}
<tr {% if not p.active %}style="opacity:.55"{% endif %}>
<tr data-name="{{ p.product_name }}" data-code="{{ p.product_code }}" {% if not p.active %}style="opacity:.55"{% endif %}>
<td>{{ p.product_name }}</td>
<td>{{ p.product_code }}</td>
<td>{% if p.active %}<span class="erp-badge erp-badge-success">활성</span>{% else %}<span class="erp-badge erp-badge-neutral">비활성</span>{% endif %}</td>
@@ -67,7 +74,7 @@
</tr>
{% endfor %}
{% if not products %}
<tr><td colspan="4" class="erp-muted">등록된 제품명이 없습니다. 왼쪽에서 선택해 등록하세요.</td></tr>
<tr class="cpg-no-sort"><td colspan="4" class="erp-muted">등록된 제품명이 없습니다. 왼쪽에서 선택해 등록하세요.</td></tr>
{% endif %}
</tbody>
</table>
@@ -77,6 +84,43 @@
</div>
</section>
<script>
// 등록된 제품명 표 — 제품명/제품코드 오름차순·내림차순 정렬 (클라이언트).
(function () {
var tbody = document.getElementById("cpg-prod-tbody");
if (!tbody) return;
var buttons = Array.prototype.slice.call(document.querySelectorAll(".cpg-sort"));
var state = { key: null, dir: 1 };
var collator = new Intl.Collator("ko", { numeric: true, sensitivity: "base" });
function apply() {
var rows = Array.prototype.slice.call(tbody.querySelectorAll("tr:not(.cpg-no-sort)"));
if (rows.length < 2) return;
rows.sort(function (a, b) {
var av = a.getAttribute("data-" + state.key) || "";
var bv = b.getAttribute("data-" + state.key) || "";
return collator.compare(av, bv) * state.dir;
});
rows.forEach(function (r) { tbody.appendChild(r); });
}
buttons.forEach(function (btn) {
btn.addEventListener("click", function () {
var key = btn.getAttribute("data-sort-key");
if (state.key === key) { state.dir = -state.dir; }
else { state.key = key; state.dir = 1; }
buttons.forEach(function (b) {
var on = b === btn;
b.classList.toggle("is-asc", on && state.dir === 1);
b.classList.toggle("is-desc", on && state.dir === -1);
b.closest("th").setAttribute("aria-sort", on ? (state.dir === 1 ? "ascending" : "descending") : "none");
});
apply();
});
});
})();
</script>
{% if search_enabled %}
<script type="application/json" id="cpg-registered">{{ registered_codes | tojson }}</script>
<script>