Files
dbx-main/app/modules/malaysia
king eacde5b322 style(malaysia): 입수량·박스 한 줄 + 칸 합계 제거
- 입수량/박스 입력을 한 줄로(.rk-line)
- 칸 ∑ 합계 제거 — 서로 다른 상품을 합산해 의미 없음(입력·랙보기 양쪽)
- 상품별 행 소계(합계)는 유지(개별 SKU 기준 유효)
- malaysia_rack.js: 칸 합계 로직 삭제, 행 소계만 갱신

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 17:10:49 +09:00
..

말레이시아 창고 재고관리 모듈 (malaysia)

말레이시아 현지 창고의 입고/출고/조정과 세트 BOM, 일일 재고조사를 관리한다. cupang 모듈과 동일한 패턴: malaysia_stock_db(PostgreSQL) 전용, JSON 폴백 없음. 상품명은 기존 itemcode_db(읽기 전용)을 재사용한다.

  • 경로(prefix): /malaysia
  • 권한키: malaysia (admin 은 항상 통과)
  • 환경변수: MALAYSIA_STOCK_DB_URL (미설정 시 "설정 필요" 안내), ITEMCODE_DB_URL(세트 BOM/이름)
  • DB: malaysia_stock_db / 역할 malaysia_app

세트 구성(BOM)은 별도 관리하지 않는다. itemcode_db set_components (set_code / single_code / quantity)에서 읽는다. 모듈 안에 세트구성 메뉴 없음. malaysia_stock_db.set_bom 테이블은 더 이상 쓰지 않는다(레거시, 무시). 입출고·재고조사는 전체 아이템(+세트) 그리드에 수량만 키인해 일괄 등록한다.


재고 원칙

  • 입고/출고/조정은 낱개 아이템(MT-/MX-/MZ-) 기준으로만 movement 저장.
  • 세트(MY-)는 movement 불가. 세트는 ① 재고조사 입력, ② BOM 구성 계산에만 사용.
  • 세트 주문 출고는 set_bom 으로 분해해 구성품별 OUT movement 를 생성(/malaysia/movements/set-out).
  • 뚜껑(MD-)은 재고관리 대상에서 완전 제외(어디에도 사용 불가).

현재고 계산

현재고 = SUM(IN) - SUM(OUT) + SUM(ADJUST) + SUM(STOCKTAKE)
  • IN/OUT qty 는 양수만. ADJUST/STOCKTAKE 는 음수(±) 허용.
  • 재고조사 확정 시 시스템 재고와 조사 최종치의 "차이"만 STOCKTAKE movement 로 기록 → 이력 보존 + 계산 단순.

일일 재고조사 집계

낱개 최종 재고(total_qty)
  = direct_qty(낱개 직접 조사)
  + from_set_qty(세트 수량을 set_bom 으로 분해한 합)

예) MT-0320 낱개 100 + MY-0002(MT-0320 1개 포함) 20세트 → MT-0320 total = 120.

낱개 입력 시 세트 안에 든 건 빼고 낱개 보관분만 입력한다. 세트 안 상품은 BOM 으로 자동 계산.

랙(rack) 입력 — 재고조사 상세

재고조사 상세는 평면 수량 그리드 대신 창고 랙 그림(A/B 두 면, 각 3행×3열×2분할 = 36칸) 으로 입력한다. 각 칸에 아이템 · 박스당 입수량 · 박스 수를 넣고, 한 칸에 여러 아이템은 + 로 행을 추가한다. 저장하면 서버가 SKU별로

qty = SUM(units_per_box × box_count)

집계해 daily_stocktake_line재생성한다(랙이 라인의 단일 출처). 낱개·콤보(MY-) 모두 랙에 입력 가능하며, 이후 분해/확정 로직(compute_result/finalize)은 라인 기준으로 기존과 동일하게 동작한다. 칸 코드 형식: {면}{행}-{열}-{분할} (예 A3-1-1).


테이블 (scripts/sql/malaysia_stock_db_init.sql)

테이블 용도
warehouses 창고. seed: MY-WH-01 / Malaysia Warehouse
malaysia_items 관리 대상 코드 스코프(낱개/세트) + 이름 스냅샷. seed: 낱개 12 + 세트 5
set_bom 세트 구성표. UNIQUE(set_code, component_code). prefix CHECK 내장
stock_movement 입고/출고/조정/조사 이력. item_code 는 낱개만(CHECK)
daily_stocktake 재고조사 헤더. 같은 날짜+창고 finalized 1건(부분 유니크)
daily_stocktake_line 조사 라인(SKU별 최종 qty). 랙 입력 집계로 재생성됨. UNIQUE(stocktake_id, sku_code)
daily_stocktake_rack 랙 칸별 입력(셀×SKU×입수량×박스수). 라인의 단일 출처. cell_codeA3-1-1

검증 규칙(요구사항 8)은 DB CHECK + 서비스 레이어(store.py) 양쪽에 걸려 있다.


주요 화면 / API

화면: /malaysia/(재고 현황) · /malaysia/movements(입출고) · /malaysia/stocktakes(재고조사) · /malaysia/sets(세트 구성)

JSON API:

Method 경로 설명
GET /malaysia/api/warehouses 창고 목록
GET /malaysia/api/items?kind=individual|set 아이템 목록
GET/POST /malaysia/api/bom 세트 구성 조회/등록
GET /malaysia/api/stock?wh= 현재고 현황
POST /malaysia/api/movements 낱개 movement 등록
POST /malaysia/api/movements/set-out 세트 출고(BOM 분해)
GET /malaysia/api/stocktakes/{id}/result 재고조사 최종 계산
POST /malaysia/stocktakes/{id}/rack/bulk 랙 입력 일괄 저장(병렬배열 rk_cell/rk_sku/rk_upb/rk_box) → 라인 재생성

초기화 (운영, 1회 — 사용자 승인 후)

read -s -p "malaysia_app password: " APP_PWD; echo
docker exec -i postgres-db psql -U postgres \
  -v app_password="$APP_PWD" \
  < scripts/sql/malaysia_stock_db_init.sql

# main-app .env 에 추가:
#   MALAYSIA_STOCK_DB_URL=postgresql://malaysia_app:<APP_PWD>@postgres-db:5432/malaysia_stock_db
cd /opt/www/main && docker compose up -d --build

멱등 스크립트. 기존 DB 가 있으면 DROP 하지 않음. itemcode_db 는 건드리지 않음. 랙 입력 추가(daily_stocktake_rack) 후 기존 운영 DB 에 반영하려면 위 init 스크립트를 그대로 1회 재실행한다(CREATE TABLE IF NOT EXISTS + grant 만 적용, 기존 데이터 보존).

테스트

python -m pytest tests/test_malaysia_stock.py -v   # pytest 있으면
python tests/test_malaysia_stock.py                # 없으면 standalone 폴백

순수 로직(코드 검증 / 세트 분해 / 재고조사 집계)만 검증하므로 DB 불필요.