크라우니 ERP WM(창고) 갭 3종 구현 — WM-G1 웨이브피킹 API 배선 / WM-G2 2단계 피킹 / WM-G3 크로스도킹
개요
ERP서버B(:9983, HR/QM/PM/PS/WM 모듈군)의 창고(WM) 모듈에 갭 3종을 추가.
한선씨 순정(4상균형3진: 티/옴/타/음), 셀코어ERP 공용 코어(거래기록→셀·원장기록→PSV) 직결.
무엇을 했는지
WM-G1 웨이브피킹 API 배선
- 기존
웨이브피킹생성(선행,위치배열,자재배열,수량배열,주체,조직) 함수는 이미 있었으나 배열 인자라 HTTP API 미배선 상태였음.
웨이브피킹실행(자재코드들콤마문자열, 수량, 조직) 신설 — 콤마 문자열을 자체 파서(WM콤마수/WM콤마필드)로 분해해 배열을 구성한 뒤 기존 함수에 위임.
- 자재 0건=옴 / 콤마 파싱 실패(빈 항목)=타 / 5건 초과=음(대형 웨이브, 미실행 상신) / 정상=티(기존 함수 결과 그대로 전달).
WM-G2 2단계 피킹
이단계피킹(자재코드,총수량,중간위치코드,목적위치코드,조직) 신설.
- 설계: 1단계(집하→중간)=기존
입고배정() 재사용, 2단계(중간→목적)=기존 창고이동(선행=1단계셀id,...) 재사용.
창고이동이 이미 선행셀id를 받아 거래기록에 넘기므로
PLM 2단 체인(S선행)이 자동 형성됨(별도 셀링크 호출 불필요).
- 위치 미등록=타 / 중간==목적=타 / 총수량≤0=옴 / 총수량≥500=음(상신, 웨이브피킹생성과 동일하게
셀갱신(S사상)으로 2단계 셀의 사상만 덮어씀) / 정상=티.
- 라이브 검증:
/api/erp/plm/trace/{2단계셀id} → "1단계id→2단계id" 체인 확인 완료.
WM-G3 크로스도킹
크로스도킹(자재코드,수량,입고구역코드,출고구역코드,조직) 신설.
- 입고→저장 생략→즉시 출고를 표현하기 위해 위치 재고를 전혀 건드리지 않고 감사 셀만 기록(설계 의도: 크로스도킹은 재고 이동이 아니라 통과 흐름).
- 구역 동일=타 / 자재 미등록(자재코드≤0, WM 서버에는 MM 자재마스터가 없어 코드값 유효성으로 대체)=타 / 수량≤0=옴 / 수량≥300=음 / 정상=티.
발견한 VM 함정(신규, 가드레일 템플릿에 반영 완료)
위치있나(A) == 0 또는 위치있나(B) == 0 같이
버퍼I/O 내장 함수(위치있나→위치행→버퍼파일읽기)를 하나의 또는 조건 안에서 2회 인라인 호출하면 컴파일·실행 에러 없이 조건이 조용히 반대로 평가됨(9999 같은 미등록 위치를 넣어도 "위치 없음" 분기를 타지 않고 새어나감). 격리 재현(
/tmp/testloc.한선 vs
/tmp/testloc2.한선)으로 원인 확정 — 각 호출을 변수에 먼저 캡처한 뒤 비교하면 정상.
- 이 함정은 기존 함수(창고이동/보충전략실행)에도 동일 패턴으로 이미 존재하지만, 이번 과업 지시("기존 함수 수정 금지")에 따라 손대지 않았음 — 잔여 이슈로 아래에 기록.
- 신규 함수
이단계피킹은 변수 선캡처로 수정해 배포.
- 템플릿 갱신:
~/.claude/templates/한선씨-가드레일.md (VM 함정 섹션 말미에 추가).
관련 파일
/Users/ef/crowny-erp/core/libs/erp_WM.한선 — WM-G1/G2/G3 함수 3종 + 헬퍼(WM트림/WM콤마수/WM콤마필드/WM결과사상/WM결과ID/WM결과메시지) 추가, 신규 DT코드(DT2단계피킹=9, DT크로스도킹=10) 및 임계 상수 추가.
/Users/ef/crowny-erp/core/servers/ERP서버B.한선 — 액션WM()에 wave-picking/two-step-pick/cross-dock 3개 분기 추가.
/Users/ef/crowny-erp/core/servers/ERP서버B.toau — 재컴파일 배포본.
/Users/ef/crowny-erp/data/규칙/사상규칙.psv — R560~R568 9행 추가(3 doctype × 3규칙).
/Users/ef/crowny-nexus-app/public/erp/wm.html — FORMS 3종 추가(폼 11개), DEFAULTS/TEXT_FIELDS/DOC_LABEL 갱신.
/tmp/erp페이지스펙.json — WM 배열에 3 doctype 추가(전체 135→138).
~/.claude/templates/한선씨-가드레일.md — 신규 VM 함정(버퍼I/O 함수 또는-조건 2회 인라인 호출) 반영.
검증
- 컴파일:
hanseonc_high 에러 0, 3,359,580바이트 toau.
- 배포:
kill -9 후 LaunchAgent(org.crowny.erpb) 자동 재기동, /api/health 200 확인.
- 4상 실발현: WM-G1(티/옴/타/음 전부), WM-G2(티/옴/타 확인, 음은 시드 데이터 용량 한계로 정상 임계값 500 도달 전에 1단계 용량초과로 선차단 — 로직 순서는 정상, 시드 캡재티 제약으로 단독 재현은 어려웠음), WM-G3(티/옴/타/음 전부).
- 계보(PLM trace) 증거:
/api/erp/plm/trace/5001698 → "5001697→5001698" (1단계→2단계 체인 확정).
- 성능: 신규 3종 응답시간 185~562ms(<2s).
- 스모크:
ERP페이지스모크.sh 전체 138/138 PASS.
- wm.html:
http://127.0.0.1:9802/app/erp/wm.html → 200, 폼 11개 확인.
- 크라우니코드 학습:
crownycode-learn.sh add 3건(wm웨이브피킹API/wm이단계피킹/wm크로스도킹).
잔여 이슈
- 기존 함수(창고이동·보충전략실행)의 "위치있나 2회 인라인 또는" 버그가 살아있음 — 미등록 위치(존재하지 않는 위치코드)를 출발/도착 또는 대상/원천으로 넣어도 "보관위치 없음" 분기를 타지 않고 조용히 다음 검증(재고부족 등)으로 새어나간다. 기능상 최종적으로 타(규정위반)로 귀결되는 경우가 많아 외부에서 체감하기 어렵지만, 메시지가 부정확(예: "보관위치 없음"이어야 할 것이 "재고부족"으로 표시)하고 잠재적으로 위치현재적재(존재하지 않는 코드)가 0을 반환해 우연히 안전한 방향으로만 새는 것이므로 별도 티켓으로 수정 필요.
- WM-G2 총수량≥500(음) 분기는 시드 마스터의 위치 용량이 작아(최대 1000) 실제 라이브에서 "500 이상이지만 용량 이내"인 조합을 만들기 어려움 — 로직은 코드 리뷰로 확인했으나 전용 대용량 위치를 시드에 추가하면 더 깔끔하게 재현 가능.
- 사상규칙.psv에 추가한 9행은 참고/문서화용 임계값 테이블(기존 파일 관례를 따름)이며 런타임 로직은 erp_WM.한선 함수 내부에 이미 하드코딩되어 있어 실제 게이트를 구동하지 않음(기존 파일 전체가 동일한 성격).