From 56cff672e2e1e2ab439d0f148f68debb84df6b3b Mon Sep 17 00:00:00 2001 From: king Date: Fri, 12 Jun 2026 10:59:09 +0900 Subject: [PATCH] =?UTF-8?q?fix(malaysia):=20=EC=BD=A4=EB=B3=B4=20=EC=9E=85?= =?UTF-8?q?=EA=B3=A0=20=EC=B0=A8=EB=8B=A8=20=E2=80=94=20=EB=82=B1=EA=B0=9C?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20=EC=9E=85=EA=B3=A0=20=EC=95=88=EB=82=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 콤보(MY-)는 입고 불가 구조. 입고 선택 + 콤보 수량 입력 시 차단. - 클라이언트: 제출 전 alert 안내(낱개로 분리 입고) - 서버: 동일 조건 400 (JS 우회 대비) - 세트 movement 는 항상 OUT 유지(create_set_out 원복) Co-Authored-By: Claude Opus 4.8 --- app/modules/malaysia/db.py | 1 + app/modules/malaysia/router.py | 17 ++++++++++++++++- .../malaysia/templates/malaysia/movements.html | 18 +++++++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/app/modules/malaysia/db.py b/app/modules/malaysia/db.py index 34316dd..4d7f3f1 100644 --- a/app/modules/malaysia/db.py +++ b/app/modules/malaysia/db.py @@ -233,6 +233,7 @@ class MalaysiaStockStore: """세트 주문 출고 → BOM(itemcode_db)으로 분해해 구성품별 OUT movement 생성. 예: MY-0002 1세트 출고 → MT-0320, MT-0550 ... 각각 OUT. + 콤보는 입고 불가(낱개로만 입고). 출고만 BOM 분해한다. bom_map 은 라우터가 itemcode 리더에서 받아 주입. 구성 없으면 ValueError. """ sc = store.validate_bom_set_code(set_code) diff --git a/app/modules/malaysia/router.py b/app/modules/malaysia/router.py index d7a800d..3b781c8 100644 --- a/app/modules/malaysia/router.py +++ b/app/modules/malaysia/router.py @@ -222,6 +222,7 @@ async def movements_apply(request: Request, user: dict[str, Any] = Depends(_requ - 낱개(individual): 선택한 movement_type 으로 등록. IN/OUT 양수만, ADJUST ±(0 스킵). - 세트(set): 항상 OUT 으로 처리 — BOM(itemcode_db) 분해해 구성품별 OUT 생성. + 콤보는 입고 불가(낱개로 분리 입고). IN 선택 + 콤보 수량 입력 시 400 안내. 빈칸/0 은 스킵. 코드별 에러는 모아서 부분 적용 후 안내. """ st = _store(request) @@ -238,6 +239,20 @@ async def movements_apply(request: Request, user: dict[str, Any] = Depends(_requ memo = str(form.get("memo") or "").strip() bmap = _bom_map(request) + # 콤보는 입고 불가 — IN 선택 + 세트 수량 입력 시 차단(낱개로 분리 입고 안내) + if mtype == "IN": + set_codes_keyed = [ + it["item_code"] + for it in st.list_items(kind="set") + if str(form.get(f"qty_{it['item_code']}") or "").strip() not in ("", "0") + ] + if set_codes_keyed: + raise HTTPException( + status_code=400, + detail="콤보 상품은 입고할 수 없습니다. 낱개로 분리해서 입고하세요. " + "(입고 불가 콤보: " + ", ".join(set_codes_keyed) + ")", + ) + applied = 0 errors: list[str] = [] @@ -264,7 +279,7 @@ async def movements_apply(request: Request, user: dict[str, Any] = Depends(_requ except ValueError as exc: errors.append(f"{code}: {exc}") - # 세트 — 항상 OUT(BOM 분해) + # 세트 — 항상 OUT(BOM 분해). 콤보 입고는 위에서 이미 차단됨. for it in st.list_items(kind="set"): code = it["item_code"] raw = str(form.get(f"qty_{code}") or "").strip() diff --git a/app/modules/malaysia/templates/malaysia/movements.html b/app/modules/malaysia/templates/malaysia/movements.html index 851b15a..ebe26d4 100644 --- a/app/modules/malaysia/templates/malaysia/movements.html +++ b/app/modules/malaysia/templates/malaysia/movements.html @@ -22,7 +22,7 @@ {% include "malaysia/_nav.html" %} -
+
@@ -89,6 +89,22 @@