您的订单到现金:开票与发票处理数据模板
您的订单到现金:开票与发票处理数据模板
- 全面分析所需的推荐属性
- 需要跟踪的关键流程步骤和里程碑
- SAP ECC实用数据提取指南
订单到收款-开票与发票处理属性
| 名称 | 说明 | ||
|---|---|---|---|
| 发票编号 InvoiceNumber | 开票凭证的唯一标识符,也是发票处理流程的主要案例ID。 | ||
| 说明 发票编号在SAP中称为开票凭证编号,用于唯一标识每张发票。在流程挖掘中,它充当CaseId,将创建、过账、发送、付款和清账等所有相关活动归入同一个端到端流程实例。 按发票编号分析流程,可以完整查看每笔开票交易从创建到最终结算的生命周期。这对于计算应收账款周转天数(DSO)和整体发票周期时间等关键绩效指标至关重要,也为绩效衡量和改进提供清晰依据。 为什么重要 这是跟踪发票完整生命周期的关键字段,可按每笔开票交易分析周期时间、瓶颈和流程变体。 获取位置 SAP ECC表:VBRK,字段:VBELN 示例 90001234900012359000123690001237 | |||
| 开始时间 EventTime | 表示特定活动或事件发生时间的时间戳。 | ||
| 说明 事件时间记录发票生命周期中每项活动的准确日期和时间。该时间戳是流程挖掘中所有基于时间的分析的基础,包括计算周期时间、识别瓶颈,以及监控流程绩效是否达到服务级别协议要求。 此属性通常由多个SAP表中的日期字段和时间字段组合构成,例如记录变更或凭证创建的BKPF(BUDAT、CPUTM)、VBRK(ERDAT、ERZET)以及变更日志表CDHDR(UDATE、UTIME)。准确的时间戳对于构建可靠的事件日志、确保绩效分析有效性至关重要。 为什么重要 此属性是所有绩效分析的基础,可用于计算流程步骤之间的周期时间、持续时间和等待时间。 获取位置 由多个表中的日期和时间字段构成,例如BKPF(BUDAT、CPUTM)、VBRK(ERDAT、ERZET)以及CDHDR等变更日志表(UDATE、UTIME)。 示例 2023-04-15T10:30:00Z2023-04-16T11:00:00Z2023-05-20T09:00:00Z | |||
| 活动 ActivityName | 发票生命周期中发生的业务事件或步骤名称。 | ||
| 说明 该属性描述开票流程中的具体操作或状态变化,例如“发票已生成”“发票已过账”或“已收到客户付款”。这些活动源自各种系统事件、单据状态变化或用户执行的特定事务代码。 这些活动的顺序构成流程,是流程挖掘分析的基础。通过检查活动,组织可以了解实际执行了哪些步骤、执行顺序以及执行频率,从而比较实际流程与设计流程。 为什么重要 它定义流程图中的步骤,用于可视化和分析流程、偏差及瓶颈。 获取位置 这是一个从多个来源推导出的概念属性,例如事务代码(CDHDR-TCODE)、凭证状态变化(VBUK-FKSTK)和会计凭证过账记录。 示例 发票已生成发票已过账已发出付款提醒发票已清账 | |||
| 公司代码 CompanyCode | 开具发票的法人实体标识符。 | ||
| 说明 公司代码代表SAP中的独立法人和会计核算单位。包括发票在内的所有财务交易,都必须过账至特定公司代码。这是基础组织数据要素。 在流程挖掘场景中,公司代码用于分析和比较企业内不同法人实体的开票流程绩效,帮助识别可供其他实体借鉴的最佳实践,并确保分析符合企业组织结构。 为什么重要 支持跨不同法人实体筛选和比较流程,是财务分析和组织基准对比的基础。 获取位置 SAP ECC表:VBRK,字段:BUKRS 示例 10002000US01DE01 | |||
| 发票总金额 TotalInvoiceAmount | 账单凭证的总净值。 | ||
| 说明 此属性表示发票的总净额,不含税费。发票金额是与开票流程相关的重要财务数据。 它可用于多种分析,例如将发票划分为高价值和低价值类别,以判断两者的流程是否存在差异。您还可以据此确定催收优先级,或调查高价值发票为何需要更长时间才能获批或完成付款。这一财务背景为流程分析增加了重要的深度。 为什么重要 提供必要的财务背景,支持基于发票价值的分析,例如识别高价值发票是否遵循不同流程,或需要更长时间才能完成结算。 获取位置 SAP ECC表:VBRK,字段:NETWR 示例 1500.7525000.00500.0012345.67 | |||
| 客户编号 CustomerNumber | 用于唯一标识发票开具对象客户的编号。 | ||
| 说明 客户编号将发票关联到特定客户或业务合作伙伴。该属性对于根据客户特征细分和分析开票流程至关重要。 分析人员可以使用此字段比较不同客户的应收账款周转天数(DSO)、识别经常逾期付款的客户,或分析付款条件合规情况。了解这些模式,是管理客户关系和制定针对不同客户群体的收款策略的关键。 为什么重要 支持以客户为中心的分析,帮助识别付款行为、按客户评估DSO,并制定有针对性的收款策略。 获取位置 SAP ECC表:VBRK,字段:KUNRG(付款方)或KUNAG(售达方)。 示例 100023200541CUST-A487910345 | |||
| 开票凭证类型 BillingDocumentType | 用于对开票凭证类型进行分类的代码,例如发票、贷项凭证或借项凭证。 | ||
| 说明 开票凭证类型根据业务用途将交易划分为不同类别。例如,“F2”表示标准客户发票,“G2”表示贷项凭证。此分类在SAP中配置,用于控制不同开票凭证的处理方式。 对于流程挖掘而言,该属性对于筛选和比较不同开票场景至关重要。分析人员可以将标准发票与贷项凭证分开分析,了解各自的流程、周期时间和挑战,从而制定更有针对性的流程改进措施。 为什么重要 该属性支持对不同开票流程进行分组和分析,例如区分标准发票与贷项通知单,因为两者通常具有明显不同的流程顺序。 获取位置 SAP ECC表:VBRK,字段:FKART 示例 F2G2L2IV | |||
| 用户名 UserName | 执行活动或创建凭证的用户ID。 | ||
| 说明 此属性记录负责某项事件的SAP用户ID,例如创建发票或过账付款的用户。它对于分析流程中的人为因素至关重要。 借助这些数据,您可以调查不同用户或团队之间的绩效差异、识别培训需求并发现潜在合规问题。它还可用于区分人工用户执行的手动活动与系统用户或批处理用户执行的自动化步骤,这对于计算自动化率十分关键。 为什么重要 支持分析用户绩效和工作负载分布,并区分手动活动与自动化活动,为自动化和效率提升计划提供依据。 获取位置 SAP ECC表:VBRK,字段:ERNAM(创建者);或BKPF,字段:USNAM(用户名);或CDHDR,字段:USERNAME(用户)。 示例 JSMITHBW_BATCHLROSSIMKUMAR | |||
| 事务代码 TransactionCode | 用于执行某项活动的SAP事务代码。 | ||
| 说明 事务代码(即T-Code)是SAP中特定功能或程序的唯一标识符,例如用于创建开票凭证的“VF01”。记录每个事件的T-Code,可以从技术和系统层面了解流程的执行方式。 这些信息对于根因分析非常有价值。例如,当错误频繁发生时,分析人员可以检查是否使用了非标准事务代码。它还有助于推导活动名称,并了解流程使用了哪些系统功能。 为什么重要 提供活动执行方式的技术背景,支持流程偏差的根因分析,并帮助识别非标准用户操作。 获取位置 SAP ECC表:CDHDR,字段:TCODE 示例 VF01VF02FB01F-28 | |||
| 付款条件 PaymentTerms | 卖方完成销售所依据的条件,包括付款计划。 | ||
| 说明 付款条件规定付款到期时间,例如“Net 30”或“Net 60”。这些条件由客户与卖方协商确定,是影响现金流的关键因素。 按付款条件分析流程,可以发现某些条件是否与更长的付款周期或更高的逾期付款率相关。这些洞察有助于企业与客户协商更有利的条件,或调整财务规划。付款条件也是计算发票到期日的重要输入。 为什么重要 根据协商确定的条件分析客户付款行为及其对现金流的影响,为优化商业协议提供依据。 获取位置 SAP ECC表:VBRK,字段:ZTERM 示例 Z030Z060Z001 | |||
| 最近数据更新时间 LastDataUpdate | 源系统最近一次数据刷新或提取的时间戳。 | ||
| 说明 此属性表示数据集最近一次从源系统更新的时间,为分析提供重要背景,确保用户了解当前查看数据的新鲜度。 在仪表板和报告中,该时间戳可帮助相关人员了解数据的时效性,并合理预期近期交易的可见范围。通常在数据提取过程结束时生成。 为什么重要 告知用户数据的时效性,这对于基于分析结果做出运营决策至关重要。 获取位置 在数据提取、转换和加载(ETL)过程中生成并存储。 示例 2023-10-27T02:00:00Z2023-10-28T02:00:00Z | |||
| 凭证日期 DocumentDate | 由供应商或创建者提供的原始凭证日期。 | ||
| 说明 凭证日期是原始凭证签发的日期。在开票流程中,通常指发票创建日期,并常用于计算付款到期日。 该日期对于财务报告以及计算应收账款周转天数(DSO)等关键指标至关重要。从客户角度看,它代表催收周期的起点。分析凭证日期与过账日期之间的差异,可以发现内部处理进项发票时存在的延迟。 为什么重要 作为计算发票账龄和DSO的基准,为财务分析和付款条件分析提供重要参考。 获取位置 SAP ECC表:VBRK,字段:FKDAT(开票日期) 示例 2023-04-152023-04-162023-05-20 | |||
| 发票到期日 InvoiceDueDate | 客户应完成付款的日期。 | ||
| 说明 发票到期日是付款条件规定的付款截止日期,是管理应收账款和启动催收活动的基础。 此属性用于计算按时付款率KPI,方法是将其与实际付款日期进行比较。按到期日分析发票,有助于预测现金流,并确定即将到期或逾期付款的催收优先级。该日期通常根据基准日期和付款条件计算得出。 为什么重要 这是衡量按时付款表现的基准,对于应收账款管理和现金流预测至关重要。 获取位置 根据基准日期(BSEG-ZFBDT)和付款条件(BSEG-ZTERM)计算得出,通常不会始终存储在单独的直接字段中。 示例 2023-05-152023-05-302023-06-20 | |||
| 是否自动化 IsAutomated | 用于标识某项活动是由系统用户执行,还是通过自动化完成。 | ||
| 说明 此计算属性是一个布尔标记,用于区分手动活动和自动化活动。通常通过将用户名属性与已知系统用户或批处理用户ID列表进行比对得出,例如“BATCHUSER”或“SAPSYSTEM”。 该标记对于衡量开票流程的自动化程度至关重要。许多企业都希望通过提升自动化水平来提高效率、降低成本。自动化开票率KPI可直接根据此属性计算,用于跟踪自动化项目的进展。 为什么重要 直接支持自动化开票率的计算,帮助衡量流程效率并跟踪自动化项目的影响。 获取位置 根据用户名属性派生。逻辑示例:IF UserName IN ('BATCH', 'SYSTEM', 'RFCUSER') THEN true ELSE false。 示例 truefalse | |||
| 是否返工 IsRework | 用于标识某项活动是否属于返工或纠正步骤。 | ||
| 说明 此计算属性用于识别代表返工的活动,例如“发票已更正”或凭证冲销。通常根据活动名称,或与更正和取消相关的交易代码派生为布尔标记,例如用于取消账单凭证的“VF11”。 在流程挖掘中,该标记对于量化开票流程中的返工量非常有价值。它直接支持发票更正率等KPI,并帮助在流程图中呈现返工循环,突出会增加运营成本、延迟付款的低效和质量问题。 为什么重要 通过突出显示用于纠正错误的工作量,帮助量化流程低效和质量问题,并直接支持返工相关KPI。 获取位置 根据活动名称或交易代码派生。例如:IF ActivityName = 'Invoice Corrected' OR TransactionCode = 'VF11' THEN true ELSE false。 示例 truefalse | |||
| 清账日期 ClearingDate | 收到付款并从应收账款中清除发票的日期。 | ||
| 说明 清账日期是开放项目(如发票)在财务系统中被标记为已付款或“已清账”的日期。该日期通常代表现金完成收取并核对的时间。 这是订单到现金周期中最重要的日期之一。它是计算应收账款周转天数(DSO)和发票到现金整体周期时间的终点。分析清账日期有助于衡量催收流程的有效性。 为什么重要 标志着发票生命周期的最后一步,是计算DSO和整体周期时间的结束日期,也反映现金收款效率。 获取位置 SAP ECC表:BSAD,字段:AUGDT 示例 2023-05-142023-06-012023-06-25 | |||
| 源系统 SourceSystem | 标识数据提取自哪个源系统。 | ||
| 说明 此属性指定数据来源的记录系统。在包含多个ERP实例或集成系统的企业环境中,该字段有助于区分不同来源的数据。 对于流程挖掘而言,它对于数据验证以及跨系统或组织单元比较流程的分析至关重要。通常在数据提取过程中以静态值填充,用于标记数据集。 为什么重要 提供数据来源背景。在多系统环境中,这对于确保数据完整性和开展系统专项分析至关重要。 获取位置 通常在数据提取、转换和加载(ETL)过程中添加静态值,用于标识具体的SAP ECC实例,例如“ECC_PROD_NA”。 示例 SAP_ECC_PRODECC_EU_100SAP_US_FIN | |||
| 货币 Currency | 发票中金额所使用的货币代码。 | ||
| 说明 此属性表示交易所使用的货币,例如USD、EUR或JPY。它为总发票金额等货币数值提供必要背景。 分析跨国组织的数据时,货币字段对于正确解读和换算财务数据至关重要。它有助于统一报告,并确保金额在完成适当的货币换算后再进行汇总,避免因直接汇总不同货币而导致财务分析错误。 为什么重要 为所有货币数值提供必要背景,确保财务分析准确,尤其适用于多币种环境。 获取位置 SAP ECC表:VBRK,字段:WAERK 示例 USDEURGBPJPY | |||
| 过账日期 PostingDate | 凭证过账至财务会计账簿的日期。 | ||
| 说明 过账日期决定交易记入总账的会计期间,是会计核算和财务报告中的关键日期。凭证创建日期与过账日期之间的延迟,可能表明内部处理账单凭证的效率存在问题。 从流程挖掘角度看,过账日期标志着发票生命周期中的重要里程碑。发票生成到完成过账之间的时间差,可作为衡量开票部门处理效率的关键绩效指标。 为什么重要 标志着重要的财务里程碑,对会计核算至关重要。发票创建到过账之间的时间差,是衡量内部处理效率的重要指标。 获取位置 SAP ECC表:BKPF,字段:BUDAT 示例 2023-04-152023-04-172023-05-21 | |||
| 销售凭证编号 SalesDocumentNumber | 促成发票生成的原始销售订单标识符。 | ||
| 说明 此属性将发票直接关联回发起交易的销售订单。对于完整的端到端订单到现金分析,这种可追溯性至关重要。 将开票流程与前置的销售订单流程连接起来后,企业可以分析从客户下单到收到款项的完整周期时间。该属性有助于判断开票延迟是由销售、履约还是开票部门自身的问题造成,从而更全面地了解流程。 为什么重要 将开票流程关联回销售订单,支持真正的端到端订单到现金分析,并帮助识别跨部门延迟。 获取位置 SAP ECC表:VBRP,字段:VGBEL 示例 100000451000004610000047 | |||
| 销售组织 SalesOrganization | 负责销售产品或服务的组织单位。 | ||
| 说明 销售组织是SAP中负责分销商品和服务、协商销售条件的组织单位,也是构建销售与分销运营体系的重要字段。 在流程挖掘中,此属性支持从销售组织结构角度分析开票流程。您可以比较不同销售组织的绩效,识别哪些地区或业务线的开票效率更高,并推动最佳实践标准化。 为什么重要 支持不同销售部门或地区之间的绩效对标与分析,帮助识别最佳实践和改进方向。 获取位置 SAP ECC表:VBRK,字段:VKORG 示例 1000NA01EU01AP01 | |||
订单到收款-开票与发票处理活动
| 活动 | 说明 | ||
|---|---|---|---|
| 发票已发送给客户 | 表示发票已通过打印、电子邮件或EDI等指定输出渠道发送给客户。通常从输出管理系统日志中捕获此事件。 | ||
| 为什么重要 这是触发客户付款条件计时的关键里程碑。此处的延迟会直接影响预计收款时间,并影响收款效率。 获取位置 可根据消息状态表(NAST)中与发票对应输出类型的处理日期和时间推断。 采集 根据NAST表中处理状态为“1”(处理成功)的记录推断。 事件类型 inferred | |||
| 发票已清账 | 表示发票已成功付款的最终状态,说明未清项目已通过对应付款或贷项凭证关闭。该发票被视为已全部结清。 | ||
| 为什么重要 标志着某张发票的订单到收款周期成功完成。这是衡量整体平均发票周期时间的主要结束事件。 获取位置 当BSEG表中发票行项目的清账凭证(AUGBL)和清账日期(AUGDT)字段已填充时发生。 采集 事件发生在BSEG表中发票行项目记录的清账日期(AUGDT)。 事件类型 explicit | |||
| 发票已生成 | 表示系统中已创建开票凭证。当会计凭证抬头表(BKPF)中新增一条具有特定发票凭证类型的记录时,系统会捕获此事件。 | ||
| 为什么重要 这是整个发票处理流程的起点。分析从该事件开始经过的时间,有助于衡量发票创建周期时间,也是计算应收账款周转天数(DSO)的基础。 获取位置 记录在BKPF表中。特定凭证编号(BELNR)的创建日期(CPUDT)和时间(CPUTM)标记此事件。凭证类型(BLART)用于识别该凭证是否为发票。 采集 取自BKPF表中发票凭证的创建时间戳(CPUDT)。 事件类型 explicit | |||
| 发票已过账 | 发票已正式记录在应收账款明细账和总账中。此事件使发票具有法律约束力,并反映客户所欠债务。 | ||
| 为什么重要 这是一个关键里程碑,标志着收款计时正式开始。发票生成到过账之间的时间,可以揭示影响现金流的内部处理延迟。 获取位置 记录在BKPF表中。凭证编号(BELNR)的过账日期(BUDAT)标记此事件。对于暂存凭证,该事件发生在凭证转换为已过账凭证时。 采集 取自BKPF表中发票凭证的过账日期(BUDAT)。 事件类型 explicit | |||
| 已收到客户付款 | 已收到客户付款,并作为现金收款或银行存款过账到系统中。这会创建一个独立的付款凭证,但该付款尚未核销到具体发票。 | ||
| 为什么重要 这是现金转换周期中的重要里程碑。从发票发送到收到付款的时间,是应收账款周转天数(DSO)的主要组成部分。 获取位置 记录为BKPF和BSEG中的新凭证,通常使用表示客户付款的凭证类型,例如“DZ”。过账日期(BUDAT)标记此事件。 采集 取自BKPF中客户付款凭证的过账日期。 事件类型 explicit | |||
| 付款已核销到发票 | 收到的客户付款已与具体未清发票匹配并完成核销,标记该项目为已清账。这是将付款与债务关联起来的对账步骤。 | ||
| 为什么重要 此活动对于衡量现金核销周期时间至关重要。现金核销延迟可能导致应收账款实际状态失真,并掩盖可用现金。 获取位置 根据清账事务推断,例如F-32。该事务会填充发票行项目中的清账字段,事件时间戳为清账日期。 采集 根据发票行项目表(BSEG)中已填充的清账日期(AUGDT)推断。 事件类型 inferred | |||
| 发票已到期 | 一个计算得出的事件,标记根据付款条件正式到期的发票付款日。它不是用户或系统执行的活动,而是一个关键时间点。 | ||
| 为什么重要 对于分析付款行为和合规至关重要。它是判断按时付款与逾期付款,以及计算按时付款率KPI的基准。 获取位置 通过比较当前日期与净到期日得出。到期日位于字段BSEG-ZFBDT中,也可以根据基准日期和付款条件计算得出。 采集 将系统日期与发票行项目(BSEG)中的净到期日字段进行比较。 事件类型 calculated | |||
| 发票已审批 | 表示发票已正式获批,可以过账或发送给客户。通常可通过暂存凭证转换为已过账凭证来推断此事件。 | ||
| 为什么重要 用于跟踪内部审批工作流,这是常见的瓶颈来源。分析此活动有助于支持发票审批流程分析仪表板,并识别审批缓慢的人员。 获取位置 可通过凭证从暂存状态(VBKPF)转为已过账状态(BKPF)来推断。若使用工作流系统,也可能在工作流日志中记录为明确事件。 采集 比较暂存凭证(VBKPF)的创建日期与最终凭证(BKPF)的过账日期。 事件类型 inferred | |||
| 发票已暂存 | 发票凭证已保存为初步状态,但尚未过账至总账。信息不完整或需要在最终过账前审核时,通常会使用此状态。 | ||
| 为什么重要 用于跟踪过账前步骤和潜在延迟。暂存状态持续时间过长,可能表明数据质量问题或预审批流程存在瓶颈。 获取位置 暂存凭证存储在VBKPF表中。在该表中创建、随后完成过账的凭证,即表示此活动发生。 采集 使用FV70等事务保存暂存凭证时记录。 事件类型 explicit | |||
| 发票已更正 | 表示一项返工活动:初始发票被发现存在错误,随后被冲销。通过识别与原发票关联的冲销凭证来捕获此事件。 | ||
| 为什么重要 突出流程低效和质量问题。更正频率较高,说明上游销售或开票数据存在问题,可为发票返工与错误率仪表板提供支持。 获取位置 通过查找BKPF-STBLG指向原凭证的冲销凭证来识别。创建该冲销凭证即表示此事件发生。 采集 创建冲销凭证时记录,例如通过FB08创建。 事件类型 explicit | |||
| 发票已核销为坏账 | 一种替代性的最终状态:发票被认定为无法收回,未偿金额冲销至坏账科目。该操作无需客户付款即可关闭发票。 | ||
| 为什么重要 表示负面的流程结果和收入损失。跟踪此类事件有助于分析坏账原因,并改进信用管理政策。 获取位置 通过分析发票的清账事务推断。如果清账凭证过账至指定的坏账费用总账科目,则视为发票已核销为坏账。 采集 当清账事务涉及过账至指定坏账总账科目时推断。 事件类型 inferred | |||
| 已创建争议案件 | 已针对发票登记正式争议,通常源于客户投诉。该事件记录在SAP争议管理系统中。 | ||
| 为什么重要 用于识别存在付款延迟风险的发票,并突出导致客户不满的潜在问题。这标志着重要异常处理流程的开始。 获取位置 通过在争议案件表(UDM_CASE)中创建与发票会计凭证关联的案件来捕获。 采集 用户通过事务UDM_DISPUTE创建争议案件时记录。 事件类型 explicit | |||
| 已发出付款提醒 | 系统已针对逾期发票生成并向客户发送催款通知或付款提醒。此事件从催款历史日志中捕获。 | ||
| 为什么重要 有助于评估收款策略的有效性。分析从提醒发出到收到付款之间的时间,是付款提醒有效性KPI的关键。 获取位置 记录在催款数据表中,具体包括MHNK(催款数据抬头)和MHND(催款数据行项目)。这些记录由催款运行(事务F150)生成。 采集 针对逾期项目执行催款运行(F150)时记录。 事件类型 explicit | |||
提取指南
步骤
- 访问ABAP编辑器:登录您的SAP ECC系统。使用事务代码
SE38打开ABAP编辑器。 - 创建程序:在Program字段中输入新程序的名称,例如
Z_PM_O2C_INVOICE_EXTRACT,然后点击Create按钮。填写描述性标题,并将程序Type设置为“Executable Program”。 - 定义选择屏幕:在程序源代码中定义选择屏幕参数,以便用户筛选要提取的数据。关键参数包括单据创建日期范围(
S_ERDAT)、公司代码(S_BUKRS)和开票单据类型(S_VBTYP)。 - 定义数据结构:声明用于存储最终事件日志数据的内表结构。该结构必须包含
InvoiceNumber、ActivityName、EventTime字段,以及建议的属性,如UserName、BillingDocumentType、CustomerNumber、CompanyCode和TotalInvoiceAmount。 - 实现数据选择逻辑:编写核心ABAP逻辑以选择数据。首先,根据用户在选择屏幕中输入的条件,从
VBRK和BKPF表中选择主要开票单据,并将结果存入临时内表。 - 提取活动:遍历初始开票单据列表。针对每张单据,从不同表中继续选择数据,以识别所需的13项活动。例如,从
NAST查询“Invoice Sent To Customer”事件,从BSEG获取清账信息(“Invoice Cleared”“Payment Applied”),从MHNK获取催款数据(“Payment Reminder Issued”)。 - 构建事件日志表:针对上一步找到的每项活动,在最终事件日志内表中新增一条记录。确保
InvoiceNumber、ActivityName、EventTime及其他属性均正确映射自源表。 - 写入应用服务器:循环完成且最终事件日志表填充完毕后,使用
OPEN DATASET、LOOP AT... TRANSFER和CLOSE DATASET语句,将内表内容写入SAP应用服务器上的平面文件。请指定可访问的逻辑文件路径。 - 获取文件:使用事务代码
AL11浏览应用服务器目录并定位生成的文件。与SAP Basis团队协调,将文件从服务器下载到本地计算机或共享网络位置。 - 最终格式处理:打开下载的文件,确认其为带表头行的逗号分隔值(CSV)文件。确保文件使用UTF-8编码,以便兼容ProcessMind上传。
配置
- 前置条件:具备创建和执行ABAP程序的权限(事务SE38),并获授权读取FI和SD表,包括
VBRK、VBRP、BKPF、BSEG、NAST、MHNK和UDM_CASE_ATTR00(用于Dispute Management)。 - 日期范围选择:程序应设置必填的日期范围参数,通常依据单据创建日期(VBRK/BKPF中的
ERDAT)。首次提取建议选择3至6个月,以控制数据集规模。 - 关键筛选条件:始终按公司代码(
BUKRS)筛选,以限制提取范围。同时强烈建议按开票单据类型(VBRK中的VBTYP)或会计单据类型(BKPF中的BLART)筛选,仅纳入相关发票类型,例如标准会计发票“RV”,并排除贷项通知单及其他单据。 - 性能注意事项:对于覆盖数月的大型数据集,应将程序作为后台作业执行,以避免会话超时。ABAP逻辑应优化为使用索引表读取,并避免在嵌套循环中执行数据库选择。建议先将数据选择到内表,再进行处理。
- 输出文件配置:ABAP代码必须指定应用服务器上的输出文件路径及CSV文件分隔符,通常为逗号或分号。请确保路径为全局配置且可访问的目录。
a 示例查询 abap
REPORT Z_PM_O2C_INVOICE_EXTRACT.
*&---------------------------------------------------------------------*
*& Tables
*&---------------------------------------------------------------------*
TABLES: VBRK, BKPF.
*&---------------------------------------------------------------------*
*& Type Definitions for Event Log Output
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
invoicenumber TYPE vbrk-vbeln,
activityname TYPE string,
eventtime TYPE timestamp,
username TYPE xubname,
billingdocumenttype TYPE vbrk-vbtyp,
customernumber TYPE vbrk-kunnr,
companycode TYPE vbrk-bukrs,
totalinvoiceamount TYPE vbrk-netwr,
END OF ty_event_log.
*&---------------------------------------------------------------------*
*& Data Declarations
*&---------------------------------------------------------------------*
DATA: gt_event_log TYPE TABLE OF ty_event_log,
gs_event_log TYPE ty_event_log.
DATA: BEGIN OF gs_invoice,
vbeln TYPE vbrk-vbeln, " SD Doc (Invoice)
awkey TYPE bkpf-awkey, " Accounting Doc Reference Key
bukrs TYPE vbrk-bukrs, " Company Code
kunnr TYPE vbrk-kunnr, " Customer
vbtyp TYPE vbrk-vbtyp, " SD Doc Type
netwr TYPE vbrk-netwr, " Net Value
waerk TYPE vbrk-waerk, " Currency
fkdat TYPE vbrk-fkdat, " Billing Date
erdat TYPE vbrk-erdat, " Creation Date
erzet TYPE vbrk-erzet, " Creation Time
ernam TYPE vbrk-ernam, " Creator
belnr TYPE bkpf-belnr, " Acct Doc
gjahr TYPE bkpf-gjahr, " Fiscal Year
cpudt TYPE bkpf-cpudt, " Acct Doc Entry Date
cputm TYPE bkpf-cputm, " Acct Doc Entry Time
usnam TYPE bkpf-usnam, " Acct Doc User
stblg TYPE bkpf-stblg, " Reversal Doc
END OF gs_invoice.
DATA: gt_invoices LIKE TABLE OF gs_invoice.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_erdat FOR vbrk-erdat OBLIGATORY,
s_bukrs FOR vbrk-bukrs OBLIGATORY,
s_vbtyp FOR vbrk-vbtyp.
PARAMETERS: p_path TYPE string DEFAULT '/usr/sap/trans/tmp/invoice_extract.csv' OBLIGATORY.
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
" 1. Select base set of invoices
SELECT vbrk~vbeln, vbrk~bukrs, vbrk~kunnr, vbrk~vbtyp, vbrk~netwr, vbrk~waerk,
vbrk~fkdat, vbrk~erdat, vbrk~erzet, vbrk~ernam,
bkpf~belnr, bkpf~gjahr, bkpf~cpudt, bkpf~cputm, bkpf~usnam, bkpf~stblg, bkpf~awkey
INTO CORRESPONDING FIELDS OF TABLE gt_invoices
FROM vbrk
INNER JOIN bkpf ON bkpf~awkey = vbrk~vbeln AND bkpf~awtyp = 'VBRK'
WHERE vbrk~erdat IN s_erdat
AND vbrk~bukrs IN s_bukrs
AND vbrk~vbtyp IN s_vbtyp.
IF gt_invoices IS INITIAL.
MESSAGE 'No invoices found for the selected criteria.' TYPE 'I'.
RETURN.
ENDIF.
LOOP AT gt_invoices INTO gs_invoice.
CLEAR gs_event_log.
gs_event_log-invoicenumber = gs_invoice-vbeln.
gs_event_log-billingdocumenttype = gs_invoice-vbtyp.
gs_event_log-customernumber = gs_invoice-kunnr.
gs_event_log-companycode = gs_invoice-bukrs.
gs_event_log-totalinvoiceamount = gs_invoice-netwr.
" Activity: Invoice Generated (using accounting doc creation)
gs_event_log-activityname = 'Invoice Generated'.
gs_event_log-username = gs_invoice-usnam.
CONCATENATE gs_invoice-cpudt gs_invoice-cputm INTO DATA(lv_ts_gen).
CONVERT DATE gs_invoice-cpudt TIME gs_invoice-cputm INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
" Activity: Invoice Posted (same as generated for non-parked docs)
gs_event_log-activityname = 'Invoice Posted'.
gs_event_log-username = gs_invoice-usnam.
CONVERT DATE gs_invoice-cpudt TIME gs_invoice-cputm INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
" Activity: Invoice Approved (inferred by posting)
gs_event_log-activityname = 'Invoice Approved'.
APPEND gs_event_log TO gt_event_log.
" Activity: Invoice Sent To Customer
SELECT SINGLE addat, aduhr FROM nast
INTO (DATA(lv_nast_date), DATA(lv_nast_time))
WHERE kappl = 'V3' AND objky = gs_invoice-vbeln AND vszst > '0'.
IF sy-subrc = 0.
gs_event_log-activityname = 'Invoice Sent To Customer'.
gs_event_log-username = sy-uname.
CONVERT DATE lv_nast_date TIME lv_nast_time INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
ENDIF.
" Activity: Invoice Corrected / Reversed
IF gs_invoice-stblg IS NOT INITIAL.
SELECT SINGLE cpudt, cputm, usnam FROM bkpf
INTO (DATA(lv_rev_date), DATA(lv_rev_time), DATA(lv_rev_user))
WHERE belnr = gs_invoice-stblg AND gjahr = gs_invoice-gjahr.
IF sy-subrc = 0.
gs_event_log-activityname = 'Invoice Corrected'.
gs_event_log-username = lv_rev_user.
CONVERT DATE lv_rev_date TIME lv_rev_time INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDIF.
" Activity: Payment Applied, Cleared, Due Date, Written Off (from BSEG)
SELECT SINGLE augdt, augbl, zfBDT, hkont FROM bseg
INTO (DATA(lv_augdt), DATA(lv_augbl), DATA(lv_zfbdt), DATA(lv_hkont))
WHERE bukrs = gs_invoice-bukrs
AND belnr = gs_invoice-belnr
AND gjahr = gs_invoice-gjahr
AND koart = 'D'. " Customer line
IF sy-subrc = 0.
" Due Date Reached (Calculated event)
IF lv_zfbdt IS NOT INITIAL.
gs_event_log-activityname = 'Invoice Due Date Reached'.
gs_event_log-username = 'System'.
CONVERT DATE lv_zfbdt INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
ENDIF.
" Cleared, Applied, Write-Off
IF lv_augdt IS NOT INITIAL.
SELECT SINGLE usnam, cpudt, cputm, blart FROM bkpf
INTO (DATA(lv_clear_user), DATA(lv_clear_date), DATA(lv_clear_time), DATA(lv_clear_type))
WHERE belnr = lv_augbl AND bukrs = gs_invoice-bukrs.
IF sy-subrc = 0.
gs_event_log-username = lv_clear_user.
CONVERT DATE lv_clear_date TIME lv_clear_time INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
IF lv_clear_type = 'DZ'. " Standard Customer Payment
gs_event_log-activityname = 'Customer Payment Received'. APPEND gs_event_log TO gt_event_log.
gs_event_log-activityname = 'Payment Applied To Invoice'. APPEND gs_event_log TO gt_event_log.
gs_event_log-activityname = 'Invoice Cleared'. APPEND gs_event_log TO gt_event_log.
ELSE. " Assuming other clearing doc types could be write-offs
gs_event_log-activityname = 'Invoice Written Off'.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
" Activity: Payment Reminder Issued (Dunning)
SELECT COUNT(*) FROM mhnk WHERE kunnr = gs_invoice-kunnr AND bukrs = gs_invoice-bukrs AND lafdn > gs_invoice-cpudt.
IF sy-subrc = 0 AND sy-dbcnt > 0.
SELECT SINGLE lafdn FROM mhnk
INTO DATA(lv_dunning_date)
WHERE kunnr = gs_invoice-kunnr AND bukrs = gs_invoice-bukrs AND lafdn > gs_invoice-cpudt.
gs_event_log-activityname = 'Payment Reminder Issued'.
gs_event_log-username = 'System'.
CONVERT DATE lv_dunning_date INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
ENDIF.
" Activity: Invoice Parked (Example from VBKPF, may require system specific logic)
SELECT SINGLE cpudt, cputm, usnam FROM vbkpf
INTO (DATA(lv_park_date), DATA(lv_park_time), DATA(lv_park_user))
WHERE awkey = gs_invoice-vbeln AND awsys = 'LOG' AND bstat = 'V'.
IF sy-subrc = 0.
gs_event_log-activityname = 'Invoice Parked'.
gs_event_log-username = lv_park_user.
CONVERT DATE lv_park_date TIME lv_park_time INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
ENDIF.
" Activity: Dispute Case Created (Requires Dispute Management module)
SELECT SINGLE create_date, create_time, create_user FROM udm_case_attr00
INTO (DATA(lv_disp_date), DATA(lv_disp_time), DATA(lv_disp_user))
WHERE [Your logic to link invoice to dispute case, e.g., via a custom field or object link].
IF sy-subrc = 0.
gs_event_log-activityname = 'Dispute Case Created'.
gs_event_log-username = lv_disp_user.
CONVERT DATE lv_disp_date TIME lv_disp_time INTO TIME STAMP gs_event_log-eventtime TIME ZONE sy-zonlo.
APPEND gs_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
*&---------------------------------------------------------------------*
*& Write data to file
*&---------------------------------------------------------------------*
OPEN DATASET p_path FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc <> 0.
MESSAGE 'Error opening file.' TYPE 'E'.
ENDIF.
" Header
DATA(lv_header) = 'InvoiceNumber,ActivityName,EventTime,UserName,BillingDocumentType,CustomerNumber,CompanyCode,TotalInvoiceAmount'.
TRANSFER lv_header TO p_path.
LOOP AT gt_event_log INTO gs_event_log.
DATA(lv_line) = |
{ gs_event_log-invoicenumber }|
,{ gs_event_log-activityname }|
,{ gs_event_log-eventtime }|
,{ gs_event_log-username }|
,{ gs_event_log-billingdocumenttype }|
,{ gs_event_log-customernumber }|
,{ gs_event_log-companycode }|
,{ gs_event_log-totalinvoiceamount }|.
TRANSFER lv_line TO p_path.
ENDLOOP.
CLOSE DATASET p_path.
WRITE: 'Extraction complete. File created at:', p_path. 步骤
- 前置条件与访问权限:确保您拥有数据库用户,并对所需SAP ECC表具有只读访问权限,包括VBRK、BKPF、BSAD、NAST、CDHDR、CDPOS、SCASE以及查询中指定的其他表。此级别的访问权限通常仅授予系统管理员或特定数据分析团队。
- 连接数据库:使用标准SQL客户端工具,例如DBeaver、Oracle SQL Developer或Microsoft SQL Server Management Studio,连接SAP ECC数据库。
- 准备SQL查询:将“query”部分提供的完整SQL查询复制到SQL客户端编辑器中。
- 自定义占位符:查询包含多个需要替换为您所在环境具体值的占位符,包括:
'YYYYMMDD':将所有实例替换为所需分析期间的开始和结束日期。务必将数据筛选到可管理的时间范围内。'XXXX':替换为您要分析的具体公司代码。[Your Invoice Output Type]:指定用于向客户发送发票的输出类型代码,例如“RD00”。[Your Bad Debt G/L Account]:输入用于核销无法收回发票的总账科目编号。[Your Dispute Case Invoice Attribute]:指定Dispute Management配置中用于存储发票编号的属性名称,例如“INVOICE_ID”。
- 检查时间戳函数:查询使用通用的
CAST(CONCAT(date_field, time_field) AS TIMESTAMP)语法。您可能需要根据具体数据库系统进行调整,例如Oracle使用TO_TIMESTAMP,SQL Server使用DATETIMEFROMPARTS。 - 执行查询:运行修改后的查询。具体耗时取决于SAP表规模和所选日期范围,可能需要较长时间。
- 检查结果:查询完成后,检查输出是否包含预期列:InvoiceNumber、ActivityName、EventTime及建议的属性。同时检查是否存在错误或空结果。
- 导出为CSV:通过SQL客户端将完整结果集导出为CSV文件。确保文件使用UTF-8编码,以避免特殊字符出现问题。
- 准备上传:上传到流程挖掘工具前,确认CSV列标题与所需属性名称完全一致,例如
InvoiceNumber、ActivityName、EventTime和UserName。
配置
- 数据库连接:需要直接连接底层SAP ECC数据库,并具有只读权限。此方法会完全绕过SAP应用层。
- 授权:数据库用户必须对查询使用的所有表拥有
SELECT权限,这些表涉及FI、SD以及可能的FSCM模块。 - 日期范围:必须按具体日期范围筛选查询,以确保性能和数据量处于合理水平。建议首次选择3至6个月。日期筛选占位符
'YYYYMMDD'必须在查询的多个部分中设置。 - 公司代码筛选:查询设计为按公司代码(
BUKRS)筛选。一次分析一个或少数几个公司代码是标准做法。 - 单据类型配置:识别发票更正、核销或已发送单据等事件的逻辑取决于SAP标准配置。如果您的组织使用自定义单据类型(
BLART)、输出类型(KSCHL)或相关流程的总账科目,可能需要调整查询。 - 性能注意事项:针对在线生产SAP系统执行此查询可能消耗大量资源,并影响运营性能。强烈建议在业务低峰期执行大型提取,或针对专用报表数据库副本运行。
a 示例查询 sql
WITH InvoiceBase AS (
SELECT
VBRK.VBELN AS InvoiceNumber,
VBRK.FKART AS BillingDocumentType,
VBRK.KUNRG AS CustomerNumber,
VBRK.BUKRS AS CompanyCode,
VBRK.NETWR AS TotalInvoiceAmount,
VBRK.ERNAM AS CreatorName,
VBRK.ERDAT AS CreationDate,
VBRK.ERZET AS CreationTime
FROM VBRK
WHERE VBRK.ERDAT BETWEEN '20230101' AND '20231231' -- Filter by Invoice Creation Date
AND VBRK.BUKRS IN ('1000') -- Filter by Company Code
AND VBRK.FKART NOT IN ('S1', 'S2') -- Exclude cancelled invoices
)
-- 1. Invoice Generated
SELECT
ib.InvoiceNumber,
'Invoice Generated' AS ActivityName,
CAST(CONCAT(ib.CreationDate, ib.CreationTime) AS TIMESTAMP) AS EventTime,
ib.CreatorName AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
ib.CompanyCode,
ib.TotalInvoiceAmount
FROM InvoiceBase ib
UNION ALL
-- 2. Invoice Parked
SELECT
SUBSTRING(b.AWKEY, 1, 10) AS InvoiceNumber,
'Invoice Parked' AS ActivityName,
CAST(CONCAT(b.CPUDT, b.CPUTM) AS TIMESTAMP) AS EventTime,
b.USNAM AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
b.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM BKPF b
JOIN InvoiceBase ib ON SUBSTRING(b.AWKEY, 1, 10) = ib.InvoiceNumber
WHERE b.AWTYP = 'VBRK' AND b.BSTAT = 'V' AND b.CPUDT BETWEEN '20230101' AND '20231231'
UNION ALL
-- 3. Invoice Posted
SELECT
SUBSTRING(b.AWKEY, 1, 10) AS InvoiceNumber,
'Invoice Posted' AS ActivityName,
CAST(CONCAT(b.CPUDT, b.CPUTM) AS TIMESTAMP) AS EventTime,
b.USNAM AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
b.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM BKPF b
JOIN InvoiceBase ib ON SUBSTRING(b.AWKEY, 1, 10) = ib.InvoiceNumber
WHERE b.AWTYP = 'VBRK' AND b.BSTAT = '' AND b.CPUDT BETWEEN '20230101' AND '20231231'
UNION ALL
-- 4. Invoice Approved (from Parked to Posted)
SELECT
SUBSTRING(h.OBJECTID, 4, 10) AS InvoiceNumber,
'Invoice Approved' as ActivityName,
CAST(CONCAT(h.UDATE, h.UTIME) AS TIMESTAMP) AS EventTime,
h.USERNAME AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
ib.CompanyCode,
ib.TotalInvoiceAmount
FROM CDHDR h
JOIN CDPOS p ON h.MANDANT = p.MANDANT AND h.OBJECTCLAS = p.OBJECTCLAS AND h.OBJECTID = p.OBJECTID AND h.CHANGENR = p.CHANGENR
JOIN InvoiceBase ib ON SUBSTRING(h.OBJECTID, 4, 10) = ib.InvoiceNumber
WHERE h.OBJECTCLAS = 'BELEGV'
AND p.TABNAME = 'BKPF'
AND p.FNAME = 'BSTAT'
AND p.VALUE_OLD = 'V'
AND p.VALUE_NEW = ' '
AND h.UDATE BETWEEN '20230101' AND '20231231'
UNION ALL
-- 5. Invoice Sent To Customer
SELECT
n.OBJKY AS InvoiceNumber,
'Invoice Sent To Customer' AS ActivityName,
CAST(CONCAT(n.DATVR, n.UHRVR) AS TIMESTAMP) AS EventTime,
n.VSTAT AS UserName, -- User who processed is not directly available, using processing status as a proxy
ib.BillingDocumentType,
ib.CustomerNumber,
ib.CompanyCode,
ib.TotalInvoiceAmount
FROM NAST n
JOIN InvoiceBase ib ON n.OBJKY = ib.InvoiceNumber
WHERE n.KSCHL = '[Your Invoice Output Type]' -- E.g., 'RD00'
AND n.VSTAT = '1' -- Processed successfully
AND n.DATVR BETWEEN '20230101' AND '20231231'
UNION ALL
-- 6. Invoice Corrected (Reversed)
SELECT
SUBSTRING(orig_doc.AWKEY, 1, 10) AS InvoiceNumber,
'Invoice Corrected' AS ActivityName,
CAST(CONCAT(rev_doc.CPUDT, rev_doc.CPUTM) AS TIMESTAMP) AS EventTime,
rev_doc.USNAM AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
rev_doc.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM BKPF orig_doc
JOIN BKPF rev_doc ON orig_doc.STBLG = rev_doc.BELNR AND orig_doc.BUKRS = rev_doc.BUKRS AND orig_doc.GJAHR = rev_doc.STJAH
JOIN InvoiceBase ib ON SUBSTRING(orig_doc.AWKEY, 1, 10) = ib.InvoiceNumber
WHERE orig_doc.AWTYP = 'VBRK' AND orig_doc.STBLG IS NOT NULL AND rev_doc.CPUDT BETWEEN '20230101' AND '20231231'
UNION ALL
-- 7. Invoice Due Date Reached
SELECT
SUBSTRING(b.AWKEY, 1, 10) AS InvoiceNumber,
'Invoice Due Date Reached' AS ActivityName,
CAST(CONCAT(bs.ZFBDT, '000000') AS TIMESTAMP) AS EventTime,
'System' AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
b.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM BSEG bs
JOIN BKPF b ON bs.MANDT = b.MANDT AND bs.BUKRS = b.BUKRS AND bs.BELNR = b.BELNR AND bs.GJAHR = b.GJAHR
JOIN InvoiceBase ib ON SUBSTRING(b.AWKEY, 1, 10) = ib.InvoiceNumber
WHERE b.AWTYP = 'VBRK' AND bs.KOART = 'D' AND bs.ZFBDT BETWEEN '20230101' AND '20231231'
UNION ALL
-- 8. Payment Reminder Issued
SELECT
SUBSTRING(b.AWKEY, 1, 10) AS InvoiceNumber,
'Payment Reminder Issued' AS ActivityName,
CAST(CONCAT(h.LAUFD, '000000') AS TIMESTAMP) AS EventTime,
h.LAUFI AS UserName, -- Dunning Run ID
ib.BillingDocumentType,
ib.CustomerNumber,
d.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM MHND d
JOIN MHNK h ON d.MANDT = h.MANDT AND d.LAUFD = h.LAUFD AND d.LAUFI = h.LAUFI
JOIN BKPF b ON d.MANDT = b.MANDT AND d.BUKRS = b.BUKRS AND d.BELNR = b.BELNR AND d.GJAHR = b.GJAHR
JOIN InvoiceBase ib ON SUBSTRING(b.AWKEY, 1, 10) = ib.InvoiceNumber
WHERE h.LAUFD BETWEEN '20230101' AND '20231231'
UNION ALL
-- 9. Dispute Case Created
SELECT
attr.ATTR_VALUE AS InvoiceNumber,
'Dispute Case Created' AS ActivityName,
sc.CREATE_TIME AS EventTime,
sc.CREATED_BY AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
ib.CompanyCode,
ib.TotalInvoiceAmount
FROM SCMG_T_CASE_ATTR attr
JOIN SCASE sc ON attr.CASE_GUID = sc.CASE_GUID
JOIN InvoiceBase ib ON attr.ATTR_VALUE = ib.InvoiceNumber
WHERE attr.ATTR_NAME = '[Your Dispute Case Invoice Attribute]' -- e.g., 'INVOICE_ID'
AND CAST(sc.CREATE_TIME AS DATE) BETWEEN '20230101' AND '20231231'
UNION ALL
-- 10, 11, 12. Clearing Events (Payment, Clearing, Write-Off)
SELECT
InvoiceNumber,
ActivityName,
EventTime,
UserName,
BillingDocumentType,
CustomerNumber,
CompanyCode,
TotalInvoiceAmount
FROM (
SELECT
bsad.XBLNR AS InvoiceNumber,
CASE
WHEN clearing_item.HKONT = '[Your Bad Debt G/L Account]' THEN 'Invoice Written Off'
ELSE 'Customer Payment Received'
END AS ActivityName,
CAST(CONCAT(clearing_doc.CPUDT, clearing_doc.CPUTM) AS TIMESTAMP) AS EventTime,
clearing_doc.USNAM AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
bsad.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM BSAD bsad
JOIN InvoiceBase ib ON bsad.XBLNR = ib.InvoiceNumber
JOIN BKPF clearing_doc ON bsad.MANDT = clearing_doc.MANDT AND bsad.BUKRS = clearing_doc.BUKRS AND bsad.AUGBL = clearing_doc.BELNR AND bsad.AUGGJ = clearing_doc.GJAHR
LEFT JOIN BSEG clearing_item ON clearing_doc.MANDT = clearing_item.MANDT AND clearing_doc.BUKRS = clearing_item.BUKRS AND clearing_doc.BELNR = clearing_item.BELNR AND clearing_doc.GJAHR = clearing_item.GJAHR AND clearing_item.HKONT = '[Your Bad Debt G/L Account]' -- e.g. '148000'
WHERE bsad.AUGDT BETWEEN '20230101' AND '20231231' AND bsad.UMSKZ = ''
UNION ALL
SELECT
bsad.XBLNR AS InvoiceNumber,
'Payment Applied To Invoice' AS ActivityName,
CAST(CONCAT(bsad.AUGDT, '000000') AS TIMESTAMP) AS EventTime,
clearing_doc.USNAM AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
bsad.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM BSAD bsad
JOIN InvoiceBase ib ON bsad.XBLNR = ib.InvoiceNumber
JOIN BKPF clearing_doc ON bsad.MANDT = clearing_doc.MANDT AND bsad.BUKRS = clearing_doc.BUKRS AND bsad.AUGBL = clearing_doc.BELNR AND bsad.AUGGJ = clearing_doc.GJAHR
WHERE bsad.AUGDT BETWEEN '20230101' AND '20231231' AND bsad.UMSKZ = ''
UNION ALL
SELECT
bsad.XBLNR AS InvoiceNumber,
'Invoice Cleared' AS ActivityName,
CAST(CONCAT(bsad.AUGDT, '235959') AS TIMESTAMP) AS EventTime, -- Add time to separate from 'Payment Applied'
clearing_doc.USNAM AS UserName,
ib.BillingDocumentType,
ib.CustomerNumber,
bsad.BUKRS AS CompanyCode,
ib.TotalInvoiceAmount
FROM BSAD bsad
JOIN InvoiceBase ib ON bsad.XBLNR = ib.InvoiceNumber
JOIN BKPF clearing_doc ON bsad.MANDT = clearing_doc.MANDT AND bsad.BUKRS = clearing_doc.BUKRS AND bsad.AUGBL = clearing_doc.BELNR AND bsad.AUGGJ = clearing_doc.GJAHR
WHERE bsad.AUGDT BETWEEN '20230101' AND '20231231' AND bsad.UMSKZ = ''
) AS ClearingEvents 步骤
- 前置条件:确保您拥有带认证SAP Connector的ETL工具许可证,例如带SAP Connector的Informatica PowerCenter或Talend。确认您拥有具备必要授权的SAP用户凭据,可读取所需财务、销售和系统表(BKPF、BSEG、VBRK、NAST、MHNK、UDM_CASE_ATTR00、CDHDR、CDPOS)。
- 建立SAP连接:在ETL工具中创建与SAP ECC系统的新连接。配置应用服务器、系统编号、客户端、用户和密码等连接信息。测试连接,确保连接成功。
- 定义数据源:为每项要提取的活动,将对应SAP表定义为ETL作业中的数据源。例如,为发票生成添加VBRK,为过账事件添加BKPF,为客户沟通添加NAST。
- 为每项活动构建提取逻辑:为13项所需活动分别创建数据流或转换。在每个数据流中应用筛选条件,选择相关记录。例如,按公司代码(BUKRS)、单据类型(BLART)和具体日期范围(如创建日期ERDAT)筛选。
- 映射字段并转换数据:在每个数据流中,将SAP源表字段映射到目标事件日志结构:InvoiceNumber、ActivityName、EventTime、UserName及其他建议的属性。使用转换逻辑为每个数据流固定设置“ActivityName”,并正确格式化日期和时间戳。
- 处理复杂活动:对于“Invoice Due Date Reached”等计算事件,使用基准付款日期(ZFBDT)和付款条件逻辑计算到期日,或直接从BSEG读取净到期日(NETDT)。对于“Invoice Approved”等源自变更日志的事件,可能需要根据单据编号和日期连接BKPF与CDHDR/CDPOS等表。
- 合并活动数据:使用ETL工具中的“Union”或“Merge”转换,将13个独立数据流的输出合并为单一数据集。合并前确保所有数据流的列名和数据类型一致。
- 配置目标位置:定义事件日志的最终输出位置,可以是平面文件(CSV)、数据库表或直接连接到暂存区。
- 设置提取计划:配置提取的日期范围参数。首次加载可提取6至12个月的数据;后续增量加载则配置为从上次运行日期开始提取。
- 执行并导出:运行ETL作业。完成后检查输出文件,确保其符合要求的格式。最终输出应为单一CSV文件,每行代表一个唯一事件,可直接上传到ProcessMind。
配置
- SAP连接:需要连接目标SAP ECC系统的应用服务器。SAP用户需要具备RFC访问权限,以及读取VBRK、BKPF、BSEG、NAST等查询中指定表的授权。
- ETL工具许可证:必须拥有商业ETL工具及其专用SAP Connector的有效许可证。
- 日期范围:建议提取3至6个月的数据,以获得具有代表性的分析样本,同时避免对系统造成过大负载。请使用可配置参数设置开始和结束日期。
- 关键筛选条件:始终按公司代码(BUKRS)筛选,以限制提取范围。同时必须按相关开票单据类型(VBRK-FKART)和会计单据类型(BKPF-BLART)筛选,仅纳入标准发票,并排除贷项通知单或内部单据等其他类型。
- 性能:从BSEG等大型表中提取数据可能较慢。请使用选择性筛选条件,避免提取不必要的字段,并安排在业务低峰期执行,以降低对SAP源系统性能的影响。
a 示例查询 config
// ETL Data Extraction Logic for SAP Order-to-Cash Invoicing
// This represents the configuration logic within a graphical ETL tool.
// == Global Parameters ==
// $StartDate: '[Start Date]' (e.g., '2023-01-01')
// $EndDate: '[End Date]' (e.g., '2023-06-30')
// $CompanyCodes: '[Company Code(s)]' (e.g., '1000', '2000')
// $BillingDocTypes: '[Billing Document Type(s)]' (e.g., 'F1', 'F2')
// == Source 1: Invoice Generated ==
// Tables: VBRK
DATA_SOURCE generated_invoices FROM VBRK WHERE
ERDAT >= $StartDate AND ERDAT <= $EndDate
AND BUKRS IN ($CompanyCodes)
AND FKART IN ($BillingDocTypes)
MAP {
InvoiceNumber: VBELN,
ActivityName: 'Invoice Generated',
EventTime: ERDAT + ERZET, // Combine date and time
UserName: ERNAM,
BillingDocumentType: FKART,
CustomerNumber: KUNAG,
CompanyCode: BUKRS,
TotalInvoiceAmount: NETWR
}
// == Source 2: Invoice Posted ==
// Tables: BKPF joined with VBRK
DATA_SOURCE posted_invoices FROM BKPF as A
INNER JOIN VBRK as B ON (A.AWKEY = B.VBELN AND A.AWTYP = 'VBRK')
WHERE A.BUDAT >= $StartDate AND A.BUDAT <= $EndDate
AND A.BUKRS IN ($CompanyCodes)
AND A.BSTAT = ' '
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Invoice Posted',
EventTime: A.BUDAT + A.CPUTM, // Posting date and entry time
UserName: A.USNAM,
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Source 3: Invoice Parked ==
// Tables: BKPF joined with VBRK
DATA_SOURCE parked_invoices FROM BKPF as A
INNER JOIN VBRK as B ON (A.AWKEY = B.VBELN AND A.AWTYP = 'VBRK')
WHERE A.CPUDT >= $StartDate AND A.CPUDT <= $EndDate
AND A.BUKRS IN ($CompanyCodes)
AND A.BSTAT = 'V'
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Invoice Parked',
EventTime: A.CPUDT + A.CPUTM,
UserName: A.USNAM,
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Source 4: Invoice Approved (Transition from Parked to Posted) ==
// Tables: BKPF joined with VBRK
DATA_SOURCE approved_invoices FROM BKPF as A
INNER JOIN VBRK as B ON (A.AWKEY = B.VBELN AND A.AWTYP = 'VBRK')
WHERE A.BUDAT >= $StartDate AND A.BUDAT <= $EndDate
AND A.BUKRS IN ($CompanyCodes)
AND A.BSTAT = ' '
AND EXISTS (SELECT 1 FROM VBELEGV C WHERE C.BELNR = A.BELNR) // Check if it was ever parked
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Invoice Approved',
EventTime: A.BUDAT + A.CPUTM, // Use posting date as approval date
UserName: A.USNAM,
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Source 5: Invoice Sent To Customer ==
// Tables: NAST joined with VBRK
DATA_SOURCE sent_invoices FROM NAST as A
INNER JOIN VBRK as B ON (A.OBJKY = B.VBELN)
WHERE A.ERDAT >= $StartDate AND A.ERDAT <= $EndDate
AND B.BUKRS IN ($CompanyCodes)
AND A.VSTAT = '1' // Successfully processed
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Invoice Sent To Customer',
EventTime: A.ERDAT + A.ERUHR,
UserName: A.USNAM,
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: B.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Source 6: Invoice Corrected (Reversed) ==
// Tables: VBRK (for the reversal document)
DATA_SOURCE corrected_invoices FROM VBRK as A
WHERE A.ERDAT >= $StartDate AND A.ERDAT <= $EndDate
AND A.BUKRS IN ($CompanyCodes)
AND A.SFAKN <> '' // SFAKN is the original cancelled invoice
MAP {
InvoiceNumber: A.SFAKN, // Case ID is the original invoice
ActivityName: 'Invoice Corrected',
EventTime: A.ERDAT + A.ERZET,
UserName: A.ERNAM,
BillingDocumentType: A.FKART,
CustomerNumber: A.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: NULL // Amount belongs to the reversal doc, not original
}
// == Source 7: Invoice Due Date Reached ==
// Tables: BSEG joined with VBRK
DATA_SOURCE due_invoices FROM BSEG as A
INNER JOIN BKPF as H ON (A.BUKRS = H.BUKRS AND A.BELNR = H.BELNR AND A.GJAHR = H.GJAHR)
INNER JOIN VBRK as B ON (H.AWKEY = B.VBELN AND H.AWTYP = 'VBRK')
WHERE A.NETDT >= $StartDate AND A.NETDT <= $EndDate
AND A.BUKRS IN ($CompanyCodes)
AND A.KOART = 'D' // Customer line item
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Invoice Due Date Reached',
EventTime: A.NETDT, // Net due date
UserName: 'System',
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Source 8: Payment Reminder Issued ==
// Tables: MHNK, MHND, VBRK
DATA_SOURCE reminders FROM MHNK as A
INNER JOIN MHND as D ON (A.LAUFD = D.LAUFD AND A.LAUFI = D.LAUFI)
INNER JOIN VBRK as B ON (SUBSTRING(D.XBLNR, 1, 10) = B.VBELN) // XBLNR may need parsing
WHERE A.LAUFD >= $StartDate AND A.LAUFD <= $EndDate
AND D.BUKRS IN ($CompanyCodes)
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Payment Reminder Issued',
EventTime: A.LAUFD, // Dunning date
UserName: A.IDAPS,
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: D.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Source 9: Dispute Case Created ==
// Tables: UDM_CASE_ATTR00
DATA_SOURCE disputes FROM UDM_CASE_ATTR00 as A
WHERE A.CREATE_TIMESTAMP >= $StartDate // Timestamp format may vary
AND A.FIN_COMP_CODE IN ($CompanyCodes)
AND A.PROCESS = 'FIN_FSCM_DIS'
MAP {
InvoiceNumber: A.BILL_DOC_ID,
ActivityName: 'Dispute Case Created',
EventTime: A.CREATE_TIMESTAMP,
UserName: A.CREATE_USER,
BillingDocumentType: NULL,
CustomerNumber: A.BP_NUMBER,
CompanyCode: A.FIN_COMP_CODE,
TotalInvoiceAmount: A.DISPUTED_AMOUNT
}
// == Source 10: Customer Payment Received ==
// Tables: BKPF
DATA_SOURCE payments FROM BKPF
WHERE BUDAT >= $StartDate AND BUDAT <= $EndDate
AND BUKRS IN ($CompanyCodes)
AND BLART = 'DZ' // Example for Customer Payment
MAP {
InvoiceNumber: NULL, // Invoice not yet known
ActivityName: 'Customer Payment Received',
EventTime: BUDAT + CPUTM,
UserName: USNAM,
BillingDocumentType: NULL,
CustomerNumber: NULL, // Requires join to BSEG to get customer
CompanyCode: BUKRS,
TotalInvoiceAmount: NULL
}
// == Source 11 & 12: Payment Applied To Invoice & Invoice Cleared ==
// Tables: BSEG joined with VBRK
DATA_SOURCE cleared_items FROM BSEG as A
INNER JOIN BKPF as H ON (A.BUKRS = H.BUKRS AND A.BELNR = H.BELNR AND A.GJAHR = H.GJAHR)
INNER JOIN VBRK as B ON (H.AWKEY = B.VBELN AND H.AWTYP = 'VBRK')
WHERE A.AUGDT >= $StartDate AND A.AUGDT <= $EndDate
AND A.BUKRS IN ($CompanyCodes)
AND A.AUGBL <> ''
// Generate two records from this source
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Payment Applied To Invoice',
EventTime: A.AUGDT, // Clearing Date
UserName: H.USNAM, // User from header of original invoice doc
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: B.NETWR
}
UNION WITH {
InvoiceNumber: B.VBELN,
ActivityName: 'Invoice Cleared',
EventTime: A.AUGDT, // Clearing Date
UserName: H.USNAM,
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Source 13: Invoice Written Off ==
// Tables: BSEG (for the invoice line) and BKPF (for clearing doc type)
DATA_SOURCE written_off FROM BSEG as A
INNER JOIN BKPF as H ON (A.BUKRS = H.BUKRS AND A.BELNR = H.BELNR AND A.GJAHR = H.GJAHR)
INNER JOIN VBRK as B ON (H.AWKEY = B.VBELN AND H.AWTYP = 'VBRK')
INNER JOIN BKPF as C ON (A.AUGBL = C.BELNR AND A.BUKRS = C.BUKRS AND A.AUGGJ = C.GJAHR)
WHERE A.AUGDT >= $StartDate AND A.AUGDT <= $EndDate
AND A.BUKRS IN ($CompanyCodes)
AND C.BLART = '[Your Write-Off Document Type]' // e.g., 'AB'
MAP {
InvoiceNumber: B.VBELN,
ActivityName: 'Invoice Written Off',
EventTime: A.AUGDT,
UserName: C.USNAM, // User who posted the write-off
BillingDocumentType: B.FKART,
CustomerNumber: B.KUNAG,
CompanyCode: A.BUKRS,
TotalInvoiceAmount: B.NETWR
}
// == Final Union of all sources ==
OUTPUT generated_invoices
UNION ALL posted_invoices
UNION ALL parked_invoices
UNION ALL approved_invoices
UNION ALL sent_invoices
UNION ALL corrected_invoices
UNION ALL due_invoices
UNION ALL reminders
UNION ALL disputes
UNION ALL payments
UNION ALL cleared_items
UNION ALL written_off 加速现金回流:立即优化开票与发票处理!
消除低效环节,将周期时间缩短30%,提升现金流。
无需信用卡。几分钟内即可开始优化。