Parsing and Validating an IDoc Flat File
한국어 원문으로 표시합니다.
목표
SAP IDoc 플랫 파일을 제어/데이터 레코드로 분해하고, 세그먼트 레이아웃대로 SDATA 를 파싱해 검증하고, 내부 표준 JSON 으로 변환할 수 있게 됩니다.
왜 중요한가
국내 대기업 프로젝트에서 ERP 연동은 거의 항상 만납니다. 그리고 회의에서
"IDoc 으로 받으시면 됩니다"라는 말이 나오는 순간, 구조를 모르면 아무것도
결정할 수 없습니다. 실제로 IDoc 파싱은 세그먼트 이름으로 레이아웃을 찾아
1000자짜리 SDATA 를 위치로 자르는 일이고, 앞 모듈의 고정길이 파싱과 같은 작업입니다.
그리고 운영에서 가장 자주 보게 될 상태 코드 51 이 '전송 실패'가 아니라
'SAP 안에서 업무 처리 실패'라는 것을 아는 것만으로도, 연동 담당자 간 평행선을
한 번 끊을 수 있습니다.
단계
- 원본:
/opt/lab/fixtures/eai/idoc/ORDERS05.txt, 레이아웃:/opt/lab/fixtures/eai/idoc/segments.md /root/idoc을 만들고 제어 레코드만/root/idoc/control.txt, 데이터 레코드만/root/idoc/data.txt로 분리합니다. 두 파일의 줄 수 합이 원본 줄 수와 같아야 합니다./root/idoc/ctrl.csv를 만듭니다. 첫 줄은docnum,idoctyp,mestyp,sndprn,rcvprn,credat. 제어 레코드 한 건당 한 행이고docnum오름차순입니다./root/idoc/segstat.csv를 만듭니다. 첫 줄은segnam,count. 세그먼트 이름별 건수를 건수 내림차순, 동수면 이름 오름차순으로 적습니다.E1EDK01세그먼트를 파싱해/root/idoc/header.csv를 만듭니다. 첫 줄은docnum,belnr,curcy,netwr.netwr은 헤더 총액입니다.E1EDP01세그먼트를 파싱해/root/idoc/items.csv를 만듭니다. 첫 줄은docnum,posex,matnr,menge,netpr,amount.amount는menge × netpr입니다./root/idoc/validate.sh를 만듭니다. 인자 없이 실행하며, 헤더의netwr과 품목amount합계가 다른 IDoc 의docnum을 한 줄에 하나씩 출력하고, 하나라도 있으면 0 이 아닌 종료코드로 끝냅니다. 실행 결과를/root/idoc/mismatch.txt에 저장하세요. (1건이 있습니다.)/root/idoc/status.csv를 만듭니다. 첫 줄은code,meaning,action.03,12,51,53,64,68여섯 코드를 모두 넣고,action은정상,대기,조사,재전송중 하나입니다./root/idoc/orders.json을 만듭니다. 최상위는 배열이고, 각 원소는 아래 구조입니다.docnum오름차순입니다.{ "docnum": "...", "belnr": "...", "currency": "...", "netAmount": <숫자>, "items": [ { "posex": "...", "matnr": "...", "qty": <숫자>, "price": <숫자> }, ... ] }
참고
- 고정길이 자르기는 파이썬 슬라이싱이 편합니다:
line[10:30](정의서의 위치는 1부터이므로 인덱스는 -1 해야 합니다) - jq 로 구조 확인:
jq '.[0].items | length' orders.json - 흔한 실수 1: 정의서의 1-based 위치를 0-based 인덱스에 그대로 쓰는 것.
- 흔한 실수 2: 수량·금액 필드의 앞자리 0 과 소수점 처리를 정하지 않는 것.
- 흔한 실수 3: 상태 코드 51 을 '전송 실패'로 해석하는 것. 데이터는 도착했고 SAP 안에서 업무 처리가 실패한 상태입니다.
제어·데이터 레코드 분리
/root/idoc 을 만들고 제어 레코드만 /root/idoc/control.txt,
데이터 레코드만 /root/idoc/data.txt 로 분리합니다.
두 파일의 줄 수 합이 원본 줄 수와 같아야 합니다.
레코드 종류는 각 줄의 앞부분에 구분자로 표시돼 있습니다. 먼저 파일 구조를 눈으로 확인한 뒤 분리 기준을 정하세요.
제어 레코드 파싱
/root/idoc/ctrl.csv 를 만듭니다. 첫 줄은
docnum,idoctyp,mestyp,sndprn,rcvprn,credat.
제어 레코드 한 건당 한 행이고 docnum 오름차순입니다.
제어 레코드는 이 문서가 무엇이고 누구에게서 누구에게로 가는지를 담습니다. 레이아웃 정의서의 위치대로 잘라야 합니다.
세그먼트 통계
/root/idoc/segstat.csv 를 만듭니다. 첫 줄은 segnam,count.
세그먼트 이름별 건수를 건수 내림차순, 동수면 이름 오름차순으로 적습니다.
세그먼트 이름별로 몇 건인지 세면 문서 구조가 보입니다. 헤더성 세그먼트는 1건, 품목성 세그먼트는 여러 건이어야 정상입니다.
헤더 세그먼트 파싱
E1EDK01 세그먼트를 파싱해 /root/idoc/header.csv 를 만듭니다.
첫 줄은 docnum,belnr,curcy,netwr. netwr 은 헤더 총액입니다.
SDATA 는 고정길이 문자열입니다. 세그먼트마다 레이아웃이 다르므로 정의서에서 해당 세그먼트를 찾아야 합니다.
품목 세그먼트 파싱
E1EDP01 세그먼트를 파싱해 /root/idoc/items.csv 를 만듭니다.
첫 줄은 docnum,posex,matnr,menge,netpr,amount.
amount 는 menge × netpr 입니다.
품목은 여러 건입니다. 각 건의 수량과 단가를 뽑아 금액을 계산해 두면 다음 단계에서 씁니다.
헤더-품목 금액 검증
/root/idoc/validate.sh 를 만듭니다. 인자 없이 실행하며,
헤더의 netwr 과 품목 amount 합계가
다른 IDoc 의 docnum 을 한 줄에 하나씩 출력하고,
하나라도 있으면 0 이 아닌 종료코드로 끝냅니다.
실행 결과를 /root/idoc/mismatch.txt 에 저장하세요. (1건이 있습니다.)
헤더에 적힌 총액과 품목 합계가 다르면 그 문서는 처리하면 안 됩니다. 어느 IDoc 이 문제인지 번호로 알려 주세요.
상태 코드 매핑표
/root/idoc/status.csv 를 만듭니다. 첫 줄은 code,meaning,action.
03, 12, 51, 53, 64, 68 여섯 코드를 모두 넣고,
action 은 정상, 대기, 조사, 재전송 중 하나입니다.
'전송 실패'와 'SAP 안에서 업무 처리 실패'는 다릅니다. 이 구분을 못 하면 양쪽 담당자가 평행선을 그립니다.
내부 표준 JSON 변환
/root/idoc/orders.json 을 만듭니다. 최상위는 배열이고,
각 원소는 아래 구조입니다. docnum 오름차순입니다.
{ "docnum": "...", "belnr": "...", "currency": "...",
"netAmount": <숫자>,
"items": [ { "posex": "...", "matnr": "...",
"qty": <숫자>, "price": <숫자> }, ... ] }
세그먼트의 계층 레벨을 살려 품목을 헤더 아래 배열로 넣습니다. jq 로 구조를 검증할 수 있게 만드세요.