From 90e286dc4d9e085b1ebb773acfd1b51ced3f40a6 Mon Sep 17 00:00:00 2001 From: king Date: Sat, 30 May 2026 06:11:57 +0900 Subject: [PATCH] =?UTF-8?q?ui(cupang):=20=EB=B0=95=EC=8A=A4=EB=A3=B0=20?= =?UTF-8?q?=ED=8F=BC=203=ED=96=89=20=EB=B0=B0=EC=B9=98=20+=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=BB=AC=EB=9F=BC=20=EC=A0=95=EB=A6=AC/=ED=95=98?= =?UTF-8?q?=EB=93=9C=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 폼: 1행 제품명180/제품코드100, 2행 박스이름/박스당입수량, 3행 메모(전체폭) - 목록 순서 제품명·제품코드·박스명·입수량·메모, 상태열/비활성 제거 - 삭제 버튼=완전삭제(delete_box_rule, 참조 라인 box_rule_id NULL 처리) - 캐시 버전 f Co-Authored-By: Claude Opus 4.8 --- app/modules/cupang/db.py | 15 +++++ app/modules/cupang/router.py | 2 +- .../cupang/templates/cupang/box_rules.html | 60 ++++++++++--------- .../cupang/templates/cupang/centers.html | 2 +- .../cupang/templates/cupang/detail.html | 2 +- app/modules/cupang/templates/cupang/form.html | 4 +- .../cupang/templates/cupang/index.html | 2 +- .../cupang/templates/cupang/products.html | 2 +- app/static/cupang.css | 17 +++--- app/templates/erp_base.html | 4 +- 10 files changed, 66 insertions(+), 44 deletions(-) diff --git a/app/modules/cupang/db.py b/app/modules/cupang/db.py index f6ad3dd..582876c 100644 --- a/app/modules/cupang/db.py +++ b/app/modules/cupang/db.py @@ -197,6 +197,21 @@ class CupangDBStore: if cur.rowcount == 0: raise KeyError(rule_id) + def delete_box_rule(self, *, rule_id: int) -> None: + """완전 삭제(hard). 라인의 box_rule_id 는 ON DELETE 미설정이므로 + 참조 중이면 FK 위반 가능 → 참조 라인의 box_rule_id 를 먼저 NULL 처리.""" + with self._pool.connection() as conn: + with conn.transaction(): + conn.execute( + "UPDATE cupang_shipment_lines SET box_rule_id = NULL WHERE box_rule_id = %s", + (rule_id,), + ) + cur = conn.execute( + "DELETE FROM cupang_box_rules WHERE id = %s", (rule_id,) + ) + if cur.rowcount == 0: + raise KeyError(rule_id) + def box_rule_map(self) -> dict[str, dict[str, Any]]: """product_code → rule. 폼/계산에서 빠르게 조회하기 위한 dict.""" return {r["product_code"]: r for r in self.list_box_rules()} diff --git a/app/modules/cupang/router.py b/app/modules/cupang/router.py index 4c79b53..c293be7 100644 --- a/app/modules/cupang/router.py +++ b/app/modules/cupang/router.py @@ -594,7 +594,7 @@ async def box_rule_delete( if store is None: raise HTTPException(status_code=503, detail="cupang_db 미설정") try: - store.deactivate_box_rule(rule_id=rule_id) + store.delete_box_rule(rule_id=rule_id) except KeyError: raise HTTPException(status_code=404, detail="규칙을 찾을 수 없습니다.") return RedirectResponse(url="/cupang/box-rules", status_code=303) diff --git a/app/modules/cupang/templates/cupang/box_rules.html b/app/modules/cupang/templates/cupang/box_rules.html index 66d1108..3da9295 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 %}
@@ -20,24 +20,30 @@
- - - - - +
+ + +
+
+ + +
+
+ +
@@ -68,27 +74,27 @@
- + {% for r in box_rules %} - - + + - {% endfor %} + {% if not box_rules %} + + {% endif %}
제품코드제품명박스명입수량상태메모
제품명제품코드박스명입수량메모동작
{{ r.product_code }}
{{ r.product_name_snapshot or '—' }}{{ r.product_code }} {{ r.box_name }} {{ r.units_per_box }}{% if r.active %}활성{% else %}비활성{% endif %} {{ r.memo or '—' }} - {% if r.active %} - + onsubmit="return confirm('이 규칙을 삭제합니다. 계속할까요?');"> + - {% else %}—{% endif %}
등록된 입수량 규칙이 없습니다.
diff --git a/app/modules/cupang/templates/cupang/centers.html b/app/modules/cupang/templates/cupang/centers.html index 1e02ee6..4eec7ef 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 ef160a0..d85ec73 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 fae0be9..b2ab0eb 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 %}
@@ -118,4 +118,4 @@ {% endblock %} -{% block scripts %}{% endblock %} +{% block scripts %}{% endblock %} diff --git a/app/modules/cupang/templates/cupang/index.html b/app/modules/cupang/templates/cupang/index.html index 3bd7faf..f2e460d 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 c4d55ac..d320b97 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 eacf321..e61547c 100644 --- a/app/static/cupang.css +++ b/app/static/cupang.css @@ -246,20 +246,21 @@ @media (max-width: 1420px) { .cpg-brule-list { flex-basis: auto; width: 100%; } } @media (max-width: 540px) { .cpg-brule-add { flex-basis: 100%; width: 100%; } } -.cpg-brule-fields { display: flex; flex-wrap: wrap; gap: 12px 16px; } -/* 제품명·제품코드·박스이름 140px 고정 (erp.css min-width:240 오버라이드) */ -.cpg .cpg-brule-fields .erp-field > .erp-input, -.cpg .cpg-brule-fields .erp-field > .erp-select { - width: 140px; min-width: 140px; max-width: 140px; box-sizing: border-box; -} +.cpg-brule-fields { display: flex; flex-direction: column; gap: 12px; } +.cpg-brule-row { display: flex; gap: 16px; align-items: flex-end; } +.cpg-brule-memo-field { flex: 1 1 auto; min-width: 0; } +/* 필드별 고정 폭 (erp.css min-width:240 오버라이드) */ +.cpg .cpg-brule-fields .cpg-brule-name { width: 180px; min-width: 180px; max-width: 180px; box-sizing: border-box; } +.cpg .cpg-brule-fields .cpg-brule-code { width: 100px; min-width: 100px; max-width: 100px; box-sizing: border-box; } +.cpg .cpg-brule-fields .cpg-brule-box { width: 140px; min-width: 140px; max-width: 140px; box-sizing: border-box; } /* 박스당 입수량 60px + "개" */ .cpg-upb-wrap { display: inline-flex; align-items: center; gap: 4px; } .cpg .cpg-brule-fields .cpg-upb-wrap > .cpg-brule-upb { width: 60px; min-width: 60px; max-width: 60px; box-sizing: border-box; } .cpg-upb-unit { font-size: 13px; color: var(--color-midtone-gray); } -/* 메모는 넓게 */ -.cpg .cpg-brule-fields .cpg-brule-memo { width: 300px; min-width: 300px; max-width: 300px; } +/* 메모: 프레임 전체 너비 */ +.cpg .cpg-brule-fields .cpg-brule-memo { width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box; } /* ── 상품 검색 드롭다운 ── */ .cpg-search-pop { diff --git a/app/templates/erp_base.html b/app/templates/erp_base.html index 23f9c4c..90dcdfb 100644 --- a/app/templates/erp_base.html +++ b/app/templates/erp_base.html @@ -4,8 +4,8 @@ {{ page_title or "ERP" }} — DBX Corporation - - + + {% block head_extra %}{% endblock %}