feat(dispatch): 말레이시아 재고 차감 버튼(날짜 1회성)
- 달력 다운로드 아래 '말레이시아 재고 차감' 버튼. 선택 날짜 출고를 말레이시아 재고관리에 OUT 으로 반영(movement_date=해당 날짜) · 낱개(MT/MX/MZ)=낱개 OUT, 콤보(MY-)=세트 OUT(재고관리가 BOM 분해) · _N 배수 반영, MD-(뚜껑) 제외 - 날짜당 1회만: dispatch_stock_deductions 마커로 재차감 차단(이중 출고 방지) · 마커 선점 후 반영, 콤보 BOM 누락은 사전검증으로 차단 - export.split_singles_combos, db 차감 가드 메서드, 라우터 POST /dispatch/stock-deduct - 스키마: dispatch_stock_deductions (init + 마이그레이션 dispatch_add_deductions.sql) - 이미 차감된 날짜는 버튼 비활성 + 안내 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -139,6 +139,32 @@ def build_workbook_bytes(
|
||||
# ── 사방넷 재고 업로드 엑셀(낱개 분해) ──
|
||||
_STOCK_HEADERS: tuple[str, ...] = ("상품코드[필수]", "가용수량", "불용수량", "바코드")
|
||||
_LID_PREFIX = "MD-" # 뚜껑 — 재고 집계 제외
|
||||
_SET_PREFIX = "MY-" # 콤보(세트)
|
||||
|
||||
|
||||
def split_singles_combos(
|
||||
rows: list[dict[str, Any]],
|
||||
) -> tuple[dict[str, int], dict[str, int]]:
|
||||
"""SKU별 합산 행 → (낱개 {code: qty}, 콤보 {code: qty}).
|
||||
|
||||
_N 배수 반영, MD-(뚜껑) 제외. 콤보는 MY- 접두사. 분해는 하지 않는다
|
||||
(말레이시아 재고관리가 세트 OUT 시 BOM 으로 분해하므로 콤보 그대로 넘긴다).
|
||||
"""
|
||||
singles: dict[str, int] = {}
|
||||
combos: dict[str, int] = {}
|
||||
for r in rows:
|
||||
base, mult = split_sku(r.get("seller_sku", ""))
|
||||
base = base.upper()
|
||||
if not base:
|
||||
continue
|
||||
pieces = int(r.get("qty", 0)) * mult
|
||||
if pieces <= 0 or base.startswith(_LID_PREFIX):
|
||||
continue
|
||||
if base.startswith(_SET_PREFIX):
|
||||
combos[base] = combos.get(base, 0) + pieces
|
||||
else:
|
||||
singles[base] = singles.get(base, 0) + pieces
|
||||
return singles, combos
|
||||
|
||||
|
||||
def explode_to_singles(
|
||||
|
||||
Reference in New Issue
Block a user