Record to Report - 분개 데이터 템플릿
Record to Report - 분개 데이터 템플릿
- 수집 권장 속성
- 추적할 주요 활동
- 실무에 필요한 데이터 추출 안내
Record to Report - 분개 속성
| 이름 | 설명 | ||
|---|---|---|---|
| 분개 ID JournalEntryId | 재무 분개를 식별하는 고유 ID로, 프로세스의 기본 케이스 식별자로 사용됩니다. | ||
| 설명 분개 ID는 SAP S/4HANA에서 각 회계 문서를 생성할 때 부여하는 고유 번호입니다. 이 ID를 사용하면 분개 생성 또는 임시 저장부터 승인 워크플로, 최종 전기, 취소 또는 반제까지 전체 처리 이력을 추적할 수 있습니다. process mining 분석에서는 이 ID를 사용해 관련 활동을 하나의 케이스로 연결합니다. 공통 분개 ID를 기준으로 이벤트를 그룹화하면 분석 담당자가 처음부터 끝까지의 프로세스 흐름을 재구성하고 처리 주기를 측정하며 각 금융 거래의 편차와 병목을 찾을 수 있습니다. 전체 프로세스 뷰를 구성하는 기본 속성입니다. 중요한 이유 이 ID는 관련된 모든 프로세스 단계를 연결해 각 분개의 전체 처리 과정을 분석할 수 있게 합니다. 확보 방법 일반적으로 회사 코드(BKPF-BUKRS), 문서 번호(BKPF-BELNR), 회계연도(BKPF-GJAHR)를 연결해 구성하는 복합 키입니다. 예시 1000-1000000001-20231710-1900000055-20242000-2100003412-2023 | |||
| 이벤트 시각 EventTime | 분개에서 특정 활동이 발생한 시점을 나타내는 타임스탬프입니다. | ||
| 설명 이벤트 시각은 업무 활동이 실행되어 시스템에 기록된 정확한 날짜와 시간입니다. 케이스의 각 활동에는 고유한 타임스탬프가 있어 이벤트를 시간순으로 배열할 수 있습니다. 시간 기반 프로세스 분석에 반드시 필요한 속성입니다. 처리 주기와 활동 간 소요 시간, 대기 시간을 계산하고 업무가 시간대별로 어떻게 분포하는지 파악하는 데 사용합니다. 신뢰할 수 있는 프로세스 모델을 만들고 승인 주기 시간과 같은 주요 성과 지표를 계산하려면 정확한 타임스탬프가 필요합니다. 중요한 이유 이벤트의 시간순서를 제공하므로 모든 소요 시간 기반 지표를 계산하고 프로세스 일정을 파악하는 데 필요합니다. 확보 방법 변경 문서 로그(CDHDR-UDATE, CDHDR-UTIME), 워크플로 로그 또는 BKPF의 생성 및 입력 타임스탬프(CPUDT, CPUTM)에서 가져옵니다. 예시 2023-10-26T10:05:00Z2023-11-15T14:30:15Z2024-01-20T09:00:45Z | |||
| 활동 ActivityName | 분개 프로세스의 특정 시점에 발생한 업무 활동의 이름입니다. | ||
| 설명 활동은 '분개 생성', '검토를 위해 분개 제출', '분개 전기'와 같이 분개의 처리 과정에서 발생하는 구체적인 단계나 이벤트를 나타냅니다. 일반적으로 시스템에 기록된 변경 로그와 상태 업데이트, 트랜잭션 코드에서 도출합니다. 활동을 분석하면 프로세스 흐름을 시각화하고 일반적인 경로를 파악하며 표준 절차에서 벗어난 사례를 찾을 수 있습니다. 활동 빈도와 단계 간 대기 시간, 절차 준수율 등의 지표를 계산하는 데도 필요합니다. 중요한 이유 프로세스의 단계를 정의해 프로세스 맵을 시각화하고 워크플로 패턴을 분석할 수 있게 합니다. 확보 방법 헤더 및 개별 항목 테이블의 상태 필드(예: BKPF-BSTAT), 변경 문서 로그(CDHDR/CDPOS), 워크플로 로그 등 다양한 출처에서 도출합니다. 예시 분개 생성분개 임시 저장검토를 위해 분개 제출분개 승인분개 전기 | |||
| 분개 유형 JournalEntryType | 자산 전기, 공급업체 송장, 총계정원장 전기 등 업무 목적에 따라 분개를 분류합니다. | ||
| 설명 SAP 용어로 문서 유형이라고도 하는 분개 유형은 회계 문서를 분류하는 키입니다. 문서에 지정되는 번호 범위와 전기에 허용되는 계정 유형 등을 제어합니다. 분개 유형별 분석은 유형에 따른 프로세스 차이를 파악하는 데 중요합니다. 예를 들어 단순한 발생주의 분개(유형 SA)의 승인 절차는 복잡한 자산 취득(유형 AA)보다 훨씬 간단할 수 있습니다. 이 속성은 '분개 유형별 규정 준수' 대시보드에 사용됩니다. 중요한 이유 업무 맥락에 따라 분개를 분류하여 재무 거래 유형별 프로세스 차이와 성과를 분석할 수 있습니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 BLART(문서 유형)입니다. 예시 SAKRAA | |||
| 생성 사용자 CreatedByUser | 분개를 생성한 사용자의 ID입니다. | ||
| 설명 이 속성은 최초 문서를 생성해 분개 프로세스를 시작한 사용자의 고유 식별자를 저장합니다. 회계 담당자나 현업 사용자일 수도 있고, 자동 분개의 경우 시스템 ID일 수도 있습니다. 생성자별로 프로세스를 분석하면 특정 사용자나 팀과 관련된 패턴을 파악할 수 있습니다. 특정 사용자의 반려율이 높다면 교육이 필요한지 확인할 수 있고, 성과가 높은 사용자를 찾을 수도 있습니다. '사용자 활동 및 처리량' 대시보드에 필요한 속성입니다. 중요한 이유 프로세스 활동을 사용자별로 구분하여 성과와 업무량을 분석하고 교육이 필요한 영역을 파악할 수 있습니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 USNAM(사용자 이름)입니다. 예시 ABROWNCJONESBATCH_USER | |||
| 전기일 PostingDate | 분개가 총계정원장에 기록되는 날짜로, 재무 기간에 영향을 줍니다. | ||
| 설명 전기일은 거래가 재무제표에 반영되는 회계 기간을 결정합니다. 회계에서 중요한 날짜이며 문서를 생성하거나 시스템에 입력한 날짜와 다를 수 있습니다. process mining에서는 전기일을 기준으로 기간별 집단 분석을 수행할 수 있습니다. 예를 들어 월말 결산 프로세스를 비교하거나 회계 기간별 성과 추이를 분석할 수 있습니다. 분개 생성부터 실제 전기까지 걸린 지연 시간을 측정하는 데도 사용됩니다. 중요한 이유 월말이나 연말 등 특정 회계 기간의 프로세스 성과를 분석하는 데 필요한 재무 맥락을 제공합니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 BUDAT(문서 전기일)입니다. 예시 2023-10-312023-11-012024-02-29 | |||
| 현지 통화 금액 AmountInLocalCurrency | 회사 코드의 현지 통화로 표시한 분개 총액입니다. | ||
| 설명 이 속성은 분개의 재무 규모를 나타냅니다. 일반적으로 문서의 차변 또는 대변 개별 항목 금액을 절댓값으로 합산한 뒤 회사 코드의 현지 통화로 환산합니다. 금액별로 프로세스를 나누면 재무 영향에 따라 분석할 수 있습니다. 예를 들어 고액 분개는 소액 분개보다 엄격한 승인 절차를 거칠 수 있습니다. 재무 위험이 큰 거래를 우선적으로 개선하는 데도 도움이 됩니다. 중요한 이유 분개의 재무 금액을 제공하여 거래 금액에 따라 프로세스가 어떻게 달라지는지 분석할 수 있습니다. 확보 방법 해당 분개(BELNR)의 개별 항목 테이블 BSEG에서 금액(필드 DMBTR)을 합산한 뒤 양수로 변환해 계산합니다. 예시 1500.75125000.0050.20 | |||
| 회사 코드 CompanyCode | 분개가 전기되는 회사 또는 법인의 고유 식별자입니다. | ||
| 설명 회사 코드는 SAP Financials의 기본 조직 단위로, 재무제표를 작성하는 독립 법인을 나타냅니다. 모든 분개는 특정 회사 코드에 지정됩니다. 이 속성은 조직 내 여러 부문의 프로세스 성과를 구분하고 비교하는 데 중요합니다. 분석가는 특정 법인의 프로세스만 조회하거나, 회사 코드별 반려율을 비교하거나, 지역별 프로세스 차이를 파악할 수 있습니다. 중요한 이유 조직 내 여러 법인이나 사업부의 분개 프로세스를 필터링하고 비교할 수 있습니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 BUKRS(회사 코드)입니다. 예시 10001710US01 | |||
| 문서 상태 DocumentStatus | 임시 저장, 전기, 반제 등 분개의 현재 처리 상태입니다. | ||
| 설명 문서 상태는 분개가 처리 과정에서 현재 어떤 단계에 있는지 나타냅니다. 예를 들어 '임시 저장' 문서는 저장됐지만 아직 총계정원장에 전기되지 않은 상태이고, '전기' 문서는 처리가 완료된 상태입니다. 상태를 분석하면 업무 흐름을 파악하고 병목을 찾을 수 있습니다. '임시 저장' 또는 '승인 대기' 상태로 장기간 남아 있는 문서가 많다면 프로세스 비효율을 의심할 수 있습니다. 프로세스 활동을 도출할 때도 중요한 데이터입니다. 중요한 이유 분개가 처리 과정의 어느 단계에 있는지 보여 주어 대기열과 병목을 파악하는 데 도움이 됩니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 BSTAT(문서 상태)입니다. 예시 VAB | |||
| 소스 시스템 SourceSystem | 분개 데이터를 추출한 소스 시스템을 식별합니다. | ||
| 설명 이 속성은 분개 데이터가 생성된 원천 시스템을 나타냅니다. ERP 인스턴스가 여러 개이거나 기존 시스템과 최신 시스템을 함께 사용하는 기업에서는 데이터 출처를 구분하는 데 도움이 됩니다. 분석할 때 시스템별 프로세스 성과를 비교하거나 특정 출처의 데이터만 필터링할 수 있습니다. 데이터 거버넌스를 위해서도 중요하며, 분석 대상 데이터의 맥락을 파악하는 데 도움이 됩니다. 중요한 이유 데이터 출처에 관한 정보를 제공하므로, 여러 시스템을 사용하는 환경에서 정확한 프로세스 분석과 비교를 수행하는 데 중요합니다. 확보 방법 일반적으로 데이터 추출 시 추가되는 고정값으로, 특정 SAP S/4HANA 인스턴스(예: SID 또는 논리 시스템 이름)를 식별합니다. 예시 S4H_PROD_100ECC_FIN_200S4C_US_EAST | |||
| 수동 전기 여부 IsManualPosting | 사용자가 분개를 수동으로 전기했는지 나타내는 불리언 값입니다. | ||
| 설명 이 속성은 시스템 작업이나 인터페이스가 자동으로 전기한 분개와 사용자가 직접 처리한 분개를 구분합니다. 일반적으로 문서 전기에 사용한 트랜잭션 코드를 기준으로 계산합니다. 이 플래그는 수동 전기율 KPI를 계산하고 Record to Report 프로세스의 자동화 진행 상황을 추적하는 데 사용됩니다. 수동 전기된 분개를 필터링하면 여전히 사람의 개입이 필요한 상황을 찾아 자동화 가능성을 검토할 수 있습니다. 중요한 이유 사용자가 처리한 전기와 시스템이 처리한 전기를 구분하여 자동화 수준을 측정하고 자동화 기회를 찾을 수 있습니다. 확보 방법 TransactionCode를 바탕으로 계산하는 속성입니다. 미리 정의한 수동 트랜잭션 코드 목록(예: 'FB01', 'F-02')에 해당하면 플래그를 'true'로 설정합니다. 예시 truefalse | |||
| 승인 사용자 ApproverUser | 분개를 승인하거나 반려한 사용자의 ID입니다. | ||
| 설명 이 속성은 제출된 분개를 검토하고 승인 여부를 결정한 사용자를 식별합니다. 여러 단계로 승인하는 workflow에서는 분개 하나에 승인자가 여러 명일 수 있습니다. 승인 프로세스를 자세히 분석하는 데 필요한 정보입니다. 승인자별 업무량과 승인 소요 시간을 측정하고 승인 단계의 병목을 찾을 수 있습니다. '사용자 활동 및 처리량' 대시보드에도 활용됩니다. 중요한 이유 승인 담당자를 식별하여 승인 업무량과 성과를 분석하고 병목을 파악할 수 있습니다. 확보 방법 승인 단계를 실행한 사용자를 추적해 workflow 로그(예: SWW_WI2OBJ, SWWLOG) 또는 변경 문서 테이블(CDHDR/CDPOS)에서 가져옵니다. 예시 DMILLERFWHITEKCHEN | |||
| 승인 소요 시간 ApprovalCycleTime | 분개를 승인 요청한 시점부터 승인 또는 반려될 때까지 걸린 시간입니다. | ||
| 설명 이 계산 지표는 승인 단계에 걸린 시간만 측정합니다. '분개 검토 제출' 활동부터 이어지는 '분개 승인' 또는 '분개 반려' 활동까지의 시간을 계산합니다. 이 KPI는 승인 workflow의 병목을 찾는 데 중요합니다. 승인 소요 시간이 길면 전체 프로세스가 크게 지연될 수 있습니다. 승인자, 회사 코드 또는 분개 유형별로 분석하면 개선이 필요한 영역을 구체적으로 파악할 수 있습니다. 중요한 이유 승인 단계에 걸린 시간을 따로 측정하여 검토 및 승인 workflow의 병목을 찾아 해결할 수 있습니다. 확보 방법 '분개 검토 제출' 이벤트와 '분개 승인' 또는 '분개 반려' 이벤트 사이의 시간 차이를 계산합니다. 예시 1일 2시간4시간 25분5일 0시간 | |||
| 역분개 사유 ReversalReason | 전기된 분개를 역분개한 이유를 나타내는 코드입니다. | ||
| 설명 전기된 분개에 오류가 있으면 삭제할 수 없으며 새 문서를 만들어 역분개해야 합니다. 역분개 사유 코드는 잘못된 전기일이나 금액 등 역분개한 이유를 설명합니다. 역분개 사유를 분석하면 Record to Report 프로세스에서 오류가 발생한 근본 원인을 찾을 수 있습니다. 특정 사유가 자주 나타나면 교육 부족이나 통제 미비와 같은 구조적 문제를 나타낼 수 있습니다. 이를 해결하면 처음부터 정확하게 처리되는 비율을 높일 수 있습니다. 중요한 이유 역분개로 이어진 오류의 근본 원인을 파악하여 재작업을 줄이고 프로세스 품질을 개선하는 데 필요한 정보를 제공합니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 STGRD(역분개 사유)입니다. 예시 010205 | |||
| 재작업 여부 IsRework | 반려 후 수정하는 등 분개에 재작업이 있었는지 나타내는 불리언 값입니다. | ||
| 설명 이 계산 속성은 이상적인 '정상 경로'에서 벗어난 분개를 표시합니다. 일반적으로 사례에 '분개 반려' 또는 '분개 수정'과 같은 활동이 있으면 true로 설정됩니다. 이 플래그를 사용하면 프로세스 효율성을 쉽게 분석할 수 있습니다. 재작업률 KPI를 간편하게 계산하고, 재작업이 있는 사례와 없는 사례의 처리 시간 및 비용을 직접 비교할 수 있습니다. 재작업 원인을 찾는 일은 많은 프로세스 개선 활동의 주요 목표입니다. 중요한 이유 수정이나 추가 처리 단계가 필요한 사례를 표시하여 프로세스 비효율을 쉽게 수치화하고 근본 원인을 분석할 수 있습니다. 확보 방법 사례의 활동 순서를 바탕으로 계산하는 속성입니다. '분개 반려'와 같은 활동이 있으면 'true'로 표시됩니다. 예시 truefalse | |||
| 종료 시간 EndTime | 활동이 완료된 시점을 나타내는 타임스탬프입니다. | ||
| 설명 종료 시간은 활동이 완료된 시점을 나타냅니다. 많은 이벤트 로그에서 활동의 시작 시간과 종료 시간은 동일하며, 이는 순간적으로 발생한 이벤트를 뜻합니다. 반면 사용자가 문서를 검토하는 것처럼 소요 시간을 측정할 수 있는 활동은 이 속성으로 지속 시간을 기록할 수 있습니다. 종료 시간이 별도로 있으면 활동 처리 시간과 대기 시간을 더 정확하게 계산할 수 있습니다. 작업이 실제로 진행된 시간과 대기열에서 처리되지 않고 머문 시간을 구분하는 데 도움이 됩니다. 중요한 이유 활동의 처리 시간을 정확히 계산하고 실제 작업 시간과 유휴 대기 시간을 구분할 수 있습니다. 확보 방법 단일 이벤트에서는 일반적으로 StartTime과 같습니다. 지속 시간이 있는 활동의 경우 workflow 로그에서 가져오거나 후속 이벤트를 기준으로 계산할 수 있습니다. 예시 2023-10-26T10:05:00Z2023-11-15T14:45:20Z2024-01-20T09:10:30Z | |||
| 최근 데이터 업데이트 LastDataUpdate | 원천 시스템에서 이 레코드의 데이터를 마지막으로 새로 고친 시점을 나타내는 타임스탬프입니다. | ||
| 설명 이 속성은 원천 시스템에서 데이터를 가장 최근에 추출하거나 업데이트한 날짜와 시간을 기록합니다. 분석 중인 데이터가 얼마나 최신인지 확인할 수 있습니다. 마지막 업데이트 시점을 알면 프로세스 분석이 현재 상황을 얼마나 반영하는지 파악할 수 있습니다. 대시보드와 KPI를 해석할 때 데이터가 거의 실시간인지, 이전 기간의 스냅샷인지 확인하는 데 도움이 됩니다. 중요한 이유 데이터의 최신 상태를 표시하여 사용자가 프로세스 분석의 기준 시점을 파악할 수 있도록 합니다. 확보 방법 메타데이터 속성으로, 일반적으로 데이터 수집 파이프라인에서 각 레코드에 생성 시각을 기록합니다. 예시 2024-03-10T02:00:00Z2024-03-11T02:00:00Z2024-03-12T02:00:00Z | |||
| 트랜잭션 코드 TransactionCode | 분개를 생성하거나 변경하는 데 사용한 SAP 트랜잭션 코드입니다. | ||
| 설명 트랜잭션 코드(T-Code)는 SAP의 특정 기능이나 프로그램을 식별하는 바로 가기입니다. 분개의 경우 T-Code에 따라 생성 방식이 달라질 수 있습니다. 예를 들어 FB01은 총계정원장 수동 전기, FV50은 임시 저장, 자동화 코드는 시스템 생성 분개를 나타낼 수 있습니다. 이 속성을 통해 활동이 사용자의 수동 작업으로 수행됐는지 시스템이 자동으로 처리했는지 파악할 수 있습니다. 수동 전기율 KPI를 계산하고 자동화 기회를 찾는 데도 사용됩니다. 중요한 이유 분개가 수동 또는 자동으로 처리됐는지 보여 주므로 자동화 분석과 프로세스 차이 파악에 중요합니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 TCODE(트랜잭션 코드)입니다. 예시 FB01FV50F-02 | |||
| 회계연도 FiscalYear | 분개가 속한 회계연도입니다. | ||
| 설명 회계연도는 회사 코드 및 문서 번호와 함께 분개를 고유하게 식별하는 키의 일부입니다. 문서가 해당하는 회계연도를 나타냅니다. 분석에서는 장기 추세를 살펴보고 사례 식별자의 고유성을 보장하는 데 사용됩니다. 회계연도별 프로세스 지표를 비교하면 시간에 따른 성과 개선이나 저하를 확인할 수 있습니다. 중요한 이유 문서를 고유하게 식별하는 데 필요한 정보를 제공하며, 전년 대비 프로세스 성과 분석을 지원합니다. 확보 방법 SAP S/4HANA 테이블 BKPF의 필드 GJAHR(회계연도)입니다. 예시 202320242022 | |||
Record to Report - 분개 활동
| 활동 | 설명 | ||
|---|---|---|---|
| 검토를 위해 분개 제출 | 분개 작성자가 검토 및 승인 워크플로를 시작하도록 문서를 공식 제출합니다. 이 활동은 데이터 입력에서 공식 통제 절차로 넘어가는 시점이며 승인 주기를 시작합니다. | ||
| 중요한 이유 이 시점부터 승인 주기 시간을 측정합니다. 여기서 최종 승인 또는 반려까지 걸리는 시간을 측정하면 검토 및 승인 단계의 병목을 구분해 파악할 수 있습니다. 확보 방법 비즈니스 객체와 연결된 워크플로 로그(테이블 SWW_WIHEAD, SWWLOG)에서 확인하는 경우가 많습니다. 문서 헤더(BKPF)의 사용자 정의 필드에서 상태 변경을 확인해 추정할 수도 있습니다. 기록 워크플로 항목 생성 타임스탬프 또는 상태 필드가 '제출됨'이나 '검토 중'으로 변경된 시점을 사용합니다. 이벤트 유형 inferred | |||
| 분개 반제 | 분개의 미결 항목이 다른 전기와 상계됩니다. 예를 들어 지급으로 송장을 반제하는 경우입니다. 이 활동은 특정 개별 항목을 대사해 마감하는 것을 의미합니다. | ||
| 중요한 이유 특히 임시 계정이나 미결 항목 관리 계정과 관련된 많은 분개에서 이 활동은 최종 대사 단계입니다. 전기부터 반제까지 걸리는 시간을 분석하면 대사 효율을 측정할 수 있습니다. 확보 방법 개별 항목 테이블(BSEG 또는 ACDOCA 뷰)에서 이 이벤트를 추정합니다. 항목이 반제되면 해당 항목의 반제일(AUGDT)과 반제 문서(AUGBL) 필드가 채워집니다. 기록 이벤트 타임스탬프에는 개별 항목의 반제일(BSEG-AUGDT)을 사용합니다. 이벤트 유형 inferred | |||
| 분개 생성 | 시스템에서 분개 문서를 처음 생성하는 활동입니다. 레코드는 헤더 테이블(BKPF)에 생성되지만 아직 총계정원장에 전기되지는 않았습니다. 분개 처리 이력은 여기서 시작됩니다. | ||
| 중요한 이유 이 활동은 프로세스의 주요 시작 이벤트입니다. 이 시점부터 전기까지 걸리는 시간을 분석하면 전체 처리 주기를 측정하고 초기 데이터 입력 지연을 찾을 수 있습니다. 확보 방법 문서 번호(BELNR)에 해당하는 생성일(CPUDT)과 생성 시간(CPUTM) 필드를 사용해 SAP 테이블 BKPF에서 이 이벤트를 직접 확인할 수 있습니다. 기록 이벤트 타임스탬프에는 BKPF-CPUDT와 BKPF-CPUTM을 사용합니다. 이벤트 유형 explicit | |||
| 분개 승인 | 권한이 있는 관리자가 분개를 최종 승인해 유효성과 정확성을 확인합니다. 이 활동은 문서를 총계정원장에 전기하기 전 마지막 관문입니다. | ||
| 중요한 이유 승인 주기를 마무리하는 중요한 단계입니다. 이 단계까지 걸리는 시간은 전체 프로세스 기간의 주요 요소이며 승인자 효율을 보여 주는 지표입니다. 확보 방법 최종 승인 단계를 보여 주는 워크플로 로그나 문서 상태 변경을 통해 이 이벤트를 추정합니다. 승인자의 사용자 ID와 타임스탬프는 워크플로 데이터나 변경 로그에서 확인할 수 있습니다. 기록 워크플로 로그에서 최종 승인 단계의 타임스탬프를 확인하거나 변경 문서에서 상태가 '승인됨'으로 변경된 시점을 확인합니다. 이벤트 유형 inferred | |||
| 분개 전기 | 분개가 총계정원장에 공식 기록되어 회사의 재무제표에 반영됩니다. 이 시점부터 문서는 영구적인 재무 기록이 됩니다. | ||
| 중요한 이유 이 단계는 주요 성공 지표이며 핵심 처리 주기의 종료를 나타냅니다. 전기된 분개의 처리량과 이 단계까지 걸리는 시간은 process mining의 기본 지표입니다. 확보 방법 BKPF 테이블의 전기일(BUDAT)로 확인할 수 있는 명시적 이벤트입니다. 전기된 문서는 문서 상태(BSTAT)가 비어 있으며, 임시 저장('V') 또는 보류('D') 문서와 구분됩니다. 기록 이벤트 타임스탬프에는 전기일(BKPF-BUDAT)과 입력일(BKPF-CPUDT)을 사용합니다. BKPF-BSTAT가 비어 있으면 전기된 문서입니다. 이벤트 유형 explicit | |||
| 분개 취소 처리 | 이미 전기된 분개를 반대 전기로 새 문서를 생성해 취소합니다. 전기된 문서의 오류를 수정하기 위한 작업이며, 명시적으로 기록되어 감사할 수 있는 거래입니다. | ||
| 중요한 이유 취소는 전기된 문서에 오류가 있었음을 나타냅니다. 취소율이 높으면 승인 프로세스나 데이터 입력 품질에 근본적인 문제가 있을 수 있습니다. 취소를 추적하면 최초 처리 정확도를 높이는 데 도움이 됩니다. 확보 방법 취소는 명시적 이벤트입니다. 새 취소 문서의 헤더(BKPF)에 있는 취소 문서 번호(STBLG) 필드가 원본 문서를 가리킵니다. 새 문서의 전기일이 이벤트 시점입니다. 기록 BKPF-STBLG가 채워진 문서를 찾습니다. 이벤트 타임스탬프는 취소 문서의 전기일입니다. 이벤트 유형 explicit | |||
| 분개 반려 | 검토자나 승인자가 분개를 반려해 전기를 막습니다. 일반적으로 문서는 수정을 위해 작성자에게 돌아가며 재작업이 시작됩니다. | ||
| 중요한 이유 반려를 추적하면 프로세스 품질을 파악하고 반복되는 오류를 찾을 수 있습니다. 반려율이 높다면 데이터 정확성, 정책 이해도 또는 증빙 문서의 충분성에 문제가 있을 수 있습니다. 확보 방법 워크플로 로그나 분개 문서의 사용자 정의 상태 필드에서 상태 변경을 확인해 이 이벤트를 추정합니다. 관련 상태 필드의 변경 문서 로그(CDHDR/CDPOS)에서 타임스탬프를 확인할 수 있습니다. 기록 변경 문서(CDHDR/CDPOS) 또는 워크플로 로그에서 상태 필드가 '반려됨'으로 변경된 시점을 확인합니다. 이벤트 유형 inferred | |||
| 분개 수정 | 사용자가 분개가 반려되거나 수정 요청과 함께 반환된 후 내용을 변경합니다. 검토 과정에서 확인된 문제를 해결하고 다시 제출하기 위해 필요한 재작업을 나타냅니다. | ||
| 중요한 이유 이 활동으로 재작업이 반복되는 횟수를 측정할 수 있습니다. 수정 빈도와 소요 시간을 분석하면 비효율의 원인을 찾고 교육 및 프로세스 명확화 기회를 확인할 수 있습니다. 확보 방법 이전에 '반려됨' 상태였던 문서의 BKPF 테이블에서 '최종 변경일'(AEDAT)을 추적해 추정할 수 있습니다. 변경 문서를 확인하면 변경된 내용을 더 구체적으로 파악할 수 있습니다. 기록 반려 후 변경 시점은 변경 문서 헤더(CDHDR-UDATE)의 타임스탬프를 사용합니다. 이벤트 유형 inferred | |||
| 분개 임시 저장 | 사용자가 미완성 분개를 전기하지 않고 저장해 나중에 작성하거나 검토할 수 있도록 합니다. 이 작업으로 문서 헤더 레코드가 생성되고 상태가 '임시 저장'으로 설정되어 전기 전 상태로 유지됩니다. | ||
| 중요한 이유 임시 저장은 제출 전에 흔히 거치는 단계입니다. 임시 저장 상태가 지속된 시간을 추적하면 공식 검토 및 승인 절차가 시작되기 전 데이터 작성과 준비 과정의 지연을 파악할 수 있습니다. 확보 방법 BKPF 테이블에서 문서 상태 필드(BSTAT)의 값이 'V'이면 임시 저장된 문서입니다. 이벤트 타임스탬프는 생성일(CPUDT)입니다. 기록 생성 시점에 BKPF-BSTAT = 'V'인 문서를 필터링합니다. 이벤트 유형 explicit | |||
| 수동 전기 확인 | 분개가 자동 인터페이스나 배치 작업이 아닌 수동 트랜잭션 코드로 전기되었습니다. 이는 시간상 발생하는 이벤트가 아니라 전기 활동의 분류입니다. | ||
| 중요한 이유 수동 전기를 파악하는 것은 자동화 추진에 중요합니다. 수동 전기 비율이 높다면 하위 시스템을 통합하거나 자동 전기 프로그램을 사용해 프로세스를 간소화할 기회가 있음을 나타냅니다. 확보 방법 문서 헤더 테이블(BKPF)의 트랜잭션 코드(TCODE) 필드를 분석해 계산합니다. 알려진 수동 T-Code 목록(예: FB01, F-02, FB50)을 사용해 분개를 분류합니다. 기록 전기 시점의 BKPF-TCODE를 사전에 정의한 수동 트랜잭션 코드 목록과 대조해 이벤트를 분류합니다. 이벤트 유형 calculated | |||
| 전기 후 분개 변경 | 사용자가 분개를 총계정원장에 전기한 후 제한된 일부 필드를 수정합니다. 전기 후 대부분의 재무 데이터는 변경할 수 없지만 텍스트나 지정 항목 등의 일부 필드는 수정할 수 있습니다. | ||
| 중요한 이유 이 활동은 규정 준수와 관련된 중요한 경고 신호입니다. 전기 후 변경은 기록을 조작하려는 시도일 수 있으므로 사기를 방지하고 데이터 무결성을 보장하기 위해 면밀히 모니터링해야 합니다. 확보 방법 변경 문서 테이블(CDHDR 및 CDPOS)에서 신뢰성 있게 추정할 수 있습니다. 문서 번호에 해당하는 CDHDR 항목의 변경일이 전기일 이후라면 전기 후 변경이 발생한 것입니다. 기록 CDHDR에서 변경 타임스탬프(UDATE/UTIME)가 문서 전기일(BKPF-BUDAT) 이후인 레코드를 찾습니다. 이벤트 유형 inferred | |||
| 증빙 문서 첨부 | 사용자가 송장이나 스프레드시트 등의 증빙 문서를 분개에 하나 이상 첨부합니다. 일반적으로 검토 및 감사 과정에서 금융 거래의 근거와 맥락을 제공하기 위한 작업입니다. | ||
| 중요한 이유 검토 전에 증빙 문서를 첨부하는 것은 규정 준수와 승인 효율에 중요합니다. 이 활동을 통해 문서화 정책 준수 여부와 승인 주기에 미치는 영향을 측정할 수 있습니다. 확보 방법 일반적으로 Generic Object Services(GOS)를 통해 연결된 첨부 파일의 생성 타임스탬프를 확인해 추정합니다. SRGBTBREL 테이블은 비즈니스 객체(예: BKPF 문서)와 첨부 파일을 연결합니다. 기록 GOS 첨부 파일 테이블(예: SRGBTBREL)에서 BKPF 객체와 연결된 항목을 조회하고 첨부 파일 생성 타임스탬프를 사용합니다. 이벤트 유형 inferred | |||
데이터 추출 가이드
단계
- 사전 요건 및 액세스 권한 확인: SAP S/4HANA의 기본 데이터베이스를 조회하거나 ABAP 보고서를 실행할 수 있는 권한이 있는 사용자 계정을 준비합니다. CDS 뷰 I_JournalEntry, I_JournalEntryItem과 CDHDR, CDPOS, SRGBREL, SOOD, SWW_WI2OBJ, SWWLOGHIST 테이블에 대한 읽기 권한이 필요합니다. 일반적으로 SAP HANA Studio, DBeaver와 같은 데이터베이스 클라이언트나 Eclipse용 SAP ABAP Development Tools(ADT)를 통해 액세스합니다.
- 시스템별 설정 확인: 쿼리를 실행하기 전에 분개 승인 워크플로에서 사용하는 작업 코드를 확인합니다. SAP 워크플로 관리 담당자에게 문의해 제출, 거부, 승인 이벤트에 해당하는 작업 ID(예: TS12345678)를 확인합니다. 최종 쿼리의 자리표시자에 이 값이 필요합니다.
- SQL 쿼리 준비:
query섹션에 제공된 전체 SQL 쿼리를 사용할 SQL 클라이언트나 개발 도구에 복사합니다. - 쿼리 매개변수 설정: 쿼리에서 자리표시자를 찾아 실제 값으로 바꿉니다.
[YourCompanyCode],[StartDate],[EndDate]를 설정하고, 이전 단계에서 확인한 값으로 워크플로 작업 ID 자리표시자([Workflow Submitted Task ID],[Workflow Rejected Task ID],[Workflow Approved Task ID])도 바꿉니다. - 추출 쿼리 실행: 수정한 SQL 쿼리를 SAP S/4HANA 데이터베이스에서 실행합니다. 날짜 범위와 데이터 양에 따라 실행에 상당한 시간이 걸릴 수 있으므로 업무 외 시간에 실행하는 것이 좋습니다.
- 초기 결과 검토: 쿼리 실행이 끝나면 결과의 처음 몇 행을 확인해 JournalEntryId, ActivityName, EventTime 등의 열에 예상한 값이 채워졌는지 살펴봅니다. 결과에는 분개 처리 과정에서 발생한 각기 다른 비즈니스 이벤트가 한 행씩 포함되어야 합니다.
- CSV로 데이터 내보내기: SQL 도구에서 전체 결과를 하나의 CSV 파일로 내보냅니다. 특수 문자 문제를 방지하려면 UTF-8 인코딩을 사용합니다.
- 업로드 준비: process mining 도구에 업로드하기 전에 CSV 파일에 필요한 헤더가 있는지 확인합니다. 데이터가 이미 이벤트 로그 형식으로 구성되어 있으므로 추가 변환이나 피벗 작업은 필요하지 않습니다.
구성
- Core Data Services(CDS) 뷰: 추출에는 헤더 데이터용
I_JournalEntry와 항목 및 금액 세부 정보용I_JournalEntryItem이 주로 사용됩니다. 이 뷰는 통합 분개장(ACDOCA)에 간결하고 의미가 명확한 인터페이스를 제공합니다. - 관련 테이블: 프로세스 전체를 확인하기 위해 쿼리는 다음과 같은 표준 SAP 테이블도 조인합니다.
- 문서 변경 내역을 추적하는
CDHDR및CDPOS. - Generic Object Services(GOS)를 통해 첨부 파일이 연결된 시점을 확인하는
SRGBREL및SOOD. - 승인 워크플로의 주요 이벤트를 추출하는
SWW_WI2OBJ및SWWLOGHIST.
- 문서 변경 내역을 추적하는
- 날짜 범위 필터링: 성능을 관리하려면 특정 날짜 범위로 데이터를 필터링해야 합니다.
WHERE절에서I_JournalEntry.CreationDateTime필드를 사용합니다. 초기 분석에는 3~6개월 범위를 권장합니다. - 조직 필터링: 관련 법인만 추출하도록 항상
CompanyCode로 필터링합니다. 대규모 시스템에서 모든 회사 코드를 한 번에 조회하면 실행 시간이 매우 길어질 수 있습니다. - 워크플로 작업 ID: 쿼리에는 워크플로 작업 ID 자리표시자(예:
[Workflow Approved Task ID])가 있습니다. 이 값은 SAP 설치 환경마다 다르므로 워크플로 활동을 추출하려면 올바르게 설정해야 합니다. 설정하지 않으면 제출, 승인, 거부 이벤트가 추출되지 않습니다. - 사전 요건: 쿼리를 실행하는 사용자에게 재무, 시스템 및 워크플로 테이블을 읽을 수 있는 폭넓은 권한이 필요합니다. 이러한 권한은 기본으로 제공되지 않으므로 별도로 부여해야 합니다.
샘플 쿼리 sql
WITH JournalEntryAmountCTE AS (
SELECT
CompanyCode,
AccountingDocument,
FiscalYear,
SUM(AmountInCompanyCodeCurrency) AS AmountInLocalCurrency
FROM I_JournalEntryItem
GROUP BY CompanyCode, AccountingDocument, FiscalYear
),
JournalEntryBaseCTE AS (
SELECT
JE.CompanyCode,
JE.AccountingDocument,
JE.FiscalYear,
JE.CreatedByUser,
JE.CreationDateTime,
JE.PostingDateTime,
JE.PostingDate,
JE.AccountingDocumentType,
JE.DocumentIsParked,
JE.ReversedJournalEntry,
JE.TransactionCode,
JEA.AmountInLocalCurrency
FROM I_JournalEntry AS JE
LEFT JOIN JournalEntryAmountCTE AS JEA
ON JE.CompanyCode = JEA.CompanyCode
AND JE.AccountingDocument = JEA.AccountingDocument
AND JE.FiscalYear = JEA.FiscalYear
WHERE JE.CompanyCode IN ('[YourCompanyCode]')
AND JE.CreationDateTime BETWEEN '[StartDate]' AND '[EndDate]'
)
-- 1. Journal Entry Created
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Created' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
UNION ALL
-- 2. Journal Entry Parked
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Parked' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 3. Supporting Documentation Attached
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Supporting Documentation Attached' AS "ActivityName",
TO_TIMESTAMP(SOOD.CREDAT || ' ' || SOOD.CRETIM, 'YYYYMMDD HH24MISS') AS "EventTime",
SOOD.OWNER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SRGBREL ON SRGBREL.INSTID_A = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND SRGBREL.TYPEID_A = 'BKPF'
AND SRGBREL.CATID_A = 'BO'
JOIN SOOD ON SOOD.OBJTP = SRGBREL.TYPEID_B
AND SOOD.OBJYR = SRGBREL.INSTID_B(3)
AND SOOD.OBJNO = SRGBREL.INSTID_B(5)
UNION ALL
-- 4. Journal Submitted For Review
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Submitted For Review' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Submitted Task ID]'
UNION ALL
-- 5. Journal Entry Rejected
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Rejected' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Rejected Task ID]'
UNION ALL
-- 6. Journal Entry Corrected (changed while parked)
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Corrected' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 7. Journal Entry Approved
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Approved' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Approved Task ID]'
UNION ALL
-- 8. Manual Posting Identified
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Manual Posting Identified' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL AND BJE.TransactionCode IN ('FB01', 'F-02', 'FB50', 'FV50', 'FBB1', 'FBV1')
UNION ALL
-- 9. Journal Entry Posted
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Posted' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL
UNION ALL
-- 10. Journal Entry Changed After Posting
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Changed After Posting' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.PostingDateTime IS NOT NULL AND TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') > BJE.PostingDateTime
UNION ALL
-- 11. Journal Entry Cleared
SELECT
JEI.AccountingDocument AS "JournalEntryId",
'Journal Entry Cleared' AS "ActivityName",
MIN(JEI.ClearingDateTime) AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser", -- Note: Clearing user is not directly available here
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM I_JournalEntryItem AS JEI
JOIN JournalEntryBaseCTE AS BJE ON JEI.AccountingDocument = BJE.AccountingDocument
AND JEI.CompanyCode = BJE.CompanyCode
AND JEI.FiscalYear = BJE.FiscalYear
WHERE JEI.ClearingDateTime IS NOT NULL
GROUP BY JEI.AccountingDocument, BJE.CreatedByUser, BJE.CompanyCode, BJE.AccountingDocumentType, BJE.PostingDate, BJE.AmountInLocalCurrency
UNION ALL
-- 12. Journal Entry Reversal Processed
SELECT
OriginalDoc.AccountingDocument AS "JournalEntryId",
'Journal Entry Reversal Processed' AS "ActivityName",
ReversalDoc.PostingDateTime AS "EventTime",
ReversalDoc.CreatedByUser AS "CreatedByUser",
OriginalDoc.CompanyCode AS "CompanyCode",
OriginalDoc.AccountingDocumentType AS "JournalEntryType",
OriginalDoc.PostingDate AS "PostingDate",
OriginalDoc.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS ReversalDoc
JOIN JournalEntryBaseCTE AS OriginalDoc
ON ReversalDoc.ReversedJournalEntry = OriginalDoc.AccountingDocument
AND ReversalDoc.CompanyCode = OriginalDoc.CompanyCode
AND ReversalDoc.ReversalFiscalYear = OriginalDoc.FiscalYear
WHERE ReversalDoc.ReversedJournalEntry IS NOT NULL; 단계
- SAP HANA 데이터베이스에 직접 SQL로 액세스하는 것이 승인되었는지, 추출 사용자에게 BKPF와 ACDOCA 및 시스템에 필요한 워크플로, 첨부 파일, 변경 이력, 반제, 역분개 데이터 원본에 대한 읽기 권한이 있는지 확인합니다. 데이터베이스에 직접 액세스할 때는 일반적으로 SAP HANA Database Explorer, SAP HANA Studio 또는 승인된 SQL 클라이언트를 사용합니다. 시스템에서 명시적으로 지원하지 않는 한 SAP 애플리케이션 트랜잭션에서 추출 쿼리를 실행하지 마세요.
- 클라이언트 필드, 회사 코드 필드, 회계연도 필드, 문서 번호 필드, 문서 유형 필드, 전기일 필드, 생성일 필드, 생성 시간 필드, 사용자 필드, 현지 통화 금액 필드, 역분개 또는 반제 필드를 포함해 BKPF와 ACDOCA의 실제 스키마를 확인합니다. SAP S/4HANA 배포 환경에 따라 스키마와 필드 사용 가능 여부가 다를 수 있으므로 쿼리의 대괄호로 표시된 자리표시자를 시스템에서 확인한 필드로 바꿉니다.
- 워크플로 및 첨부 파일 이벤트의 기준 데이터 원본을 확인합니다. BKPF와 ACDOCA에는 회계 문서와 개별 항목 데이터가 있지만, 보류, 제출, 반려, 수정, 승인 또는 첨부 파일 이벤트가 모두 안정적으로 기록되는 것은 아닙니다. 대괄호로 표시된 워크플로 및 첨부 파일 원본 자리표시자를 해당 시스템에서 승인된 View나 테이블로 바꿉니다. 원본을 사용할 수 없다면 이벤트를 임의로 만들지 마세요. 해당 원본을 설정하거나 문서화된 승인을 받아 활동을 제외합니다.
- 필요한 기간, 회사 코드, 문서 유형, 클라이언트에 맞게 추출 매개변수를 설정합니다. 초기 검증에는 3~6개월 범위를 권장합니다. 합의된 프로세스 범위에 따라 운영 이벤트에는 이벤트 타임스탬프 범위를, 회계 이벤트에는 전기일 범위를 사용합니다.
- 승인된 HANA SQL 클라이언트에서 전체 SQL 쿼리를 실행합니다. 쿼리는 명시적으로 추출한 각 활동에 대해 이벤트 행 하나를 생성합니다. 회계 이벤트에는 BKPF와 ACDOCA를 사용하고, 워크플로, 첨부 파일, 변경, 반제, 역분개 이벤트에는 설정된 원본 View를 사용합니다. 문서가 존재한다는 이유만으로 활동을 추정하지 않습니다.
- 출력 스키마를 확인합니다. JournalEntryId는 케이스 식별자, ActivityName은 활동 레이블, EventTime은 이벤트 타임스탬프이며, 사용 가능한 경우 권장 업무 속성도 반환됩니다. EventTime이 타임스탬프인지, 모든 행에 JournalEntryId와 ActivityName 값이 있는지 확인합니다.
- 선택한 클라이언트, 회사 코드, 회계연도, 기간에 해당하는 BKPF의 예상 데이터와 고유 JournalEntryId 수를 비교해 회계 데이터 범위를 대조합니다. 워크플로 및 첨부 파일 데이터는 보존 기간과 타임스탬프 기준이 회계 데이터와 다를 수 있으므로 각각 별도로 대조합니다.
- 이벤트 순서와 중복 처리 방식을 검증합니다. 프로세스 설계상 개별 항목 수준의 이벤트가 필요한 경우가 아니라면 ACDOCA의 여러 개별 항목이 회계 이벤트 중복을 만들지 않도록 합니다. 쿼리의 집계 로직을 사용해 분개 및 이벤트 유형별로 회계 이벤트를 하나씩 생성하고, 사용 가능한 경우 설정된 원본 이벤트 식별자는 유지합니다.
- 결과를 UTF-8 CSV 또는 ProcessMind에서 지원하는 다른 표 형식으로 내보냅니다. JournalEntryId, ActivityName, EventTime 열 이름은 그대로 유지합니다. 파일을 JournalEntryId와 EventTime 순으로 정렬하고 추가 속성은 열로 보존합니다. 파일을 ProcessMind에 업로드한 뒤 JournalEntryId를 케이스 식별자, ActivityName을 활동, EventTime을 이벤트 타임스탬프로 설정합니다.
구성
- 기간: 먼저 3~6개월 범위로 시작합니다. 성능을 시험할 때는 더 짧은 기간을 사용하고, 행 수와 이벤트 범위를 검증한 뒤에만 기간을 늘립니다.
- 클라이언트 및 회사 범위: [Client parameter]를 설정하고 CompanyCode를 필요한 법인으로 제한합니다. 클라이언트가 여러 개인 시스템에서는 클라이언트 조건을 반드시 포함합니다.
- 회계 범위: [Document type filter]를 설정하고 필요한 경우 회계연도와 전기일 필터도 적용합니다. 선택한 원본에서 안정적으로 확인할 수 있는 경우에만 전기 문서와 미전기 문서를 모두 포함합니다.
- 워크플로 범위: [Workflow event source]와 제출, 반려, 수정, 승인 활동에 해당하는 이벤트 유형 매핑을 설정합니다. 타임스탬프가 워크플로 작업의 생성, 실행, 완료 중 어느 시점을 나타내는지 확인합니다.
- 첨부 파일 범위: [Attachment event source]와 첨부 파일을 분개에 연결하는 관계 필드를 설정합니다. 원본에 첨부 파일 생성, 교체, 삭제 중 어떤 작업이 기록되는지 확인합니다.
- 변경 범위: 전기 후 변경을 확인할 [Change history source]를 설정합니다. 원본에서 분개를 식별할 수 있고 신뢰할 수 있는 변경 타임스탬프를 제공하는지 확인합니다.
- 반제 범위: [Clearing source]와 반제된 회계 문서 및 반제 문서 간의 관계를 설정합니다. 이벤트를 원래 분개, 반제 문서 또는 양쪽 중 어디에 연결할지 결정합니다.
- 역분개 범위: [Reversal source]와 원본 문서 및 역분개 문서 간의 관계를 설정합니다. 해당 관계를 확인할 수 있으면 쿼리는 역분개 활동을 원래 JournalEntryId에 연결합니다.
- 수기 전기 분류: [Manual posting source] 또는 검증된 전기 출처 필드를 설정합니다. Manual Posting Identified는 분류 이벤트이므로 전기 타임스탬프나 승인된 다른 타임스탬프를 일관되게 사용해야 합니다.
- 통화 금액: ACDOCA는 개별 항목 단위로 구성됩니다. 쿼리는 분개별 현지 통화 금액을 집계합니다. 부호 규칙과 통계, 원장별 또는 확장 원장 행의 포함 여부를 확인합니다.
- 성능: 필요한 열만 선택하고, 초기에 필터를 적용하며, ACDOCA 전체를 제한 없이 조회하지 않습니다. 승인된 보고 시간대에 실행합니다. 지원되는 경우 클라이언트, 회계연도, 회사 코드, 전기일 조건으로 파티션을 줄입니다.
- 중복 처리: 사용 가능한 경우 원본 이벤트 식별자를 사용합니다. 원본에 동일한 기술 레코드가 반복될 수 있다면 실제로 별개인 워크플로 작업은 합치지 않도록 문서화된 중복 제거 규칙을 적용합니다.
- 사전 요건: 필요한 데이터베이스 권한, 승인된 SAP HANA 연결, 설정된 워크플로 및 첨부 파일 원본에 대한 액세스, 적절한 SAP Financial Accounting 및 워크플로 설정, ProcessMind에서 지원하는 내보내기 형식이 필요합니다.
샘플 쿼리 sql
WITH
accounting_base AS (
SELECT
b.[Client field] AS ClientId,
b.[Company code field] AS CompanyCode,
b.[Fiscal year field] AS FiscalYear,
b.[Document number field] AS AccountingDocumentNumber,
b.[Document type field] AS JournalEntryType,
b.[Created by field] AS CreatedByUser,
b.[Document date field] AS DocumentDate,
b.[Posting date field] AS PostingDate,
b.[Creation date field] AS CreationDate,
b.[Creation time field] AS CreationTime,
b.[Reversal document field] AS ReversalDocumentNumber,
b.[Reversed document field] AS ReversedDocumentNumber,
b.[Reversal fiscal year field] AS ReversalFiscalYear,
SUM(a.[Local currency amount field]) AS AmountInLocalCurrency,
MAX(a.[Local currency field]) AS LocalCurrency
FROM [Your schema].[BKPF] b
INNER JOIN [Your schema].[ACDOCA] a
ON a.[Client field] = b.[Client field]
AND a.[Company code field] = b.[Company code field]
AND a.[Fiscal year field] = b.[Fiscal year field]
AND a.[Document number field] = b.[Document number field]
WHERE b.[Client field] = '[Client parameter]'
AND b.[Company code field] IN ([Company code filter])
AND b.[Posting date field] BETWEEN '[Start date parameter]' AND '[End date parameter]'
AND b.[Document type field] IN ([Document type filter])
GROUP BY
b.[Client field],
b.[Company code field],
b.[Fiscal year field],
b.[Document number field],
b.[Document type field],
b.[Created by field],
b.[Document date field],
b.[Posting date field],
b.[Creation date field],
b.[Creation time field],
b.[Reversal document field],
b.[Reversed document field],
b.[Reversal fiscal year field]
),
base_cases AS (
SELECT
ClientId,
CompanyCode,
FiscalYear,
AccountingDocumentNumber,
CAST(CompanyCode || '/' || FiscalYear || '/' || AccountingDocumentNumber AS NVARCHAR(100)) AS JournalEntryId,
JournalEntryType,
CreatedByUser,
PostingDate,
AmountInLocalCurrency,
LocalCurrency,
CreationDate,
CreationTime,
ReversalDocumentNumber,
ReversedDocumentNumber,
ReversalFiscalYear
FROM accounting_base
),
created_events AS (
SELECT
JournalEntryId,
'Journal Entry Created' AS ActivityName,
CAST(CreationDate || ' ' || CreationTime AS TIMESTAMP) AS EventTime,
CreatedByUser,
CompanyCode,
JournalEntryType,
PostingDate,
AmountInLocalCurrency,
LocalCurrency
FROM base_cases
),
parked_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Parked' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Parked event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
attachment_events AS (
SELECT
CAST(x.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Supporting Documentation Attached' AS ActivityName,
CAST(x.[Event timestamp field] AS TIMESTAMP) AS EventTime,
x.[User field] AS CreatedByUser,
x.[Company code field] AS CompanyCode,
x.[Journal entry type field] AS JournalEntryType,
x.[Posting date field] AS PostingDate,
x.[Amount in local currency field] AS AmountInLocalCurrency,
x.[Local currency field] AS LocalCurrency
FROM [Your schema].[Attachment event source] x
WHERE x.[Client field] = '[Client parameter]'
AND x.[Event type field] = '[Attachment created event type]'
AND CAST(x.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
submitted_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Submitted For Review' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Submitted event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
rejected_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Rejected' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Rejected event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
corrected_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Corrected' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Corrected event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
approved_events AS (
SELECT
CAST(w.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Approved' AS ActivityName,
CAST(w.[Event timestamp field] AS TIMESTAMP) AS EventTime,
w.[User field] AS CreatedByUser,
w.[Company code field] AS CompanyCode,
w.[Journal entry type field] AS JournalEntryType,
w.[Posting date field] AS PostingDate,
w.[Amount in local currency field] AS AmountInLocalCurrency,
w.[Local currency field] AS LocalCurrency
FROM [Your schema].[Workflow event source] w
WHERE w.[Client field] = '[Client parameter]'
AND w.[Event type field] = '[Approved event type]'
AND CAST(w.[Event timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
manual_events AS (
SELECT
JournalEntryId,
'Manual Posting Identified' AS ActivityName,
CAST(PostingDate AS TIMESTAMP) AS EventTime,
CreatedByUser,
CompanyCode,
JournalEntryType,
PostingDate,
AmountInLocalCurrency,
LocalCurrency
FROM base_cases
WHERE [Manual posting condition verified for this system]
),
posted_events AS (
SELECT
JournalEntryId,
'Journal Entry Posted' AS ActivityName,
CAST(PostingDate AS TIMESTAMP) AS EventTime,
CreatedByUser,
CompanyCode,
JournalEntryType,
PostingDate,
AmountInLocalCurrency,
LocalCurrency
FROM base_cases
WHERE [Posted document condition verified for this system]
),
changed_events AS (
SELECT
CAST(c.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Changed After Posting' AS ActivityName,
CAST(c.[Change timestamp field] AS TIMESTAMP) AS EventTime,
c.[User field] AS CreatedByUser,
c.[Company code field] AS CompanyCode,
c.[Journal entry type field] AS JournalEntryType,
c.[Posting date field] AS PostingDate,
c.[Amount in local currency field] AS AmountInLocalCurrency,
c.[Local currency field] AS LocalCurrency
FROM [Your schema].[Change history source] c
WHERE c.[Client field] = '[Client parameter]'
AND c.[Post posting change indicator field] = '[Post posting change value]'
AND CAST(c.[Change timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
cleared_events AS (
SELECT
CAST(cl.[Journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Cleared' AS ActivityName,
CAST(cl.[Clearing timestamp field] AS TIMESTAMP) AS EventTime,
cl.[User field] AS CreatedByUser,
cl.[Company code field] AS CompanyCode,
cl.[Journal entry type field] AS JournalEntryType,
cl.[Posting date field] AS PostingDate,
cl.[Amount in local currency field] AS AmountInLocalCurrency,
cl.[Local currency field] AS LocalCurrency
FROM [Your schema].[Clearing source] cl
WHERE cl.[Client field] = '[Client parameter]'
AND CAST(cl.[Clearing timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
),
reversal_events AS (
SELECT
CAST(r.[Original journal entry ID field] AS NVARCHAR(100)) AS JournalEntryId,
'Journal Entry Reversal Processed' AS ActivityName,
CAST(r.[Reversal timestamp field] AS TIMESTAMP) AS EventTime,
r.[User field] AS CreatedByUser,
r.[Company code field] AS CompanyCode,
r.[Journal entry type field] AS JournalEntryType,
r.[Posting date field] AS PostingDate,
r.[Amount in local currency field] AS AmountInLocalCurrency,
r.[Local currency field] AS LocalCurrency
FROM [Your schema].[Reversal source] r
WHERE r.[Client field] = '[Client parameter]'
AND CAST(r.[Reversal timestamp field] AS DATE) BETWEEN '[Start date parameter]' AND '[End date parameter]'
)
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM created_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM parked_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM attachment_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM submitted_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM rejected_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM corrected_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM approved_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM manual_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM posted_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM changed_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM cleared_events
UNION ALL
SELECT JournalEntryId, ActivityName, EventTime, CreatedByUser, CompanyCode, JournalEntryType, PostingDate, AmountInLocalCurrency, LocalCurrency FROM reversal_events
ORDER BY JournalEntryId, EventTime, ActivityName; 단계
- ABAP 프로그램 생성: 트랜잭션 코드
SE38을 사용해 ABAP Editor를 엽니다. 새 프로그램 이름(예:Z_PM_JE_EXTRACT)을 입력하고 'Create'를 클릭합니다. 적절한 제목을 입력하고 'Type'을 'Executable Program'으로 설정한 뒤 로컬 객체나 패키지에 저장합니다. - 선택 화면 정의: 프로그램에서 사용자가 데이터를 필터링할 수 있도록 매개변수와 선택 옵션을 정의합니다. 분개 생성일 범위(
P_CPUDT_FR,P_CPUDT_TO), 회사 코드 선택 옵션(SO_BUKRS), 애플리케이션 서버의 출력 파일 경로(P_FPATH)를 포함해야 합니다. - 데이터 구조 선언: 필요한 이벤트 로그 형식에 맞는 내부 테이블 구조를 정의합니다. 이 구조에 최종 출력이 저장됩니다. 또한 BKPF, ACDOCA, CDHDR, CDPOS 및 각종 워크플로 테이블 등 조회할 SAP 테이블에 사용할 내부 테이블과 작업 영역을 선언합니다.
- 데이터 선택 로직 구현: 필요한 12개 활동의 데이터를 가져오는 ABAP 로직을 작성합니다. 코드를 체계적으로 관리할 수 있도록 활동별로 별도의 서브루틴(FORM)을 만듭니다. 예를 들어
get_created_events,get_parked_events,get_workflow_events등의 FORM을 작성합니다. - '생성' 및 '전기' 이벤트 선택: 사용자가 선택 화면에서 지정한 조건에 따라 BKPF 테이블을 읽습니다. BKPF에 항목이 있으면 문서가 생성된 것입니다. 상태가
BSTAT = ' '인 문서는 전기된 것으로 간주합니다. 생성 타임스탬프(CPUDT,CPUTM)를 이벤트 시간으로 사용합니다. - '보류' 이벤트 선택: 보류 문서 헤더를 저장하는 VBKPF 테이블을 읽습니다. 이 테이블의 생성 타임스탬프를 보류 이벤트 시간으로 사용합니다.
- '워크플로' 이벤트 선택(제출, 승인, 반려): 분개 객체를 워크플로 인스턴스에 연결하는 SWW_WI2OBJ와 특정 단계의 세부 정보 및 시간을 확인하는 SWWLOGHIST 또는 SWWIHEAD 등의 워크플로 테이블을 조회합니다. 시스템에서 제출, 승인, 반려에 사용하는 작업 ID를 확인해야 합니다.
- '변경' 및 '수정' 이벤트 선택: 변경 문서 테이블 CDHDR(헤더)과 CDPOS(항목)에서
OBJECTCLAS = 'BELEG'인 데이터를 조회합니다. '전기 후 변경'은 변경 타임스탬프가 문서 전기일 이후인 경우로 필터링합니다. '수정'은 보류 또는 반려 문서에 대한 변경으로 필터링합니다. - '역분개' 및 '반제' 이벤트 선택: BKPF의
STBLG필드(역분개 문서 번호)에 값이 있는 문서를 찾아 역분개를 식별합니다. 역분개 이벤트 시간은 역분개 문서의 생성 시간입니다. 특정 분개의 개별 항목에 대해 ACDOCA 테이블에서 가장 최근 반제일(AUGDT)을 조회해 반제 이벤트를 식별합니다. - 데이터 통합 및 정렬: 활동별 데이터를 선택할 때마다 결과를 최종 마스터 내부 테이블에 추가합니다. 모든 선택이 끝나면 각 케이스의 시간순 정렬을 위해 마스터 테이블을
JournalEntryId와EventTime기준으로 정렬합니다. - 출력 파일 생성:
OPEN DATASET,LOOP AT... TRANSFER,CLOSE DATASET문을 사용해 정렬된 최종 내부 테이블의 내용을 SAP 애플리케이션 서버에서 지정한 파일 경로에 씁니다. 파일은 헤더 행이 포함된 CSV 형식이어야 합니다. - 실행 예약: 정기적으로 추출하려면 트랜잭션 코드
SM36을 사용해Z_PM_JE_EXTRACT프로그램을 주간 또는 월간 등 지정된 일정으로 실행하는 백그라운드 작업을 만듭니다. 이렇게 하면 데이터 내보내기를 자동으로 실행할 수 있습니다.
구성
- 기간: 선택 화면에서 분개 생성일(
CPUDT) 범위를 필수로 지정해야 합니다. 성능을 유지하려면 한 번에 3~6개월 등 관리하기 쉬운 범위로 나누어 데이터를 추출하는 것이 좋습니다. - 회사 코드(
BUKRS): 프로세스 마이닝 분석에 필요한 법인만 추출하도록 제한하는 중요한 필터입니다. 모든 회사 코드를 한 번에 추출하는 것은 권장하지 않습니다. - 문서 유형(
BLART): 선택적으로 필터를 추가해 G/L 계정 전기용 'SA'나 매입처 송장용 'KR' 등 특정 분개 유형만 조회할 수 있습니다. 데이터 양을 줄이고 분석에 적합한 데이터를 추리는 데 도움이 됩니다. - 파일 경로: 프로그램은 출력 파일을 기록할 SAP 애플리케이션 서버의 논리 파일 경로가 필요합니다. 경로가 유효하고 SAP 시스템 사용자에게 해당 디렉터리에 쓸 권한이 있는지 확인합니다. 트랜잭션
AL11에서 서버 디렉터리를 관리하고 확인할 수 있습니다. - 워크플로 작업 ID: 워크플로 이벤트(제출, 승인, 반려)를 추출하는 로직에는 조직의 분개 승인 워크플로에서 사용하는 작업 ID를 설정해야 합니다. 대개 사용자 지정 값이므로 워크플로 컨설턴트나 개발자에게 확인해야 합니다.
- 사전 요건: 프로그램을 실행하는 사용자 또는 시스템 계정에는 ABAP 프로그램을 생성하고 실행할 개발 권한(
S_DEVELOP)과 재무 테이블(BKPF, ACDOCA), 변경 로그 테이블(CDHDR, CDPOS), 워크플로 테이블(SWW*)에 대한 폭넓은 읽기 권한이 필요합니다.
샘플 쿼리 abap
REPORT Z_PM_JE_EXTRACT.
*&---------------------------------------------------------------------*
*&-- Data Structures for Event Log --*
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
journalentryid TYPE string,
activityname TYPE string,
eventtime TYPE string,
createdbyuser TYPE uname,
companycode TYPE bukrs,
journalentrytype TYPE blart,
postingdate TYPE budat,
amountinlocalcurrency TYPE wrbtr,
END OF ty_event_log.
*&---------------------------------------------------------------------*
*&-- Selection Screen Definition --*
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS: p_erdat_fr TYPE dats OBLIGATORY DEFAULT sy-datum-30,
p_erdat_to TYPE dats OBLIGATORY DEFAULT sy-datum.
SELECT-OPTIONS: so_bukrs FOR bkpf-bukrs OBLIGATORY.
PARAMETERS: p_fpath TYPE string OBLIGATORY DEFAULT '/usr/sap/trans/tmp/je_event_log.csv'.
SELECTION-SCREEN END OF BLOCK b1.
*&---------------------------------------------------------------------*
*&-- Internal Tables --*
*&---------------------------------------------------------------------*
DATA: gt_event_log TYPE TABLE OF ty_event_log.
*&---------------------------------------------------------------------*
*&-- Main Processing Block --*
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM get_created_posted_events.
PERFORM get_parked_events.
PERFORM get_attachment_events.
PERFORM get_workflow_events.
PERFORM get_change_events.
PERFORM get_cleared_events.
PERFORM get_reversal_events.
SORT gt_event_log BY journalentryid eventtime.
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*&-- Subroutines for Extracting Individual Activities --*
*&---------------------------------------------------------------------*
FORM get_created_posted_events.
DATA: lt_bkpf TYPE TABLE OF bkpf,
ls_event_log TYPE ty_event_log,
lv_timestamp TYPE string.
SELECT * FROM bkpf INTO TABLE lt_bkpf
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to.
LOOP AT lt_bkpf ASSIGNING FIELD-SYMBOL(<fs_bkpf>).
CLEAR ls_event_log.
CONCATENATE <fs_bkpf>-bukrs <fs_bkpf>-belnr <fs_bkpf>-gjahr INTO ls_event_log-journalentryid.
ls_event_log-companycode = <fs_bkpf>-bukrs.
ls_event_log-journalentrytype = <fs_bkpf>-blart.
ls_event_log-postingdate = <fs_bkpf>-budat.
ls_event_log-createdbyuser = <fs_bkpf>-usnam.
" Timestamp format YYYY-MM-DDTHH:MI:SS
CONCATENATE <fs_bkpf>-cpudt(4) '-' <fs_bkpf>-cpudt+4(2) '-' <fs_bkpf>-cpudt+6(2) 'T' <fs_bkpf>-cputm(2) ':' <fs_bkpf>-cputm+2(2) ':' <fs_bkpf>-cputm+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
" Activity: Journal Entry Created
ls_event_log-activityname = 'Journal Entry Created'.
SELECT SUM( hsl ) INTO ls_event_log-amountinlocalcurrency FROM acdoca WHERE belnr = <fs_bkpf>-belnr AND gjahr = <fs_bkpf>-gjahr AND bukrs = <fs_bkpf>-bukrs.
APPEND ls_event_log TO gt_event_log.
" Activity: Journal Entry Posted (if not parked)
IF <fs_bkpf>-bstat = ' '.
ls_event_log-activityname = 'Journal Entry Posted'.
APPEND ls_event_log TO gt_event_log.
" Activity: Manual Posting Identified (based on T-Code)
CASE <fs_bkpf>-tcode.
WHEN 'FB01' OR 'F-02' OR 'FB50' OR 'F-22' OR 'F-43'.
ls_event_log-activityname = 'Manual Posting Identified'.
APPEND ls_event_log TO gt_event_log.
ENDCASE.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_parked_events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM vbkpf
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to.
CLEAR ls_event_log.
CONCATENATE vbkpf-bukrs vbkpf-belnr vbkpf-gjahr INTO ls_event_log-journalentryid.
CONCATENATE vbkpf-cpudt(4) '-' vbkpf-cpudt+4(2) '-' vbkpf-cpudt+6(2) 'T' vbkpf-cputm(2) ':' vbkpf-cputm+2(2) ':' vbkpf-cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Journal Entry Parked'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = vbkpf-usnam.
ls_event_log-companycode = vbkpf-bukrs.
ls_event_log-journalentrytype = vbkpf-blart.
ls_event_log-postingdate = vbkpf-budat.
APPEND ls_event_log TO gt_event_log.
ENDSELECT.
ENDFORM.
FORM get_attachment_events.
DATA: lt_bdocs TYPE TABLE OF srgbtbrel, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM srgbtbrel INTO TABLE lt_bdocs
WHERE typeid_a = 'BUS2081' " Object type for Accounting Document
AND catid_a = 'BO'.
LOOP AT lt_bdocs ASSIGNING FIELD-SYMBOL(<fs_bdocs>).
CHECK <fs_bdocs>-instid_a(4) IN so_bukrs.
DATA(lv_bukrs) = <fs_bdocs>-instid_a(4).
DATA(lv_belnr) = <fs_bdocs>-instid_a+4(10).
DATA(lv_gjahr) = <fs_bdocs>-instid_a+14(4).
SELECT SINGLE cpudt, cputm, usnam, blart, budat FROM bkpf
INTO (DATA(lv_cpudt), DATA(lv_cputm), DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = lv_bukrs AND belnr = lv_belnr AND gjahr = lv_gjahr.
IF sy-subrc = 0 AND lv_cpudt BETWEEN p_erdat_fr AND p_erdat_to.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
" Note: Using document creation time as a proxy for attachment time.
CONCATENATE lv_cpudt(4) '-' lv_cpudt+4(2) '-' lv_cpudt+6(2) 'T' lv_cputm(2) ':' lv_cputm+2(2) ':' lv_cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Supporting Documentation Attached'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = lv_bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_workflow_events.
" This is a simplified example. Real workflow logic can be complex.
" You must identify your specific Task IDs for these events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
DATA: BEGIN OF ls_wi, wi_id TYPE sww_wiid, cr_date TYPE sww_cd, cr_time TYPE sww_ct, task TYPE sww_task, instid TYPE swo_typeid, END OF ls_wi.
SELECT h~wi_id h~cr_date h~cr_time h~wi_rh_task o~instid
FROM swwwihead AS h
JOIN sww_wi2obj AS o ON h~wi_id = o~wi_id
INTO @ls_wi
WHERE o~typeid = 'BUS2081' AND o~catid = 'BO'
AND h~cr_date BETWEEN @p_erdat_fr AND @p_erdat_to.
DATA(lv_bukrs) = ls_wi-instid(4).
DATA(lv_belnr) = ls_wi-instid+4(10).
DATA(lv_gjahr) = ls_wi-instid+14(4).
IF lv_bukrs IN so_bukrs.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
CONCATENATE ls_wi-cr_date(4) '-' ls_wi-cr_date+4(2) '-' ls_wi-cr_date+6(2) 'T' ls_wi-cr_time(2) ':' ls_wi-cr_time+2(2) ':' ls_wi-cr_time+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-companycode = lv_bukrs.
CASE ls_wi-task.
WHEN '[Your Submit Task ID]'. " e.g., TS20000139
ls_event_log-activityname = 'Journal Submitted For Review'.
APPEND ls_event_log TO gt_event_log.
WHEN '[Your Approve Task ID]'. " e.g., TS20000142
ls_event_log-activityname = 'Journal Entry Approved'.
APPEND ls_event_log TO gt_event_log.
WHEN '[Your Reject Task ID]'. " e.g., TS20000141
ls_event_log-activityname = 'Journal Entry Rejected'.
APPEND ls_event_log TO gt_event_log.
ENDCASE.
ENDIF.
ENDSELECT.
ENDFORM.
FORM get_change_events.
DATA: lt_cdhdr TYPE TABLE OF cdhdr, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM cdhdr INTO TABLE lt_cdhdr
WHERE objectclas = 'BELEG'
AND udate BETWEEN p_erdat_fr AND p_erdat_to.
LOOP AT lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>).
DATA(lv_bukrs) = <fs_cdhdr>-objectid(4).
DATA(lv_belnr) = <fs_cdhdr>-objectid+4(10).
DATA(lv_gjahr) = <fs_cdhdr>-objectid+14(4).
IF lv_bukrs IN so_bukrs.
SELECT SINGLE bstat, budat, blart FROM bkpf
INTO (DATA(lv_bstat), DATA(lv_budat), DATA(lv_blart))
WHERE bukrs = lv_bukrs AND belnr = lv_belnr AND gjahr = lv_gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
CONCATENATE <fs_cdhdr>-udate(4) '-' <fs_cdhdr>-udate+4(2) '-' <fs_cdhdr>-udate+6(2) 'T' <fs_cdhdr>-utime(2) ':' <fs_cdhdr>-utime+2(2) ':' <fs_cdhdr>-utime+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = <fs_cdhdr>-username.
ls_event_log-companycode = lv_bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
IF lv_bstat = ' ' AND <fs_cdhdr>-udate > lv_budat.
ls_event_log-activityname = 'Journal Entry Changed After Posting'.
APPEND ls_event_log TO gt_event_log.
ELSEIF lv_bstat <> ' '.
ls_event_log-activityname = 'Journal Entry Corrected'.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_cleared_events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
DATA: BEGIN OF ls_clear, belnr TYPE belnr_d, gjahr TYPE gjahr, bukrs TYPE bukrs, augdt TYPE augdt, END OF ls_clear, lt_clear LIKE TABLE OF ls_clear.
SELECT belnr, gjahr, bukrs, MAX( augdt ) AS augdt FROM acdoca
INTO TABLE @lt_clear
WHERE bukrs IN @so_bukrs
AND augdt NE '00000000'
AND augdt BETWEEN @p_erdat_fr AND @p_erdat_to
GROUP BY belnr, gjahr, bukrs.
LOOP AT lt_clear INTO ls_clear.
SELECT SINGLE usnam, blart, budat FROM bkpf
INTO (DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = ls_clear-bukrs AND belnr = ls_clear-belnr AND gjahr = ls_clear-gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE ls_clear-bukrs ls_clear-belnr ls_clear-gjahr INTO ls_event_log-journalentryid.
CONCATENATE ls_clear-augdt(4) '-' ls_clear-augdt+4(2) '-' ls_clear-augdt+6(2) 'T12:00:00' INTO lv_timestamp. " Clearing date has no time, use midday
ls_event_log-activityname = 'Journal Entry Cleared'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = ls_clear-bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_reversal_events.
DATA: lt_reversals TYPE TABLE OF bkpf, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM bkpf INTO TABLE lt_reversals
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to
AND stblg IS NOT NULL.
LOOP AT lt_reversals ASSIGNING FIELD-SYMBOL(<fs_rev>).
SELECT SINGLE usnam, blart, budat FROM bkpf
INTO (DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = <fs_rev>-bukrs AND belnr = <fs_rev>-stblg AND gjahr = <fs_rev>-gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE <fs_rev>-bukrs <fs_rev>-stblg <fs_rev>-gjahr INTO ls_event_log-journalentryid.
CONCATENATE <fs_rev>-cpudt(4) '-' <fs_rev>-cpudt+4(2) '-' <fs_rev>-cpudt+6(2) 'T' <fs_rev>-cputm(2) ':' <fs_rev>-cputm+2(2) ':' <fs_rev>-cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Journal Entry Reversal Processed'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = <fs_rev>-bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM write_output_file.
DATA: lv_line TYPE string.
FIELD-SYMBOLS: <fs_event_log> TYPE ty_event_log.
OPEN DATASET p_fpath FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc NE 0.
MESSAGE 'Error opening file.' TYPE 'E'.
RETURN.
ENDIF.
" Write Header
lv_line = 'JournalEntryId,ActivityName,EventTime,CreatedByUser,CompanyCode,JournalEntryType,PostingDate,AmountInLocalCurrency'.
TRANSFER lv_line TO p_fpath.
LOOP AT gt_event_log ASSIGNING <fs_event_log>.
CONCATENATE <fs_event_log>-journalentryid <fs_event_log>-activityname <fs_event_log>-eventtime <fs_event_log>-createdbyuser <fs_event_log>-companycode <fs_event_log>-journalentrytype <fs_event_log>-postingdate <fs_event_log>-amountinlocalcurrency
INTO lv_line SEPARATED BY ','.
TRANSFER lv_line TO p_fpath.
ENDLOOP.
CLOSE DATASET p_fpath.
WRITE: / 'File successfully written to', p_fpath.
ENDFORM. 시작할 준비가 되셨나요?
이 템플릿을 활용해 데이터를 준비하고 Record to Report - 분개 프로세스에 관한 유용한 인사이트를 확인하세요. 지금 프로세스 개선을 시작해 보세요.
Record to Report 분개 프로세스를 간소화해 효율성 향상
프로세스를 개선해 Record to Report 분개 처리 주기를 30% 단축하세요.
신용카드가 필요하지 않습니다. 몇 분이면 설정할 수 있습니다.