SAP MM — 자재 · 재고 · 구매 · 입고 · 송장
자재 마스터와 재고, 구매 오더, 입고 이력, 송장 검증, 공급업체 평가까지 조달 흐름을 SQL 로 따라갑니다.
1. 자재 마스터와 재고 — MARA · MARC · MARD · MBEW
MARA 는 자재 번호(MATNR)마다 한 행인 자재 마스터입니다. 자재 유형(MTART: FERT 완제품, HALB 반제품, ROH 원자재), 자재 그룹(MATKL), 기본 단위(MEINS)처럼 어느 플랜트에서나 같은 값을 담습니다. MARC 는 자재 × 플랜트(WERKS)마다 한 행이고, MARD 는 자재 × 플랜트 × 저장 위치(LGORT)마다 재고 수량을 담습니다.
SELECT D.MATNR, D.WERKS, SUM(D.LABST) AS UNRESTRICTED
FROM MARD D
JOIN MARC C ON C.MATNR = D.MATNR AND C.WERKS = D.WERKS
GROUP BY D.MATNR, D.WERKS;
- 가용 재고는 LABST, 품질 검사 재고는 INSME, 보류 재고는 SPEME 입니다.
- MBEW 는 자재의 가격입니다. 가격 관리(VPRSV)가 S 면 표준가(STPRS), V 면 이동평균가(VERPR)를 쓰고, 가격 단위(PEINH)당 금액이므로 재고 금액은
수량 × 가격 / PEINH. - 자재 이름은 MARA 가 아니라 언어별 내역 MAKT 에 있습니다. 한국어는
SPRAS = '3'. - MARD·MARC 는 자재 + 플랜트 두 컬럼으로 이어야 다른 플랜트 행이 섞이지 않습니다.
문제
2. 구매 오더 — EKKO · EKPO · EKET
구매 오더는 헤더 EKKO(문서 번호 EBELN, 회사 코드 BUKRS, 공급업체 LIFNR, 문서 일자 BEDAT, 통화 WAERS)와 품목 EKPO(품목 EBELP, 자재 MATNR, 플랜트 WERKS, 수량 MENGE, 순단가 NETPR, 순금액 NETWR)로 나뉩니다. 납품 일정은 별도 테이블 EKET 에 있습니다.
SELECT K.EBELN, K.BEDAT, P.EBELP, P.MATNR, P.NETWR
FROM EKKO K
JOIN EKPO P ON P.EBELN = K.EBELN
WHERE K.BUKRS = '1000'
AND K.WAERS = 'KRW'
AND P.LOEKZ <> 'X';
- 헤더와 품목은 EBELN 으로 잇고, 금액은 품목 기준(EKPO) 으로 합칩니다.
- 품목의
LOEKZ = 'X'는 삭제 표시,ELIKZ = 'X'는 납품 완료 표시입니다. 보고서 목적에 따라 제외 여부가 달라집니다. - 납품 예정일과 일정 수량은 EKPO 가 아니라 EKET(EBELN + EBELP + 일정 번호 ETENR)에 있습니다.
- 공급업체 이름은 LFA1, 구매 요청은 EBAN 에서 가져옵니다.
문제
3. 입고와 구매 이력 — EKBE · MATDOC
EKBE 는 구매 품목의 이력입니다. 거래 유형 VGABE 가 1 이면 입고, 2 면 송장이고, 입고가 여러 번이면 행도 여러 개입니다. 실제 재고 이동은 MATDOC(이동 유형 BWART, 수량 MENGE, 차변/대변 SHKZG)에 남습니다.
SELECT EBELN, EBELP,
SUM(CASE WHEN SHKZG = 'S' THEN MENGE ELSE -MENGE END) AS NET_RECEIVED
FROM EKBE
WHERE VGABE = '1'
GROUP BY EBELN, EBELP;
- 입고 취소는 이동 유형 102, 반품은 161 처럼 입고와 반대 방향으로 기록됩니다. 그래서 순입고는 부호를 붙여 합산해야 합니다.
- 미입고 잔량 = 발주 수량 − 순입고 수량. 취소·반품을 빼지 않으면 잔량이 틀립니다.
- 납기 준수는 납품 예정일(EKET.EINDT) 과 실제 입고일(EKBE.BUDAT)을 비교합니다. 여러 번 입고되면 마지막 입고를 기준으로 삼을지 정해야 합니다.
- 통화가 다른 입고 금액은 환율 때문에 발주 금액과 바로 비교할 수 없습니다.
문제
4. 송장 검증과 GR/IR — RBKP · RSEG · EKBE
공급업체 송장은 RBKP(헤더: 송장 번호 BELNR, 회계 연도 GJAHR, 공급업체 LIFNR, 전기일 BUDAT)와 RSEG(품목: 구매 오더 EBELN, 품목 EBELP, 수량 MENGE, 금액 WRBTR)로 들어옵니다. EKBE 의 VGABE = 2 도 송장 이력입니다.
SELECT R.EBELN, R.EBELP, R.WRBTR
FROM RSEG R
JOIN EKPO P ON P.EBELN = R.EBELN AND P.EBELP = R.EBELP
WHERE R.WRBTR <> P.NETWR;
- 3-way match: 구매 오더(주문 수량·단가) ↔ 입고(실제 수량) ↔ 송장(청구 수량·금액)을 맞춥니다.
- GR/IR 잔액은 입고 누적 − 송장 누적입니다. 입고했지만 송장이 없는 품목은 이 잔액이 남습니다.
- 가격 차이는 송장 단가와 구매 오더 단가의 차이입니다. 수량 차이와 구분해서 봐야 원인을 찾을 수 있습니다.
- 한 오더에 입고·송장이 여러 번이면 품목별로 누적한 뒤 비교하세요. 행끼리 직접 비교하면 짝이 어긋납니다.
문제
5. 공급업체 평가 — 납기 · 검사 · 클레임
공급업체 평가는 서로 다른 테이블의 지표를 공급업체 단위로 모아 한 표로 만드는 작업입니다.
- 납기: EKET 의 납품 예정일과 EKBE 의 입고일을 비교해 납기 준수율을 냅니다.
- 품질: QALS 검사 로트(검사 유형 ART, 자재 MATNR, 공급업체 LIFNR, 로트 수량 LOSMENGE)와 QAVE 사용 결정으로 불합격률을 냅니다.
- 클레임: QMEL 품질 통지(유형 QMART, 검사 로트 PRUEFLOS)로 건수를 셉니다.
SELECT L.LIFNR, COUNT(*) AS LOT_COUNT
FROM QALS L
JOIN QAVE A ON A.PRUEFLOS = L.PRUEFLOS
GROUP BY L.LIFNR;
- 비율은 분모가 0 이 될 수 있으니
CASE/NULLIF로 처리합니다. - 지표마다 행 수가 다릅니다. 먼저 지표별로 집계한 뒤 공급업체 키로 조인해야 중복 계산이 없습니다.
문제
- 공급업체별 입고 검사 결정 소요일 (초급)
- 공급업체별 입고 검사 불합격률 (중급)
- 공급업체 클레임 건수와 미완료 현황 (중급)
- 불합격 입고 로트 상세 목록 (중급)
- 공급업체 종합 평가표: 납기 준수율·불합격률·클레임 (고급)
- 공급업체별 불합격 로트의 클레임 제기 현황 (고급)
6. 재고 이동 분석 — MATDOC
입고·출고·이전 같은 재고 이동은 MATDOC 에 남습니다. 이동 유형(BWART)이 업무를 구분합니다.
| 이동 유형 | 뜻 |
|---|---|
| 101 | 구매 오더 입고 |
| 102 | 입고 취소 |
| 201 | 코스트 센터 출고 |
| 261 | 생산 오더 출고 |
| 301 | 플랜트 간 이전 |
| 311 | 저장 위치 이전 |
SELECT BWART,
SUM(CASE WHEN SHKZG = 'S' THEN MENGE ELSE -MENGE END) AS NET_QTY
FROM MATDOC
WHERE WERKS = '1000'
AND BUDAT BETWEEN '20250101' AND '20251231'
GROUP BY BWART;
- 수량 MENGE 는 양수이고
SHKZG가 S 면 재고 증가, H 면 감소입니다. 순변동은 부호를 붙여 합산합니다. - 저장 위치 이전(311)은 보내는 쪽 H, 받는 쪽 S 두 줄이 함께 생깁니다. 플랜트 전체로 합치면 0 이 됩니다.
- 회전율은
출고 수량 / 평균 재고입니다. 기간 평균 재고를 어떻게 잡는지(기초·기말 평균 등)를 먼저 정하세요.