주문부터 현금 회수까지: 판매 오더 처리 데이터 템플릿
주문부터 현금 회수까지: 판매 오더 처리 데이터 템플릿
- 수집 권장 속성
- 추적할 주요 활동
- SAP ECC 데이터 추출 안내
주문부터 현금 회수까지: 판매 오더 처리 속성
| 이름 | 설명 | ||
|---|---|---|---|
| 판매 오더 SalesOrder | 판매 오더 문서의 고유 식별자입니다. Order-to-Cash 프로세스 전체를 추적할 때 기본 케이스로 사용됩니다. | ||
| 설명 판매 오더는 영업 프로세스의 중심 문서로, 고객이 상품이나 서비스를 요청한 내용을 나타냅니다. 고객 요청을 처음부터 끝까지 처리하는 데 필요한 정보가 모두 포함됩니다. process mining에서는 이 속성을 Case ID로 사용합니다. 고유한 판매 오더 번호 하나가 전체 프로세스 인스턴스 하나에 해당합니다. 판매 오더별로 분석하면 전체 처리 과정을 추적하고, 소요 시간을 측정하며, 고객 오더마다 발생하는 차이를 파악할 수 있습니다. 중요한 이유 관련된 모든 활동과 이벤트를 연결하는 기준이므로 고객 오더별 전체 처리 과정을 분석할 수 있습니다. 확보 방법 판매 문서 헤더 데이터 테이블(VBAK)의 VBELN 필드에서 확인할 수 있습니다. 예시 900001234590000123469000012347 | |||
| 소스 시스템 SourceSystem | 데이터를 추출한 소스 시스템을 식별합니다. | ||
| 설명 데이터가 생성된 시스템을 지정합니다. 예를 들어 특정 SAP ECC 인스턴스 이름이나 클라이언트 번호가 해당합니다. 여러 운영 시스템을 사용하거나 레거시 시스템의 데이터를 함께 다루는 환경에서 데이터의 출처를 파악하는 데 도움이 됩니다. 분석할 때는 데이터 출처별로 필터링하거나 구분하는 데 사용합니다. 시스템 간 프로세스를 비교하거나 시스템 마이그레이션 중 데이터의 무결성과 일관성을 확인할 때 특히 유용합니다. 중요한 이유 여러 시스템을 사용하는 환경에서 데이터 출처를 명확히 하고 프로세스를 비교할 수 있도록 필요한 맥락을 제공합니다. 확보 방법 일반적으로 데이터 추출 과정에서 추가하는 값으로, SAP 시스템 ID(SAPSID) 또는 클라이언트(MANDT)를 나타내는 고정값인 경우가 많습니다. 예시 ECC_PROD_800SAP_ERP_EU1ECC_QAS_300 | |||
| 시작 시간 StartTime | 활동 또는 이벤트가 시작된 시점을 나타내는 타임스탬프입니다. | ||
| 설명 이벤트 타임스탬프라고도 하는 시작 시간은 특정 활동이 발생한 날짜와 시각을 기록합니다. 예를 들어 판매 오더 생성, 상품 출고 또는 송장 전기 시점을 기록합니다. 이 타임스탬프는 process mining의 모든 시간 기반 분석에 사용됩니다. 활동 간 소요 시간을 계산하고, 케이스 전체 처리 시간을 측정하며, 지연이나 병목을 찾는 데 활용합니다. 정시 납품이나 이행 리드 타임을 모니터링하는 대시보드 등 성과 분석에 정확한 타임스탬프가 필요합니다. 중요한 이유 소요 시간과 처리 시간 등 성과 지표를 계산하는 데 필요한 속성으로, 병목을 찾는 데도 중요합니다. 확보 방법 여러 SAP 테이블의 날짜 필드(예: ERDAT)와 시간 필드(예: ERZET)를 결합해 생성하는 복합 속성입니다. VBAK(판매 오더), LIKP(납품), VBRK(송장) 등이 해당합니다. 예시 2023-04-15T09:00:12Z2023-04-16T14:30:00Z2023-04-20T11:22:45Z | |||
| 최근 데이터 업데이트 LastDataUpdate | 이 레코드의 데이터를 소스 시스템에서 마지막으로 새로 고친 시점을 나타내는 타임스탬프입니다. | ||
| 설명 이 속성은 해당 이벤트 또는 케이스의 데이터를 마지막으로 추출하거나 업데이트한 날짜와 시각을 기록합니다. 분석에 사용되는 데이터가 얼마나 최신인지 확인할 수 있습니다. 대시보드와 보고서에서 이 정보는 인사이트가 얼마나 최신인지 사용자가 판단하는 데 중요합니다. 분석이 현재 운영 상태를 반영하는지, 오래된 데이터를 기반으로 하는지 확인해 데이터의 최신성에 대한 기대치를 조정할 수 있습니다. 중요한 이유 사용자가 데이터의 최신성을 파악할 수 있도록 합니다. process mining 분석을 바탕으로 시의적절하고 정확한 의사결정을 내리는 데 필요한 정보입니다. 확보 방법 데이터 수집 시 데이터 추출 도구나 프로세스가 입력하는 메타데이터 속성입니다. 소스 SAP 테이블에는 저장되지 않습니다. 예시 2024-06-10T05:00:00Z2024-06-11T05:00:00Z2024-06-12T05:00:00Z | |||
| 활동 Activity | 판매 오더 프로세스에서 발생한 특정 업무 단계 또는 이벤트의 이름입니다. | ||
| 설명 이 속성은 Order-to-Cash 프로세스의 개별 단계를 나타냅니다. 예를 들면 '판매 오더 생성', '납품 문서 생성', '대금 수령' 등이 있습니다. 이러한 활동을 바탕으로 판매 오더별 프로세스 흐름을 재구성합니다. 활동의 순서와 시점을 분석하는 것이 process mining의 핵심입니다. 프로세스 맵을 시각화하고, 병목을 찾고, 프로세스 변형을 파악하며, 표준 모델에 따른 규정 준수 여부를 확인할 수 있습니다. 활동은 일반적으로 시스템에 기록된 문서 생성 이벤트, 상태 변경 또는 특정 트랜잭션 코드에서 도출합니다. 중요한 이유 활동은 프로세스 맵의 기반이 됩니다. 이를 통해 프로세스 흐름과 편차, 병목을 시각화하고 분석할 수 있습니다. 확보 방법 데이터 추출 과정에서 생성되는 파생 속성입니다. SAP 트랜잭션 코드(T-Code), 문서 상태 변경(예: VBUK, VBUP 테이블) 또는 변경 문서 로그(CDHDR, CDPOS 테이블)를 사용자에게 익숙한 활동 이름에 매핑해 생성합니다. 예시 판매 오더 생성배송 문서 생성상품 출고송장 생성대금 수령 | |||
| 거부 사유 RejectionReason | 판매 오더 항목이 거부되거나 취소된 이유를 나타내는 코드입니다. | ||
| 설명 거부 사유를 통해 판매 오더 또는 개별 항목이 이행되지 않은 이유를 파악할 수 있습니다. 고객 취소, 제품 재고 부족 또는 기타 업무상 사유가 해당할 수 있습니다. 이 속성은 '판매 오더 취소 추이' 대시보드에 필요합니다. 자주 발생하는 거부 사유를 분석하면 판매 손실의 근본 원인을 찾을 수 있습니다. 분석 결과를 재고 관리, 가격 전략 또는 고객 커뮤니케이션 개선에 활용해 오더 취소율을 낮출 수 있습니다. 중요한 이유 오더가 취소된 이유를 파악해 판매 손실을 줄이고 예측 정확도를 높이는 근본 원인 분석에 활용할 수 있습니다. 확보 방법 판매 문서 항목 데이터 테이블(VBAP)의 ABGRU 필드에서 확인할 수 있습니다. 예시 0215Z5 | |||
| 고객 번호 CustomerNumber | 판매 오더를 요청한 고객의 고유 식별자입니다. | ||
| 설명 이 속성은 판매 오더와 연결된 기본 고객 계정인 '판매처'를 나타냅니다. 거래를 마스터 데이터의 특정 고객과 연결합니다. 고객 번호별로 분석하면 고객 특성에 따른 프로세스와 성과를 파악할 수 있습니다. 처리 시간이 가장 긴 고객, 재작업 비율이 가장 높은 고객, 오더 변경이 가장 잦은 고객 등을 확인할 수 있습니다. 고객 관계 관리와 서비스 수준을 개선하는 데 필요한 정보입니다. 중요한 이유 고객별로 프로세스를 분석해 특정 고객에게 영향을 주는 문제를 찾고 고객별 성과를 측정할 수 있습니다. 확보 방법 판매 문서 헤더 데이터 테이블(VBAK)의 KUNNR 필드에서 확인할 수 있습니다. 예시 100234100567200112 | |||
| 납품 차단 DeliveryBlock | 판매 오더의 납품 차단 여부를 나타내는 코드입니다. 차단되면 납품 문서를 생성할 수 없습니다. | ||
| 설명 납품 차단은 납품 단계 전에 프로세스를 일시 중지하기 위해 판매 오더의 헤더 또는 항목 수준에 설정하는 상태입니다. 사용자가 직접 설정하거나 신용 한도 초과, 데이터 누락 등의 이유로 시스템이 자동 설정할 수 있습니다. 이 속성은 '판매 오더 차단 및 재작업 분석' 대시보드에 필요합니다. 납품 차단의 빈도와 지속 시간, 사유를 분석하면 이행 프로세스의 주요 병목을 찾을 수 있습니다. 차단을 줄이면 정시 납품과 전체 처리 시간을 개선할 수 있습니다. 중요한 이유 이행 프로세스의 병목을 직접 파악할 수 있습니다. 오더가 차단되는 이유와 빈도를 분석하면 프로세스 흐름의 효율성을 높이는 데 도움이 됩니다. 확보 방법 판매 문서 헤더 데이터 테이블(VBAK)의 LIFSK 필드에서 확인할 수 있습니다. 예시 0102Z1 | |||
| 사용자 User | 문서를 생성하거나 마지막으로 변경한 직원 또는 활동을 수행한 직원의 사용자 ID입니다. | ||
| 설명 이 속성은 프로세스의 특정 이벤트를 수행한 SAP 사용자 ID를 기록합니다. 예를 들어 오더를 생성한 영업 담당자나 상품 출고를 전기한 창고 직원을 식별합니다. 사용자별로 프로세스를 분석하면 업무량 분포를 파악하고, 교육이 필요한 부분을 찾으며, 같은 작업을 사용자마다 다르게 처리하는지 확인할 수 있습니다. 리소스 성과와 규정 준수를 살펴보고 수작업 개입을 파악하는 대시보드에도 필요합니다. 중요한 이유 리소스 성과와 업무량을 파악하고, 사용자별 프로세스 편차를 찾는 데 도움이 됩니다. 규정 준수와 자동화 분석에도 활용할 수 있습니다. 확보 방법 VBAK, LIKP, VBRK 등 여러 SAP 헤더 테이블의 '생성자' 필드(ERNAM) 또는 '변경자' 필드(AENAM)에서 확인할 수 있습니다. 예시 CBURKEJSMITHRWILLIAMS | |||
| 순액 NetAmount | 세금과 할인액을 제외한 판매 오더의 총액입니다. 헤더 수준에서 집계합니다. | ||
| 설명 순액은 판매 오더의 금액을 나타내며, 각 프로세스 인스턴스와 연결되는 주요 재무 지표입니다. 이 속성은 금액을 기준으로 프로세스를 분석하는 데 필요합니다. 금액이 큰 오더에 우선순위를 두어 프로세스 개선 과제를 정할 수 있습니다. 지연이나 재작업 같은 문제와 재무 영향을 연계하면 개선의 필요성을 더 구체적으로 설명할 수 있습니다. 예를 들어 고액 오더가 저액 오더보다 효율적으로 처리되는지 분석할 수 있습니다. 중요한 이유 재무 영향이 큰 오더를 중심으로 개선 과제의 우선순위를 정할 수 있습니다. 확보 방법 판매 문서 헤더 데이터 테이블(VBAK)의 NETWR 필드에서 확인할 수 있습니다. 예시 1500.0012550.75850.50 | |||
| 영업 조직 SalesOrganization | 제품이나 서비스의 판매를 담당하는 조직 단위입니다. | ||
| 설명 영업 조직은 SAP에서 회사의 영업 요건에 따라 조직을 구성하는 주요 단위입니다. 판매 조건을 협의하고 상품과 서비스를 유통하는 업무를 담당합니다. process mining에서는 주요 분석 기준으로 사용합니다. 영업 조직, 지역 또는 사업부별로 프로세스 성과와 효율성, 규정 준수 여부를 비교할 수 있습니다. 이를 통해 성과가 높은 조직의 모범 사례와 다른 조직의 개선 영역을 찾을 수 있습니다. 중요한 이유 조직 단위나 지역별로 프로세스 효율성과 규정 준수 여부를 비교할 수 있습니다. 확보 방법 판매 문서 헤더 데이터 테이블(VBAK)의 VKORG 필드에서 확인할 수 있습니다. 예시 100025003100 | |||
| 자재 번호 MaterialNumber | 판매하는 제품이나 서비스를 식별하는 고유 번호입니다. | ||
| 설명 자재 번호는 판매 오더의 개별 항목에 포함된 제품을 식별합니다. 판매 오더 하나에 여러 자재가 포함될 수 있으므로 일반적으로 항목 수준에서 분석합니다. 자재 번호별로 프로세스를 분석하면 제품별 문제를 찾을 수 있습니다. 특정 제품의 이행 시간이 더 길거나, 납품 차단이 잦거나, 송장 불일치가 자주 발생하는지 확인할 수 있습니다. 제품군별 프로세스를 최적화하려는 공급망 및 제품 관리 업무에 필요한 정보입니다. 중요한 이유 제품별로 프로세스를 분석해 지연, 차단, 재작업 등 비효율과 관련된 제품을 찾을 수 있습니다. 확보 방법 판매 문서 항목 데이터 테이블(VBAP)의 MATNR 필드에서 확인할 수 있습니다. 예시 FG-1001-ARAW-205BSERV-INSTALL | |||
| 배송 조건 ShippingConditions | 고객에게 상품을 배송하는 기본 방식을 정합니다. | ||
| 설명 배송 조건은 오더의 배송 방식을 정합니다. 예를 들어 일반 배송, 특급 배송 또는 고객 직접 수령이 있습니다. 고객과 합의하며 물류 계획에 영향을 줍니다. 이 속성은 '배송 방식별 효율 및 비용' 분석에 사용합니다. 배송 조건별로 프로세스를 나누어 분석하면 특정 방식에서 지연이 더 자주 발생하거나 처리 시간이 더 긴지 확인할 수 있습니다. 이 데이터는 물류를 최적화하고 고객의 납품 일정에 대한 기대를 조정하는 데 도움이 됩니다. 중요한 이유 물류 성과를 분석해 특정 배송 방식이 지연 또는 높은 효율성과 연관되는지 확인할 수 있습니다. 확보 방법 판매 문서 헤더 데이터 테이블(VBAK)의 VSBED 필드에서 확인할 수 있습니다. 예시 011020 | |||
| 신용 확인 상태 CreditCheckStatus | 판매 문서의 신용 확인 상태를 나타냅니다. | ||
| 설명 이 속성은 판매 오더에 대해 자동 또는 수동으로 수행한 신용 확인 결과를 보여줍니다. 일반적인 상태로는 '승인', '거부', '차단'이 있습니다. 이 속성은 '신용 확인 처리 시간 분석' 대시보드에 필요합니다. 신용 확인 단계의 지연이나 차단은 전체 오더 이행 시간에 큰 영향을 줄 수 있습니다. 상태를 분석하면 신용 관리 프로세스의 효율성과 영업 처리 속도에 미치는 영향을 파악할 수 있습니다. 중요한 이유 오더 처리 속도에 직접 영향을 줍니다. 상태를 분석해 오더 이행을 지연시키는 신용 관리의 병목을 찾을 수 있습니다. 확보 방법 판매 문서 헤더 상태 테이블(VBUK) 또는 VBAK의 신용 상태 필드(예: CMGST)에서 확인할 수 있습니다. 예시 ABD | |||
| 재작업 여부 IsRework | 판매 오더가 처음 생성된 후 주요 변경이나 재작업을 거쳤는지 나타내는 불리언 값입니다. | ||
| 설명 이 계산 속성은 '판매 오더 변경' 활동이 한 번 이상 발생하는 등 재작업을 거친 프로세스 인스턴스를 식별합니다. 가격, 수량 또는 납품일 변경을 재작업으로 볼지 등 구체적인 기준은 프로젝트 설정 시 정의합니다. 이 속성은 '판매 오더 재작업 및 변경 빈도' 대시보드와 판매 오더 재작업률 KPI에 필요합니다. 필터링을 통해 별도 수작업 변경 없이 진행된 오더와 수동 변경이 필요한 오더를 바로 비교할 수 있습니다. 이를 통해 재작업이 처리 시간과 비용에 미치는 영향을 측정할 수 있습니다. 중요한 이유 재작업 빈도를 측정해 원인과 전체 프로세스 효율성 및 처리 시간에 미치는 영향을 분석할 수 있습니다. 확보 방법 이벤트 로그에서 도출하는 계산 속성입니다. '판매 오더 변경' 활동이 있는지 또는 CDHDR/CDPOS 테이블에 특정 변경 이벤트가 기록되었는지 확인합니다. 예시 truefalse | |||
| 정시 납품 여부 IsOnTimeDelivery | 확정 납품일 당일 또는 그 전에 상품이 출고되었는지 나타내는 불리언 값입니다. | ||
| 설명 이 계산 속성은 실제 상품 출고일과 판매 오더의 'ConfirmedDeliveryDate'를 비교합니다. 상품 출고일이 확정 납품일과 같거나 이르면 참, 늦으면 거짓으로 표시합니다. 이 속성을 사용하면 '정시 납품 성과' 대시보드를 만들고 정시 납품률 KPI를 계산하기 쉽습니다. 분석이나 차트마다 날짜를 비교하는 수식을 작성하지 않고도 성과를 집계하고 시각화할 수 있어 납품 신뢰성을 한눈에 파악할 수 있습니다. 중요한 이유 납품 성과를 간단하고 명확하게 측정해 전체 정시 납품률 KPI를 쉽게 계산할 수 있습니다. 확보 방법 계산 속성입니다. '상품 출고' 활동의 타임스탬프와 'ConfirmedDeliveryDate' 속성의 값을 비교합니다. 예시 truefalse | |||
| 확정 납품일 ConfirmedDeliveryDate | 상품이나 서비스의 납품일로 고객에게 확정해 안내한 날짜입니다. | ||
| 설명 자재 가용성과 일정에 따라 고객에게 약속한 납품일입니다. 납품 성과를 측정하는 기준으로 사용합니다. 이 속성은 '정시 납품 성과' 대시보드와 정시 납품률 KPI의 기준입니다. 확정 납품일과 실제 '상품 출고' 날짜를 비교해 오더가 제때, 일찍 또는 늦게 납품되었는지 확인할 수 있습니다. 공급망의 신뢰성과 고객 만족도를 측정하는 주요 지표입니다. 중요한 이유 정시 납품 성과를 측정하는 기준입니다. 고객 만족도와 공급망 효율성을 평가하는 주요 KPI입니다. 확보 방법 판매 문서 납품 일정 테이블(VBEP)의 EDATU 필드에서 확인할 수 있습니다. 예시 2023-05-102023-06-202023-07-01 | |||
주문부터 현금 회수까지: 판매 오더 처리 활동
| 활동 | 설명 | ||
|---|---|---|---|
| 대금 수령 | 고객의 대금이 수령되어 송장에 반영되고 미결 매출채권 항목이 반제되었음을 나타내는 이벤트입니다. 재무 문서의 반제 여부를 바탕으로 추론하는 회계 이벤트입니다. | ||
| 중요한 이유 판매 대금을 회수하는 마지막 단계입니다. '송장 발행부터 대금 결제까지의 소요 시간'과 전체 '판매 오더 이행 소요 시간'을 측정하는 종료 시점입니다. 확보 방법 고객 개별 항목에 대한 BSEG 테이블의 반제 문서 정보를 바탕으로 추론합니다. BSEG-AUGBL(반제 문서)과 BSEG-AUGDT(반제일)에 값이 있으면 대금을 수령한 것으로 봅니다. 기록 매출채권 개별 항목의 BSEG 테이블에 반제일(AUGDT)이 입력된 것을 기준으로 추론합니다. 이벤트 유형 inferred | |||
| 상품 출고 | 상품의 소유권이 이전되고 상품이 공식적으로 창고를 떠나는 중요한 이벤트입니다. 자재 문서를 생성하고 재고를 갱신하는 명시적인 재무 전기입니다. | ||
| 중요한 이유 이 이벤트는 '배송'을 나타내며 정시 배송과 이행 리드타임을 측정하는 주요 단계입니다. 재무 데이터가 갱신되며 실제 이행 프로세스에서 되돌릴 수 없는 시점입니다. 확보 방법 배송 문서와 연결된 출고 이동 유형(예: 601)의 자재 문서(MKPF/MSEG)가 생성됩니다. 기록 배송과 연결된 출고 이동 유형의 자재 문서(MKPF/MSEG)가 생성됩니다. 이벤트 유형 explicit | |||
| 송장 생성 | 고객 송장 또는 청구 문서가 생성되었음을 나타냅니다. 시스템에 새 문서를 생성하는 명시적 이벤트로, 프로세스의 대금 결제 단계가 시작됩니다. | ||
| 중요한 이유 '송장 발행부터 대금 결제까지의 소요 시간'을 측정하기 시작하는 중요한 시점입니다. 송장 발행이 지연되면 현금 흐름에 직접 영향을 줍니다. 확보 방법 VBRK 테이블(청구 문서: 헤더 데이터)에 생성일(ERDAT)을 기준으로 기록됩니다. 판매 오더 또는 납품 문서와의 연결 정보는 VBFA 테이블에 있습니다. 기록 VBRK 테이블의 생성 타임스탬프(ERDAT)를 기준으로 하는 이벤트입니다. 이벤트 유형 explicit | |||
| 오더 항목 종료 | 판매 오더 항목이 최종 종료되었음을 나타냅니다. 해당 항목이 모두 납품되고 송장이 발행되어 처리가 완료된 상태입니다. 항목의 전체 상태를 바탕으로 추론합니다. | ||
| 중요한 이유 프로세스가 성공적으로 끝났음을 나타내는 종료 이벤트입니다. 항목이 종료되는 시점을 분석하면 전체 프로세스 소요 시간을 파악하고 불필요하게 미결 상태로 남은 오더를 찾을 수 있습니다. 확보 방법 해당 항목의 VBUP 테이블(판매 문서: 항목 상태)에 있는 전체 상태 필드를 바탕으로 추론합니다. VBUP-GBSTA가 'C'(완전히 처리됨)이면 항목이 종료된 것으로 봅니다. 기록 항목 상태(VBUP-GBSTA)가 'C'(완전히 처리됨)로 변경된 것을 기준으로 추론합니다. 이벤트 유형 inferred | |||
| 오더 확인 | 판매 오더가 초기 점검을 모두 통과해 이행이 확정되었음을 나타냅니다. 일반적으로 오더의 차단이 해제되고 납품 일정 라인에 확정 수량이 있을 때로 추론합니다. | ||
| 중요한 이유 오더 입력과 이행을 구분하는 주요 단계입니다. 이 시점부터 이행 리드타임과 정시 배송 성과를 측정할 수 있습니다. 확보 방법 VBEP의 납품 일정 라인에 확정 수량(BMENG > 0)이 있고 오더의 배송 차단이 해제된 경우(예: VBUK-LIFSK가 비어 있음)로 추론할 수 있습니다. 기록 납품 일정 라인의 확정(VBEP-BMENG > 0)과 헤더 수준 차단 해제를 기준으로 추론합니다. 이벤트 유형 inferred | |||
| 판매 오더 생성 | 새 판매 오더 문서가 생성된 시점을 나타냅니다. 사용자가 새 오더를 저장할 때 명시적으로 기록되는 이벤트이며, 일반적으로 SAP의 VA01 트랜잭션을 통해 생성됩니다. | ||
| 중요한 이유 Order-to-Cash 프로세스의 주요 시작 이벤트입니다. 전체 처리 주기와 오더 접수율을 측정하려면 발생 시점을 분석해야 합니다. 확보 방법 VBAK 테이블(판매 문서 헤더 데이터)의 생성일(ERDAT)과 생성 시각(ERZET)에 기록됩니다. 트랜잭션 코드는 VBAK-TCODE에 저장됩니다. 기록 VBAK 테이블의 생성 시각(ERDAT, ERZET)을 기준으로 하는 이벤트입니다. 이벤트 유형 explicit | |||
| 배송 문서 생성 | 창고에 피킹과 배송 작업을 시작하도록 지시하는 출고 배송 문서가 생성된 시점을 나타냅니다. 문서 흐름에서 명시적으로 확인할 수 있는 이벤트입니다. | ||
| 중요한 이유 실제 이행 프로세스의 첫 단계입니다. 오더 확인부터 배송 문서 생성까지 걸리는 시간을 보면 물류 처리가 얼마나 빨리 시작되는지 알 수 있습니다. 확보 방법 LIKP 테이블(SD 문서: 배송 헤더 데이터)에 레코드가 생성된 시점입니다. 판매 오더와의 연결은 문서 흐름 테이블 VBFA에 저장됩니다. 기록 LIKP 테이블의 생성 시각을 기준으로 하며 VBFA 테이블을 통해 연결하는 이벤트입니다. 이벤트 유형 explicit | |||
| 배송 차단 설정 | 판매 오더에 배송 차단이 설정되어 배송 문서를 생성할 수 없게 된 상태를 나타냅니다. 변경 로그에서 명시적으로 확인하거나 상태 테이블을 통해 추론할 수 있습니다. | ||
| 중요한 이유 '판매 오더 정체율' KPI와 직접 관련된 활동입니다. 차단이 설정된 이유와 빈도를 파악하면 이행 지연의 원인을 찾을 수 있습니다. 확보 방법 VBAK-LIFSK 필드의 변경 로그(CDHDR/CDPOS)에서 확인할 수 있습니다. 또는 VBAK-LIFSK 필드에 값이 입력된 시점을 기준으로 추론할 수 있습니다. 기록 VBAK-LIFSK 또는 VBAP-LIFSP 필드의 변경 문서를 기준으로 하는 이벤트입니다. 이벤트 유형 explicit | |||
| 송장 취소 | 기존 청구 문서를 취소하는 것을 나타냅니다. 원본 문서의 금액을 상쇄하는 취소 문서를 새로 생성하는 명시적 트랜잭션입니다. | ||
| 중요한 이유 송장 취소 내역을 추적하면 가격 책정 문제, 배송 불일치 또는 데이터 오류를 파악할 수 있습니다. 이를 통해 '송장 불일치율' KPI를 확인할 수 있습니다. 확보 방법 취소 청구 문서(VBRK-VBTYP = 'N' 또는 'O')가 생성될 때 포착되는 명시적 이벤트입니다. 원본 송장은 VBRK-SFAKN에 참조됩니다. 기록 원본 송장을 참조하는 취소 문서를 VBRK에 생성합니다. 이벤트 유형 explicit | |||
| 신용 조회 완료 | 판매 오더에 대한 고객의 자동 또는 수동 신용 조회가 완료된 시점을 나타냅니다. 일반적으로 문서의 전체 신용 상태가 변경된 것으로 추론합니다. | ||
| 중요한 이유 신용 조회는 주요 병목이 되는 경우가 많습니다. 이 단계에 걸리는 시간을 측정하면 '신용 조회 처리 시간 분석'을 수행하고 오더 처리를 앞당기는 데 도움이 됩니다. 확보 방법 VBUK 테이블(판매 문서: 헤더 상태)의 신용 상태 필드에서 추론합니다. VBUK-CMGST가 차단에서 해제로 바뀌면 이 활동이 발생한 것으로 봅니다. 기록 전체 신용 상태 필드(VBUK-CMGST)의 변경을 기준으로 추론합니다. 이벤트 유형 inferred | |||
| 오더 취소 | 이행 전에 판매 오더가 취소되었음을 나타냅니다. 일반적으로 오더의 관련 항목 전체에 거부 사유를 적용해 기록합니다. | ||
| 중요한 이유 '오더 취소율' KPI를 산출하는 데 필요한 주요 실패 종료 지점입니다. 오더가 취소된 시점과 이유를 파악하면 영업 프로세스의 문제를 확인할 수 있습니다. 확보 방법 판매 오더의 모든 활성 항목에 VBAP-ABGRU(거부 사유) 필드가 입력된 것을 기준으로 추론합니다. 변경 날짜는 CDHDR/CDPOS에서 확인할 수 있습니다. 기록 모든 항목의 '거부 사유' 필드(VBAP-ABGRU)에 값이 입력된 것을 기준으로 추론합니다. 이벤트 유형 inferred | |||
| 인도 증명 확인 | 고객이 상품을 수령했음을 확인하는 활동입니다. 인수증이 시스템에 기록될 때 포착되며, 이 과정에서 납품 문서의 상태가 갱신되는 경우가 많습니다. | ||
| 중요한 이유 이 이벤트는 실제 납품일을 제공하며, 약속한 날짜를 기준으로 '정시 납품률'을 정확하게 측정하는 데 필요합니다. 확보 방법 인수증 상태(VBUK-PODAT)가 'C'(확인됨)로 설정된 것을 기준으로 추론합니다. 확인 날짜는 VLPOD-PODAT에 저장됩니다. 이 기능이 항상 구현되어 있는 것은 아닙니다. 기록 납품 문서의 POD 상태(VBUK-PODAT) 변경 또는 VLPOD 테이블 항목을 기준으로 추론합니다. 이벤트 유형 inferred | |||
| 판매 오더 변경 | 판매 오더를 처음 생성한 뒤 변경한 내역을 나타냅니다. 수량, 가격, 날짜 등의 필드가 바뀌면 전용 변경 로그 테이블(CDHDR, CDPOS)에 기록됩니다. | ||
| 중요한 이유 변경 내역을 추적하면 재작업과 프로세스 불안정, 데이터 품질 문제를 파악할 수 있습니다. 변경이 잦다면 최초 오더 입력 과정에 문제가 있어 지연이 발생할 수 있습니다. 확보 방법 OBJECTCLAS = 'VERKBELEG' 조건으로 변경 문서 테이블 CDHDR(헤더)과 CDPOS(품목)에서 가져옵니다. 타임스탬프와 변경된 필드를 확인할 수 있습니다. 기록 판매 문서 객체의 변경 문서 테이블(CDHDR, CDPOS)을 기준으로 하는 이벤트입니다. 이벤트 유형 explicit | |||
| 피킹 완료 | 배송할 모든 품목을 창고에서 실제로 피킹한 상태를 나타냅니다. 창고 관리(WM)를 사용하는 경우 Transfer Order 상태를 기준으로 추론할 수 있습니다. | ||
| 중요한 이유 피킹 시간을 분석하면 창고 운영을 최적화할 수 있습니다. 이 단계의 지연은 전체 배송 일정과 이행 주기에 직접 영향을 줍니다. 확보 방법 LIPS-KOSTA 필드의 배송 품목 피킹 상태가 'C'(피킹 완료)로 바뀐 경우로 추론합니다. WM을 사용하는 경우 Transfer Order 확인(LTAK/LTAP 테이블)을 기준으로 추론할 수 있습니다. 기록 피킹 상태(LIPS-KOSTA) 변경 또는 WM Transfer Order 확인을 기준으로 추론합니다. 이벤트 유형 inferred | |||
데이터 추출 안내
단계
- 프로그램 개발: 트랜잭션 SE38 또는 SE80에서 새 실행 가능 ABAP 프로그램을 만듭니다. 이 프로그램에 전체 추출 로직을 작성합니다.
- 선택 화면 정의: 프로그램에서 데이터를 필터링할 선택 화면을 만듭니다. Sales Document Creation Date(VBAK-ERDAT), Sales Organization(VBAK-VKORG), Sales Document Type(VBAK-AUART) 매개변수를 포함합니다. 이렇게 하면 추출을 반복해서 사용할 수 있고 관리하기도 쉽습니다.
- 데이터 선언: 여러 SAP 테이블(VBAK, VBAP, VBFA, CDHDR, CDPOS, VBRK, BSAD 등)의 데이터를 담을 내부 테이블과 구조를 정의합니다. 필수 속성에 맞는 이벤트 로그 최종 출력 구조도 정의합니다.
- 기본 판매 주문 조회: 사용자가 선택 화면에 입력한 조건을 기준으로 판매 주문 헤더(VBAK)와 항목(VBAP)을 가져오는 초기 SELECT 문을 작성합니다. 이 데이터가 분석 대상 케이스의 기본 데이터가 됩니다.
- 'Creation' 이벤트 추출: 선택한 VBAK 레코드를 반복 처리합니다. 각 레코드에서 이벤트 로그 구조에 'Sales Order Created' 활동을 입력하고, VBAK-ERDAT와 VBAK-ERZET을 StartTime으로 사용합니다.
- 변경 이력 이벤트 추출: 선택한 판매 주문에 대해 OBJECTCLAS가 'VERKBELEG'인 CDHDR 및 CDPOS 레코드를 조회합니다. 결과를 반복 처리해 특정 필드 변경을 찾습니다. 예를 들어 VBAK-LIFSK 변경은 'Delivery Block Set', VBUK-CMGST 변경은 'Credit Check Performed'를 나타냅니다. 그 밖의 관련 변경은 'Sales Order Changed'로 기록할 수 있습니다.
- 문서 흐름 데이터 추출: 선택한 판매 주문에 대해 문서 흐름 테이블(VBFA)을 조회합니다. 이 테이블은 판매 주문과 납품, 자재 이동, 송장 등의 후속 문서를 연결합니다. 추가 처리를 위해 관련 문서를 모두 선택합니다.
- 납품 및 이행 이벤트 추출: VBFA에서 가져온 납품 문서 번호를 사용해 LIKP와 LIPS를 조회하여 'Delivery Created' 이벤트를 수집합니다. MKPF와 MSEG에서 이동 유형이 '601'인 출고 문서를 조회해 'Goods Issued' 이벤트를 수집합니다. Warehouse Management가 활성화되어 있으면 LTAK와 LTAP에서 마지막 이체 주문 항목의 확인 시각을 찾아 'Picking Completed'를 판별합니다. 납품 헤더 상태 VBUK-PODAT를 확인해 'Proof of Delivery Confirmed'를 파악합니다.
- 송장 및 결제 이벤트 추출: VBFA에서 가져온 청구 문서 번호를 사용해 VBRK와 VBRP를 조회하여 'Invoice Created' 및 'Invoice Cancelled'(VBRK-FKSTO = 'X'인 경우) 이벤트를 수집합니다. 'Payment Received'를 찾으려면 VBRK의 송장을 BKPF의 회계 문서와 연결한 다음 BSAD에서 반제 문서와 반제 날짜를 찾습니다.
- 상태 기반 이벤트 추출: 상태 테이블 VBUP(항목 상태)과 VBUK(헤더 상태)를 사용해 업무 이벤트를 추론합니다. 예를 들어 VBUP-GBSTA가 'C'이면 항목을 'Order Item Closed'로 간주합니다. 관련된 모든 항목에 'Reason for Rejection'(VBAP-ABGRU)이 설정되어 있으면 주문을 'Order Cancelled'로 처리합니다.
- 통합 및 형식 지정: 수집한 모든 이벤트를 하나의 최종 내부 테이블로 통합합니다. 각 이벤트 레코드에 SalesOrder, Activity, StartTime, User 등의 속성이 올바르게 입력되었는지 확인합니다. SourceSystem과 LastDataUpdate 타임스탬프도 추가합니다.
- 출력 파일 생성: GUI_DOWNLOAD 함수 모듈 또는 cl_gui_frontend_services=>gui_download 메서드를 사용해 최종 내부 테이블을 사용자 로컬 컴퓨터의 CSV 파일로 내보냅니다. 파일을 UTF-8 인코딩으로 저장합니다.
구성
- 사전 요건: ABAP 개발자 권한 (예: SE38 트랜잭션 접근 권한)과 VBAK, VBAP, CDHDR, CDPOS, VBFA, LIKP, LIPS, VBRK, VBRP, MKPF, MSEG, BSAD 등 필요한 모든 SAP 테이블에 대한 읽기 권한이 필요합니다.
- 선택 매개변수: 프로그램에 필터링용 선택 화면을 포함해야 합니다. 주요 매개변수는 다음과 같습니다.
- 날짜 범위: 판매 오더 생성일 (VBAK-ERDAT)의 날짜 범위는 필수입니다. 데이터 양을 관리할 수 있도록 최근 3~6개월부터 시작합니다.
- 영업 조직: VBAK-VKORG로 필터링해 특정 사업부에 초점을 맞춥니다.
- 판매 문서 유형: VBAK-AUART로 필터링해 필요한 주문 유형 (예: 표준 주문)만 포함하고 견적이나 반품 등은 제외합니다.
- 성능 고려 사항: 변경 내역 테이블 (CDHDR, CDPOS)과 문서 흐름 (VBFA)에서 대량의 데이터를 추출하면 시간이 오래 걸릴 수 있습니다. WHERE 절에서 인덱스 필드를 사용하도록 프로그램을 최적화해야 합니다. 대량 추출은 트랜잭션 SM36을 사용해 업무량이 적은 시간대에 백그라운드 작업으로 예약합니다.
- 변경 내역 기록 활성화: 이 방법은 SAP의 변경 문서 기능을 사용합니다. LIFSK, CMGST, ABGRU 등 주요 데이터 요소의 변경 기록이 활성화되어 있는지 확인합니다. 트랜잭션 SCDO에서 객체 VERKBELEG을 확인할 수 있습니다.
샘플 쿼리 abap
REPORT Z_O2C_PM_EXTRACTOR.
*&---------------------------------------------------------------------*
*& Data Declarations
*&---------------------------------------------------------------------*
TABLES: vbak.
TYPES: BEGIN OF ty_event_log,
salesorder TYPE vbeln_va,
activity TYPE string,
starttime TYPE string,
sourcesystem TYPE logsys,
lastdataupdate TYPE string,
user TYPE ernam,
customernumber TYPE kunnr,
salesorganization TYPE vkorg,
netamount TYPE netwr,
materialnumber TYPE matnr,
deliveryblock TYPE lifsk,
rejectionreason TYPE abgru,
salesordercycletime TYPE string, " Placeholder for calculation
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
DATA: gs_event_log TYPE ty_event_log.
DATA: gv_sysid TYPE logsys.
DATA: gv_last_update TYPE string.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_erdat FOR vbak-erdat OBLIGATORY,
s_vkorg FOR vbak-vkorg,
s_auart FOR vbak-auart.
PARAMETERS: p_file TYPE rlgrap-filename OBLIGATORY DEFAULT 'C:\temp\o2c_event_log.csv'.
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = gv_sysid.
CONCATENATE sy-datum sy-uzeit INTO gv_last_update.
PERFORM get_base_data.
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*& Form get_base_data
*&---------------------------------------------------------------------*
FORM get_base_data.
TYPES: BEGIN OF ty_order_item,
vbeln TYPE vbeln_va,
posnr TYPE posnr_va,
erdat TYPE erdat,
erzet TYPE erzet,
ernam TYPE ernam,
kunnr TYPE kunnr,
vkorg TYPE vkorg,
netwr TYPE netwr_ak,
matnr TYPE matnr,
lifsk TYPE lifsk,
abgru TYPE abgru,
END OF ty_order_item.
DATA: lt_order_items TYPE TABLE OF ty_order_item.
SELECT h~vbeln i~posnr h~erdat h~erzet h~ernam h~kunnr h~vkorg h~netwr i~matnr h~lifsk i~abgru
INTO TABLE lt_order_items
FROM vbak AS h
INNER JOIN vbap AS i ON h~vbeln = i~vbeln
WHERE h~erdat IN s_erdat
AND h~vkorg IN s_vkorg
AND h~auart IN s_auart.
CHECK sy-subrc = 0.
DATA(lt_vbeln_range) = VALUE rsdsselopt_t(
FOR <fs_item> IN lt_order_items WHERE ( vbeln = <fs_item>-vbeln )
( sign = 'I' option = 'EQ' low = <fs_item>-vbeln ) ).
SORT lt_vbeln_range BY low.
DELETE ADJACENT DUPLICATES FROM lt_vbeln_range COMPARING low.
PERFORM extract_order_created USING lt_order_items.
PERFORM extract_changes USING lt_vbeln_range lt_order_items.
PERFORM extract_doc_flow_events USING lt_vbeln_range lt_order_items.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form extract_order_created
*&---------------------------------------------------------------------*
FORM extract_order_created USING it_order_items TYPE ANY TABLE.
FIELD-SYMBOLS: <fs_item> TYPE any.
DATA: lt_unique_orders TYPE HASHED TABLE OF vbeln_va WITH UNIQUE KEY table_line.
lt_unique_orders = VALUE #( FOR <order> IN it_order_items ( CONV vbeln_va( <order>-vbeln ) ) ).
LOOP AT it_order_items ASSIGNING <fs_item> WHERE table_line IN lt_unique_orders.
CLEAR gs_event_log.
gs_event_log-salesorder = <fs_item>-vbeln.
gs_event_log-activity = 'Sales Order Created'.
CONCATENATE <fs_item>-erdat <fs_item>-erzet INTO gs_event_log-starttime.
gs_event_log-user = <fs_item>-ernam.
gs_event_log-customernumber = <fs_item>-kunnr.
gs_event_log-salesorganization = <fs_item>-vkorg.
gs_event_log-netamount = <fs_item>-netwr.
APPEND gs_event_log TO gt_event_log.
DELETE lt_unique_orders WHERE table_line = <fs_item>-vbeln.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form extract_changes
*&---------------------------------------------------------------------*
FORM extract_changes USING it_vbeln_range TYPE rsdsselopt_t it_order_items TYPE ANY TABLE.
DATA: lt_cdhdr TYPE TABLE OF cdhdr,
lt_cdpos TYPE TABLE OF cdpos.
SELECT * INTO TABLE lt_cdhdr FROM cdhdr
WHERE objectclas = 'VERKBELEG'
AND objectid IN it_vbeln_range
AND tcode = 'VA02'.
IF sy-subrc = 0.
SELECT * INTO TABLE lt_cdpos FROM cdpos
FOR ALL ENTRIES IN lt_cdhdr
WHERE objectclas = lt_cdhdr-objectclas
AND objectid = lt_cdhdr-objectid
AND changenr = lt_cdhdr-changenr.
ENDIF.
LOOP AT lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>).
DATA(lv_order_info) = REF #( it_order_items[ vbeln = <fs_cdhdr>-objectid ] ).
IF lv_order_info IS NOT BOUND. CONTINUE. ENDIF.
CLEAR gs_event_log.
gs_event_log-salesorder = <fs_cdhdr>-objectid.
gs_event_log-user = <fs_cdhdr>-username.
CONCATENATE <fs_cdhdr>-udate <fs_cdhdr>-utime INTO gs_event_log-starttime.
gs_event_log-customernumber = lv_order_info->kunnr.
gs_event_log-salesorganization = lv_order_info->vkorg.
gs_event_log-netamount = lv_order_info->netwr.
" Generic Change Event
gs_event_log-activity = 'Sales Order Changed'.
APPEND gs_event_log TO gt_event_log.
LOOP AT lt_cdpos ASSIGNING FIELD-SYMBOL(<fs_cdpos>)
WHERE objectclas = <fs_cdhdr>-objectclas
AND objectid = <fs_cdhdr>-objectid
AND changenr = <fs_cdhdr>-changenr.
CASE <fs_cdpos>-fname.
WHEN 'LIFSK'. " Delivery Block
gs_event_log-activity = 'Delivery Block Set'.
gs_event_log-deliveryblock = <fs_cdpos>-value_new.
APPEND gs_event_log TO gt_event_log.
WHEN 'CMGST'. " Credit Status
IF <fs_cdpos>-value_new = 'B'. " B = Credit Check OK
gs_event_log-activity = 'Credit Check Performed'.
APPEND gs_event_log TO gt_event_log.
ENDIF.
WHEN 'ABGRU'. " Rejection Reason
IF <fs_cdpos>-value_new IS NOT INITIAL.
gs_event_log-activity = 'Order Cancelled'.
gs_event_log-rejectionreason = <fs_cdpos>-value_new.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDCASE.
ENDLOOP.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form extract_doc_flow_events
*&---------------------------------------------------------------------*
FORM extract_doc_flow_events USING it_vbeln_range TYPE rsdsselopt_t it_order_items TYPE ANY TABLE.
DATA: lt_vbfa TYPE TABLE OF vbfa,
lt_vbrk TYPE TABLE OF vbrk,
lt_likp TYPE TABLE OF likp,
lt_mseg TYPE TABLE OF mseg,
lt_bsad TYPE TABLE OF bsad,
lt_vbup TYPE TABLE OF vbup.
SELECT * INTO TABLE lt_vbfa FROM vbfa
WHERE vbelv IN it_vbeln_range
AND ( vbtyp_n = 'J' " Delivery
OR vbtyp_n = 'M' " Invoice
OR vbtyp_n = 'N' " Invoice Cancellation
OR vbtyp_n = 'R' ). " Goods Movement
IF lt_vbfa IS INITIAL. RETURN. ENDIF.
SELECT vbeln, erdat, erzet, ernam, fksto, belnr FROM vbrk INTO TABLE lt_vbrk
FOR ALL ENTRIES IN lt_vbfa
WHERE vbeln = lt_vbfa-vbeln
AND ( lt_vbfa-vbtyp_n = 'M' OR lt_vbfa-vbtyp_n = 'N' ).
SELECT vbeln, erdat, erzet, ernam, podat FROM likp INTO TABLE lt_likp
FOR ALL ENTRIES IN lt_vbfa
WHERE vbeln = lt_vbfa-vbeln AND lt_vbfa-vbtyp_n = 'J'.
SELECT mblnr, mjahr, zeile, bwart, budat, cpuzt, usnam FROM mseg INTO TABLE lt_mseg
FOR ALL ENTRIES IN lt_vbfa
WHERE mblnr = lt_vbfa-vbeln AND mjahr = lt_vbfa-mjahr AND zeile = lt_vbfa-posnn AND lt_vbfa-vbtyp_n = 'R' AND bwart = '601'.
SELECT augdt, belnr, gjahr, kunnr FROM bsad INTO TABLE lt_bsad
FOR ALL ENTRIES IN lt_vbrk
WHERE belnr = lt_vbrk-belnr AND gjahr = SUBSTRING( val = lt_vbrk-erdat len = 4 ).
SELECT vbeln, posnr, gbsta FROM vbup INTO TABLE lt_vbup
FOR ALL ENTRIES IN lt_vbfa
WHERE vbeln = lt_vbfa-vbelv AND posnr = lt_vbfa-posnv.
LOOP AT lt_vbfa ASSIGNING FIELD-SYMBOL(<fs_vbfa>).
DATA(lv_order_info) = REF #( it_order_items[ vbeln = <fs_vbfa>-vbelv ] ).
IF lv_order_info IS NOT BOUND. CONTINUE. ENDIF.
CLEAR gs_event_log.
gs_event_log-salesorder = <fs_vbfa>-vbelv.
gs_event_log-customernumber = lv_order_info->kunnr.
gs_event_log-salesorganization = lv_order_info->vkorg.
gs_event_log-netamount = lv_order_info->netwr.
gs_event_log-materialnumber = lv_order_info->matnr.
CASE <fs_vbfa>-vbtyp_n.
WHEN 'J'. " Delivery
READ TABLE lt_likp ASSIGNING FIELD-SYMBOL(<fs_likp>) WITH KEY vbeln = <fs_vbfa>-vbeln.
IF sy-subrc = 0.
gs_event_log-activity = 'Delivery Created'.
CONCATENATE <fs_likp>-erdat <fs_likp>-erzet INTO gs_event_log-starttime.
gs_event_log-user = <fs_likp>-ernam.
APPEND gs_event_log TO gt_event_log.
" Picking Completed - simplified logic, check status
gs_event_log-activity = 'Picking Completed'. APPEND gs_event_log TO gt_event_log.
" POD Confirmed
IF <fs_likp>-podat IS NOT INITIAL.
gs_event_log-activity = 'Proof Of Delivery Confirmed'.
gs_event_log-starttime = <fs_likp>-podat.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDIF.
WHEN 'R'. " Goods Issue
READ TABLE lt_mseg ASSIGNING FIELD-SYMBOL(<fs_mseg>) WITH KEY mblnr = <fs_vbfa>-vbeln mjahr = <fs_vbfa>-mjahr zeile = <fs_vbfa>-posnn.
IF sy-subrc = 0.
gs_event_log-activity = 'Goods Issued'.
CONCATENATE <fs_mseg>-budat <fs_mseg>-cpuzt INTO gs_event_log-starttime.
gs_event_log-user = <fs_mseg>-usnam.
APPEND gs_event_log TO gt_event_log.
ENDIF.
WHEN 'M'. " Invoice
READ TABLE lt_vbrk ASSIGNING FIELD-SYMBOL(<fs_vbrk>) WITH KEY vbeln = <fs_vbfa>-vbeln.
IF sy-subrc = 0.
gs_event_log-activity = 'Invoice Created'.
CONCATENATE <fs_vbrk>-erdat <fs_vbrk>-erzet INTO gs_event_log-starttime.
gs_event_log-user = <fs_vbrk>-ernam.
APPEND gs_event_log TO gt_event_log.
" Payment Received
READ TABLE lt_bsad ASSIGNING FIELD-SYMBOL(<fs_bsad>) WITH KEY belnr = <fs_vbrk>-belnr.
IF sy-subrc = 0 AND <fs_bsad>-augdt IS NOT INITIAL.
gs_event_log-activity = 'Payment Received'.
gs_event_log-starttime = <fs_bsad>-augdt.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDIF.
WHEN 'N'. " Invoice Cancellation
READ TABLE lt_vbrk ASSIGNING <fs_vbrk> WITH KEY vbeln = <fs_vbfa>-vbeln.
IF sy-subrc = 0 AND <fs_vbrk>-fksto = 'X'.
gs_event_log-activity = 'Invoice Cancelled'.
CONCATENATE <fs_vbrk>-erdat <fs_vbrk>-erzet INTO gs_event_log-starttime.
gs_event_log-user = <fs_vbrk>-ernam.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDCASE.
ENDLOOP.
" Infer other events from status
LOOP AT lt_vbup ASSIGNING FIELD-SYMBOL(<fs_vbup>).
IF <fs_vbup>-gbsta = 'C'.
DATA(lv_order_info_stat) = REF #( it_order_items[ vbeln = <fs_vbup>-vbeln ] ).
IF lv_order_info_stat IS NOT BOUND. CONTINUE. ENDIF.
gs_event_log-salesorder = <fs_vbup>-vbeln.
gs_event_log-activity = 'Order Item Closed'.
" Timestamp for closed is harder, using current time as placeholder
CONCATENATE sy-datum sy-uzeit INTO gs_event_log-starttime.
gs_event_log-user = sy-uname.
gs_event_log-customernumber = lv_order_info_stat->kunnr.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
" Order Confirmed (Simplified - assumes if not blocked it's confirmed)
LOOP AT it_order_items ASSIGNING FIELD-SYMBOL(<fs_item>).
IF <fs_item>-lifsk IS INITIAL.
gs_event_log-salesorder = <fs_item>-vbeln.
gs_event_log-activity = 'Order Confirmed'.
CONCATENATE <fs_item>-erdat <fs_item>-erzet INTO gs_event_log-starttime.
gs_event_log-user = <fs_item>-ernam.
gs_event_log-customernumber = <fs_item>-kunnr.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form write_output_file
*&---------------------------------------------------------------------*
FORM write_output_file.
DATA: lt_final_output TYPE TABLE OF ty_event_log.
" Add common fields
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_event>).
<fs_event>-sourcesystem = gv_sysid.
<fs_event>-lastdataupdate = gv_last_update.
ENDLOOP.
SORT gt_event_log BY salesorder starttime.
DELETE ADJACENT DUPLICATES FROM gt_event_log COMPARING ALL FIELDS.
lt_final_output = gt_event_log.
DATA: lt_fieldnames TYPE TABLE OF string.
APPEND 'SalesOrder' TO lt_fieldnames.
APPEND 'Activity' TO lt_fieldnames.
APPEND 'StartTime' TO lt_fieldnames.
APPEND 'SourceSystem' TO lt_fieldnames.
APPEND 'LastDataUpdate' TO lt_fieldnames.
APPEND 'User' TO lt_fieldnames.
APPEND 'CustomerNumber' TO lt_fieldnames.
APPEND 'SalesOrganization' TO lt_fieldnames.
APPEND 'NetAmount' TO lt_fieldnames.
APPEND 'MaterialNumber' TO lt_fieldnames.
APPEND 'DeliveryBlock' TO lt_fieldnames.
APPEND 'RejectionReason' TO lt_fieldnames.
APPEND 'SalesOrderCycleTime' TO lt_fieldnames.
DATA(lv_header) = REDUCE string(
INIT s = ''
FOR field IN lt_fieldnames
NEXT s = s && COND #( WHEN s = '' THEN field ELSE |,{ field }| ) ).
DATA: lt_file_content TYPE TABLE OF string.
APPEND lv_header TO lt_file_content.
LOOP AT lt_final_output INTO DATA(ls_output).
DATA(lv_line) = |"{ ls_output-salesorder }","{ ls_output-activity }","{ ls_output-starttime }","{ ls_output-sourcesystem }","{ ls_output-lastdataupdate }","{ ls_output-user }","{ ls_output-customernumber }","{ ls_output-salesorganization }",{ ls_output-netamount },"{ ls_output-materialnumber }","{ ls_output-deliveryblock }","{ ls_output-rejectionreason }","{ ls_output-salesordercycletime }"|.
APPEND lv_line TO lt_file_content.
ENDLOOP.
cl_gui_frontend_services=>gui_download(
EXPORTING
filename = p_file
filetype = 'ASC'
CHANGING
data_tab = lt_file_content ).
ENDFORM. 단계
- 사전 준비: SAP ECC 데이터베이스에 직접 읽기 전용으로 접근할 수 있는지 확인합니다. 연결하고 쿼리를 실행하려면 DBeaver, SQL Server Management Studio, Oracle SQL Developer와 같은 데이터베이스 클라이언트 도구가 필요합니다.
- SQL 스크립트 가져오기: 이 문서의 'query' 섹션에 있는 전체 SQL 쿼리를 복사합니다.
- 데이터베이스 연결: 데이터베이스 클라이언트를 열고 SAP ECC 데이터베이스 인스턴스에 연결합니다. 서버 주소, 포트, 데이터베이스 이름, 적절한 로그인 자격 증명이 필요합니다.
- 쿼리 설정: 새 쿼리 편집기 창에 SQL 스크립트를 붙여 넣습니다. SalesOrders라는 기본 공통 테이블 식(CTE)에서 설정 섹션을 찾습니다. 시작일('{StartDate}'), 종료일('{EndDate}'), 영업 조직('{SalesOrgs}'), 문서 유형('{DocTypes}')의 자리표시자 값을 분석에 사용할 실제 값으로 바꿉니다.
- 쿼리 실행: 설정한 SQL 스크립트를 실행합니다. 날짜 범위와 SAP 데이터베이스 크기에 따라 완료까지 몇 분 정도 걸릴 수 있습니다.
- 결과 검토: 쿼리가 완료되면 결과 집합이 표시됩니다. 예상한 열(SalesOrder, Activity, StartTime 등)이 포함되어 있고 여러 활동의 행이 반환되는지 간단히 확인합니다.
- 데이터 내보내기: 데이터베이스 클라이언트의 내보내기 기능을 사용해 결과 집합을 CSV 파일로 저장합니다. 파일 이름은 SAP_O2C_Event_Log.csv처럼 내용을 알아보기 쉽게 지정합니다.
- ProcessMind에 맞게 형식 지정: 스프레드시트 편집기에서 CSV 파일을 엽니다. 열 머리글이 필수 속성 이름(예: SalesOrder, Activity, StartTime)과 정확히 일치하는지 확인합니다. StartTime과 LastDataUpdate의 날짜 및 시간 형식이 일관되고 ProcessMind에서 지원되는지 확인합니다. 예: YYYY-MM-DD HH:MI:SS.
- ProcessMind에 업로드: 형식을 정리한 최종 CSV 파일을 ProcessMind 프로젝트에 업로드해 분석합니다.
구성
- 날짜 범위: Query는 '{StartDate}' 및 '{EndDate}' 자리 표시자를 사용해 판매 오더 생성일 (VBAK.ERDAT)을 기준으로 데이터를 필터링합니다. 데이터베이스에 과도한 부하를 주지 않으면서 대표성 있는 표본을 확보하려면 일반적으로 3~6개월의 데이터를 분석합니다.
- 영업 조직 필터: '{SalesOrgs}' 자리 표시자를 사용해 특정 영업 조직 (예: '1000', '2000')만 추출합니다. 분석 범위를 좁히고 Query 성능을 높이는 데 중요합니다.
- 문서 유형 필터: '{DocTypes}' 자리 표시자를 사용해 특정 판매 오더 유형 (예: 표준 주문의 경우 'OR')을 선택합니다. 이렇게 하면 무상 납품이나 반품 등 분석 대상이 아닌 문서를 주요 프로세스 흐름에서 제외할 수 있습니다.
- 소스 시스템 식별자: '{SourceSystemName}' 자리 표시자를 코드에 지정해 모든 레코드에 출처 시스템을 표시합니다. SAP ECC 인스턴스를 식별할 수 있는 이름 (예: SAP_ECC_PRD)을 입력합니다.
- 데이터베이스 호환성: 날짜와 시간 필드를 결합하는 함수 [Your DB-specific timestamp function]은 자리 표시자입니다. 사용 중인 데이터베이스에 맞는 함수로 바꿔야 합니다 (예: SAP HANA의 경우 TO_TIMESTAMP(CONCAT(CDHDR.UDATE, CDHDR.UZEIT), 'YYYYMMDDHH24MISS'), SQL Server의 경우 CAST(CDHDR.UDATE AS DATETIME) + CAST(CDHDR.UZEIT AS DATETIME)).
- 사전 요건: 이 방법을 사용하려면 데이터베이스에 직접 읽기 전용으로 접속할 수 있는 계정이 필요합니다. 데이터베이스 사용자는 Query에서 참조하는 VBAK, VBAP, VBFA, CDHDR, CDPOS, LIKP, VBRK, BSAD 테이블에 접근할 권한이 있어야 합니다.
샘플 쿼리 sql
WITH SalesOrders AS (
SELECT VBELN
FROM VBAK
WHERE ERDAT BETWEEN '{StartDate}' AND '{EndDate}' -- Filter by creation date
AND VKORG IN ('{SalesOrgs}') -- Filter by Sales Organization(s)
AND AUART IN ('{DocTypes}') -- Filter by Sales Document Type(s)
)
-- 1. Sales Order Created
SELECT
vbak.VBELN AS "SalesOrder",
'Sales Order Created' AS "Activity",
[Your DB-specific timestamp function](vbak.ERDAT, vbak.ERZET) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
vbak.ERNAM AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
vbak.LIFSK AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM VBAK vbak
JOIN SalesOrders so ON vbak.VBELN = so.VBELN
UNION ALL
-- 2. Sales Order Changed
SELECT
cdhdr.OBJECTID AS "SalesOrder",
'Sales Order Changed' AS "Activity",
[Your DB-specific timestamp function](cdhdr.UDATE, cdhdr.UZEIT) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
cdhdr.USERNAME AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
vbak.LIFSK AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM CDHDR cdhdr
JOIN SalesOrders so ON cdhdr.OBJECTID = so.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE cdhdr.OBJECTCLASS = 'VERKBELEG' AND cdhdr.TCODE IN ('VA02')
UNION ALL
-- 3. Credit Check Performed (Release)
SELECT
cdhdr.OBJECTID AS "SalesOrder",
'Credit Check Performed' AS "Activity",
[Your DB-specific timestamp function](cdhdr.UDATE, cdhdr.UZEIT) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
cdhdr.USERNAME AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
vbak.LIFSK AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM CDHDR cdhdr
JOIN CDPOS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
JOIN SalesOrders so ON cdhdr.OBJECTID = so.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE cdhdr.OBJECTCLASS = 'VERKBELEG'
AND cdpos.TABNAME = 'VBUK'
AND cdpos.FNAME = 'CMGST'
AND cdpos.VALUE_NEW = 'B' -- Credit status 'Released'
UNION ALL
-- 4. Order Confirmed (Overall status not blocked)
SELECT
cdhdr.OBJECTID AS "SalesOrder",
'Order Confirmed' AS "Activity",
[Your DB-specific timestamp function](cdhdr.UDATE, cdhdr.UZEIT) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
cdhdr.USERNAME AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
NULL AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM CDHDR cdhdr
JOIN CDPOS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
JOIN SalesOrders so ON cdhdr.OBJECTID = so.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE cdhdr.OBJECTCLASS = 'VERKBELEG'
AND cdpos.TABNAME = 'VBUK'
AND cdpos.FNAME = 'GBSTK'
AND cdpos.VALUE_OLD <> 'A' AND cdpos.VALUE_NEW = 'A' -- Status changes to 'Not yet processed'
UNION ALL
-- 5. Delivery Block Set
SELECT
cdhdr.OBJECTID AS "SalesOrder",
'Delivery Block Set' AS "Activity",
[Your DB-specific timestamp function](cdhdr.UDATE, cdhdr.UZEIT) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
cdhdr.USERNAME AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
cdpos.VALUE_NEW AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM CDHDR cdhdr
JOIN CDPOS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
JOIN SalesOrders so ON cdhdr.OBJECTID = so.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE cdhdr.OBJECTCLASS = 'VERKBELEG'
AND cdpos.TABNAME = 'VBAK'
AND cdpos.FNAME = 'LIFSK'
AND cdpos.VALUE_NEW IS NOT NULL AND cdpos.VALUE_NEW <> ''
UNION ALL
-- 6. Delivery Created
SELECT
vbfa.VBELV AS "SalesOrder",
'Delivery Created' AS "Activity",
[Your DB-specific timestamp function](likp.ERDAT, likp.ERZET) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
likp.ERNAM AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
vbak.LIFSK AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM VBFA vbfa
JOIN SalesOrders so ON vbfa.VBELV = so.VBELN
JOIN LIKP likp ON vbfa.VBELN = likp.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE vbfa.VBTYP_V = 'C' AND vbfa.VBTYP_N = 'J'
UNION ALL
-- 7. Picking Completed
SELECT
vbfa.VBELV AS "SalesOrder",
'Picking Completed' AS "Activity",
[Your DB-specific timestamp function](cdhdr.UDATE, cdhdr.UZEIT) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
cdhdr.USERNAME AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
NULL AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM VBFA vbfa
JOIN SalesOrders so ON vbfa.VBELV = so.VBELN
JOIN CDHDR cdhdr ON vbfa.VBELN = cdhdr.OBJECTID
JOIN CDPOS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE vbfa.VBTYP_V = 'C' AND vbfa.VBTYP_N = 'J'
AND cdhdr.OBJECTCLASS = 'LIEFERUNG'
AND cdpos.TABNAME = 'VBUK'
AND cdpos.FNAME = 'PKSTK'
AND cdpos.VALUE_NEW = 'C'
UNION ALL
-- 8. Goods Issued
SELECT
vbfa_gi.VBELV AS "SalesOrder",
'Goods Issued' AS "Activity",
[Your DB-specific timestamp function](mkpf.BUDAT, mkpf.CPUTM) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
mkpf.USNAM AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
NULL AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM VBFA vbfa_gi
JOIN SalesOrders so ON vbfa_gi.VBELV = so.VBELN
JOIN MKPF mkpf ON vbfa_gi.VBELN = mkpf.XBLNR -- XBLNR is Reference Document Number
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE vbfa_gi.VBTYP_V = 'J' AND vbfa_gi.VBTYP_N = 'R'
UNION ALL
-- 9. Proof Of Delivery Confirmed
SELECT
vbfa.VBELV AS "SalesOrder",
'Proof Of Delivery Confirmed' AS "Activity",
[Your DB-specific timestamp function](likp.PODAT, '000000') AS "StartTime", -- PODAT is only a date
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
likp.AENAM AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
NULL AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM VBFA vbfa
JOIN SalesOrders so ON vbfa.VBELV = so.VBELN
JOIN LIKP likp ON vbfa.VBELN = likp.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE vbfa.VBTYP_V = 'C' AND vbfa.VBTYP_N = 'J' AND likp.PODAT IS NOT NULL AND likp.PODAT <> '00000000'
UNION ALL
-- 10. Invoice Created
SELECT
vbfa.VBELV AS "SalesOrder",
'Invoice Created' AS "Activity",
[Your DB-specific timestamp function](vbrk.ERDAT, vbrk.ERZET) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
vbrk.ERNAM AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
NULL AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM VBFA vbfa
JOIN SalesOrders so ON vbfa.VBELV = so.VBELN
JOIN VBRK vbrk ON vbfa.VBELN = vbrk.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE vbfa.VBTYP_V = 'C' AND vbfa.VBTYP_N = 'M'
UNION ALL
-- 11. Invoice Cancelled
SELECT
vbfa.VBELV AS "SalesOrder",
'Invoice Cancelled' AS "Activity",
[Your DB-specific timestamp function](vbrk.ERDAT, vbrk.ERZET) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
vbrk.ERNAM AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
NULL AS "RejectionReason"
FROM VBFA vbfa
JOIN SalesOrders so ON vbfa.VBELV = so.VBELN
JOIN VBRK vbrk ON vbfa.VBELN = vbrk.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE vbfa.VBTYP_V = 'M' AND vbfa.VBTYP_N = 'N'
UNION ALL
-- 12. Payment Received
SELECT
vbfa.VBELV AS "SalesOrder",
'Payment Received' AS "Activity",
[Your DB-specific timestamp function](bsad.AUGDT, '000000') AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
NULL AS "User", -- Clearing user not readily available here
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
NULL AS "MaterialNumber",
NULL AS "DeliveryBlock",
NULL AS "RejectionReason"
FROM VBFA vbfa
JOIN SalesOrders so ON vbfa.VBELV = so.VBELN
JOIN VBRK vbrk ON vbfa.VBELN = vbrk.VBELN
JOIN BSAD bsad ON vbrk.VBELN = bsad.VBLNR
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE vbfa.VBTYP_V = 'C' AND vbfa.VBTYP_N = 'M'
AND bsad.AUGDT IS NOT NULL AND bsad.AUGDT <> '00000000'
UNION ALL
-- 13. Order Item Closed
SELECT DISTINCT
cdhdr.OBJECTID AS "SalesOrder",
'Order Item Closed' AS "Activity",
[Your DB-specific timestamp function](cdhdr.UDATE, cdhdr.UZEIT) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
cdhdr.USERNAME AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
vbap.MATNR AS "MaterialNumber",
NULL AS "DeliveryBlock",
vbap.ABGRU AS "RejectionReason"
FROM CDHDR cdhdr
JOIN CDPOS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
JOIN VBAP vbap ON cdhdr.OBJECTID = vbap.VBELN AND SUBSTRING(cdpos.TABKEY, 4, 6) = vbap.POSNR
JOIN SalesOrders so ON cdhdr.OBJECTID = so.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE cdhdr.OBJECTCLASS = 'VERKBELEG'
AND cdpos.TABNAME = 'VBUP'
AND cdpos.FNAME = 'GBSTA'
AND cdpos.VALUE_NEW = 'C' -- Item is completely processed
UNION ALL
-- 14. Order Cancelled
SELECT DISTINCT
cdhdr.OBJECTID AS "SalesOrder",
'Order Cancelled' AS "Activity",
[Your DB-specific timestamp function](cdhdr.UDATE, cdhdr.UZEIT) AS "StartTime",
'{SourceSystemName}' AS "SourceSystem",
CURRENT_TIMESTAMP AS "LastDataUpdate",
cdhdr.USERNAME AS "User",
vbak.KUNNR AS "CustomerNumber",
vbak.VKORG AS "SalesOrganization",
vbak.NETWR AS "NetAmount",
vbap.MATNR AS "MaterialNumber",
NULL AS "DeliveryBlock",
cdpos.VALUE_NEW AS "RejectionReason"
FROM CDHDR cdhdr
JOIN CDPOS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
JOIN VBAP vbap ON cdhdr.OBJECTID = vbap.VBELN AND SUBSTRING(cdpos.TABKEY, 4, 6) = vbap.POSNR
JOIN SalesOrders so ON cdhdr.OBJECTID = so.VBELN
JOIN VBAK vbak ON so.VBELN = vbak.VBELN
WHERE cdhdr.OBJECTCLASS = 'VERKBELEG'
AND cdpos.TABNAME = 'VBAP'
AND cdpos.FNAME = 'ABGRU'
AND cdpos.VALUE_NEW IS NOT NULL AND cdpos.VALUE_NEW <> ''; 시작할 준비가 되셨나요?
이 데이터 템플릿을 활용해 주문부터 현금 회수까지 이어지는 판매 오더 처리 프로세스를 개선해 보세요. 효율을 높이고 현금 흐름을 개선하는 첫걸음을 시작하세요.
주문부터 현금 회수까지의 판매 처리를 지금 개선하세요
병목을 해소하고 처리 시간을 30% 단축해 현금 흐름을 빠르게 개선하세요.
신용카드가 필요하지 않습니다. 몇 분이면 설정할 수 있습니다.