feat(malaysia): 뚜껑(MD-) 랙 위치확인 배치 허용, 재고는 미반영

뚜껑(MD-0000~0005)을 재고조사 랙 입력 드롭다운에 노출해 창고 랙
어디에 있는지 위치만 기록할 수 있게 함. 재고에는 반영하지 않음.

- store.LID_ITEMS / lid_name_map 추가
- validate_rack_code 신설(개별/세트/뚜껑 허용) → replace_rack·
  reposition_rack 검증에 적용. 직접 라인 입력(validate_stocktake_code)은
  여전히 MD- 차단해 재고 오염 방지.
- aggregate_rack 에서 MD- 집계 제외 → daily_stocktake_line 미생성.
- 랙 드롭다운 목록에 LID_ITEMS 추가, 랙 보기 이름맵에 뚜껑 이름 병합.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 14:40:17 +09:00
parent fa396bd237
commit 55a2fc8793
4 changed files with 42 additions and 6 deletions
+35 -1
View File
@@ -25,7 +25,22 @@ STOCKTAKE_STATUSES: tuple[str, ...] = ("draft", "finalized", "cancelled")
# ── 코드 prefix ──
INDIVIDUAL_PREFIXES: tuple[str, ...] = ("MT-", "MX-", "MZ-")
SET_PREFIX: str = "MY-"
BLOCKED_PREFIX: str = "MD-" # 뚜껑 — 재고관리 대상에서 제외
BLOCKED_PREFIX: str = "MD-" # 뚜껑 — 재고(입출고/조사 집계) 대상에서 제외
# 뚜껑(MD-) 아이템 목록 — 재고에는 반영하지 않고 '창고 랙 위치 확인' 용도로만
# 랙 칸에 배치할 수 있다(드롭다운 노출). malaysia_items 테이블엔 넣지 않는다.
LID_ITEMS: tuple[dict[str, str], ...] = (
{"item_code": "MD-0000", "item_name": "Lid XS", "kind": "lid"},
{"item_code": "MD-0001", "item_name": "Lid S", "kind": "lid"},
{"item_code": "MD-0002", "item_name": "Lid M", "kind": "lid"},
{"item_code": "MD-0003", "item_name": "Lid L", "kind": "lid"},
{"item_code": "MD-0005", "item_name": "Lid 5", "kind": "lid"},
)
def lid_name_map() -> dict[str, str]:
"""뚜껑 코드 → 이름(랙 보기 표시용)."""
return {it["item_code"]: it["item_name"] for it in LID_ITEMS}
# ── 창고 랙 레이아웃 (재고조사 랙 입력용) ──
# 그림 고정: A/B 두 면, 각 면 3행 × 3열, 각 열은 2분할 → 면당 18칸, 총 36칸.
@@ -87,6 +102,9 @@ def aggregate_rack(entries: Iterable[dict[str, Any]]) -> dict[str, int]:
code = _norm(e.get("sku_code"))
if not code:
continue
# 뚜껑(MD-)은 위치 확인용일 뿐 재고에 반영하지 않으므로 집계 제외.
if is_blocked_code(code):
continue
try:
upb = int(e.get("units_per_box") or 0)
box = int(e.get("box_count") or 0)
@@ -166,6 +184,22 @@ def validate_stocktake_code(code: str) -> str:
return c
def validate_rack_code(code: str) -> str:
"""창고 랙 칸에 배치할 수 있는 코드 검증.
낱개(MT-/MX-/MZ-)·세트(MY-)에 더해 뚜껑(MD-)도 허용한다.
뚜껑은 위치 확인 용도로만 랙에 두며, aggregate_rack 에서 집계 제외되어
재고(daily_stocktake_line)에는 반영되지 않는다.
"""
c = _norm(code)
if not c:
raise ValueError("SKU 코드가 비어 있습니다.")
kind = classify_code(c)
if kind not in ("individual", "set", "blocked"):
raise ValueError(f"허용되지 않는 코드입니다(MT-/MX-/MZ-/MY-/MD- 만 가능): {c}")
return c
def validate_bom_set_code(code: str) -> str:
"""set_bom 의 set_code 검증 — MY- 만 허용."""
c = _norm(code)