구매부터 지급까지, 송장 처리 데이터 템플릿
구매부터 지급까지, 송장 처리 데이터 템플릿
- 수집 권장 속성
- 추적할 주요 활동
- SAP S/4HANA 데이터 추출 안내
구매부터 지급까지, 송장 처리 속성
| 이름 | 설명 | ||
|---|---|---|---|
| 송장 번호 InvoiceNumber | 공급업체 송장 문서의 고유 식별자로, 프로세스의 기본 케이스 식별자입니다. | ||
| 설명 송장 번호는 SAP S/4HANA에서 각 공급업체 송장에 부여하는 고유 식별자입니다. 송장 생성, 임시 보관, 승인, 지급 등 관련 활동을 하나의 프로세스 인스턴스로 연결합니다. process mining에서 이 속성은 각 송장의 전체 처리 과정을 추적하는 데 필수적입니다. 접수부터 최종 지급까지 프로세스 흐름을 재구성해 개별 송장의 처리 시간, 병목, 프로세스 변형을 분석할 수 있습니다. 중요한 이유 관련 이벤트를 모두 연결하는 필수 키로, 시스템에서 송장 처리 전 과정을 추적할 수 있습니다. 확보 방법 BKPF 테이블의 BELNR 필드에 있는 회계 문서 번호입니다. 예시 190000000119000000451900000132 | |||
| 이벤트 시간 EventTime | 활동이 발생한 정확한 날짜와 시간입니다. | ||
| 설명 이벤트 시간은 특정 활동이 발생한 시점을 정확히 기록하는 타임스탬프입니다. 프로세스 단계별 소요 시간, 전체 처리 시간, 대기 시간을 계산하는 데 필요합니다. process mining 분석에서는 정확한 타임스탬프를 활용해 '평균 송장 처리 시간'과 '송장 승인 처리 시간' 같은 성과 KPI를 측정합니다. 활동 간 경과 시간을 분석하면 송장 처리가 지연되는 병목을 찾아내고 프로세스를 단축할 기회를 파악할 수 있습니다. 중요한 이유 이 타임스탬프는 성과 모니터링, 병목 식별, SLA 추적 등 시간 기반 분석의 토대입니다. 확보 방법 일반적으로 변경 문서 테이블 CDHDR(헤더)와 CDPOS(항목)의 UDATE 및 UTIME 필드에서 가져옵니다. 일부 이벤트는 BKPF 테이블의 생성일 또는 입력일 필드(CPUDT, CPUTM)를 사용할 수 있습니다. 예시 2023-04-15T10:30:00Z2023-04-18T14:05:21Z2023-05-02T09:00:00Z | |||
| 활동 이름 ActivityName | 송장에서 특정 시점에 발생한 업무 활동 또는 이벤트의 이름입니다. | ||
| 설명 활동 이름은 송장 처리 과정의 특정 단계나 상태 변경을 나타냅니다. 예를 들면 '송장 문서 생성', '송장 승인 요청', '지급 차단 설정', '지급 실행' 등이 있습니다. 이 속성은 활동 흐름을 시각적으로 나타내는 프로세스 맵을 구성하는 데 중요합니다. 활동의 순서와 빈도, 활동 간 소요 시간을 분석하면 병목, 재작업 반복, 규정을 준수하지 않는 프로세스 변형을 파악할 수 있습니다. process mining 분석의 기반이 되는 속성입니다. 중요한 이유 프로세스의 단계를 정의해 프로세스 맵을 시각화하고 프로세스 흐름과 변형을 분석할 수 있습니다. 확보 방법 SAP 트랜잭션 코드(SY-TCODE), 변경 문서 객체 상태(CDHDR/CDPOS), 상태 변경을 나타내는 특정 필드 값을 조합해 도출합니다. 예시 송장 보류송장 승인지급 실행 | |||
| 공급업체 번호 VendorNumber | 송장을 제출한 공급업체의 고유 식별자입니다. | ||
| 설명 공급업체 번호는 송장과 관련된 공급업체 또는 채권자를 식별합니다. 송장 거래를 공급업체 마스터 데이터와 연결합니다. 이 속성을 활용하면 '공급업체 지급 성과'를 평가하거나 예외 또는 지급 차단을 유발하는 문제가 있는 송장을 자주 제출하는 공급업체를 파악하는 등 공급업체별 분석을 할 수 있습니다. 공급업체 관계를 관리하고 공급업체의 신뢰성을 평가하는 데 도움이 됩니다. 중요한 이유 공급업체별 프로세스 성과를 분석해 패턴을 파악하고 관계를 관리하며 공급업체 관련 문제를 평가할 수 있습니다. 확보 방법 일반적으로 회계 문서 세그먼트 테이블 BSEG의 LIFNR 필드에서 확인할 수 있습니다. 예시 100345700012V9832 | |||
| 구매 주문 PurchasingDocument | 송장과 연결된 구매 주문 번호입니다. | ||
| 설명 구매 문서 번호는 공급업체 송장을 원래 구매 주문(PO)과 연결합니다. 이 연결은 송장, 구매 주문, 입고 내역을 대조하는 3자 대조 프로세스의 기반입니다. 이 속성으로 분석하면 구매 주문이 있는 송장과 없는 송장의 처리 차이를 파악할 수 있습니다. 대조 과정의 불일치를 조사하고 프로세스 중 구매 단계의 효율성을 이해하는 데 중요합니다. 중요한 이유 송장을 조달 프로세스와 연결하므로 대조 불일치와 구매 주문 규정 준수를 분석하는 데 필요합니다. 확보 방법 일반적으로 문서 세그먼트 테이블 BSEG의 EBELN 필드(구매 문서 번호)에서 확인할 수 있습니다. 예시 450000123445000056784500009012 | |||
| 문서 유형 DocumentType | 공급업체 송장이나 대변 메모 등 회계 문서의 유형을 구분하는 코드입니다. | ||
| 설명 SAP에서 문서 유형은 서로 다른 업무 거래를 구분하는 데 사용됩니다. 예를 들어 'KR'은 일반 공급업체 송장, 'KG'는 공급업체 대변 메모를 나타내는 경우가 많습니다. 문서 유형별로 분석하면 거래 유형에 따라 프로세스가 어떻게 처리되는지 구분해 파악할 수 있습니다. 예를 들어 대변 메모 처리 과정은 일반 송장과 크게 다를 수 있습니다. 이렇게 구분하면 더 정확하고 관련성 높은 프로세스 인사이트를 얻을 수 있습니다. 중요한 이유 일반 송장과 대변 메모처럼 서로 다른 프로세스 경로를 따르는 금융 거래를 구분하는 데 도움이 됩니다. 확보 방법 문서 헤더 테이블 BKPF의 BLART 필드에서 확인할 수 있습니다. 예시 KRREKG | |||
| 사용자 이름 UserName | 활동을 수행한 사람 또는 시스템의 SAP 사용자 ID입니다. | ||
| 설명 이 속성은 특정 트랜잭션을 실행하거나 문서를 생성한 사용자를 식별합니다. 개인 사용자 ID일 수도 있고 자동 배치 작업에 사용되는 시스템 ID일 수도 있습니다. 사용자별로 분석하면 업무량 분포와 교육 필요성을 파악하고 비정상적인 사용자 행동을 찾을 수 있습니다. 예를 들어 예외를 자주 처리하는 사용자나 자동으로 처리되는 송장(예: 사용자 'BATCHUSER')을 확인할 수 있으며, 이는 '송장 자동화율' KPI 계산에 중요합니다. 중요한 이유 프로세스 활동을 특정 사용자나 시스템 계정에 연결해 업무량 분석, 성과 비교, 자동화 여부 확인을 지원합니다. 확보 방법 BKPF-USNAM(입력자) 또는 CDHDR-USERNAME(변경자) 등의 필드에서 가져옵니다. 예시 SMITHJMUELLERTWF-BATCH | |||
| 송장 금액 AmountInCompanyCodeCurrency | 회사 코드의 현지 통화로 표시한 송장 총액입니다. | ||
| 설명 이 속성은 송장의 총액을 나타냅니다. 송장 처리 운영의 재무적 영향과 규모를 파악하는 주요 지표입니다. 송장 금액을 분석하면 고액 송장의 우선 처리를 검토하고 지출 추세를 파악하며 프로세스 문제와 재무적 가치를 연관 지을 수 있습니다. 예를 들어 고액 송장이 지급 차단되거나 승인에 더 오래 걸리는지 조사할 수 있습니다. 중요한 이유 프로세스의 재무적 맥락을 제공하므로 금액을 기준으로 분석할 수 있습니다. 예를 들어 고액 송장이 다르게 처리되는지 확인할 수 있습니다. 확보 방법 일반적으로 BSEG 테이블의 WRBTR 필드(현지 통화 금액)에 있는 관련 개별 항목을 합산해 도출합니다. 예시 1500.75125000.00850.20 | |||
| 지급 기한 PaymentDueDate | 연체를 피하기 위해 송장을 지급해야 하는 날짜입니다. | ||
| 설명 지급 기한은 송장 날짜와 합의된 지급 조건을 바탕으로 계산한 공급업체 대금 지급일입니다. 프로세스에서 중요한 기한으로 사용됩니다. 이 속성은 '정시 지급률' KPI와 '공급업체 지급 성과' 대시보드에 필요합니다. 실제 지급일과 지급 기한을 비교하면 지급 의무를 제때 이행하는지 측정할 수 있습니다. 이는 공급업체 관계와 재무 평판에 영향을 줍니다. 중요한 이유 정시 지급 성과를 측정하는 주요 기준입니다. 공급업체와의 관계를 유지하고 연체료를 피하는 데 중요합니다. 확보 방법 이 날짜는 BSEG 테이블의 공급업체 개별 항목에 있는 ZFBDT 필드(지급 기한 계산 기준일)에서 확인할 수 있는 경우가 많습니다. 순지급기한은 이 기준일과 지급 조건을 바탕으로 계산합니다. 예시 2023-05-302023-06-152023-07-01 | |||
| 지급 차단 사유 PaymentBlockReason | 송장 지급이 차단된 이유를 나타내는 코드입니다. | ||
| 설명 송장 지급이 차단되면 이 속성에 '수량 불일치' 또는 '가격 불일치'와 같은 구체적인 사유가 표시됩니다. SAP에서 사유를 설정해 예외 처리를 표준화합니다. 이 속성은 '지급 차단 발생 및 지속 시간' 대시보드에 중요합니다. 차단 사유별 빈도를 분석하면 특정 공급업체나 자재, 내부 프로세스와 관련된 문제 등 지급 지연의 근본 원인을 찾아내고 적절한 시정 조치를 취할 수 있습니다. 중요한 이유 지급 차단의 구체적인 원인을 제공해 지연을 줄이고 최초 처리 성공률을 높이기 위한 분석을 지원합니다. 확보 방법 BSEG 테이블의 공급업체 개별 항목에 있는 ZLSPR 필드(지급 차단 키)에서 확인할 수 있습니다. 예시 RIA | |||
| 회사 코드 CompanyCode | 재무제표를 작성하는 법적으로 독립된 회사를 나타내는 조직 단위입니다. | ||
| 설명 회사 코드는 SAP Finance의 기본 조직 단위입니다. 각 송장은 특정 회사 코드에 배정되며, 이 코드가 거래를 책임지는 법인을 결정합니다. process mining에서는 회사 코드별로 필터링하거나 비교해 사업부, 법인 또는 국가별 프로세스 성과를 분석할 수 있습니다. 지역별 효율성, 규정 준수, 자동화 수준의 차이를 파악해 개선 활동의 우선순위를 정하는 데 도움이 됩니다. 중요한 이유 조직 내 법인이나 지역별로 송장 처리 성과를 구분하고 비교할 수 있습니다. 확보 방법 문서 헤더 테이블 BKPF의 표준 필드인 BUKRS입니다. 예시 1000US01DE01 | |||
| 반제 문서 번호. ClearingDocumentNumber | 송장을 반제하는 문서 번호로, 일반적으로 지급 문서를 나타냅니다. | ||
| 설명 반제 문서 번호는 미결 송장 항목을 해당 항목을 반제하는 거래와 연결하며, 대부분 지급 문서가 이에 해당합니다. 이 번호로 송장 지급 여부를 확인할 수 있습니다. 이 속성은 송장과 지급을 연결하는 확정적인 기준입니다. '지급 실행' 활동과 해당 타임스탬프를 식별하는 데 사용하며, 전체 처리 시간과 정시 지급률을 계산하는 데 필요합니다. 중요한 이유 송장 지급 여부를 확인하고 해당 송장을 특정 지급 거래와 연결합니다. 처리 시간과 지급 성과를 분석하는 데 중요합니다. 확보 방법 문서 세그먼트 테이블 BSEG의 AUGBL 필드(반제 문서 번호)에서 확인할 수 있습니다. 예시 150000000115000000231500000088 | |||
| 소스 시스템 ID SourceSystemId | 데이터를 추출한 SAP S/4HANA 소스 시스템의 식별자입니다. | ||
| 설명 이 속성은 'S4H_PROD' 또는 'ERP_EU'와 같이 데이터의 출처가 되는 시스템을 나타냅니다. 여러 ERP 인스턴스나 기존 시스템과 최신 시스템이 함께 운영되는 환경에서 특히 중요합니다. 분석 시 시스템이나 지역별 프로세스 성과를 비교할 수 있습니다. 데이터 출처를 확인할 수 있어 데이터 거버넌스에 도움이 되며, 여러 소스의 데이터를 중앙 process mining 플랫폼에 통합할 때 문제를 해결하는 데도 중요합니다. 중요한 이유 데이터 출처를 파악할 수 있어 데이터 거버넌스와 시스템 또는 사업장별 프로세스 비교에 필요합니다. 확보 방법 일반적으로 데이터 추출 시 SAP 시스템 ID(sy-sysid)에서 가져오거나 ETL 파이프라인에 고정값으로 설정합니다. 예시 S4PS4H_PROD_100ECC_EU | |||
| 송장 날짜 InvoiceDate | 공급업체가 송장 문서를 발행한 날짜입니다. | ||
| 설명 문서 날짜라고도 하는 송장 날짜는 공급업체가 송장에 기재한 날짜입니다. 합의된 지급 조건에 따라 지급 기한을 계산할 때 기준으로 사용합니다. 분석에서는 송장 경과 기간이나 조기 지급 할인 적용 여부 등 재무 계산의 기준이 됩니다. '조기 지급 할인 적용률' KPI를 계산하는 주요 입력값입니다. 중요한 이유 지급 조건과 지급 기한을 계산하는 기준입니다. 운전자본 관리와 할인 혜택 적용에 중요합니다. 확보 방법 문서 헤더 테이블 BKPF의 BLDAT 필드(문서 날짜)에서 확인할 수 있습니다. 예시 2023-04-122023-05-152023-06-20 | |||
| 승인 주기 횟수 ApprovalCycleCount | 송장이 승인 요청된 횟수입니다. | ||
| 설명 이 지표는 단일 송장에서 '송장 승인 요청' 활동이 발생한 횟수를 계산합니다. 횟수가 1보다 크면 송장이 한 번 이상 거부되거나 반려되어 다시 승인 절차를 거쳤음을 나타냅니다. 이 속성은 '최초 승인율' KPI를 직접 뒷받침합니다. 승인 주기 횟수가 많은 송장을 분석하면 정보 부족이나 잘못된 코드 입력 등 승인 실패 원인을 파악하고 프로세스를 개선할 수 있습니다. 중요한 이유 승인 하위 프로세스의 재작업을 측정해 최초 처리 성공률을 파악하고 승인 거부 사유를 찾는 데 도움이 됩니다. 확보 방법 고유한 각 InvoiceNumber에서 '송장 승인 요청' 활동이 발생한 횟수를 세어 계산합니다. 예시 123 | |||
| 자동화 여부 IsAutomated | 활동을 자동화된 시스템 사용자가 수행했는지 나타내는 플래그입니다. | ||
| 설명 활동과 연결된 사용자가 'WF-BATCH' 또는 'SAP_SYSTEM'과 같은 시스템 계정이나 배치 계정으로 확인되면 이 불리언 속성은 true입니다. 수동 단계와 자동화된 단계를 구분하는 데 도움이 됩니다. 이 속성은 '송장 자동화율' KPI 계산에 필요합니다. 프로세스의 어느 부분이 자동화되었는지 분석하면 자동화 활동의 성과를 측정하고 수작업을 줄여 효율성을 높일 추가 기회를 찾을 수 있습니다. 중요한 이유 수동 활동과 시스템이 수행한 활동을 구분합니다. 자동화율 측정과 추가 자동화 기회 파악에 기본이 됩니다. 확보 방법 사용자 이름 속성에서 도출합니다. 특정 사용자 ID를 '자동화됨'으로 분류하는 매핑이나 규칙을 설정합니다. 예시 truefalse | |||
| 재작업 여부 IsRework | 승인 거부나 지급 차단 해제 등 송장에 재작업 활동이 있었는지 나타내는 플래그입니다. | ||
| 설명 이 속성은 한 번 이상 재작업을 거친 송장을 표시합니다. 재작업은 '송장 거부' 후 '송장 승인', 또는 '지급 차단 설정' 후 '지급 차단 해제'와 같은 특정 활동 순서로 식별합니다. 이 속성을 사용하면 '송장 재작업률' KPI를 간편하게 계산할 수 있습니다. 분석가는 재작업이 발생한 케이스를 쉽게 추려 조사하고 비효율과 반복적인 수작업의 근본 원인을 파악할 수 있습니다. 중요한 이유 작업을 반복해야 하는 비효율적인 프로세스 흐름을 식별해 낭비를 측정하고 프로세스 예외의 근본 원인을 찾는 데 도움이 됩니다. 확보 방법 이벤트 로그의 활동 순서를 바탕으로 계산합니다. 예를 들어 송장 처리 기록에 '송장 거부'가 있으면 이 플래그를 true로 설정합니다. 예시 truefalse | |||
| 정시 지급 여부 IsPaidOnTime | 송장이 지급 기한 당일 또는 그 전에 지급된 경우 true로 표시하는 플래그입니다. | ||
| 설명 이 불리언 속성은 실제 지급일('지급 실행' 활동의 타임스탬프)과 '지급 기한'을 비교한 결과입니다. 각 송장의 지급 상태를 명확한 두 가지 값으로 나타냅니다. '정시 지급률' KPI를 계산하는 기본 속성입니다. 이를 기준으로 필터링하고 분석해 지연 지급이 잦은 공급업체, 회사 코드, 송장 금액 등 지연과 관련된 특성을 파악할 수 있습니다. 중요한 이유 지급 조건 준수 여부를 직접 측정합니다. 공급업체 관계 관리와 재무 운영에 중요한 KPI입니다. 확보 방법 '지급 실행' 활동의 EventTime과 PaymentDueDate 속성을 비교해 계산합니다. (지급일 <= PaymentDueDate). 예시 truefalse | |||
| 지급 조건 PaymentTerms | 지급 기한과 할인 기간 등 공급업체와 합의한 지급 조건을 정의하는 코드입니다. | ||
| 설명 지급 조건은 조기 지급 할인 여부를 포함해 송장 지급 규칙을 정의합니다. 예를 들어 'Z030'은 '30일 이내 순액 지급'을 의미할 수 있습니다. 이 속성은 재무 계획과 운전자본 최적화에 필요합니다. process mining에서는 '지급 기한'을 계산하고 조기 지급 할인 적용 여부를 판단하는 데 사용하며, '조기 지급 할인 적용률' KPI를 직접 뒷받침합니다. 중요한 이유 지급 기한과 할인 규칙을 정의하며, 정시 지급 KPI와 운전자본 관리에 직접 영향을 줍니다. 확보 방법 BSEG 테이블의 공급업체 개별 항목에 있는 ZTERM 필드(지급 조건 키)에서 확인할 수 있습니다. 예시 0001Z030NT60 | |||
| 추출 타임스탬프 ExtractionTimestamp | 소스 시스템에서 데이터를 추출한 날짜와 시간입니다. | ||
| 설명 이 속성은 데이터 추출 시점의 타임스탬프를 기록합니다. process mining 도구에서 분석하는 데이터의 최신성을 나타냅니다. 분석 결과가 얼마나 최신인지 확인하는 데 사용합니다. 운영 모니터링 대시보드에서 최신 정보를 바탕으로 의사결정하고 데이터 갱신 주기를 효과적으로 관리하는 데 중요합니다. 중요한 이유 데이터의 최신성을 나타내므로, 분석과 보고에 이용 가능한 최신 정보가 반영되었는지 확인할 수 있습니다. 확보 방법 SAP 필드가 아닙니다. 데이터를 가져올 때 데이터 추출 도구나 ETL 프로세스에서 생성해 추가합니다. 예시 2023-10-27T02:00:00Z2023-10-28T02:00:00Z2023-10-29T02:00:00Z | |||
| 취소 사유 ReversalReason | 송장 문서를 취소한 이유를 나타내는 코드입니다. | ||
| 설명 송장이 잘못 전기되면 취소하는 경우가 많습니다. 취소 사유 코드는 '잘못된 전기일' 또는 '데이터 입력 오류'처럼 취소한 이유를 설명합니다. 취소 사유를 분석하면 송장 전기 프로세스의 오류 패턴을 파악할 수 있습니다. 이 정보를 활용해 교육을 개선하고 시스템 통제를 강화하거나 재무 재작업과 관리 부담을 유발하는 반복 문제를 해결할 수 있습니다. 중요한 이유 송장을 취소한 이유를 설명해 전기 프로세스에서 오류와 재작업이 발생하는 원인을 직접 파악할 수 있습니다. 확보 방법 원본 문서의 헤더에 있는 BKPF 테이블의 STGRD 필드(취소 사유)에서 확인할 수 있습니다. 예시 010205 | |||
구매부터 지급까지, 송장 처리 활동
| 활동 | 설명 | ||
|---|---|---|---|
| 송장 문서 생성 | SAP에서 송장 문서가 생성될 때 기록되는 첫 번째 이벤트입니다. 사용자가 새 송장 문서를 저장할 때 포착할 수 있으며, 문서가 보류 또는 전기 전 상태일 수도 있습니다. | ||
| 중요한 이유 이 활동은 송장 처리 수명 주기의 시작을 나타냅니다. 전체 처리 소요 시간을 측정하려면 이 이벤트부터 다른 이벤트까지 걸리는 시간을 분석해야 합니다. 확보 방법 이 이벤트는 일반적으로 문서 헤더 테이블의 생성 날짜와 시간(CPUDT, CPUTM)에서 가져옵니다. 물류 송장에는 보통 BKPF 또는 RBKP를 사용합니다. FB60, MIRO, MIR7과 같은 트랜잭션 코드(BKPF-TCODE)로 생성 방식을 확인할 수 있습니다. 기록 송장 문서의 생성 시각은 BKPF-CPUDT와 BKPF-CPUTM을 사용합니다. 이벤트 유형 explicit | |||
| 송장 승인 | 지정된 권한자가 송장을 승인했음을 나타냅니다. 승인 워크플로가 성공적으로 완료되거나 릴리스 표시가 설정될 때 포착합니다. | ||
| 중요한 이유 이 중요한 이정표를 지나면 송장을 지급할 수 있습니다. 승인 지연은 흔히 발생하는 병목이며, 이 활동을 추적하면 승인이 느린 담당자나 프로세스 단계를 찾을 수 있습니다. 확보 방법 SAP 워크플로의 최종 릴리스 단계나 송장 또는 구매 문서 관련 테이블의 릴리스 상태 필드 변경을 바탕으로 추정할 수 있습니다. 기록 워크플로 완료 이벤트나 문서의 릴리스 상태 필드 변경을 기준으로 추정합니다. 이벤트 유형 inferred | |||
| 송장 전기 | 보류 또는 승인된 송장을 총계정원장에 정식으로 전기하는 주요 재무 이벤트입니다. 이 작업을 통해 공급업체에 대한 부채가 인식됩니다. | ||
| 중요한 이유 전기는 데이터 입력과 승인 단계에서 재무 결산 단계로 넘어가는 주요 이정표입니다. 송장 생성부터 전기까지 걸리는 시간은 내부 처리 효율을 보여주는 주요 지표입니다. 확보 방법 문서 헤더의 전기일(BKPF-BUDAT)로 이 이벤트를 식별합니다. 먼저 임시 보관된 문서는 전기 상태로 전환된 시점을 이벤트 타임스탬프로 사용합니다. 기록 전기일(BKPF-BUDAT)을 이벤트 타임스탬프로 사용합니다. 이벤트 유형 explicit | |||
| 송장 취소 | 이미 전기된 송장 문서를 취소하는 활동입니다. 잘못된 송장은 이 단계에서 종료되며, 이후 올바른 내용으로 다시 입력하는 경우가 많습니다. | ||
| 중요한 이유 취소는 프로세스 초기에 발견하지 못한 중대한 오류가 있었음을 나타냅니다. 취소 빈도와 근본 원인을 추적하면 프로세스를 개선하고 재무 데이터의 부정확성을 줄일 수 있습니다. 확보 방법 취소 문서가 생성되면 취소를 식별할 수 있습니다. 원본 문서 헤더(BKPF)에는 취소 문서 번호(BKPF-STBLG)가 기록되며, 취소 문서에도 원본 문서 번호가 기록됩니다. 이벤트 시간은 취소 문서의 전기일입니다. 기록 BKPF-STBLG 필드에 값이 있는 문서를 식별하고 취소 문서의 전기일을 사용합니다. 이벤트 유형 explicit | |||
| 지급 실행 | 표준 프로세스의 마지막 활동으로, 지급이 이루어지고 송장이 반제됩니다. 이 시점에 공급업체로 대금이 지급됩니다. | ||
| 중요한 이유 이 단계는 P2P 송장 처리 주기가 끝나는 시점입니다. 전체 처리 시간을 계산하고 지급 기한 준수 실적을 측정하는 데 필요합니다. 확보 방법 공급업체 개별 항목의 반제 문서 정보에서 이 이벤트를 확인합니다. 반제일(BSEG-AUGDT)과 반제 문서(BSEG-AUGBL)는 지급이 완료되었음을 나타냅니다. 기록 반제된 공급업체 개별 항목의 반제일(BSEG-AUGDT)을 사용합니다. 이벤트 유형 explicit | |||
| 송장 데이터 수정 | 송장 문서를 처음 생성한 뒤 변경한 활동을 나타냅니다. 반려 후 재작업하거나 오류를 수정할 때 흔히 발생합니다. | ||
| 중요한 이유 잦은 수정은 재작업이 많거나 입력 단계에서 데이터 품질 문제가 발생했음을 나타냅니다. 변경 사항을 추적하면 수정에 드는 노력을 측정하고 자주 발생하는 오류를 찾을 수 있습니다. 확보 방법 주요 필드의 변경 사항은 SAP의 변경 문서 테이블인 CDHDR(헤더)와 CDPOS(항목)에 기록됩니다. 관련 송장 객체의 변경 사항을 필터링해 이벤트를 생성할 수 있습니다. 기록 송장 객체에 대한 변경 이벤트를 CDHDR 및 CDPOS 테이블에서 추출합니다. 이벤트 유형 explicit | |||
| 송장 반려 | 승인 과정에서 송장이 반려된 상태를 나타냅니다. 반려되면 수정 후 다시 제출해야 하므로 재작업이 발생합니다. | ||
| 중요한 이유 송장 반려는 프로세스 비효율과 데이터 품질 문제를 보여주는 주요 지표입니다. 반려 빈도와 사유를 분석하면 개선과 교육이 필요한 부분을 찾을 수 있습니다. 확보 방법 SAP 워크플로의 '반려'와 같은 특정 상태 업데이트나 현재 승인 워크플로를 취소하고 처리 담당자에게 돌려보내는 이벤트를 바탕으로 추정합니다. 기록 반려를 나타내는 워크플로 상태 변경을 기준으로 추정합니다. 이벤트 유형 inferred | |||
| 송장 보류 | 시스템에 입력했지만 아직 총계정원장에 전기되지 않은 송장을 나타냅니다. 미완성 송장을 저장하거나 전기 전에 검토할 때 보류 기능을 사용합니다. | ||
| 중요한 이유 보류는 프로세스가 의도적으로 중단된 상태를 나타냅니다. 보류된 송장의 건수와 보류 기간을 추적하면 정식 전기 및 승인 절차가 시작되기 전에 지연이 발생하는 이유를 파악할 수 있습니다. 확보 방법 MIR7, FV60과 같은 보류 트랜잭션으로 생성된 문서를 확인하거나 BKPF 테이블의 특정 상태 필드 또는 VBKPF와 같은 전용 보류 문서 테이블을 조회할 수 있습니다. 기록 보류 트랜잭션으로 생성된 문서를 찾거나 문서의 보류 상태를 확인합니다. 이벤트 유형 explicit | |||
| 승인 요청된 송장 | 이 활동은 송장에 대한 정식 승인 워크플로가 시작되었음을 나타냅니다. 송장 상태가 '승인 대기'로 변경되거나 워크플로 항목이 생성된 시점으로 추정하는 경우가 많습니다. | ||
| 중요한 이유 승인 주기 시간을 측정하는 시작점입니다. 승인이 언제 시작되는지 파악해야 승인 워크플로 자체의 병목을 찾을 수 있습니다. 확보 방법 일반적으로 송장 객체(예: BUS2081)와 연결된 SAP Business Workflow의 시작(SWW_WI2OBJ 테이블)이나 문서 헤더의 사용자 정의 상태 필드 변경을 바탕으로 추정합니다. 기록 송장 문서와 관련된 워크플로 항목이 생성된 시점을 기준으로 추정합니다. 이벤트 유형 inferred | |||
| 지급 보류 설정 | 송장 대금을 지급하지 못하도록 의도적으로 보류를 설정하는 활동입니다. 가격이나 수량 불일치, 미결 대변 메모 등이 원인일 수 있습니다. | ||
| 중요한 이유 지급 보류는 연체와 공급업체 분쟁의 주요 원인입니다. 정시 지급률을 높이려면 보류의 빈도와 기간, 사유를 분석해야 합니다. 확보 방법 송장 개별 항목의 지급 보류 키 필드(BSEG-ZLSPR) 변경을 추적해 이 이벤트를 포착합니다. CDHDR 및 CDPOS의 변경 로그에서 보류 설정 시각과 사용자를 확인할 수 있습니다. 기록 변경 문서(CDHDR/CDPOS)를 통해 BSEG-ZLSPR 필드에 값이 입력된 시점을 확인합니다. 이벤트 유형 explicit | |||
| 지급 보류 해제 | 이전에 설정한 지급 보류가 해제되어 문제가 해결된 상태를 나타냅니다. 이후 해당 송장을 다시 지급할 수 있습니다. | ||
| 중요한 이유 지급 보류 설정부터 해제까지 걸리는 시간은 프로세스 예외를 해결하는 데 걸린 시간입니다. 이 시간을 줄이면 효율과 공급업체와의 관계를 개선할 수 있습니다. 확보 방법 지급 보류 키 필드(BSEG-ZLSPR)의 값이 지워질 때 이 이벤트를 포착합니다. 변경 사항은 CDHDR 및 CDPOS 테이블에 기록되어 해제 시각을 확인할 수 있습니다. 기록 변경 문서(CDHDR/CDPOS)를 통해 BSEG-ZLSPR 필드의 값이 지워진 시점을 확인합니다. 이벤트 유형 explicit | |||
| 지급 제안 생성 | 지급 실행의 일부로 송장을 선택해 지급 제안에 포함합니다. 자동 지급 프로세스의 첫 단계입니다. | ||
| 중요한 이유 이 활동은 지급 의사가 있음을 나타냅니다. 이 단계부터 실제 지급 실행까지 지연이 발생하면 지급 실행 프로세스, 승인 또는 은행과의 통신에 문제가 있을 수 있습니다. 확보 방법 지급 실행 테이블, 특히 지급 제안에 포함된 항목이 저장되는 REGUP에서 확인할 수 있습니다. 해당 REGUH 테이블의 실행일이 타임스탬프를 제공합니다. 기록 지급 제안 실행 후 송장이 REGUP 테이블에 나타나는 시점을 식별합니다. 이벤트 유형 explicit | |||
| 지연 지급 실행 | 송장의 지급이 계산된 지급 기한을 넘긴 경우 발생하는 계산 이벤트입니다. 두 날짜 필드를 비교해 판별합니다. | ||
| 중요한 이유 이 활동은 정시 지급 KPI를 직접 뒷받침합니다. 지연 지급이 잦은 공급업체나 사업부를 파악하는 데 도움이 되며, 잦은 지연은 공급업체와의 관계를 악화시키고 벌금으로 이어질 수 있습니다. 확보 방법 반제일(BSEG-AUGDT)과 순지급기한을 비교해 계산합니다. 지급 기한은 기준일(BSEG-ZFBDT)과 지급 조건(BSEG-ZTERM)을 바탕으로 계산합니다. 기록 BSEG-AUGDT > (BSEG-ZFBDT + 지급 조건 일수)를 비교해 판별합니다. 이벤트 유형 calculated | |||
데이터 추출 가이드
단계
- 사전 요건 및 권한: 추출을 실행하는 사용자에게 필요한 Core Data Services (CDS) 뷰에 접근할 수 있는 SAP S/4HANA 권한이 있는지 확인합니다. 주요 뷰에는
I_InvoiceDocument,I_OperationalAcctgDocItem,I_ChangeDocument,I_ChangeDocumentItem,I_PaymentProposalItem이 포함됩니다. 또한 OData 서비스나 직접 SQL 연결 등 선택한 인터페이스를 통해 쿼리를 실행할 권한이 필요합니다. - 연결 방식 확인: SQL 쿼리를 실행하기 위해 SAP S/4HANA 시스템에 연결하는 방법을 정합니다. 일반적인 방법으로는 SAP Data Services, SAP Data Intelligence, SAP 커넥터가 포함된 타사 ETL 도구, 조직의 보안 정책이 허용하는 경우 SAP HANA 데이터베이스에 직접 SQL로 연결하는 방법이 있습니다.
- 추출 매개변수 설정: 쿼리를 실행하기 전에 주요 매개변수를 정합니다. 예를 들어
CreationDate가'YYYY-MM-DD'부터'YYYY-MM-DD'사이인 날짜 범위를 지정합니다. 추출 범위를 제한할CompanyCode값도 선택합니다. - SQL 쿼리 맞춤 설정: 제공된 SQL 쿼리를 선택한 SQL 클라이언트나 데이터 추출 도구에 복사합니다.
'{StartDate}','{EndDate}',('{CompanyCode1}', '{CompanyCode2}')와 같은 자리표시자를 확인하고 앞 단계에서 정한 실제 값으로 바꿉니다. SAP 설정에 따라 워크플로 상태 필드 이름을 조정해야 할 수도 있습니다. - 쿼리 실행: 전체 SQL 쿼리를 SAP S/4HANA 데이터베이스 또는 적절한 서비스 계층에서 실행합니다. 쿼리는 여러 데이터를 포함하므로 데이터 양과 날짜 범위에 따라 실행 시간이 길어질 수 있습니다. 실행 중 오류나 시간 초과가 발생하는지 확인합니다.
- 초기 결과 검토: 쿼리가 완료되면 결과를 간단히 검토합니다.
InvoiceNumber,ActivityName,EventTime열에 값이 있는지 확인합니다.ActivityName열에 'Invoice Document Created'만 있는 것이 아니라 여러 활동이 표시되는지도 확인합니다. - 데이터 변환 확인: 쿼리는 정돈된 이벤트 로그 형식으로 결과를 생성하도록 구성되어 있습니다.
EventTime열이YYYY-MM-DDTHH:MM:SS와 같이 일관된 타임스탬프 형식인지 확인합니다. 필요한 경우 제공된 쿼리가 날짜와 시간 필드를 하나의 타임스탬프로 결합합니다. - 데이터 내보내기: 도구에서 최종 결과를 CSV (쉼표로 구분된 값) 파일로 내보냅니다. 이 형식은 ProcessMind를 비롯한 process mining 도구와 폭넓게 호환됩니다.
- 업로드 준비: 업로드 전에 CSV 파일이 UTF-8 인코딩인지 확인해 문자 깨짐을 방지합니다. 파일의 열 머리글이 필수 속성인
InvoiceNumber,ActivityName,EventTime,UserName,CompanyCode등과 정확히 일치하는지 확인합니다. - ProcessMind에 업로드: 준비한 CSV 파일을 process mining 프로젝트에 업로드합니다. 도구의 데이터 모델 설정에서 파일의 열을 해당 케이스 ID, 활동 이름, 타임스탬프 필드에 매핑합니다.
구성
- 사용된 CDS View: 주요 데이터 소스는 표준 SAP CDS 뷰입니다. 주요 뷰로는 헤더 데이터용
I_InvoiceDocument, 재무 전기 및 반제 세부 정보용I_OperationalAcctgDocItem, 송장 속성의 지급 보류 및 워크플로 상태 등 변경 이력을 추적하는I_ChangeDocument와I_ChangeDocumentItem이 있습니다. - 날짜 범위 필터링: 성능을 관리하려면 특정 날짜 범위로 데이터를 필터링해야 합니다. 제공된 쿼리는
I_InvoiceDocument뷰의CreationDate에 자리표시자를 사용합니다. 처음에는 3~6개월의 데이터를 추출하는 것이 좋습니다. - 회사 코드 필터: 추출 데이터의 관련성과 관리 편의성을 확보하려면 하나 이상의
CompanyCode로 항상 필터링합니다. 쿼리에는 이를 위한WHERE inv.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')자리표시자가 포함되어 있습니다. - 문서 유형 필터:
InvoiceDocumentType으로 필터링해 추출 범위를 더 좁힐 수 있습니다. 예를 들어 표준 공급업체 송장 (RE)은 포함하고 대변 메모는 제외할 수 있습니다. 이 조건은 초기 CTE의WHERE절에 추가할 수 있습니다. - 사전 요건: 쿼리를 실행하는 사용자에게 지정된 회사 코드의 재무 및 구매 문서를 조회할 적절한 권한이 필요합니다. SQL 클라이언트를 통한 기본 HANA 데이터베이스 접근은 일반적으로 제공되지 않으며 별도 권한이 필요합니다.
- 성능 고려 사항: 변경 문서 테이블 (
I_ChangeDocument,I_ChangeDocumentItem)에서 데이터를 추출하면 성능 부담이 클 수 있습니다. 실행 시간이 길어지지 않도록 날짜, 회사 코드, 객체 클래스 (INCOMINGINVOICE)를 엄격하게 필터링해야 합니다.
샘플 쿼리 sql
WITH InvoiceBase AS (
SELECT
inv.InvoiceDocument,
inv.FiscalYear,
inv.CompanyCode,
inv.Supplier AS VendorNumber,
inv.DocumentType,
inv.GrossInvoiceAmountInCoCoCrcy AS AmountInCompanyCodeCurrency,
inv.NetDueDate AS PaymentDueDate,
inv.PurchasingDocument,
inv.CreationDateTime,
inv.CreatedByUser,
accdoc.AccountingDocument,
accdoc.ClearingDate,
accdoc.ClearingJournalEntry,
accdoc.PaymentBlockReason,
accdoc.IsReversed
FROM I_InvoiceDocument AS inv
LEFT JOIN I_OperationalAcctgDocItem AS accdoc
ON inv.AccountingDocument = accdoc.AccountingDocument
AND inv.FiscalYear = accdoc.FiscalYear
AND inv.CompanyCode = accdoc.CompanyCode
WHERE
inv.CreationDate BETWEEN '{StartDate}' AND '{EndDate}'
AND inv.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')
)
-- 1. Invoice Document Created
SELECT
InvoiceDocument AS "InvoiceNumber",
'Invoice Document Created' AS "ActivityName",
CreationDateTime AS "EventTime",
CreatedByUser AS "UserName",
CompanyCode AS "CompanyCode",
VendorNumber AS "VendorNumber",
AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
PaymentDueDate AS "PaymentDueDate",
DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase
UNION ALL
-- 2. Invoice Parked
SELECT
i.InvoiceDocument AS "InvoiceNumber",
'Invoice Parked' AS "ActivityName",
i.CreationDateTime AS "EventTime",
i.CreatedByUser AS "UserName",
i.CompanyCode AS "CompanyCode",
i.Supplier AS "VendorNumber",
i.GrossInvoiceAmountInCoCoCrcy AS "AmountInCompanyCodeCurrency",
i.NetDueDate AS "PaymentDueDate",
i.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
i.PurchasingDocument AS "PurchasingDocument"
FROM I_InvoiceDocument AS i
WHERE
i.InvoiceDocumentIsParked = 'X'
AND i.CreationDate BETWEEN '{StartDate}' AND '{EndDate}'
AND i.CompanyCode IN ('{CompanyCode1}', '{CompanyCode2}')
UNION ALL
-- 3, 4, 5. Workflow activities (Sent for Approval, Approved, Rejected) from Change Docs
SELECT
cdpos.ObjectValue AS "InvoiceNumber",
CASE
WHEN cdpos.ValueNew = '[StatusSentForApproval]' THEN 'Invoice Sent For Approval'
WHEN cdpos.ValueNew = '[StatusApproved]' THEN 'Invoice Approved'
WHEN cdpos.ValueNew = '[StatusRejected]' THEN 'Invoice Rejected'
END AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.InvoiceDocument
WHERE
cdhdr.ObjectClassName = 'INCOMINGINVOICE'
AND cdpos.FieldName = '[WorkflowStatusFieldName]'
AND cdpos.ValueNew IN ('[StatusSentForApproval]', '[StatusApproved]', '[StatusRejected]')
UNION ALL
-- 6. Invoice Data Updated
SELECT
cdpos.ObjectValue AS "InvoiceNumber",
'Invoice Data Updated' AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.InvoiceDocument
WHERE
cdhdr.ObjectClassName = 'INCOMINGINVOICE'
AND cdpos.FieldName IN ('GrossInvoiceAmount', 'DocumentDate', 'PaymentTerms')
AND cdhdr.ChangeDate BETWEEN '{StartDate}' AND '{EndDate}'
UNION ALL
-- 7 & 8. Payment Block Set/Removed
SELECT
inv.InvoiceDocument AS "InvoiceNumber",
CASE
WHEN cdpos.ValueNew <> '' AND cdpos.ValueOld = '' THEN 'Payment Block Set'
WHEN cdpos.ValueNew = '' AND cdpos.ValueOld <> '' THEN 'Payment Block Removed'
END AS "ActivityName",
CAST(cdhdr.ChangeDate AS TIMESTAMP) + CAST(cdhdr.ChangeTime AS TIME) AS "EventTime",
cdhdr.UserName AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
cdpos.ValueNew AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM I_ChangeDocument AS cdhdr
JOIN I_ChangeDocumentItem AS cdpos ON cdhdr.ChangeDocument = cdpos.ChangeDocument
JOIN InvoiceBase AS inv ON cdpos.ObjectValue = inv.AccountingDocument
WHERE
cdhdr.ObjectClassName = 'BELEG'
AND cdpos.TableName = 'BSEG'
AND cdpos.FieldName = 'ZLSPR'
AND ( (cdpos.ValueNew <> '' AND cdpos.ValueOld = '') OR (cdpos.ValueNew = '' AND cdpos.ValueOld <> '') )
UNION ALL
-- 9. Invoice Posted
SELECT
inv.InvoiceDocument AS "InvoiceNumber",
'Invoice Posted' AS "ActivityName",
CAST(accdoc.PostingDate AS TIMESTAMP) AS "EventTime",
accdoc.CreatedByUser AS "UserName",
inv.CompanyCode AS "CompanyCode",
inv.VendorNumber AS "VendorNumber",
inv.AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
inv.PaymentDueDate AS "PaymentDueDate",
inv.DocumentType AS "DocumentType",
accdoc.PaymentBlockReason AS "PaymentBlockReason",
inv.PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase AS inv
JOIN I_OperationalAcctgDocItem AS accdoc ON inv.AccountingDocument = accdoc.AccountingDocument
WHERE inv.AccountingDocument IS NOT NULL AND inv.IsReversed = FALSE
UNION ALL
-- 10. Payment Proposal Created
SELECT
item.InvoiceReference AS "InvoiceNumber",
'Payment Proposal Created' AS "ActivityName",
CAST(prun.PaymentRunDate AS TIMESTAMP) AS "EventTime",
prun.CreatedByUser AS "UserName",
item.CompanyCode AS "CompanyCode",
item.Supplier AS "VendorNumber",
item.AmountInTransactionCurrency AS "AmountInCompanyCodeCurrency",
item.NetDueDate AS "PaymentDueDate",
item.AccountingDocumentType AS "DocumentType",
item.PaymentBlockReason AS "PaymentBlockReason",
item.PurchasingDocument AS "PurchasingDocument"
FROM I_PaymentProposalItem as item
JOIN I_PaymentRun as prun ON item.PaymentRunName = prun.PaymentRunName
JOIN InvoiceBase AS inv ON item.InvoiceReference = inv.InvoiceDocument
UNION ALL
-- 11 & 12. Payment Executed / Late Payment Executed
SELECT
InvoiceDocument AS "InvoiceNumber",
CASE
WHEN ClearingDate > PaymentDueDate THEN 'Late Payment Executed'
ELSE 'Payment Executed'
END AS "ActivityName",
CAST(ClearingDate AS TIMESTAMP) AS "EventTime",
CAST(NULL AS VARCHAR(12)) AS "UserName", -- User for clearing is not always straightforward
CompanyCode AS "CompanyCode",
VendorNumber AS "VendorNumber",
AmountInCompanyCodeCurrency AS "AmountInCompanyCodeCurrency",
PaymentDueDate AS "PaymentDueDate",
DocumentType AS "DocumentType",
'' AS "PaymentBlockReason",
PurchasingDocument AS "PurchasingDocument"
FROM InvoiceBase
WHERE ClearingDate IS NOT NULL AND IsReversed = FALSE
UNION ALL
-- 13. Invoice Reversed
SELECT
rev.OriginalInvoiceDocument AS "InvoiceNumber",
'Invoice Reversed' AS "ActivityName",
rev.CreationDateTime AS "EventTime",
rev.CreatedByUser AS "UserName",
rev.CompanyCode AS "CompanyCode",
rev.Supplier AS "VendorNumber",
rev.GrossInvoiceAmountInCoCoCrcy AS "AmountInCompanyCodeCurrency",
CAST(NULL AS DATE) AS "PaymentDueDate",
rev.DocumentType AS "DocumentType",
CAST(NULL AS VARCHAR(1)) AS "PaymentBlockReason",
rev.PurchasingDocument AS "PurchasingDocument"
FROM I_InvoiceDocument AS rev
WHERE rev.OriginalInvoiceDocument IN (SELECT InvoiceDocument FROM InvoiceBase) AND rev.IsReversal = 'X' 단계
- SAP HANA 테넌트 또는 데이터베이스 스키마에 대한 직접 읽기 권한이 승인되었는지 확인하고, 필요한 SAP 테이블과 승인된 변경 이력 또는 워크플로 테이블에 접근할 수 있는 읽기 전용 데이터베이스 사용자를 발급받습니다. SAP HANA Database Explorer, SAP HANA Studio 또는 승인된 SQL 클라이언트를 사용합니다. 운영 시스템에 쓰기 권한을 사용하지 마세요.
- 대상 S/4HANA 시스템에서 실제 테이블 및 열 이름을 확인합니다. ACDOCA, BKPF, RBKP는 일반적인 시작점이지만 워크플로, 임시 저장, 지급 제안, 지급 실행, 변경 이력, 지급 보류 이력에는 릴리스나 고객별 객체가 사용될 수 있습니다. 쿼리의 대괄호로 표시된 자리표시자를 시스템 카탈로그에서 확인한 객체와 관련 업무 의미에 맞게 바꿉니다.
- [Start timestamp]와 [End timestamp]를 사용해 추출 기간을 설정합니다. 일반적으로 3~6개월의 문서 및 이벤트 기간을 추출하되, 지급 기한이나 연체 지급이 송장 생성 기간 이후에 발생할 수 있으면 기간을 늘립니다.
- 설정된 송장 키를 사용해 송장 케이스를 식별합니다. 쿼리는
InvoiceNumber를 케이스 식별자로 사용하며, 중복을 방지하기 위해 필요한 경우 회사 코드와 회계연도를 내부적으로 결합합니다. 업무 정의에 따라 ProcessMind 케이스 식별자에 회계연도나 회사 코드 키를 추가해야 하는지 확인합니다. - 전기된 송장 데이터는 RBKP, BKPF, ACDOCA에서 매핑합니다. RBKP는 송장 헤더 정보, BKPF는 회계 문서의 타임스탬프와 사용자, ACDOCA는 사용 가능한 경우 공급업체, 금액, 구매 문서, 반제 및 지급 관련 회계 정보를 제공합니다. 모든 전기 시나리오에서 모든 필드가 채워진다고 가정하지 마세요.
- 확인된 시스템별 소스에서 임시 저장, 승인, 반려, 업데이트, 지급 보류, 역분개, 지급 제안 및 지급 실행 이벤트를 매핑합니다. 이벤트 타임스탬프, 송장 참조, 사용자, 상태, 이전 값과 새 값을 제공하는 승인된 뷰나 테이블로 자리표시자 소스를 바꿉니다. ProcessMind는 이벤트를 추론하지 않으므로 각 활동을 명시적인 이벤트 행으로 출력해야 합니다.
- 비운영 또는 읽기 전용 세션에서 전체 SQL 쿼리를 실행합니다. 실행 계획을 검토하고 필요한 경우 회사 코드, 문서 유형, 회계연도, 이벤트 타임스탬프로 쿼리 범위를 제한합니다. 대용량 분개 테이블과 이력 테이블을 제한 없이 조인하지 마세요.
- 아래 설명된 검사를 통해 결과를 검증합니다. 필수 열이 모두 있는지, 모든 이벤트에
EventTime이 입력되었는지, 모든 케이스에InvoiceNumber가 입력되었는지, 해당 소스 데이터가 있는 경우 13개 활동 이름이 모두 포함되는지 확인합니다. - 결과를 ProcessMind에서 지원하는 구분 파일 형식으로 내보냅니다. UTF-8 CSV를 권장하며, 이벤트당 한 행으로 구성하고
InvoiceNumber,ActivityName,EventTime,UserName,CompanyCode,VendorNumber,AmountInCompanyCodeCurrency,PaymentDueDate,DocumentType,PaymentBlockReason,PurchasingDocument열을 포함합니다. 타임스탬프의 시간대를 일관되게 유지하고 식별자의 앞자리 0을 보존합니다. - 이벤트 로그를 ProcessMind에 업로드하고
InvoiceNumber를 케이스 식별자,ActivityName을 활동 열,EventTime을 타임스탬프 열로 설정합니다. ProcessMind 설정에서 추가 케이스 키를 지원하는 경우 추출 시 적용한 것과 동일한 복합 키 정책을 사용합니다.
구성
- 날짜 범위: 초기 추출에는 최근 3~6개월을 사용합니다. 승인, 지급, 반제, 역분개 또는 연체 지급 이벤트가 송장 생성 기간 이후에 발생할 수 있으면 과거 데이터를 추가로 포함합니다.
- 회사 범위: [회사 코드 필터]를 적용하고 선택한 회사 코드에 추출 권한이 있는지 확인합니다.
- 문서 범위: [문서 유형 필터]를 적용하고 대상 프로세스의 공급업체 송장, 대변 메모, 임시 저장 송장, 역분개를 나타내는 문서 유형을 포함합니다.
- 케이스 식별자: 프로세스 정의에 따라
InvoiceNumber를 사용합니다. 송장 번호가 전역적으로 고유하지 않으면 소스 결과에 회사 코드와 회계연도를 유지하거나 ProcessMind 모델에 따라 복합 케이스 키를 설정합니다. - 이벤트 소스: 워크플로 상태 변경, 승인 결정, 임시 저장, 변경 이력, 지급 보류, 지급 제안, 지급 실행의 실제 소스를 확인합니다. 소스는 S/4HANA 릴리스, 활성화된 범위, 워크플로 설계, 고객 확장에 따라 달라집니다.
- 타임스탬프 정책: 추출 시각이 아닌 업무 이벤트 시각을 선택합니다. 시간대를 문서화하고 업로드 전에 모든 이벤트 타임스탬프를 동일한 기준으로 변환합니다.
- 금액 정책: 회사 코드 통화 금액을 사용하고 선택한 소스에서 차변과 대변의 부호가 일관되게 저장되는지 확인합니다. 송장 케이스에 적용할 집계 규칙을 검증하지 않았다면 분개 항목을 합산하지 마세요.
- 지급 정책: 지급 실행의 의미가 반제, 지급 문서 전기, 은행 지급 실행 또는 다른 업무 이정표 중 무엇인지 정의합니다. 합의된 프로세스 정의에 맞는 소스를 사용합니다.
- 연체 지급: 지급 실행이
PaymentDueDate이후에 발생한 경우에만 연체 지급 실행 이벤트를 출력합니다. 쿼리는 이 이벤트를 명시적으로 계산하며 ProcessMind의 추론에 의존하지 않습니다. - 성능: 날짜, 회사 코드, 문서 유형, 관련 회계연도로 소스 조회 범위를 제한합니다. 필요한 열만 선택하고 쿼리 계획을 검토합니다. 소스 이력 데이터가 많으면 승인된 중간 뷰를 구체화합니다.
- 사전 요건: SAP HANA 직접 연결, 선택한 모든 객체에 대한 읽기 권한, 메타데이터 조회 권한, 관련 매입채무, 총계정원장, 구매, 워크플로, 지급 데이터에 대한 접근 권한이 필요합니다. 필요한 SAP 라이선스, 데이터베이스 접근 정책, 데이터 보호 승인이 마련되었는지 확인합니다.
- 보안: 읽기 전용 기술 사용자를 사용하고 공급업체 및 지급 데이터를 보호하며 조직의 전송, 감사, 마스킹, 자격 증명 관리 정책을 준수합니다.
샘플 쿼리 sql
WITH
invoice_base AS (
SELECT
r.INV_DOC_NO AS InvoiceNumber,
r.COMPANY_CODE AS CompanyCode,
r.FISCAL_YEAR AS FiscalYear,
r.DOCUMENT_TYPE AS DocumentType,
r.VENDOR_NO AS VendorNumber,
r.GROSS_AMOUNT_CC AS AmountInCompanyCodeCurrency,
r.PAYMENT_DUE_DATE AS PaymentDueDate,
r.PURCHASING_DOCUMENT AS PurchasingDocument,
r.CREATED_AT AS InvoiceCreatedAt,
r.CREATED_BY AS InvoiceCreatedBy
FROM [Your RBKP invoice header source] r
WHERE r.CREATED_AT >= '[Start timestamp]'
AND r.CREATED_AT < '[End timestamp]'
AND r.COMPANY_CODE IN ([Company code filter])
AND r.DOCUMENT_TYPE IN ([Document type filter])
),
posted_accounting AS (
SELECT
b.INV_DOC_NO AS InvoiceNumber,
b.COMPANY_CODE AS CompanyCode,
b.FISCAL_YEAR AS FiscalYear,
b.ACCOUNTING_DOCUMENT AS AccountingDocument,
b.POSTING_DATE AS PostingDate,
b.CREATED_AT AS PostedAt,
b.CREATED_BY AS PostedBy,
b.REVERSAL_DOCUMENT AS ReversalDocument,
b.REVERSED_DOCUMENT AS ReversedDocument
FROM [Your BKPF accounting document source] b
WHERE b.CREATED_AT >= '[Start timestamp]'
AND b.CREATED_AT < '[End timestamp]'
AND b.COMPANY_CODE IN ([Company code filter])
),
journal_attributes AS (
SELECT
a.COMPANY_CODE AS CompanyCode,
a.FISCAL_YEAR AS FiscalYear,
a.ACCOUNTING_DOCUMENT AS AccountingDocument,
MAX(a.VENDOR_NO) AS VendorNumber,
SUM(a.AMOUNT_IN_COMPANY_CODE_CURRENCY) AS AmountInCompanyCodeCurrency,
MAX(a.PURCHASING_DOCUMENT) AS PurchasingDocument,
MAX(a.CLEARING_DATE) AS ClearingDate,
MAX(a.CLEARING_DOCUMENT) AS ClearingDocument
FROM [Your ACDOCA universal journal source] a
WHERE a.COMPANY_CODE IN ([Company code filter])
AND a.POSTING_DATE >= '[Start date]'
AND a.POSTING_DATE < '[End date]'
GROUP BY
a.COMPANY_CODE,
a.FISCAL_YEAR,
a.ACCOUNTING_DOCUMENT
),
source_events AS (
SELECT
e.INV_DOC_NO AS InvoiceNumber,
e.COMPANY_CODE AS CompanyCode,
e.FISCAL_YEAR AS FiscalYear,
e.EVENT_TIMESTAMP AS EventTime,
e.EVENT_USER AS UserName,
e.PAYMENT_BLOCK_REASON AS PaymentBlockReason,
e.PURCHASING_DOCUMENT AS PurchasingDocument,
e.VENDOR_NO AS VendorNumber,
e.AMOUNT_IN_COMPANY_CODE_CURRENCY AS AmountInCompanyCodeCurrency,
e.PAYMENT_DUE_DATE AS PaymentDueDate,
e.DOCUMENT_TYPE AS DocumentType,
e.EVENT_TYPE AS SourceEventType
FROM [Your verified invoice event and workflow source] e
WHERE e.EVENT_TIMESTAMP >= '[Start timestamp]'
AND e.EVENT_TIMESTAMP < '[End timestamp]'
AND e.COMPANY_CODE IN ([Company code filter])
),
base_events AS (
SELECT
i.InvoiceNumber,
'Invoice Document Created' AS ActivityName,
i.InvoiceCreatedAt AS EventTime,
i.InvoiceCreatedBy AS UserName,
i.CompanyCode,
COALESCE(i.VendorNumber, j.VendorNumber) AS VendorNumber,
COALESCE(i.AmountInCompanyCodeCurrency, j.AmountInCompanyCodeCurrency) AS AmountInCompanyCodeCurrency,
i.PaymentDueDate,
i.DocumentType,
CAST(NULL AS NVARCHAR(20)) AS PaymentBlockReason,
COALESCE(i.PurchasingDocument, j.PurchasingDocument) AS PurchasingDocument
FROM invoice_base i
LEFT JOIN posted_accounting p
ON p.InvoiceNumber = i.InvoiceNumber
AND p.CompanyCode = i.CompanyCode
AND p.FiscalYear = i.FiscalYear
LEFT JOIN journal_attributes j
ON j.CompanyCode = p.CompanyCode
AND j.FiscalYear = p.FiscalYear
AND j.AccountingDocument = p.AccountingDocument
WHERE i.InvoiceCreatedAt IS NOT NULL
UNION ALL
SELECT
s.InvoiceNumber,
'Invoice Parked' AS ActivityName,
s.EventTime,
s.UserName,
s.CompanyCode,
COALESCE(s.VendorNumber, i.VendorNumber) AS VendorNumber,
COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency) AS AmountInCompanyCodeCurrency,
COALESCE(s.PaymentDueDate, i.PaymentDueDate) AS PaymentDueDate,
COALESCE(s.DocumentType, i.DocumentType) AS DocumentType,
s.PaymentBlockReason,
COALESCE(s.PurchasingDocument, i.PurchasingDocument) AS PurchasingDocument
FROM source_events s
LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PARKED'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Sent For Approval', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'SENT_FOR_APPROVAL'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Approved', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'APPROVED'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Rejected', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'REJECTED'
UNION ALL
SELECT s.InvoiceNumber, 'Invoice Data Updated', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'DATA_UPDATED'
UNION ALL
SELECT s.InvoiceNumber, 'Payment Block Set', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_BLOCK_SET'
UNION ALL
SELECT s.InvoiceNumber, 'Payment Block Removed', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_BLOCK_REMOVED'
UNION ALL
SELECT
i.InvoiceNumber,
'Invoice Posted',
p.PostedAt,
p.PostedBy,
i.CompanyCode,
COALESCE(i.VendorNumber, j.VendorNumber),
COALESCE(i.AmountInCompanyCodeCurrency, j.AmountInCompanyCodeCurrency),
i.PaymentDueDate,
i.DocumentType,
CAST(NULL AS NVARCHAR(20)),
COALESCE(i.PurchasingDocument, j.PurchasingDocument)
FROM invoice_base i
INNER JOIN posted_accounting p ON p.InvoiceNumber = i.InvoiceNumber AND p.CompanyCode = i.CompanyCode AND p.FiscalYear = i.FiscalYear
LEFT JOIN journal_attributes j ON j.CompanyCode = p.CompanyCode AND j.FiscalYear = p.FiscalYear AND j.AccountingDocument = p.AccountingDocument
WHERE p.PostedAt IS NOT NULL
UNION ALL
SELECT s.InvoiceNumber, 'Payment Proposal Created', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_PROPOSAL_CREATED'
UNION ALL
SELECT s.InvoiceNumber, 'Payment Executed', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_EXECUTED'
UNION ALL
SELECT s.InvoiceNumber, 'Late Payment Executed', s.EventTime, s.UserName, s.CompanyCode, COALESCE(s.VendorNumber, i.VendorNumber), COALESCE(s.AmountInCompanyCodeCurrency, i.AmountInCompanyCodeCurrency), COALESCE(s.PaymentDueDate, i.PaymentDueDate), COALESCE(s.DocumentType, i.DocumentType), s.PaymentBlockReason, COALESCE(s.PurchasingDocument, i.PurchasingDocument)
FROM source_events s LEFT JOIN invoice_base i ON i.InvoiceNumber = s.InvoiceNumber AND i.CompanyCode = s.CompanyCode AND i.FiscalYear = s.FiscalYear
WHERE s.SourceEventType = 'PAYMENT_EXECUTED'
AND s.EventTime > CAST(COALESCE(s.PaymentDueDate, i.PaymentDueDate) AS TIMESTAMP)
UNION ALL
SELECT
i.InvoiceNumber,
'Invoice Reversed',
p.ReversalEventAt,
p.ReversalUser,
i.CompanyCode,
COALESCE(i.VendorNumber, j.VendorNumber),
COALESCE(i.AmountInCompanyCodeCurrency, j.AmountInCompanyCodeCurrency),
i.PaymentDueDate,
i.DocumentType,
CAST(NULL AS NVARCHAR(20)),
COALESCE(i.PurchasingDocument, j.PurchasingDocument)
FROM invoice_base i
INNER JOIN [Your verified reversal event source] p ON p.INV_DOC_NO = i.InvoiceNumber AND p.COMPANY_CODE = i.CompanyCode AND p.FISCAL_YEAR = i.FiscalYear
LEFT JOIN journal_attributes j ON j.CompanyCode = p.COMPANY_CODE AND j.FiscalYear = p.FISCAL_YEAR AND j.AccountingDocument = p.ACCOUNTING_DOCUMENT
WHERE p.ReversalEventAt IS NOT NULL
)
SELECT
InvoiceNumber,
ActivityName,
EventTime,
UserName,
CompanyCode,
VendorNumber,
AmountInCompanyCodeCurrency,
PaymentDueDate,
DocumentType,
PaymentBlockReason,
PurchasingDocument
FROM base_events
WHERE InvoiceNumber IS NOT NULL
AND EventTime IS NOT NULL
ORDER BY InvoiceNumber, EventTime, ActivityName; 단계
- ABAP 편집기 열기: SAP S/4HANA 시스템에 로그인합니다. 트랜잭션
SE38(ABAP Editor)을 엽니다. - 프로그램 생성: 프로그램 필드에 새 프로그램 이름을 입력합니다. 예를 들어
Z_PM_INVOICE_EXTRACT를 입력하고 '생성' 버튼을 클릭합니다. 제목을 입력하고 유형을 '실행 프로그램'으로 설정한 다음 적절한 패키지에 저장합니다. - 프로그램 구조 및 선택 화면 정의: 편집기에서 최종 이벤트 로그 출력에 사용할 데이터 구조를 정의합니다. 그런 다음 사용자가 송장 입력일의 날짜 범위, 회사 코드, 문서 유형 등의 매개변수를 입력할 선택 화면을 만듭니다. 이렇게 하면 프로그램을 재사용하고 유연하게 활용할 수 있습니다.
- 데이터 선택 로직 구현: 여러 SAP 테이블에서 데이터를 선택하는 핵심 ABAP SQL 문을 작성합니다. 프로그램은 필요한 13개 활동 각각에 대해 순차적으로 쿼리를 실행합니다.
- 헤더 및 항목 데이터 추출: '송장 문서 생성' 및 '송장 전기'와 같은 기본 이벤트는
RBKP(물류 송장 헤더),BKPF(회계 문서 헤더) 등의 기본 테이블에서 데이터를 선택합니다. - 변경 문서 데이터 추출: '지급 보류 설정' 및 '지급 보류 해제'와 같은 활동은 변경 문서 테이블
CDHDR(변경 문서 헤더) 및CDPOS(변경 문서 항목)에서 조회합니다. 예를 들어BSEG테이블의ZLSPR등 특정 필드의 변경 사항을 식별해야 합니다. - 지급 데이터 추출: 지급 관련 활동을 기록하려면 지급 제안용
REGUP(지급 프로그램에서 처리된 항목), 실행된 지급용BSAK(반제된 공급업체 항목) 등의 테이블을 조회합니다. 반제일 (AUGDT)과 순 지급 기한 (ZFBDT)을 비교해 '연체 지급 실행'을 구분합니다. - 워크플로 데이터 추출: 승인 활동은
SWW_WI2OBJ등 SAP Business Workflow 테이블을 조회해 워크플로 항목을 송장 객체와 연결합니다. 이 단계는 사용 중인 워크플로 설정에 따라 크게 달라지므로 상당한 수정이 필요할 수 있습니다. - 데이터를 이벤트 로그 형식으로 통합: 선택한 각 활동의 데이터를 공통 내부 테이블 구조로 변환합니다. 이 테이블의 각 행은 단일 이벤트를 나타내며 케이스 식별자 (
InvoiceNumber),ActivityName,EventTime과 기타 권장 속성을 포함해야 합니다. - 출력 파일 생성: ABAP 문
OPEN DATASET,TRANSFER,CLOSE DATASET을 사용해 최종 내부 테이블의 내용을 SAP 애플리케이션 서버에 플랫 파일로 씁니다. 쉼표로 구분된 값 (CSV) 형식을 권장합니다. - 예약 및 실행: 테스트를 위해 포그라운드에서 프로그램을 실행합니다 (
F8). 운영 실행은 트랜잭션SM36을 사용해 시스템 성능에 영향을 주지 않도록 사용량이 적은 시간대에 백그라운드 작업으로 예약합니다. - 파일 가져오기 및 업로드: 트랜잭션
AL11을 사용해 파일이 저장된 애플리케이션 서버 디렉터리로 이동합니다. 파일을 로컬 시스템에 다운로드하고 process mining 도구에 업로드하기 전에 UTF-8 인코딩과 올바른 형식을 확인합니다.
구성
- 날짜 범위: 송장 입력일 (
RBKP-CPUDT) 또는 전기일 (BKPF-BUDAT)을 기준으로 구체적인 추출 날짜 범위를 설정합니다. 초기 분석에는 데이터 양을 관리할 수 있도록 3~6개월을 권장합니다. - 회사 코드 (BUKRS): 하나 이상의 회사 코드로 필터링해야 합니다. 대규모 조직에서 모든 회사 코드의 데이터를 추출하면 실행 시간이 지나치게 길어지고 파일 크기가 커질 수 있습니다.
- 문서 유형 (BLART): 관련 문서 유형을 필터링해 공급업체 송장을 분리합니다. 일반적인 유형에는 'RE' (총액 송장)와 'KR' (공급업체 송장)이 있습니다. 이를 통해 분석과 관련 없는 문서를 제외할 수 있습니다.
- 공급업체 계정 (LIFNR): 특정 공급업체 번호를 대상으로 분석하거나 테스트할 때 유용하도록 선택적 필터를 프로그램에 포함할 수 있습니다.
- 출력 파일 설정: 애플리케이션 서버의 출력 파일 경로와 쉼표 또는 세미콜론 등의 필드 구분자를 지정하는 매개변수를 프로그램에 추가합니다.
- 사전 요건: 프로그램을 실행하는 사용자 또는 시스템 계정에는 ABAP 프로그램을 생성하고 실행할 개발자 권한 (
SE38)과BKPF,BSEG,RBKP,RSEG,CDHDR,CDPOS및 워크플로 테이블을 포함한 FI, MM, Basis 테이블에 대한 광범위한 읽기 권한이 필요합니다.
샘플 쿼리 abap
REPORT Z_PM_INVOICE_EXTRACT.
* --- Internal table structure for the final event log
TYPES: BEGIN OF ty_s_event_log,
invoicenumber TYPE char25,
activityname TYPE char50,
eventtime TYPE char19, "YYYY-MM-DD HH:MM:SS
username TYPE sy-uname,
companycode TYPE bukrs,
vendornumber TYPE lifnr,
amountincompanycodecurrency TYPE wrbtr,
paymentduedate TYPE char10, "YYYY-MM-DD
documenttype TYPE blart,
paymentblockreason TYPE char1,
purchasingdocument TYPE ebeln,
END OF ty_s_event_log.
DATA: lt_event_log TYPE STANDARD TABLE OF ty_s_event_log.
DATA: ls_event_log TYPE ty_s_event_log.
* --- Selection Screen for user inputs
PARAMETERS: p_path TYPE string DEFAULT '/usr/sap/tmp/invoice_events.csv'.
SELECT-OPTIONS: s_erdat FOR sy-datum OBLIGATORY, " Entry Date
s_bukrs FOR bkpf-bukrs OBLIGATORY, " Company Code
s_blart FOR bkpf-blart. " Document Type
START-OF-SELECTION.
* --- 1. Invoice Document Created (from Logistics Invoice Verification)
SELECT CONCAT( rbkp~belnr, rbkp~gjahr ) AS invoicenumber,
'Invoice Document Created' AS activityname,
CONCAT( rbkp~cpudt, rbkp~cputm ) AS eventtime,
rbkp~usnam AS username,
rbkp~bukrs AS companycode,
rbkp~lifnr AS vendornumber,
rbkp~rmwwr AS amountincompanycodecurrency,
'' AS paymentduedate,
rbkp~blart AS documenttype,
rbkp~zuonr AS paymentblockreason,
'' AS purchasingdocument
FROM rbkp
INTO TABLE @DATA(lt_created)
WHERE rbkp~cpudt IN @s_erdat
AND rbkp~bukrs IN @s_bukrs
AND rbkp~blart IN @s_blart.
LOOP AT lt_created INTO DATA(ls_created).
ls_event_log-invoicenumber = ls_created-invoicenumber.
ls_event_log-activityname = ls_created-activityname.
ls_event_log-eventtime = |{ ls_created-eventtime(8) } { ls_created-eventtime+8(2) }:{ ls_created-eventtime+10(2) }:{ ls_created-eventtime+12(2) }|.
ls_event_log-username = ls_created-username.
ls_event_log-companycode = ls_created-companycode.
ls_event_log-vendornumber = ls_created-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_created-amountincompanycodecurrency.
ls_event_log-paymentduedate = ''.
ls_event_log-documenttype = ls_created-documenttype.
ls_event_log-paymentblockreason = ''.
ls_event_log-purchasingdocument = ls_created-purchasingdocument.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 2. Invoice Parked (assuming status 'A' or 'B' in RBKP)
SELECT CONCAT( belnr, gjahr ) AS invoicenumber,
'Invoice Parked' AS activityname,
CONCAT( cpudt, cputm ) AS eventtime,
usnam AS username,
bukrs AS companycode,
lifnr AS vendornumber,
rmwwr AS amountincompanycodecurrency,
'' AS paymentduedate,
blart AS documenttype,
'' AS paymentblockreason,
'' AS purchasingdocument
FROM rbkp
INTO TABLE @DATA(lt_parked)
WHERE rbstat IN ('A', 'B')
AND cpudt IN @s_erdat
AND bukrs IN @s_bukrs
AND blart IN @s_blart.
LOOP AT lt_parked INTO DATA(ls_parked).
ls_event_log-invoicenumber = ls_parked-invoicenumber.
ls_event_log-activityname = ls_parked-activityname.
ls_event_log-eventtime = |{ ls_parked-eventtime(8) } { ls_parked-eventtime+8(2) }:{ ls_parked-eventtime+10(2) }:{ ls_parked-eventtime+12(2) }|.
ls_event_log-username = ls_parked-username.
ls_event_log-companycode = ls_parked-companycode.
ls_event_log-vendornumber = ls_parked-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_parked-amountincompanycodecurrency.
ls_event_log-paymentduedate = ''.
ls_event_log-documenttype = ls_parked-documenttype.
ls_event_log-paymentblockreason = ''.
ls_event_log-purchasingdocument = ''.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 3, 4, 5. Sent For Approval, Approved, Rejected (Placeholder logic, needs adaptation)
* --- This logic is a generic template for SAP Business Workflow.
* --- Your implementation will vary. You must identify the correct workflow tasks.
SELECT obj.instid, wi.wi_cd, wi.wi_ct, wi.wi_stat, wi.wi_aagent
FROM sww_wi2obj AS obj
JOIN swwlog AS wi ON obj~instid = wi~wi_id
INTO TABLE @DATA(lt_workflow)
WHERE obj~typeid = 'BUS2081' " Business Object for Incoming Invoice
AND obj~catid = 'BO'
AND wi~wi_cd IN s_erdat.
LOOP AT lt_workflow INTO DATA(ls_workflow).
* --- This is a placeholder, adapt task IDs and logic
CASE ls_workflow-wi_stat.
WHEN 'STARTED'.
ls_event_log-activityname = 'Invoice Sent For Approval'.
WHEN 'COMPLETED'.
ls_event_log-activityname = 'Invoice Approved'.
WHEN 'CANCELLED'.
ls_event_log-activityname = 'Invoice Rejected'.
WHEN OTHERS.
CONTINUE.
ENDCASE.
* --- Code to get invoice details based on ls_workflow-instid needed here
* --- ... appending to lt_event_log ...
ENDLOOP.
* --- 6, 7, 8. Payment Block Set/Removed, Data Updated (from Change Docs)
SELECT h~objectid, h~username, h~udate, h~utime, p~fname, p~value_new, p~value_old
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectclas = p~objectclas AND h~objectid = p~objectid AND h~changenr = p~changenr
INTO TABLE @DATA(lt_changes)
WHERE h~objectclas = 'BELEGV'
AND h~udate IN s_erdat.
LOOP AT lt_changes INTO DATA(ls_change).
ls_event_log-invoicenumber = |{ ls_change-objectid+10(10) }{ ls_change-objectid(4) }|.
ls_event_log-username = ls_change-username.
ls_event_log-eventtime = |{ ls_change-udate } { ls_change-utime(2) }:{ ls_change-utime+2(2) }:{ ls_change-utime+4(2) }|.
IF ls_change-fname = 'ZLSPR'. " Payment Block
IF ls_change-value_old IS INITIAL AND ls_change-value_new IS NOT INITIAL.
ls_event_log-activityname = 'Payment Block Set'.
ls_event_log-paymentblockreason = ls_change-value_new.
ELSEIF ls_change-value_old IS NOT INITIAL AND ls_change-value_new IS INITIAL.
ls_event_log-activityname = 'Payment Block Removed'.
ls_event_log-paymentblockreason = ''.
ELSE.
CONTINUE.
ENDIF.
ELSE.
ls_event_log-activityname = 'Invoice Data Updated'.
ENDIF.
* --- Need to select other attributes based on invoice number
* --- ... appending to lt_event_log ...
ENDLOOP.
* --- 9. Invoice Posted
SELECT CONCAT( bkpf~belnr, bkpf~gjahr ) AS invoicenumber,
'Invoice Posted' AS activityname,
CONCAT( bkpf~cpudt, bkpf~cputm ) AS eventtime,
bkpf~usnam AS username,
bkpf~bukrs AS companycode,
bseg~lifnr AS vendornumber,
bseg~wrbtr AS amountincompanycodecurrency,
bseg~zfBDT AS paymentduedate,
bkpf~blart AS documenttype,
bseg~zlspr AS paymentblockreason,
bseg~ebeln AS purchasingdocument
FROM bkpf
JOIN bseg ON bkpf~bukrs = bseg~bukrs AND bkpf~belnr = bseg~belnr AND bkpf~gjahr = bseg~gjahr
INTO TABLE @DATA(lt_posted)
WHERE bkpf~cpudt IN @s_erdat
AND bkpf~bukrs IN @s_bukrs
AND bkpf~blart IN @s_blart
AND bseg~koart = 'K'. " Vendor line
LOOP AT lt_posted INTO DATA(ls_posted).
ls_event_log-invoicenumber = ls_posted-invoicenumber.
ls_event_log-activityname = ls_posted-activityname.
ls_event_log-eventtime = |{ ls_posted-eventtime(8) } { ls_posted-eventtime+8(2) }:{ ls_posted-eventtime+10(2) }:{ ls_posted-eventtime+12(2) }|.
ls_event_log-username = ls_posted-username.
ls_event_log-companycode = ls_posted-companycode.
ls_event_log-vendornumber = ls_posted-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_posted-amountincompanycodecurrency.
ls_event_log-paymentduedate = ls_posted-paymentduedate.
ls_event_log-documenttype = ls_posted-documenttype.
ls_event_log-paymentblockreason = ls_posted-paymentblockreason.
ls_event_log-purchasingdocument = ls_posted-purchasingdocument.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 10. Payment Proposal Created
SELECT CONCAT( regup~belnr, regup~gjahr ) AS invoicenumber,
'Payment Proposal Created' AS activityname,
CONCAT( reguh~erfdt, reguh~erfzt ) AS eventtime,
reguh~erfbu AS username,
regup~bukrs AS companycode,
regup~lifnr AS vendornumber,
regup~wrbtr AS amountincompanycodecurrency,
'' AS paymentduedate,
regup~blart AS documenttype,
'' AS paymentblockreason,
'' AS purchasingdocument
FROM regup
JOIN reguh ON regup~laufd = reguh~laufd AND regup~laufi = reguh~laufi
INTO TABLE @DATA(lt_proposal)
WHERE reguh~erfdt IN @s_erdat
AND regup~bukrs IN @s_bukrs.
LOOP AT lt_proposal INTO DATA(ls_proposal).
ls_event_log-invoicenumber = ls_proposal-invoicenumber.
ls_event_log-activityname = ls_proposal-activityname.
ls_event_log-eventtime = |{ ls_proposal-eventtime(8) } { ls_proposal-eventtime+8(2) }:{ ls_proposal-eventtime+10(2) }:{ ls_proposal-eventtime+12(2) }|.
ls_event_log-username = ls_proposal-username.
ls_event_log-companycode = ls_proposal-companycode.
ls_event_log-vendornumber = ls_proposal-vendornumber.
ls_event_log-amountincompanycodecurrency = ls_proposal-amountincompanycodecurrency.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- 11, 12. Payment Executed / Late Payment Executed
SELECT CONCAT( belnr, gjahr ) AS invoicenumber,
augdt,
zfBDT
FROM bsak
INTO TABLE @DATA(lt_cleared)
WHERE augdt IN @s_erdat
AND bukrs IN @s_bukrs.
LOOP AT lt_cleared INTO DATA(ls_cleared).
IF ls_cleared-augdt > ls_cleared-zfbdt.
ls_event_log-activityname = 'Late Payment Executed'.
ELSE.
ls_event_log-activityname = 'Payment Executed'.
ENDIF.
ls_event_log-invoicenumber = ls_cleared-invoicenumber.
ls_event_log-eventtime = |{ ls_cleared-augdt } 00:00:00|.
* --- Need to select other attributes based on invoice number
* --- ... appending to lt_event_log ...
ENDLOOP.
* --- 13. Invoice Reversed
SELECT CONCAT( stblg, stjah ) AS invoicenumber,
'Invoice Reversed' AS activityname,
CONCAT( cpudt, cputm ) AS eventtime,
usnam AS username,
bukrs AS companycode,
'' AS vendornumber,
'' AS amountincompanycodecurrency,
'' AS paymentduedate,
blart AS documenttype,
'' AS paymentblockreason,
'' AS purchasingdocument
FROM bkpf
INTO TABLE @DATA(lt_reversed)
WHERE stblg IS NOT NULL
AND cpudt IN @s_erdat
AND bukrs IN @s_bukrs.
LOOP AT lt_reversed INTO DATA(ls_reversed).
ls_event_log-invoicenumber = ls_reversed-invoicenumber.
ls_event_log-activityname = ls_reversed-activityname.
ls_event_log-eventtime = |{ ls_reversed-eventtime(8) } { ls_reversed-eventtime+8(2) }:{ ls_reversed-eventtime+10(2) }:{ ls_reversed-eventtime+12(2) }|.
ls_event_log-username = ls_reversed-username.
ls_event_log-companycode = ls_reversed-companycode.
APPEND ls_event_log TO lt_event_log.
ENDLOOP.
* --- Write internal table to CSV file
OPEN DATASET p_path FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc <> 0.
MESSAGE 'Error opening file.' TYPE 'E'.
ENDIF.
DATA: lv_line TYPE string.
FIELD-SYMBOLS: <fs_any> TYPE any.
* --- Header row
lv_line = 'InvoiceNumber,ActivityName,EventTime,UserName,CompanyCode,VendorNumber,AmountInCompanyCodeCurrency,PaymentDueDate,DocumentType,PaymentBlockReason,PurchasingDocument'.
TRANSFER lv_line TO p_path.
LOOP AT lt_event_log INTO ls_event_log.
CLEAR lv_line.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE ls_event_log TO <fs_any>.
IF sy-subrc <> 0.
EXIT.
ENDIF.
IF sy-index = 1.
lv_line = <fs_any>.
ELSE.
CONCATENATE lv_line <fs_any> INTO lv_line SEPARATED BY ','.
ENDIF.
ENDDO.
TRANSFER lv_line TO p_path.
ENDLOOP.
CLOSE DATASET p_path.
WRITE: / 'Extraction complete. File saved to:', p_path. 시작할 준비가 되셨나요?
지금 송장 처리를 개선해 보세요. 이 템플릿을 활용해 운영을 개선하고 효율을 높이는 첫걸음을 시작할 수 있습니다.
지금 SAP S/4HANA의 P2P 송장 처리를 최적화하세요
병목을 찾아 송장 처리 주기를 30% 이상 단축하세요.
신용카드가 필요하지 않습니다. 몇 분이면 설정할 수 있습니다.