개요 및 이 글에서 다루는 범위
I_ProductionOrder는 SAP S/4HANA에서 생산 오더(Production Order) 헤더 정보를 표준화된 형태로 노출하는 기본(Basic) CDS View입니다. 내부적으로 AUFK(오더 마스터)와 AFKO(오더 헤더), AFPO(오더 품목) 등을 결합해 오더 번호, 자재, 플랜트, 상태 코드, 수량 정보를 한 번에 읽을 수 있도록 제공됩니다. 이 글에서는 AUFK 기반의 오더 상태 추출과 실적 데이터 연결을 ABAP RAP/CDS 관점에서 단계적으로 다룹니다.
- I_ProductionOrder 필드 구조와 AUFK 매핑 관계 이해
- 오더 상태(JEST/TJ02T)를 CDS에서 조인하는 패턴 학습
- 실적 수량(AFRU) 집계용 Composite View 설계
- Authority Check, 페이징, 성능 튜닝 적용
읽기 전에 갖춰두면 좋은 배경
ABAP CDS View의 DDL 문법(define view, association, @ObjectModel)과 SELECT 기반 OpenSQL 경험이 필요합니다. PP(Production Planning) 모듈의 오더 라이프사이클(CRTD/REL/TECO/CLSD)과 시스템 상태(I0001~) 개념을 알고 있으면 이해가 빠릅니다. ADT(ABAP Development Tools) 사용 경험과 S/4HANA Virtual Data Model(VDM)의 Basic/Composite/Consumption 계층 구분도 전제로 합니다.
환경 및 사전 준비
이 글의 코드는 다음 환경 기준으로 작성됐습니다.
- SAP S/4HANA 2022 On-Premise 또는 2023 FPS01 이상 (Cloud Edition도 대부분 호환, 단 일부 필드는 Released API만 사용 가능)
- ABAP Platform 7.58, NetWeaver AS ABAP for SAP S/4HANA
- ADT(Eclipse) 기반 개발, HANA DB Native
- 권한 오브젝트: C_AFKO_AWK(오더 타입), C_AFKO_DIS(MRP 그룹), S_DEVELOP
- 테스트 데이터: 트랜잭션 CO01에서 자재 FG-100, 플랜트 1010 기준으로 오더 3건 이상 생성
I_ProductionOrder는 SAP S/4HANA 1909 이후 Released 상태로 공개되어 외부 확장 View나 Service Binding에서 자유롭게 참조할 수 있습니다. 다만 Cloud Edition에서는 C1/C2 Release Contract만 사용 가능한 점에 유의해야 합니다.
I_ProductionOrder의 동작 원리와 데이터 구조
I_ProductionOrder를 단순히 "오더 테이블 뷰"라고 이해하면 활용 폭이 좁아집니다. 본질은 PP 모듈의 분산된 헤더 정보를 통일된 외부 식별자로 묶어 제공하는 의미 계층(Semantic Layer)입니다. 비유하자면, 식당의 주방 곳곳에 흩어진 주문 전표(AUFK), 조리 지시서(AFKO), 메뉴 항목 리스트(AFPO)를 한 장의 영수증 양식으로 정리해 손님(소비자 앱)에게 건네는 카운터 역할을 합니다.
핵심 매핑은 다음과 같습니다. AUFK는 모든 오더 타입(생산, 내부, 유지보수)의 공통 헤더이므로 AUFK-AUART 필터로 생산 오더만 추려냅니다. AFKO는 생산 오더 전용 헤더로 BOM, 라우팅, 일정 정보가 담깁니다. AFPO는 다중 품목 오더의 라인 정보를 담는데, 단일 품목 오더가 대부분이라 보통 AFPO-POSNR = 0001만 존재합니다.
상태 정보는 별도 트랙입니다. AUFK-OBJNR(예: OR000001234567)을 키로 JEST(상태 할당) 테이블에서 활성 상태 코드(INACT = 공백)를 모두 모은 뒤, TJ02T에서 텍스트로 변환합니다. CRTD(I0001), REL(I0002), TECO(I0045), CLSD(I0046) 등이 시스템 상태이고, 사용자 정의 상태는 TJ30T를 통해 풀어야 합니다. I_ProductionOrder 자체는 헤더만 노출하므로 상태 디테일은 I_ProductionOrderStatus_2 같은 보조 View와 조인해야 완전한 그림이 나옵니다.
실전 코드 - 1단계: 기본 조회 View 작성
첫 단계로 특정 플랜트의 미완료 생산 오더를 추출하는 Basic View를 만들어 봅니다.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: Open Production Orders by Plant
@ObjectModel.usageType:{
serviceQuality: #D,
sizeCategory: #M,
dataClass: #MIXED
}
define view entity ZC_OpenProdOrder
as select from I_ProductionOrder as ProdOrd
{
key ProdOrd.ProductionOrder as ProductionPlanID,
ProdOrd.ProductionPlant as Plant,
ProdOrd.Material as FinishedGood,
ProdOrd.MfgOrderPlannedTotalQty as PlannedQuantity,
ProdOrd.ProductionUnit as BaseUnit,
ProdOrd.MfgOrderScheduledStartDate as PlannedStart,
ProdOrd.MfgOrderScheduledEndDate as PlannedFinish
}
where ProdOrd.OrderIsReleased = X
and ProdOrd.OrderIsTechnicallyCompleted = SPACE
and ProdOrd.OrderIsDeleted = SPACE;
실전 코드 - 2단계: 상태와 실적을 결합한 Composite View
실무에서는 오더 진척률 계산이 핵심입니다. ABAP 클래스로 감싸 조회합니다.
CLASS zcl_prod_order_reader DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
TYPES: BEGIN OF ty_progress,
plan_id TYPE c LENGTH 12,
plant TYPE werks_d,
finished_good TYPE matnr,
planned_qty TYPE p LENGTH 7 DECIMALS 3,
confirmed_qty TYPE p LENGTH 7 DECIMALS 3,
progress_pct TYPE p LENGTH 3 DECIMALS 2,
END OF ty_progress.
METHODS read_progress
IMPORTING iv_plant TYPE werks_d
RETURNING VALUE(rt_result) TYPE STANDARD TABLE OF ty_progress.
ENDCLASS.
CLASS zcl_prod_order_reader IMPLEMENTATION.
METHOD read_progress.
TRY.
SELECT productionplanid, plant, finishedgood,
plannedqty, confirmedqty, progresspercent
FROM zc_prodorderprogress
WHERE plant = @iv_plant
ORDER BY productionplanid
INTO CORRESPONDING FIELDS OF TABLE @rt_result.
CATCH cx_sy_open_sql_db INTO DATA(lx_db).
cl_demo_output=>display( |DB error: { lx_db->get_text( ) }| ).
ENDTRY.
ENDMETHOD.
ENDCLASS.
실전 코드 - 3단계: 페이징, 권한, 캐시까지 적용한 프로덕션 패턴
대량 오더 환경(10만 건 이상)에서는 OFFSET/UP TO 페이징과 DCL 권한 분리가 필수입니다.
METHOD read_progress_paged.
DATA(lv_offset) = ( iv_page - 1 ) * iv_page_size.
TRY.
SELECT productionplanid, plant, finishedgood,
plannedqty, confirmedqty, progresspercent
FROM zc_prodorderprogress
WHERE plant = @iv_plant
AND tecoflag = SPACE
ORDER BY productionplanid
INTO CORRESPONDING FIELDS OF TABLE @rt_result
OFFSET @lv_offset
UP TO @iv_page_size ROWS.
CATCH cx_sy_open_sql_db INTO DATA(lx).
RAISE EXCEPTION TYPE zcx_pp_read EXPORTING previous = lx.
ENDTRY.
ENDMETHOD.
자주 마주치는 함정과 해결책
오더 데이터를 다루다 보면 동일한 실수가 반복적으로 발생합니다. 가장 흔한 세 가지를 정리합니다.
첫째, AUFK에는 오더가 있는데 I_ProductionOrder에서는 안 보입니다. AUFK-AUTYP 필드를 확인하세요. AUTYP = 10(생산 오더)만 I_ProductionOrder에 노출됩니다. 내부 오더(AUTYP = 01)는 I_InternalOrder를, PM 오더(AUTYP = 30)는 I_MaintenanceOrder를 사용해야 합니다.
둘째, 상태가 REL인데 OrderIsReleased가 빈 값입니다. JEST-STAT = I0002, INACT = 공백인지 SE16N으로 직접 확인하고, BAPI_PRODORD_GET_STATUS_INFO를 호출해 상태 캐시 재구성이 필요한지 검토합니다. 상태 캐시가 망가졌다면 RBDSTATE 리포트로 재구성이 필요합니다.
셋째, ConfirmedQty가 계획보다 큽니다. AFRU의 역분개(STZHL) 레코드를 IsReversal 필터로 걸러내야 합니다. IsReversal = 공백 조건이 빠지면 역분개 건이 합산되어 실제보다 크게 나옵니다. 단위 환산이 발생한 경우 GAMNG 대신 LMNGA를 사용해야 정확합니다.
이어서 살펴보면 좋은 주제
I_ProductionOrder를 기반으로 한 RAP Behavior Definition을 작성하면 Fiori Elements 앱에서 오더 릴리즈/TECO 액션을 직접 실행할 수 있습니다. I_ProductionOrderComponent로 BOM 컴포넌트 가용성까지 결합하면 자재 부족 분석이 가능합니다. Embedded Analytics 방향으로는 I_ProductionOrderQuery를 Analytical Cube로 노출해 SAC(SAP Analytics Cloud) 라이브 연결로 KPI 대시보드를 구성하는 패턴이 권장됩니다. 이벤트 기반 아키텍처가 필요하다면 ProductionOrder 비즈니스 이벤트를 SAP Event Mesh로 발행해 외부 MES와 연동하는 흐름도 검토해 볼 만합니다.
댓글 0
아직 댓글이 없습니다.