您的“录入到报告 - 总账分录”数据模板
您的“录入到报告 - 总账分录”数据模板
- 全面分析的推荐属性
- 需要跟踪的关键分录活动
- SAP ECC 数据提取实用指南
记录到报告——日记账分录属性
| 名称 | 描述 | ||
|---|---|---|---|
| Event 时间 EventTime | 指示日记账分录的特定活动或事件发生的时间戳。 | ||
| 描述 事件时间 (Event Time) 提供了记账凭证流程中每个活动发生的确切日期和时间。此数据对于计算所有基于时间的指标(如周期时间、处理时长以及步骤间的延迟)至关重要。该时间戳的来源视活动而定;它可以是凭证创建日期/时间 (CPUDT/CPUTM),也可以是日志中的变更时间戳 (CDHDR-UDATE/UTIME)。 在分析中,事件时间用于按时间先后顺序排列事件,构成了流程图的基础。它是计算所有与时间相关的 KPI(如平均凭证周期时间、平均审批时间以及从批准到过账的时间)的必备要素。 为何重要 此 timestamp 是所有时间相关分析的基础,可用于计算周期时间、持续时长并识别瓶颈。 获取方式 根据活动的不同,源自各种字段,主要是 BKPF 表的创建时间戳 (CPUDT, CPUTM) 或 CDHDR 表的变更凭证时间戳 (UDATE, UTIME)。 示例 2023-10-26T09:00:00Z2023-10-26T14:30:15Z2023-10-27T11:05:00Z | |||
| 日记账分录 ID JournalEntryId | 财务会计凭证的唯一标识符,结合了公司代码、凭证编号和会计年度。 | ||
| 描述 日记账分录 ID 是用于跟踪分录生命周期的主要“个案标识符”。它是一个复合键,通常通过连接公司代码 (BUKRS)、凭证编号 (BELNR) 和会计年度 (GJAHR) 形成,以确保在整个 SAP 系统中的唯一性。 在流程分析中,此 ID 将所有相关活动(如创建、暂存、提交、审批、驳回和过账)关联起来。通过追踪此标识符,我们可以构建每笔分录的端到端路径,衡量周期时间,并识别特定分录的流程偏差或瓶颈。 为何重要 这是跟踪分录从创建到最终过账的必备主键,支持端到端流程分析和变体比较。 获取方式 这是一个派生属性,通常是 BKPF 表中字段的组合:公司代码 (BUKRS)、凭证编号 (BELNR) 和会计年度 (GJAHR)。 示例 1000-1000000123-20232000-1900000456-20231000-1800000789-2024 | |||
| 活动名称 ActivityName | 在日记账分录流程的特定时点发生的业务活动或事件的名称。 | ||
| 描述 “活动名称”描述了日记账分录生命周期中的特定步骤,例如“分录已创建”、“分录已审批”或“分录已过账”。此属性通常源自 SAP 中的多个来源,包括事务代码 (TCODE)、变更文档日志(表 CDHDR 和 CDPOS)以及凭证状态字段。 活动分析是 Process Mining 的核心。它支持流程图的可视化、步骤间转换时间的计算以及返工循环(如“分录已驳回”后接“分录已更正”)的识别。这些数据是构建周期时间、返工率和流程变体等仪表板的基础。 为何重要 它定义了流程图中的各个步骤,使可视化、分析和优化日记账分录工作流成为可能。 获取方式 派生自多个来源,包括 BKPF 中的事务代码 (TCODE)、凭证状态、SWW_WI2OBJ 等表中的工作流日志,或 CDHDR 和 CDPOS 中的变更凭证。 示例 已创建日记账分录日记账分录已审批日记账分录已驳回日记账分录已过账 | |||
| 最后数据更新 LastDataUpdate | 指示数据上次从源系统提取或刷新的时间戳。 | ||
| 描述 此属性记录了最近一次从 SAP ECC 提取数据的日期和时间。这是一个元数据字段,对于了解所分析数据的实时性和时效性至关重要。 在任何 Process Mining 仪表板或分析中,了解上次更新时间对于用户信任数据并做出明智决策都非常关键。它有助于回答“这些信息的更新程度如何?”这一问题。 为何重要 告知用户数据的实时性,确保他们了解分析的时间范围并信任分析结果。 获取方式 这是一个元数据字段,由数据提取工具或 ETL 过程在数据刷新时生成并存储。 示例 2024-05-20T04:00:00Z2024-05-21T04:00:00Z2024-05-22T04:00:00Z | |||
| 源系统 SourceSystem | 提取流程数据的来源系统。 | ||
| 描述 此属性标识数据的来源,在本例中为特定的 SAP ECC 实例。它通常是在数据提取过程中添加的静态值。 虽然简单,但此属性在具有多个 ERP 或数据源的环境中非常重要。它确保了数据血缘清晰,并允许按源系统对分析进行过滤或细分。 为何重要 提供清晰的数据血缘,对于跟踪数据质量至关重要,尤其是在拥有多个源系统的环境中。 获取方式 这通常是在数据转换过程中添加的静态值,用于标识特定的 SAP ECC 实例(例如 'ECC_PROD_100')。 示例 SAP ECC EHP8ECC_FIN_PRODSAP_ERP_60 | |||
| 事务代码 TransactionCode | 用于创建或处理日记账分录的 SAP 事务代码。 | ||
| 描述 事务代码 (T-Code) 是 SAP 中特定功能或程序的唯一标识符。对于日记账分录,它指示了分录的创建方式,例如:手动 (FB01, F-02)、通过暂存 (FV50) 或通过自动接口。 此属性对于“手动活动优化”仪表板具有极高价值。通过分析 T-Code,我们可以区分手动和自动化活动,识别哪些手动流程最耗时,并精准定位自动化机会,以减少手动工作量并提升效率。 为何重要 帮助区分手动和自动流程,识别自动化机会并推动流程标准化。 获取方式 位于凭证抬头表 BKPF,字段 TCODE。 示例 FB01F-02FV50FBD1 | |||
| 公司代码 CompanyCode | 代表编制财务报表的独立法人实体的组织单位。 | ||
| 描述 公司代码是 SAP 财务模块中的核心组织单元。它代表一个独立的法人实体,是日记账分录凭证抬头的关键字段。 此属性对于按法人实体细分流程分析至关重要。它可以比较业务不同部分的流程绩效、合规率和 KPI 结果。例如,它有助于识别审批延迟或高冲销率是否仅针对特定的公司代码。 为何重要 允许筛选和比较组织内不同法律实体或业务单元的流程绩效。 获取方式 位于凭证抬头表 BKPF,字段 BUKRS。 示例 10002000US01DE01 | |||
| 凭证类型 DocumentType | 会计凭证的分类,用于控制其处理和存储方式。 | ||
| 描述 凭证类型用于区分不同类型的业务交易,如总账分录 (SA)、供应商发票 (KR) 或资产过账 (AA)。它在系统配置期间定义并分配给每个日记账分录。 这是一个关键的分析属性,可以根据交易性质对流程进行细分。“按类型划分的分录吞吐量”仪表板和“按分录类型划分的平均周期时间”KPI 直接依赖于此字段。它有助于发现某些类型的分录是否更容易发生延迟、返工或冲销。 为何重要 支持按交易类型进行细分分析,有助于确定流程问题是否仅针对某些特定类型的记账凭证。 获取方式 位于凭证抬头表 BKPF,字段 BLART。 示例 SAKRREAA | |||
| 是否已冲销 IsReversed | 布尔值标记,指示记账凭证是否已被冲销。 | ||
| 描述 此标记用于识别随后被另一个会计凭证冲销的分录。在 SAP 中,被冲销凭证会链接到冲销凭证,从而提供清晰的审计追踪。 此属性是“分录冲销分析”仪表板和“分录冲销率”KPI 的基础。它允许隔离已冲销的分录,以调查数据录入错误或会计处理不当等根因,目标是降低冲销频率。 为何重要 通过标记随后被撤销的分录,直接支持冲销分析,有助于识别错误根源并提升数据完整性。 获取方式 派生自 BKPF 表中的冲销凭证编号字段 (STBLG)。如果 STBLG 不为空,则该标记为 true。 示例 truefalse | |||
| 用户 User | 创建或更改日记账分录的人员的 SAP 用户 ID。 | ||
| 描述 此属性记录了负责特定活动(如创建、暂存或过账凭证)的 SAP 用户名。它直接源自凭证抬头或变更日志表。 分析“用户”属性是了解团队和个人绩效的关键。它通过跟踪每个用户的活动量和处理时间来支持“用户生产力”仪表板。它还有助于识别谁参与了返工循环、冲销或合规偏差,从而实现有针对性的培训或流程改进。 为何重要 识别负责各项活动的用户,从而分析用户绩效、工作负载分配和返工模式。 获取方式 通常源自 BKPF 表(USNAM 字段代表创建者)或 CDHDR 表(USERNAME 字段代表修改者)。 示例 ABROWNCJONESDSMITH | |||
| 过账日期 PostingDate | 交易在总账中记录的日期,影响所属会计期间。 | ||
| 描述 过账日期决定了分录核算的会计期间。从财务和合规角度来看,这是一个至关重要的日期字段,因为它必须与会计期间结账计划和法规保持一致。 在 Process Mining 中,此日期用于监控合规性。“合规监控”仪表板和“合规一致率”KPI 使用此属性来检查分录是否在正确的期间内过账。它还可以用于分析一段时间内分录数量的变化趋势。 为何重要 对于财务报告和合规分析至关重要,确保分录过账到正确的会计期间。 获取方式 位于凭证抬头表 BKPF,字段 BUDAT。 示例 2023-10-312023-11-302024-01-15 | |||
| 冲销原因 ReversalReason | 指示记账凭证被冲销原因的代码。 | ||
| 描述 当凭证被冲销时,SAP 允许用户指定原因代码。该代码提供了关于为何需要冲销的结构化信息,例如过账日期错误或数据录入错误。 此属性是“总账分录冲销分析”仪表板的关键输入。通过分析最常见的冲销原因,企业可以识别流程中的系统性问题或培训缺口,并采取针对性措施防止未来出错,从而降低冲销率。 为何重要 提供有关冲销发生原因的直接见解,以便进行有针对性的根因分析,从而减少未来的错误。 获取方式 位于凭证抬头表 BKPF,字段 STGRD。 示例 010205 | |||
| 单据总金额 TotalDocumentAmount | 以凭证货币计的日记账分录总额。 | ||
| 描述 此属性代表日记账分录的总财务金额。通常通过汇总与该凭证关联的所有借方或贷方行项目的绝对值来计算。 按财务金额分析流程可以揭示重要的模式。例如,高额分录可能会遵循不同的、更严格的审批路径。此属性可用于过滤或细分分析,以查看周期时间、驳回率或审批延迟是否与分录金额相关。 为何重要 支持财务影响分析,例如将处理时间或拒绝率与记账凭证的货币价值进行关联。 获取方式 这是一个计算字段,通过汇总 BSEG 表中给定分录所有行项目的金额字段 (WRBTR 或 DMBTR) 得出。 示例 1500.0025000.75125.50 | |||
| 周期时间 CycleTime | 从第一个分录活动创建到最后过账活动完成所经过的总时间。 | ||
| 描述 周期时间 (Cycle Time) 是衡量记账凭证流程端到端时长的关键绩效指标。其计算方式是取单张凭证的最终过账事件与初始创建事件之间的时间差。 这一派生指标是“凭证端到端周期时间”仪表板和“平均凭证周期时间”KPI 的核心衡量标准。它提供了流程整体效率的宏观视角,并用于追踪各项改进举措在一段时间内的实际影响。 为何重要 衡量流程的整体端到端效率,为识别瓶颈和跟踪改进效果提供核心指标。 获取方式 通过针对每个 Case (JournalEntryId),从最后一个事件的时间戳中减去第一个事件的时间戳计算得出。 示例 P2DT3H15MPT8H30MP5D | |||
| 审批耗时 ApprovalTime | 从提交分录审批到被批准或驳回所经过的时间。 | ||
| 描述 该指标衡量审批子流程的持续时间,这通常是影响整体周期时间的关键因素。其计算方式为“总账分录已提交”活动与相应的“总账分录已批准”或“总账分录已拒绝”活动之间的时间差。 审批时间是“总账分录审批绩效”仪表板和“平均总账分录审批时间”KPI 的核心指标。通过分析这段时长,可以帮助识别审批工作流中的瓶颈,评估审批人员的绩效,并为调整审批阈值等流程变革提供依据。 为何重要 量化审批阶段的持续时间,有助于定位并解决审核和审批工作流中的延误。 获取方式 通过从“凭证已批准”或“凭证已拒绝”事件的时间戳中减去“凭证已提交”事件的时间戳计算得出。 示例 P1DT2HPT4H15MP3D | |||
| 成本中心 CostCenter | 控制范围内的组织单元,代表发生费用的地点。 | ||
| 描述 成本中心是管理会计 (CO) 模块的关键主数据元素,通常在日记账分录行项目层级分配。它用于跟踪特定部门、职能或地点的成本。 引入“成本中心”可以对分录流程进行更细致的分析。它有助于确定哪些部门产生了更多返工、拥有更长的周期时间,或者负责更大量的的手动录入。这为流程效率提供了部门层级的视角。 为何重要 支持按部门或职能区域分析流程绩效,有助于精准发现局部低效环节。 获取方式 位于凭证行项目表 BSEG,字段 KOSTL。 示例 4100CC_FINANCE_US10010101 | |||
| 是否已暂存 IsParked | 布尔值标记,指示记账凭证在过账前是否曾保存为预记账凭证。 | ||
| 描述 暂存凭证允许用户在不影响财务余额的情况下保存未完成的日记账分录。之后可以由该用户或另一名用户完成补充或审核,再进行过账。此标记用于识别经历过暂存环节的分录。 分析此属性有助于了解暂存功能的使用情况。它能揭示暂存是否被当作一种非正式的审核步骤使用,从而可能导致延迟。此外,它还支持对端到端周期时间的分析,区分直接过账的分录与先暂存后过账的分录。 为何重要 识别使用暂存功能的分录。暂存可能是延误的来源,也可能反映了非正式的审核流程。 获取方式 派生自表 BKPF 中的凭证状态字段 (BSTAT)。“V”表示预记账凭证。 示例 truefalse | |||
| 是否返工 IsRework | 布尔值标记,指示记账凭证是否经历过返工循环(例如被拒绝后又进行了更正)。 | ||
| 描述 此标记用于识别偏离“理想路径”并需要采取纠正措施的个案。如果观察到诸如“分录已驳回”后接“分录已更正”之类的活动序列,则通常将此标记设为 true。 此属性对于计算“分录返工率”KPI 以及在“返工和驳回率”仪表板上进行分析至关重要。它有助于量化流程中效率低下的程度,并为调查返工的根本原因(如要求不明确或支撑文档不足)提供依据。 为何重要 标记需要更正的分录,从而量化返工并分析其根本原因,以提高一次成功率。 获取方式 这是一个计算属性,通过分析个案的活动序列得出。如果发生驳回或更正活动,则识别为返工循环。 示例 truefalse | |||
| 货币键 CurrencyKey | 日记账分录中记录金额的货币代码。 | ||
| 描述 此属性指定分录的货币,如美元 (USD)、欧元 (EUR) 或日元 (JPY)。它为凭证相关的财务金额提供了背景信息。 虽然不一定是主要的分析维度,但它对于正确解读货币价值至关重要。在跨国企业中,它还可以用于细分分析,以查看外币分录与本地货币分录的处理流程是否存在差异。 为何重要 为所有货币数值提供必要的背景信息,确保财务分析和解读的准确性。 获取方式 位于凭证抬头表 BKPF,字段 WAERS。 示例 美元EURGBPJPY | |||
记录到报告——日记账分录活动
| 活动 | 描述 | ||
|---|---|---|---|
| 已处理日记账分录冲销 | 此活动标志着对先前已过账分录的冲销。冲销是一个新的会计凭证,用于抵消原始分录。 | ||
| 为何重要 这是衡量数据质量和流程准确性的关键事件。高冲销率指向初始数据录入或审批阶段的系统性问题,且每次冲销都代表一次返工。 获取方式 此事件在原始凭证的抬头(BKPF 表)中识别。当凭证被冲销时,SAP 会填充冲销凭证编号 (BKPF-STBLG) 和冲销原因 (BKPF-STGRD)。事件时间戳为新冲销凭证的过账日期。 捕获 识别原始凭证中 BKPF-STBLG 何时被填充;时间戳为冲销凭证的过账日期。 事件类型 explicit | |||
| 日记账分录已审批 | 此活动标志着工作流中分录的最终审批完成,使其具备过账资格。当最终的“释放”或“审批”步骤完成后,该事件会从工作流日志中捕捉到。 | ||
| 为何重要 这是结束审批流程的关键里程碑。截至此活动前的持续时间是审批效率的核心 KPI,而从该事件到过账的时间则衡量了审批后的滞后情况。 获取方式 根据 SAP Business Workflow 日志中最终审批步骤的完成时间推断。这是凭证过账或进入待过账状态前的最后一次审批操作。 捕获 在工作流日志中识别最终“释放”或“审批”步骤的完成情况。 事件类型 inferred | |||
| 日记账分录已提交 | 此活动表示暂存分录已由创建者定稿,现已准备好接受审核和审批。通常通过启动与暂存凭证关联的 SAP Business Workflow 任务来捕捉此活动。 | ||
| 为何重要 这标志着从创建者到审批者的交接,开启了审批周期时间 KPI 的计时。它是衡量审批工作流效率的关键里程碑。 获取方式 通过分析链接到财务凭证对象的审批工作流实例的启动时间推断得出。这需要查询 SWW_WI2OBJ 等工作流日志表,以查找针对特定公司代码、凭证编号和会计年度启动的工作流。 捕获 识别暂存凭证对象的工作流启动事件。 事件类型 inferred | |||
| 日记账分录已暂存 | 此活动标志着分录在正式过账到总账之前的初始创建状态。当用户使用暂存事务保存凭证并将其状态设为“已暂存”时,SAP 会明确记录此活动。 | ||
| 为何重要 对于涉及审核和审批的流程,这是一个关键的起始事件。分析暂存和过账之间的时间有助于识别过账前和审批阶段的延迟。 获取方式 此事件从凭证抬头表 BKPF 中识别。当创建凭证且状态 BKPF-BSTAT = 'V' 时,该凭证被视为已暂存。事件时间戳为创建日期和时间 BKPF-CPUDT 和 BKPF-CPUTM。 捕获 在 BKPF 表中识别 BKPF-BSTAT 为 'V' 的凭证创建。 事件类型 explicit | |||
| 日记账分录已过账 | 这是日记账分录正式记录在总账中并影响财务报表的核心活动。当凭证状态设为“已过账”并分配过账日期时,会明确捕捉到此事件。 | ||
| 为何重要 这是最重要的里程碑,标志着分录处理成功。端到端周期时间通常衡量到这一时点,它也是财务关账分析中的关键事件。 获取方式 当 BKPF 表中的凭证具有过账日期 (BKPF-BUDAT) 时识别。对于暂存凭证,这对应于状态 BKPF-BSTAT 从 'V' 变为控制的状态。过账的时间戳是输入日期 BKPF-CPUDT。 捕获 识别 BKPF-BSTAT 何时从 'V' 变为空,或者对于直接过账,识别其创建事件。 事件类型 explicit | |||
| 已创建日记账分录 | 代表直接过账的日记账分录创建,没有之前的暂存步骤。当在 SAP 中使用直接过账事务创建凭证时,会捕捉到此事件。 | ||
| 为何重要 此活动作为不需要审批工作流的简单分录流程的替代起点。它有助于区分简单的直接过账与更复杂的暂存分录。 获取方式 此事件对应于 BKPF 表中的凭证创建,其中凭证状态 BKPF-BSTAT 为空(已过账)。事件时间戳为创建日期 BKPF-CPUDT。对于此类凭证,“创建”和“过账”事件是同时发生的。 捕获 在 BKPF 表中识别 BKPF-BSTAT 为空的凭证创建。 事件类型 explicit | |||
| 已删除暂存日记账分录 | 代表删除了从未过账的暂存日记账分录。这可能发生在驳回之后,或者由于分录创建错误。 | ||
| 为何重要 此活动标志着流程的非成功结束。分析暂存凭证为何被删除,可以揭示诸如重复分录或流程理解误区等问题。 获取方式 当 BKPF 表中暂存凭证的状态发生更改时,将捕捉到此事件。状态字段 BKPF-BSTAT 更新为 'Z'(已删除暂存凭证)。变更时间戳可在凭证变更日志 (CDHDR) 中找到。 捕获 识别 BKPF-BSTAT 何时更新为 'Z'。 事件类型 explicit | |||
| 已识别手动录入 | 此活动识别分录是通过手动在线交易创建的,还是通过自动接口或批处理过程创建的。这不是用户操作,而是根据系统数据得出的分录计算属性。 | ||
| 为何重要 区分手工分录和自动分录是开展针对性流程改进的关键。手工流程通常是标准化和自动化举措的关注重点。 获取方式 通过分析凭证抬头表 BKPF 中的字段计算得出。诸如 'FB01'、'FB50' 或 'FV50' 之类的事务代码 (BKPF-TCODE) 表示手动输入,而其他 T-Code 或特定的批次输入名称 (BKPF-AWKEY) 则意味着自动化处理。 捕获 从 BKPF-TCODE 或凭证抬头中的其他源系统标识派生。 事件类型 calculated | |||
| 支持文档已附加 | 此活动代表用户为分录添加支撑文档(如发票或电子表格)。此事件不会作为标准会计事件明确记录,通常通过检查链接到会计凭证对象的附件创建情况来推断。 | ||
| 为何重要 跟踪此活动有助于验证是否符合需要文档证明的合规政策。上传附件的延迟可能是导致审批周期延长的根本原因。 获取方式 由于缺乏明确的时间戳事件,此项很难可靠捕捉。一种潜在的方法是分析通用对象服务 (GOS) 附件表(如 SOOD),并将附件创建时间戳链接到分录对象键。 捕获 从 GOS 表(如 SOOD)中链接对象的创建时间戳推断。 事件类型 inferred | |||
| 日记账分录已更正 | 此活动指示原始创建者在暂存分录因需修改被退回后对其进行了修改。这是通过检测“请求更改”事件后的文档变更推断出来的。 | ||
| 为何重要 跟踪更正活动有助于量化返工投入。从变更请求到完成更正之间的时间反映了解决已提交分录问题的延迟情况。 获取方式 通过分析暂存凭证的变更文档日志(表 CDHDR 和 CDPOS)推断得出。工作流中驳回事件后的变更记录意味着已进行了更正。时间戳取自 CDHDR 表。 捕获 在驳回事件后,识别 CDHDR/CDPOS 中的变更日志条目。 事件类型 inferred | |||
| 日记账分录已驳回 | 此活动表示分录的最终驳回,此后该分录将不会过账。这通常是审批工作流中的最终状态,最终会导致暂存凭证被删除。 | ||
| 为何重要 跟踪拒绝情况对于质量管理至关重要。分析拒绝的原因和频率有助于提高总账分录的“一次性通过率”。 获取方式 这是从 SAP Business Workflow 日志中捕捉到的结果,代表终止流程的最终“驳回”用户决策。随后可能会删除该暂存凭证。 捕获 在工作流日志中识别该凭证的最终“驳回”状态。 事件类型 inferred | |||
| 日记账分录待修改 | 代表工作流中的一个时点,即审批人已审核分录并将其退回给创建者进行更正。此事件从工作流日志中获取,标记为“驳回”或“退回”的用户决策。 | ||
| 为何重要 此活动对于识别返工循环至关重要,返工循环是导致效率低下和流程偏差的主要原因。该事件发生的频率较高通常意味着分录质量存在问题或要求不够清晰。 获取方式 此事件是根据 SAP Business Workflow 日志中对应于“驳回”或“送交更正”操作的特定用户决策步骤的时间戳推断得出的。 捕获 在工作流日志中识别“驳回”或“返工”决策的时间戳。 事件类型 inferred | |||
| 日记账分录行项目已清项 | 此活动代表未清项管理的总账科目行项目(如银行清算科目)的核对。当一个行项目与另一个行项目匹配并结清时,就会发生此活动。 | ||
| 为何重要 对于银行对账等流程,清账时间是一个关键 KPI。此活动有助于分析对账和月末结账程序的效率。 获取方式 此事件从行项目表 BSEG 中捕捉。当行项目结清时,结清日期 (BSEG-AUGDT) 和结清凭证 (BSEG-AUGBL) 字段会被填充。事件的时间戳即为结清日期。 捕获 识别行项目的清帐日期 (BSEG-AUGDT) 何时被填充。 事件类型 explicit | |||
| 识别为跨公司代码过账 | 派生计算活动,用于标记涉及多个公司代码的记账凭证。通过分析单个财务凭证的行项目来确定。 | ||
| 为何重要 跨公司交易通常具有更复杂的处理和审批要求。通过识别此类交易,可以单独分析其周期时间和流程路径,从而发现独特的瓶颈。 获取方式 通过检查给定凭证编号 (BELNR) 的行项目表 BSEG 计算得出。如果行项目包含多个不同的公司代码 (BSEG-BUKRS),则该分录为跨公司代码过账。 捕获 检查单个 BKPF-BELNR 是否存在多个唯一的 BSEG-BUKRS 值。 事件类型 calculated | |||
提取指南
步骤
- 创建 ABAP 程序:在 SAP 系统中,进入事务代码 SE38(ABAP 编辑器)。输入新程序的名称,例如 Z_PM_JE_EXTRACTION,然后点击“创建”。提供合适的标题,并将程序类型设置为“可执行程序”。
- 定义选择屏幕:在程序源代码中定义选择屏幕。这允许用户指定诸如凭证创建日期范围、公司代码和凭证类型等参数,以限制提取的数据量。
- 声明数据结构:定义用于保存最终事件日志数据的内表结构。该结构必须包含所有必需字段:JournalEntryId、ActivityName、EventTime、SourceSystem、LastDataUpdate,以及 User、CompanyCode 和 PostingDate 等任何推荐属性。
- 实现数据选择逻辑:编写核心 ABAP SQL 查询以提取 14 个必需活动中每个活动的数据。这涉及从 BKPF(抬头)和 BSEG(行项目)等主表、变更日志表 CDHDR 和 CDPOS、工作流表(如 SWWLOGHIST)以及清账表(如 BSAS 和 BSAK)中选择数据。
- 提取预记账和已过账凭证:对于“凭证已预记账”事件,从 BKPF 中选择凭证状态 (BSTAT) 为“V”的记录。对于“凭证已创建”和“凭证已过账”事件,从 BKPF 中选择状态为空(表示正常的已过账凭证)的记录。
- 提取变更和删除事件:查询变更凭证表 CDHDR 和 CDPOS,对象类为 'BELEG'。按凭证键筛选,以找到对应于“凭证已更正”或“预记账凭证已删除”活动的变更。
- 提取工作流事件:要捕获“凭证已提交”、“已批准”、“已拒绝”和“要求修改”等活动,请查询工作流表。使用表 SWW_WI2OBJ 将会计凭证链接到工作流实例,然后读取 SWWLOGHIST 以获取特定的用户决策或状态更改。
- 识别计算出的事件:对于“识别为手工分录”,对照已知的手工录入事务代码列表检查事务代码 (BKPF-TCODE)。对于“识别为跨公司代码过账”,分析给定凭证的 BSEG 行项目,查看是否涉及多个公司代码。
- 合并并转换数据:在选择每个活动的数据时,将其转换为最终的事件日志结构。合并公司代码、凭证编号和财年以创建 JournalEntryId。将 SAP 的日期和时间转换为统一的 EventTime 时间戳。将每个查询的结果附加到最终内表中。
- 实现文件导出:使用 ABAP 文件处理语句(如 OPEN DATASET、LOOP AT、TRANSFER 和 CLOSE DATASET),将整合后的内表写入 SAP 应用服务器目录(可通过事务代码 AL11 查看)中的 CSV 或文本文件。
- 安排后台作业:进入事务代码 SM36(定义后台作业)。创建一个新作业,定义执行您的 ABAP 程序的步骤,并设置时间表(例如在非高峰时段每晚或每周运行一次),以实现提取过程的自动化。
- 检索并格式化文件:使用事务代码 CG3Y 或配合系统管理员将生成的文件从应用服务器下载到本地计算机。确保文件编码和格式适合上传到您的流程挖掘工具。
配置
- 日期范围:定义日期范围对于性能管理至关重要。请将凭证创建日期 (BKPF-CPUDT) 作为主要筛选器。对于初步分析,建议选择 3 到 6 个月的时间段。进行测试时,请使用已知包含数据的几天范围。
- 公司代码筛选:务必按公司代码 (BKPF-BUKRS) 进行筛选。一次性提取所有公司代码的数据可能会消耗极高的资源。建议从一个或一小组相关的公司代码开始。
- 凭证类型筛选:如果您不需要分析所有凭证类型,请使用凭证类型筛选器 (BKPF-BLART) 将范围缩小到特定类型的记账凭证(例如总账凭证“SA”)。
- 工作流任务 ID:提取工作流事件的逻辑取决于您系统中用于审批、拒绝和提交的具体任务 ID。必须根据您公司的工作流定义在程序源代码中配置这些 ID。
- 性能考量:该程序会联接多个大型表,特别是 CDPOS 和工作流历史表。在业务高峰时段运行可能会影响系统性能。请务必将其安排为在非高峰时段运行的后台作业。如果性能问题反复出现,请考虑创建辅助数据库索引。
- 先决条件:此方法需要用户具备 ABAP 开发权限(SE38)以及创建和管理后台作业的权限(SM36)。该用户或作业还需要对所有相关的财务、工作流和系统表(BKPF、BSEG、CDHDR、CDPOS、SWWLOGHIST 等)具有读取权限。
a 查询示例 abap
REPORT Z_PM_JE_EXTRACTION.
*&---------------------------------------------------------------------*
*& Data Structures for Final Event Log
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
journalentryid TYPE string,
activityname TYPE string,
eventtime TYPE timestamp,
sourcesystem TYPE string,
lastdataupdate TYPE timestamp,
username TYPE uname,
companycode TYPE bukrs,
documenttype TYPE blart,
postingdate TYPE budat,
transactioncode TYPE tcode,
isreversed TYPE abap_bool,
END OF ty_event_log.
DATA: lt_final_log TYPE STANDARD TABLE OF ty_event_log.
DATA: ls_event TYPE ty_event_log.
*&---------------------------------------------------------------------*
*& Selection Screen Parameters
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_bukrs FOR bkpf-bukrs OBLIGATORY,
s_blart FOR bkpf-blart,
s_cpudt FOR bkpf-cpudt OBLIGATORY.
PARAMETERS: p_sysid TYPE sy-sysid DEFAULT sy-sysid.
*&---------------------------------------------------------------------*
*& Main Logic
*&---------------------------------------------------------------------*
START-OF-SELECTION.
DATA(lv_last_update) = cl_abap_context_info=>get_system_timestamp( ).
" 1. Journal Entry Parked
SELECT CONCAT( a~bukrs, a~belnr, a~gjahr ) AS journalentryid,
'Journal Entry Parked' AS activityname,
a~cpudt, a~cputm,
a~usnam AS username,
a~bukrs AS companycode,
a~blart AS documenttype,
a~bldat AS postingdate,
a~tcode AS transactioncode
FROM bkpf AS a
WHERE a~bukrs IN s_bukrs
AND a~blart IN s_blart
AND a~cpudt IN s_cpudt
AND a~bstat = 'V' " Parked Document
INTO TABLE @DATA(lt_parked).
IF sy-subrc = 0.
LOOP AT lt_parked ASSIGNING FIELD-SYMBOL(<fs_parked>).
ls_event-journalentryid = <fs_parked>-journalentryid.
ls_event-activityname = <fs_parked>-activityname.
CONVERT DATE <fs_parked>-cpudt TIME <fs_parked>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
ls_event-sourcesystem = p_sysid.
ls_event-lastdataupdate = lv_last_update.
ls_event-username = <fs_parked>-username.
ls_event-companycode = <fs_parked>-companycode.
ls_event-documenttype = <fs_parked>-documenttype.
ls_event-postingdate = <fs_parked>-postingdate.
ls_event-transactioncode = <fs_parked>-transactioncode.
APPEND ls_event TO lt_final_log.
ENDLOOP.
ENDIF.
" 2. Journal Entry Created (directly posted, not parked first)
" 9. Journal Entry Posted
" These two events happen at the same time for a direct posting.
SELECT CONCAT( bukrs, belnr, gjahr ) AS journalentryid,
cpudt, cputm, usnam, bukrs, blart, budat, tcode, stblg
FROM bkpf
WHERE bukrs IN s_bukrs
AND blart IN s_blart
AND cpudt IN s_cpudt
AND bstat = '' " Normal, posted document
INTO TABLE @DATA(lt_posted).
IF sy-subrc = 0.
LOOP AT lt_posted ASSIGNING FIELD-SYMBOL(<fs_posted>).
" Activity: Journal Entry Created
ls_event-journalentryid = <fs_posted>-journalentryid.
ls_event-activityname = 'Journal Entry Created'.
CONVERT DATE <fs_posted>-cpudt TIME <fs_posted>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
ls_event-sourcesystem = p_sysid.
ls_event-lastdataupdate = lv_last_update.
ls_event-username = <fs_posted>-usnam.
ls_event-companycode = <fs_posted>-bukrs.
ls_event-documenttype = <fs_posted>-blart.
ls_event-postingdate = <fs_posted>-budat.
ls_event-transactioncode = <fs_posted>-tcode.
ls_event-isreversed = COND #( WHEN <fs_posted>-stblg IS NOT INITIAL THEN abap_true ELSE abap_false ).
APPEND ls_event TO lt_final_log.
" Activity: Journal Entry Posted
ls_event-activityname = 'Journal Entry Posted'.
APPEND ls_event TO lt_final_log.
ENDLOOP.
ENDIF.
" 3. Documentation Attached (via GOS)
SELECT a~instid_a, c~cr_timestamp
FROM srgbtbrel AS a
INNER JOIN sood AS b ON a~instid_b = b~objid
INNER JOIN socf AS c ON b~filid = c~filid
WHERE a~typeid_a = 'BKPF'
AND a~bukrs IN s_bukrs
INTO TABLE @DATA(lt_attachments).
IF sy-subrc = 0.
LOOP AT lt_attachments ASSIGNING FIELD-SYMBOL(<fs_attach>).
ls_event-journalentryid = |{ <fs_attach>-instid_a(4) }{ <fs_attach>-instid_a+4(10) }{ <fs_attach>-instid_a+14(4) }|.
ls_event-activityname = 'Documentation Attached'.
ls_event-eventtime = <fs_attach>-cr_timestamp.
" Other attributes may need to be looked up from BKPF if needed.
APPEND ls_event TO lt_final_log.
ENDLOOP.
ENDIF.
" 4, 5, 6, 7, 8: Workflow events (Submitted, Changes Requested, Corrected, Approved, Rejected)
" This is a simplified example. Real logic depends on specific workflow templates.
SELECT a~instid, b~wi_cd, b~wi_ct, b~wi_aagent, b~wi_text
FROM sww_wi2obj AS a
INNER JOIN swwloghist AS b ON a~wi_id = b~wi_id
WHERE a~typeid = 'BKPF'
AND a~catid = 'BO'
AND a~bukrs IN s_bukrs
AND b~wi_cd BETWEEN s_cpudt-low AND s_cpudt-high
INTO TABLE @DATA(lt_workflow).
IF sy-subrc = 0.
LOOP AT lt_workflow ASSIGNING FIELD-SYMBOL(<fs_wf>).
ls_event-journalentryid = |{ <fs_wf>-instid(4) }{ <fs_wf>-instid+4(10) }{ <fs_wf>-instid+14(4) }|.
ls_event-activityname = CASE <fs_wf>-wi_text. " Simplified logic based on work item text
WHEN '[Placeholder for Submit Text]' THEN 'Journal Entry Submitted'
WHEN '[Placeholder for Approve Text]' THEN 'Journal Entry Approved'
WHEN '[Placeholder for Reject Text]' THEN 'Journal Entry Rejected'
WHEN '[Placeholder for Rework Text]' THEN 'Journal Entry Changes Requested'
ELSE ''
ENDCASE.
IF ls_event-activityname IS NOT INITIAL.
CONVERT DATE <fs_wf>-wi_cd TIME <fs_wf>-wi_ct INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
ls_event-username = <fs_wf>-wi_aagent.
APPEND ls_event TO lt_final_log.
ENDIF.
ENDLOOP.
ENDIF.
" 10. Manual Entry Identified & 11. Cross-Company Posting Identified
SELECT bukrs, belnr, gjahr, tcode FROM bkpf
WHERE bukrs IN s_bukrs AND blart IN s_blart AND cpudt IN s_cpudt
INTO TABLE @DATA(lt_calc_base).
LOOP AT lt_calc_base ASSIGNING FIELD-SYMBOL(<fs_calc>).
ls_event-journalentryid = |{ <fs_calc>-bukrs }{ <fs_calc>-belnr }{ <fs_calc>-gjahr }|.
" Check for manual entry T-Codes
IF <fs_calc>-tcode = 'FB01' OR <fs_calc>-tcode = 'F-02' OR <fs_calc>-tcode = 'FB50'.
ls_event-activityname = 'Manual Entry Identified'.
APPEND ls_event TO lt_final_log.
ENDIF.
" Check for cross-company posting
SELECT SINGLE bukrs FROM bseg WHERE belnr = <fs_calc>-belnr AND gjahr = <fs_calc>-gjahr AND bukrs <> <fs_calc>-bukrs INTO @DATA(lv_cross_bukrs).
IF sy-subrc = 0.
ls_event-activityname = 'Cross-Company Posting Identified'.
APPEND ls_event TO lt_final_log.
ENDIF.
ENDLOOP.
" 12. Journal Entry Line Item Cleared
SELECT a~bukrs, a~belnr, a~gjahr, a~augdt, a~augbl
FROM bsas AS a " G/L Cleared Items
WHERE a~bukrs IN s_bukrs
AND a~budat IN s_cpudt
INTO TABLE @DATA(lt_cleared_gl).
IF sy-subrc = 0.
LOOP AT lt_cleared_gl ASSIGNING FIELD-SYMBOL(<fs_clr>).
ls_event-journalentryid = |{ <fs_clr>-bukrs }{ <fs_clr>-belnr }{ <fs_clr>-gjahr }|.
ls_event-activityname = 'Journal Entry Line Item Cleared'.
CONVERT DATE <fs_clr>-augdt INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
" User is often not directly available for clearing events
APPEND ls_event TO lt_final_log.
ENDLOOP.
ENDIF.
" 13. Parked Journal Entry Deleted & 6. Journal Entry Corrected
SELECT objectid, changenr, username, udate, utime FROM cdhdr
WHERE objectclas = 'BELEG'
AND udate IN s_cpudt
INTO TABLE @DATA(lt_cdhdr).
LOOP AT lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>).
SELECT SINGLE tcode FROM cdpos WHERE changenr = <fs_cdhdr>-changenr AND fname = 'BSTAT' AND value_new = 'Z' INTO @DATA(lv_deleted_tcode).
ls_event-journalentryid = |{ <fs_cdhdr>-objectid(4) }{ <fs_cdhdr>-objectid+4(10) }{ <fs_cdhdr>-objectid+14(4) }|.
CONVERT DATE <fs_cdhdr>-udate TIME <fs_cdhdr>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
ls_event-username = <fs_cdhdr>-username.
IF sy-subrc = 0.
ls_event-activityname = 'Parked Journal Entry Deleted'.
APPEND ls_event TO lt_final_log.
ELSE.
ls_event-activityname = 'Journal Entry Corrected'.
APPEND ls_event TO lt_final_log.
ENDIF.
ENDLOOP.
" 14. Journal Entry Reversal Processed
SELECT CONCAT( a~bukrs, a~belnr, a~gjahr ) AS journalentryid,
a~cpudt, a~cputm, a~usnam
FROM bkpf AS a
WHERE a~bukrs IN s_bukrs
AND a~blart IN s_blart
AND a~cpudt IN s_cpudt
AND a~stblg IS NOT NULL " Document is a reversal
INTO TABLE @DATA(lt_reversals).
IF sy-subrc = 0.
LOOP AT lt_reversals ASSIGNING FIELD-SYMBOL(<fs_rev>).
ls_event-journalentryid = <fs_rev>-journalentryid.
ls_event-activityname = 'Journal Entry Reversal Processed'.
CONVERT DATE <fs_rev>-cpudt TIME <fs_rev>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
ls_event-username = <fs_rev>-usnam.
APPEND ls_event TO lt_final_log.
ENDLOOP.
ENDIF.
" Final step: Output to file
DATA(lv_filename) = |/tmp/je_extraction_{ sy-datum }_{ sy-uzeit }.csv|.
OPEN DATASET lv_filename FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc = 0.
" Write header
DATA(lv_header) = 'JournalEntryId,ActivityName,EventTime,SourceSystem,LastDataUpdate,User,CompanyCode,DocumentType,PostingDate,TransactionCode,IsReversed'.
TRANSFER lv_header TO lv_filename.
LOOP AT lt_final_log INTO ls_event.
DATA(lv_line) = |"{ ls_event-journalentryid }","|
|{ ls_event-activityname }","|
|{ ls_event-eventtime }","|
|{ ls_event-sourcesystem }","|
|{ ls_event-lastdataupdate }","|
|{ ls_event-username }","|
|{ ls_event-companycode }","|
|{ ls_event-documenttype }","|
|{ ls_event-postingdate }","|
|{ ls_event-transactioncode }","|
|{ ls_event-isreversed }"|.
TRANSFER lv_line TO lv_filename.
ENDLOOP.
CLOSE DATASET lv_filename.
ENDIF. 步骤
- 建立数据库连接:获取 SAP ECC 数据库的只读凭据。使用标准的 SQL 客户端(如 DBeaver、SAP HANA Studio 或 SQL Server Management Studio)连接到数据库。
- 准备 SQL 查询:将本文档“query”部分提供的完整 SQL 查询复制到您的 SQL 客户端中。
- 设置提取参数:执行之前,必须配置查询中的占位符。将
'[START_DATE]'和'[END_DATE]'替换为所需日期范围(格式为 'YYYYMMDD')。将'[COMPANY_CODE_1]', '[COMPANY_CODE_2]'替换为您希望分析的具体 SAP 公司代码。 - 定义源系统:在主
SELECT语句中,将占位符'[Your SAP System ID]'替换为实际的 SAP 系统 ID (SID),以便正确识别数据源。 - 执行查询:针对 SAP 数据库运行配置好的 SQL 查询。执行时间将取决于日期范围和数据库表的大小。
- 检查初始结果:查询完成后,简要浏览返回的行,确保数据如预期填充。检查活动类型是否多样,以及
JournalEntryId和EventTime等关键字段是否非空。 - 处理时间戳:该查询将日期和时间字段连接为
YYYYMMDDHHMMSS字符串。请确保您的后处理系统或目标系统可以解析此格式,或者如果您的数据库支持,可以将 SQLCONCAT函数调整为 ISO 8601 格式(如YYYY-MM-DDTHH:MI:SS)。 - 导出数据:将 SQL 客户端中的完整结果集导出为 CSV 文件。确保使用 UTF-8 编码以防止特殊字符出现问题。
- 准备上传:在上传到流程挖掘工具之前,确认列标题与所需的数据架构匹配。
JournalEntryId、ActivityName和EventTime至关重要。添加LastDataUpdate列,并填入执行提取的时间戳。 - 最终验证:按照“validationSteps”部分概述的步骤进行操作,确保提取的数据在开始分析之前是完整且准确的。
配置
- 数据库授权:数据库用户需要对以下 SAP 表具有读取权限:BKPF、BSEG、CDHDR、CDPOS、T001 和 V_USERNAME。对于工作流相关活动,还需要访问 SWW_WI2OBJ 和 SWWLOGHIST。此类权限通常仅授予专门的技术团队。
- 日期范围筛选:为确保查询性能,必须按特定日期范围筛选数据。提供的查询使用了开始日期和结束日期的占位符,这些占位符将应用于凭证创建日期(
BKPF.CPUDT)。对于初步分析,建议选择 3 到 6 个月的时间范围。 - 实体筛选:为了管理数据量并集中分析,请务必按公司代码(
BKPF.BUKRS)进行筛选。您还可以考虑按凭证类型(BKPF.BLART)进行筛选,以仅包含相关的记账凭证类型(例如总账凭证“SA”),并排除不在范围内的业务凭证(如发票或付款)。 - 性能考量:直接查询 BSEG 和 CDPOS 等核心表可能会消耗大量资源。强烈建议在业务非高峰时段执行提取,以免影响终端用户的系统性能。避免在单次执行中提取超过一年的数据。
- 工作流任务 ID:查询中包含
'[WF_TASK_ID_SUBMIT]'和'[WF_TASK_ID_APPROVE]'等占位符。必须将这些占位符替换为您系统中特定记账凭证工作流配置的实际任务 ID。这些 ID 可以通过咨询 SAP 工作流专家或通过事务代码 PFTC 分析技术工作流定义来确定。
a 查询示例 sql
WITH DOC_HEADERS AS (
SELECT
BUKRS,
BELNR,
GJAHR,
BLART,
BLDAT,
BUDAT,
CPUDT,
CPUTM,
USNAM,
TCODE,
BSTAT,
STBLG,
XRECH
FROM BKPF
WHERE CPUDT BETWEEN '[START_DATE]' AND '[END_DATE]'
AND BUKRS IN ('[COMPANY_CODE_1]', '[COMPANY_CODE_2]')
)
-- Event 1: Journal Entry Created (Directly Posted)
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Journal Entry Created' AS "ActivityName",
TO_TIMESTAMP(CONCAT(H.CPUDT, H.CPUTM), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
H.TCODE AS "TransactionCode",
CASE WHEN H.STBLG IS NOT NULL AND H.STBLG <> '' THEN TRUE ELSE FALSE END AS "IsReversed"
FROM DOC_HEADERS H
LEFT JOIN V_USERNAME U ON H.USNAM = U.BNAME
WHERE H.BSTAT = '' OR H.BSTAT = 'U'
UNION ALL
-- Event 2: Journal Entry Parked
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Journal Entry Parked' AS "ActivityName",
TO_TIMESTAMP(CONCAT(H.CPUDT, H.CPUTM), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
H.TCODE AS "TransactionCode",
FALSE AS "IsReversed"
FROM DOC_HEADERS H
LEFT JOIN V_USERNAME U ON H.USNAM = U.BNAME
WHERE H.BSTAT = 'V'
UNION ALL
-- Event 3: Journal Entry Posted (from Parked state)
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Journal Entry Posted' AS "ActivityName",
TO_TIMESTAMP(CONCAT(C.UDATE, C.UTIME), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
C.TCODE AS "TransactionCode",
CASE WHEN H.STBLG IS NOT NULL AND H.STBLG <> '' THEN TRUE ELSE FALSE END AS "IsReversed"
FROM DOC_HEADERS H
JOIN CDHDR C ON C.OBJECTCLAS = 'BELEG' AND C.OBJECTID = CONCAT(H.BUKRS, H.BELNR, H.GJAHR)
JOIN CDPOS P ON C.CHANGENR = P.CHANGENR AND P.OBJECTCLAS = 'BELEG' AND P.OBJECTID = C.OBJECTID
LEFT JOIN V_USERNAME U ON C.USERNAME = U.BNAME
WHERE H.BSTAT <> 'V'
AND P.TABNAME = 'BKPF'
AND P.FNAME = 'BSTAT'
AND P.VALUE_OLD = 'V'
AND P.VALUE_NEW <> 'V'
UNION ALL
-- Event 4: Parked Journal Entry Deleted
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Parked Journal Entry Deleted' AS "ActivityName",
TO_TIMESTAMP(CONCAT(C.UDATE, C.UTIME), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
C.TCODE AS "TransactionCode",
FALSE AS "IsReversed"
FROM DOC_HEADERS H
JOIN CDHDR C ON C.OBJECTCLAS = 'BELEG' AND C.OBJECTID = CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AND C.TCODE = 'FBV0'
JOIN CDPOS P ON C.CHANGENR = P.CHANGENR AND P.OBJECTCLAS = 'BELEG' AND P.OBJECTID = C.OBJECTID
LEFT JOIN V_USERNAME U ON C.USERNAME = U.BNAME
WHERE P.TABNAME = 'BKPF'
AND P.FNAME = 'BSTAT'
AND P.VALUE_OLD = 'V'
AND P.VALUE_NEW = 'Z'
UNION ALL
-- Event 5: Journal Entry Reversal Processed
SELECT
CONCAT(H.BUKRS, H.STBLG, H.GJAHR) AS "JournalEntryId", -- Linking to the original document
'Journal Entry Reversal Processed' AS "ActivityName",
TO_TIMESTAMP(CONCAT(H.CPUDT, H.CPUTM), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
H.TCODE AS "TransactionCode",
TRUE AS "IsReversed"
FROM DOC_HEADERS H
LEFT JOIN V_USERNAME U ON H.USNAM = U.BNAME
WHERE H.STBLG IS NOT NULL AND H.STBLG <> ''
UNION ALL
-- Event 6: Journal Entry Line Item Cleared
SELECT
CONCAT(B.BUKRS, B.BELNR, B.GJAHR) AS "JournalEntryId",
'Journal Entry Line Item Cleared' AS "ActivityName",
TO_TIMESTAMP(B.AUGDT, 'YYYYMMDD') AS "EventTime", -- Clearing date used as event time
U.NAME_TEXT AS "User",
B.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
NULL AS "TransactionCode", -- Clearing transaction is in the clearing document header, complex to retrieve here
CASE WHEN H.STBLG IS NOT NULL AND H.STBLG <> '' THEN TRUE ELSE FALSE END AS "IsReversed"
FROM BSEG B
JOIN DOC_HEADERS H ON B.BUKRS = H.BUKRS AND B.BELNR = H.BELNR AND B.GJAHR = H.GJAHR
LEFT JOIN V_USERNAME U ON H.USNAM = U.BNAME
WHERE B.AUGBL IS NOT NULL AND B.AUGBL <> '' AND B.AUGDT <> '00000000'
UNION ALL
-- Event 7: Journal Entry Corrected (changes to a parked document)
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Journal Entry Corrected' AS "ActivityName",
TO_TIMESTAMP(CONCAT(C.UDATE, C.UTIME), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
C.TCODE AS "TransactionCode",
FALSE AS "IsReversed"
FROM DOC_HEADERS H
JOIN CDHDR C ON C.OBJECTCLAS = 'BELEG' AND C.OBJECTID = CONCAT(H.BUKRS, H.BELNR, H.GJAHR)
LEFT JOIN V_USERNAME U ON C.USERNAME = U.BNAME
WHERE H.BSTAT = 'V' AND C.TCODE IN ('FBV2', 'FBV4') -- FBV2 is change parked doc, FBV4 is change parked doc header
UNION ALL
-- Event 8: Documentation Attached (inferred from GOS attachment creation, requires configuration)
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Documentation Attached' AS "ActivityName",
TO_TIMESTAMP(CONCAT(REL.RECDATE, '000000'), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
H.TCODE AS "TransactionCode",
FALSE AS "IsReversed"
FROM DOC_HEADERS H
JOIN SRGBTBREL REL ON REL.INSTID_A = CONCAT('BUS2081', H.BUKRS, H.BELNR, H.GJAHR) -- BUS2081 is object type for BKPF
LEFT JOIN V_USERNAME U ON REL.RECUNAM = U.BNAME
WHERE REL.TYPEID_A = 'BUS2081' AND REL.RELTYPE = 'ATTA'
UNION ALL
-- Events 9-13 from Workflow (Submitted, Changes Requested, Approved, Rejected) requires specific workflow config
-- This is a generic template. The WI_RH_TASK must be adapted to your system.
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
CASE
WHEN LOG.WI_RH_TASK = '[WF_TASK_ID_SUBMIT]' THEN 'Journal Entry Submitted'
WHEN LOG.WI_RH_TASK = '[WF_TASK_ID_APPROVE]' AND LOG.METHOD = 'DECISION' AND LOG.EVT_ID = 'COMPLETED' THEN 'Journal Entry Approved'
WHEN LOG.WI_RH_TASK = '[WF_TASK_ID_REJECT]' AND LOG.METHOD = 'DECISION' AND LOG.EVT_ID = 'COMPLETED' THEN 'Journal Entry Rejected'
WHEN LOG.WI_RH_TASK = '[WF_TASK_ID_CHANGES_REQ]' AND LOG.METHOD = 'DECISION' AND LOG.EVT_ID = 'COMPLETED' THEN 'Journal Entry Changes Requested'
ELSE NULL
END AS "ActivityName",
TO_TIMESTAMP(CONCAT(LOG.EVT_DATE, LOG.EVT_TIME), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
NULL AS "TransactionCode",
FALSE AS "IsReversed"
FROM DOC_HEADERS H
JOIN SWW_WI2OBJ WIOBJ ON WIOBJ.INSTID = CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AND WIOBJ.TYPEID = 'BKPF'
JOIN SWWLOGHIST LOG ON WIOBJ.WI_ID = LOG.WI_ID
LEFT JOIN V_USERNAME U ON LOG.EXEC_USER = U.BNAME
WHERE LOG.WI_RH_TASK IN ('[WF_TASK_ID_SUBMIT]', '[WF_TASK_ID_APPROVE]', '[WF_TASK_ID_REJECT]', '[WF_TASK_ID_CHANGES_REQ]')
UNION ALL
-- Event 14: Manual Entry Identified
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Manual Entry Identified' AS "ActivityName",
TO_TIMESTAMP(CONCAT(H.CPUDT, H.CPUTM), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
H.TCODE AS "TransactionCode",
CASE WHEN H.STBLG IS NOT NULL AND H.STBLG <> '' THEN TRUE ELSE FALSE END AS "IsReversed"
FROM DOC_HEADERS H
LEFT JOIN V_USERNAME U ON H.USNAM = U.BNAME
WHERE H.TCODE IN ('FB01', 'F-02', 'FB50', 'F-04', 'F-22', 'F-43', 'FB60', 'FB70', 'FV50', 'FV60', 'FV70')
UNION ALL
-- Event 15: Cross-Company Posting Identified
SELECT
CONCAT(H.BUKRS, H.BELNR, H.GJAHR) AS "JournalEntryId",
'Cross-Company Posting Identified' AS "ActivityName",
TO_TIMESTAMP(CONCAT(H.CPUDT, H.CPUTM), 'YYYYMMDDHH24MISS') AS "EventTime",
U.NAME_TEXT AS "User",
H.BUKRS AS "CompanyCode",
H.BLART AS "DocumentType",
H.BUDAT AS "PostingDate",
H.TCODE AS "TransactionCode",
CASE WHEN H.STBLG IS NOT NULL AND H.STBLG <> '' THEN TRUE ELSE FALSE END AS "IsReversed"
FROM DOC_HEADERS H
LEFT JOIN V_USERNAME U ON H.USNAM = U.BNAME
WHERE H.XRECH = 'X' 步骤
- 建立 SAP 连接:在您的第三方 ETL 工具中,配置到 SAP ECC 系统的新源连接。这通常需要应用服务器详情、客户端、系统编号,以及具有必要 RFC 授权的专用 SAP 用户。
- 定义数据源:在提取项目中,将必需的 SAP 表添加为数据源。主要表包括 BKPF(会计凭证抬头)、BSEG(会计凭证段)、VBSEGK(预记账凭证抬头)、CDHDR(变更凭证抬头)、CDPOS(变更凭证项目)、SWW_WI2OBJ(工作流与对象链接)、SWWLOGHIST(工作流日志)和 SRGBTBREL(GOS 附件关系)。
- 提取基础事件(已创建与已预记账):创建第一个数据流以提取初始事件。对于“凭证已预记账”,使用 VBSEGK 作为源。对于“凭证已创建”,使用 BKPF,并确保筛选出非冲销且最初未被预记账的凭证。这可以通过与 VBSEGK 进行反连接来实现。
- 提取工作流事件:创建一个数据流,使用对象键(公司代码 + 凭证编号 + 财年)将 BKPF 连接到 SWW_WI2OBJ,以查找工作流实例 ID。将此结果与 SWWLOGHIST 连接,根据日志中记录的工作流任务结果和用户决策提取“已提交”、“已批准”、“已拒绝”和“要求修改”等事件。
- 提取变更和删除事件:使用 CDHDR 和 CDPOS 表来识别变更。对于“凭证已更正”,筛选对预记账凭证(对象类 'FIPP')所做的变更。对于“预记账凭证已删除”,在预记账凭证的变更日志中查找删除标记。
- 提取附件事件:要捕获“上传支持性文档”,请将 BKPF 连接到 SRGBTBREL,其中对象类型为 'BKPF' 且关系为 '[您的附件关系类型]'。链接的创建日期即为事件时间。
- 提取清账和冲销事件:对于“凭证行项目已清账”,查询已填充清账凭证字段 (AUGBL) 的 BSEG 表。事件时间为清账凭证的过账日期 (AUGDT)。对于“冲销已处理”,在 BKPF 中查询属于冲销凭证的记录(通过冲销凭证字段 STBLG 中的值来识别)。
- 派生计算出的事件:为计算出的事件创建单独的逻辑块。对于“识别为手工分录”,根据手工事务代码列表(如 FB01、FB50、F-02)筛选 BKPF。对于“识别为跨公司代码过账”,按凭证 ID 对 BSEG 表进行分组,并识别具有多个不同公司代码的凭证。
- 合并所有事件流:在 ETL 工具中使用 UNION 转换,将所有单个事件流(已创建、已预记账、已批准等)的输出合并到单个事件日志表中。确保所有流中的列名和数据类型保持一致。
- 映射到最终架构:将合并后的数据映射到所需的事件日志结构,创建
JournalEntryId、ActivityName、EventTime、User以及其他必需和推荐的属性。添加SourceSystem等静态列,并使用 ETL 作业的执行时间作为LastDataUpdate。 - 配置增量加载:对于持续提取,配置增量加载策略。使用最后的创建或更改日期(如 BKPF.CPUDT、CDHDR.UDATE)作为水印,以仅拉取自上次运行以来新增或更新的记录。
- 导出至 ProcessMind:安排提取作业,并配置最终输出步骤,将事件日志保存为 CSV 或 Parquet 文件,保存在 ProcessMind 可访问的位置以便上传。
配置
- 先决条件:需具备许可的第三方 ETL 工具(如 Theobald Xtract Universal、Informatica、Talend)以及专用的 SAP 连接器。一个具有 RFC 访问权限且有权读取财务表(例如针对表组 F_00、F_WF 的 S_TABU_DIS)、工作流数据和变更日志的 SAP 用户账号。
- 连接参数:您需要 SAP 应用服务器的 IP 或主机名、系统编号和客户端 ID。应对 SAP 用户名和密码使用安全的凭据管理。
- 关键筛选:务必在源端对公司代码 (BKPF.BUKRS) 和财年 (BKPF.GJAHR) 应用筛选,以限制数据量。强烈建议对凭证创建日期 (BKPF.CPUDT) 进行筛选,以定义特定的提取期间(例如过去 6 个月)。
- 日期范围选择:对于初始加载,请选择 3 到 6 个月等具有代表性的期间。对于后续的增量加载,请在
CPUDT等时间戳字段上使用水印,以仅获取新记录。 - 性能考量:对 BSEG、CDPOS 和工作流表的联接操作可能非常缓慢。请确保您的 ETL 工具尽可能将筛选器下推至 SAP 源端。如果工具允许,请分小块或分包提取数据,尤其是针对大规模历史数据加载时。
- 工作流自定义:识别“已批准”或“已拒绝”等工作流活动的逻辑在很大程度上取决于您的具体工作流模板。您需要从系统中确定正确的工作流任务 ID 和用户决策键,以便在筛选器中使用。
a 查询示例 config
/*
This is a logical representation of the extraction configuration in a third-party ETL tool.
It is not executable SQL but defines the sources, joins, and transformations for each activity.
Placeholders like [Your SAP Source], [Date Filter], and [Company Code Filter] must be configured in the tool.
*/
-- Extraction block for 'Journal Entry Parked'
SELECT
CONCAT(v.BUKRS, v.VBELN, v.GJAHR) AS JournalEntryId,
'Journal Entry Parked' AS ActivityName,
CAST(CONCAT(v.CPUDT, v.CPUTM) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
v.USNAM AS User,
v.BUKRS AS CompanyCode,
v.BLART AS DocumentType,
v.BUDAT AS PostingDate,
v.TCODE AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].VBSEGK v
WHERE [Date Filter on v.CPUDT] AND [Company Code Filter on v.BUKRS]
UNION ALL
-- Extraction block for 'Journal Entry Created'
SELECT
CONCAT(h.BUKRS, h.BELNR, h.GJAHR) AS JournalEntryId,
'Journal Entry Created' AS ActivityName,
CAST(CONCAT(h.CPUDT, h.CPUTM) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
h.USNAM AS User,
h.BUKRS AS CompanyCode,
h.BLART AS DocumentType,
h.BUDAT AS PostingDate,
h.TCODE AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].BKPF h
LEFT JOIN [Your SAP Source].VBSEGK v ON h.AWKEY = CONCAT(v.BUKRS, v.VBELN, v.GJAHR)
WHERE h.BSTAT = '' AND v.VBELN IS NULL AND h.STBLG IS NULL
AND [Date Filter on h.CPUDT] AND [Company Code Filter on h.BUKRS]
UNION ALL
-- Extraction block for 'Journal Entry Posted' (from parked)
SELECT
CONCAT(h.BUKRS, h.BELNR, h.GJAHR) AS JournalEntryId,
'Journal Entry Posted' AS ActivityName,
CAST(CONCAT(h.CPUDT, h.CPUTM) AS TIMESTAMP) AS EventTime, -- Or a more precise posting time from change logs if available
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
h.USNAM AS User,
h.BUKRS AS CompanyCode,
h.BLART AS DocumentType,
h.BUDAT AS PostingDate,
h.TCODE AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].BKPF h
JOIN [Your SAP Source].VBSEGK v ON h.AWKEY = CONCAT(v.BUKRS, v.VBELN, v.GJAHR)
WHERE [Date Filter on h.CPUDT] AND [Company Code Filter on h.BUKRS]
UNION ALL
-- Extraction block for 'Journal Entry Submitted', 'Approved', 'Rejected', 'Changes Requested'
SELECT
CONCAT(SUBSTRING(o.INSTID, 3, 4), SUBSTRING(o.INSTID, 7, 10), SUBSTRING(o.INSTID, 17, 4)) AS JournalEntryId,
CASE
WHEN wl.WI_TEXT LIKE '%Submit%' THEN 'Journal Entry Submitted'
WHEN wl.WI_TEXT LIKE '%Approve%' THEN 'Journal Entry Approved'
WHEN wl.WI_TEXT LIKE '%Reject%' THEN 'Journal Entry Rejected'
WHEN wl.WI_TEXT LIKE '%Request Changes%' THEN 'Journal Entry Changes Requested'
END AS ActivityName,
CAST(CONCAT(wl.WI_CD, wl.WI_CT) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
wl.EXEC_USER AS User,
SUBSTRING(o.INSTID, 3, 4) AS CompanyCode,
NULL AS DocumentType,
NULL AS PostingDate,
NULL AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].SWW_WI2OBJ o
JOIN [Your SAP Source].SWWLOGHIST wl ON o.WI_ID = wl.WI_ID
WHERE o.TYPEID = 'BKPF' AND o.CATID = 'BO'
AND wl.WI_TEXT IN ('[Your Submit Task Name]', '[Your Approve Task Name]', '[Your Reject Task Name]', '[Your Changes Request Task Name]')
AND [Date Filter on wl.WI_CD]
UNION ALL
-- Extraction block for 'Journal Entry Corrected'
SELECT
CONCAT(cd.OBJECTID_LONG_CHAR(3,4), cd.OBJECTID_LONG_CHAR(7,10), cd.OBJECTID_LONG_CHAR(17,4)) AS JournalEntryId,
'Journal Entry Corrected' AS ActivityName,
CAST(CONCAT(cd.UDATE, cd.UTIME) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
cd.USERNAME AS User,
cd.OBJECTID_LONG_CHAR(3,4) AS CompanyCode,
NULL AS DocumentType,
NULL AS PostingDate,
cd.TCODE AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].CDHDR cd
WHERE cd.OBJECTCLAS = 'FIPP' AND cd.CHANGE_IND = 'U'
AND [Date Filter on cd.UDATE]
UNION ALL
-- Extraction block for 'Parked Journal Entry Deleted'
SELECT
CONCAT(cd.OBJECTID_LONG_CHAR(3,4), cd.OBJECTID_LONG_CHAR(7,10), cd.OBJECTID_LONG_CHAR(17,4)) AS JournalEntryId,
'Parked Journal Entry Deleted' AS ActivityName,
CAST(CONCAT(cd.UDATE, cd.UTIME) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
cd.USERNAME AS User,
cd.OBJECTID_LONG_CHAR(3,4) AS CompanyCode,
NULL AS DocumentType,
NULL AS PostingDate,
cd.TCODE AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].CDHDR cd
WHERE cd.OBJECTCLAS = 'FIPP' AND cd.CHANGE_IND = 'D'
AND [Date Filter on cd.UDATE]
UNION ALL
-- Extraction block for 'Documentation Attached'
SELECT
CONCAT(SUBSTRING(r.INSTID_A, 3, 4), SUBSTRING(r.INSTID_A, 7, 10), SUBSTRING(r.INSTID_A, 17, 4)) AS JournalEntryId,
'Documentation Attached' AS ActivityName,
-- Note: A precise timestamp is often unavailable. Using document creation time as a proxy.
CAST(CONCAT(h.CPUDT, h.CPUTM) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
h.USNAM AS User,
h.BUKRS AS CompanyCode,
h.BLART AS DocumentType,
h.BUDAT AS PostingDate,
h.TCODE AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].SRGBTBREL r
JOIN [Your SAP Source].BKPF h ON h.BUKRS = SUBSTRING(r.INSTID_A, 3, 4) AND h.BELNR = SUBSTRING(r.INSTID_A, 7, 10) AND h.GJAHR = SUBSTRING(r.INSTID_A, 17, 4)
WHERE r.TYPEID_A = 'BKPF' AND r.RELTYPE = '[Configure based on your system]'
AND [Date Filter on h.CPUDT] AND [Company Code Filter on h.BUKRS]
UNION ALL
-- Extraction block for 'Journal Entry Reversal Processed'
SELECT
CONCAT(h.BUKRS, h.BELNR, h.GJAHR) AS JournalEntryId,
'Journal Entry Reversal Processed' AS ActivityName,
CAST(CONCAT(h.CPUDT, h.CPUTM) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
h.USNAM AS User,
h.BUKRS AS CompanyCode,
h.BLART AS DocumentType,
h.BUDAT AS PostingDate,
h.TCODE AS TransactionCode,
TRUE AS IsReversed
FROM [Your SAP Source].BKPF h
WHERE h.STBLG IS NOT NULL AND h.STBLG <> ''
AND [Date Filter on h.CPUDT] AND [Company Code Filter on h.BUKRS]
UNION ALL
-- Extraction block for 'Is Reversed' flag on original document
SELECT
CONCAT(h_orig.BUKRS, h_orig.BELNR, h_orig.GJAHR) AS JournalEntryId,
'Is Reversed' AS ActivityName, -- This is an attribute update, modeled as an event
CAST(CONCAT(h_rev.CPUDT, h_rev.CPUTM) AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
h_rev.USNAM AS User,
h_orig.BUKRS AS CompanyCode,
h_orig.BLART AS DocumentType,
h_orig.BUDAT AS PostingDate,
h_orig.TCODE AS TransactionCode,
TRUE AS IsReversed
FROM [Your SAP Source].BKPF h_rev
JOIN [Your SAP Source].BKPF h_orig ON h_rev.STBLG = h_orig.BELNR AND h_rev.BUKRS = h_orig.BUKRS AND h_rev.GJAHR_S = h_orig.GJAHR
WHERE h_rev.STBLG IS NOT NULL AND h_rev.STBLG <> ''
AND [Date Filter on h_rev.CPUDT] AND [Company Code Filter on h_rev.BUKRS]
UNION ALL
-- Extraction block for 'Journal Entry Line Item Cleared'
SELECT
CONCAT(i.BUKRS, i.BELNR, i.GJAHR) AS JournalEntryId,
'Journal Entry Line Item Cleared' AS ActivityName,
CAST(i.AUGDT AS TIMESTAMP) AS EventTime,
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
NULL AS User, -- User who performed clearing is on the clearing document header
i.BUKRS AS CompanyCode,
NULL AS DocumentType,
NULL AS PostingDate,
NULL AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].BSEG i
WHERE i.AUGBL IS NOT NULL AND i.AUGBL <> ''
AND [Date Filter on i.AUGDT] AND [Company Code Filter on i.BUKRS]
UNION ALL
-- Extraction block for 'Manual Entry Identified'
SELECT
CONCAT(h.BUKRS, h.BELNR, h.GJAHR) AS JournalEntryId,
'Manual Entry Identified' AS ActivityName,
CAST(CONCAT(h.CPUDT, h.CPUTM) AS TIMESTAMP) AS EventTime, -- Same time as creation
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
h.USNAM AS User,
h.BUKRS AS CompanyCode,
h.BLART AS DocumentType,
h.BUDAT AS PostingDate,
h.TCODE AS TransactionCode,
FALSE AS IsReversed
FROM [Your SAP Source].BKPF h
WHERE h.TCODE IN ('FB01', 'F-02', 'FB50', 'FV50', '[Add other manual T-Codes]')
AND [Date Filter on h.CPUDT] AND [Company Code Filter on h.BUKRS]
UNION ALL
-- Extraction block for 'Cross-Company Posting Identified'
SELECT
JournalEntryId,
'Cross-Company Posting Identified' AS ActivityName,
EventTime, -- Same time as creation
'SAP ECC' AS SourceSystem,
NOW() AS LastDataUpdate,
User,
CompanyCode,
DocumentType,
PostingDate,
TransactionCode,
IsReversed
FROM (
SELECT
CONCAT(h.BUKRS, h.BELNR, h.GJAHR) AS JournalEntryId,
CAST(CONCAT(h.CPUDT, h.CPUTM) AS TIMESTAMP) AS EventTime,
h.USNAM AS User,
h.BUKRS AS CompanyCode,
h.BLART AS DocumentType,
h.BUDAT AS PostingDate,
h.TCODE AS TransactionCode,
FALSE AS IsReversed,
(SELECT COUNT(DISTINCT i.BUKRS) FROM [Your SAP Source].BSEG i WHERE i.BELNR = h.BELNR AND i.BUKRS = h.BUKRS AND i.GJAHR = h.GJAHR) as CompanyCodeCount
FROM [Your SAP Source].BKPF h
WHERE [Date Filter on h.CPUDT] AND [Company Code Filter on h.BUKRS]
) AS CrossCompanyCheck
WHERE CompanyCodeCount > 1