您的供应链管理数据模板
您的供应链管理数据模板
- 建议收集的属性
- 需要追踪的关键活动
- 提取指南
供应链管理属性
| 名称 | 描述 | ||
|---|---|---|---|
| Event 时间 EventTime | 指示活动发生时间的 timestamp,包括日期和时间。 | ||
| 描述 此属性为流程中的每个活动提供精确的日期和时间。它是 event log 的时间轴骨架,按现实中发生的顺序排列流程步骤。 Event Time 对于所有基于时间的分析都至关重要。它用于计算活动之间的周期时间、衡量流程的总交付周期、识别随时间变化的绩效趋势,并精准定位瓶颈最可能发生的时刻。 为何重要 此 timestamp 对于计算所有时长和绩效指标至关重要,能够分析流程瓶颈和交付周期。 获取方式 从核心 SAP 表中与单据创建或状态更改关联的时间戳字段提取,例如用于变更单据的 CDHDR/CDPOS,或抬头表中的 ERDAT/ERZET 等特定日期/时间字段。 示例 2023-04-15T10:25:00Z2023-04-18T14:00:00Z2023-04-22T08:15:00Z | |||
| 活动名称 ActivityName | 在供应链流程的特定时间点发生的业务活动或 event 的名称。 | ||
| 描述 此属性描述了物流订单生命周期中的特定步骤或里程碑,例如“已下达采购订单”或“已过账发货”。这些活动构成了组成流程的 event 序列。 分析活动序列是 Process Mining 的核心。它允许发现实际的流程流向,与标准操作程序进行对比,并识别导致延迟或需要返工的流程步骤。 为何重要 它定义了流程的步骤,这是发现流程图、分析变体以及衡量活动间周期时间的基础。 获取方式 在数据转换过程中,通过将各种 SAP 表(如 EKKO、LIKP、VBUK)中的事务代码或状态更改映射到易于理解的活动名称而生成。 示例 采购订单已发布采购订单收货已过账创建外向交货交货签收已确认 | |||
| 物流订单 LogisticsOrder | 单个端到端供应链流程的唯一标识符(从最初需求到最终交付确认)。 | ||
| 描述 物流订单 (Logistics Order) 作为主要的 case 标识符,链接供应链中与特定需求或履行请求相关的所有活动。这种方法允许跟踪产品旅程的整个生命周期(从计划和采购到生产和分销),确保流程的全景视图。 在 Process Mining 中,按物流订单进行分析可以揭示满足需求所采取的完整路径。它有助于识别整个供应链中的常见变体、瓶颈和偏差,而不是孤立地查看采购或销售等孤立流程。 为何重要 这是将所有相关 event 连接到单个流程实例中的基本密钥,从而能够对供应链进行端到端分析。 获取方式 这是一个概念性标识符,可能需要通过链接各种单据编号来构建,例如销售订单号及其后续的采购订单号和交货单号。请咨询 SAP S/4HANA 供应链文档或相关专家。 示例 LO-4500078192LO-4500078193LO-4500078194 | |||
| 最后数据更新 LastDataUpdate | 从源系统最后一次刷新或提取数据的时间戳。 | ||
| 描述 此属性指示 event log 的 data 上次更新的时间。它为正在分析的 data 提供“新鲜度”日期,确保用户了解 data 的及时性。 在任何分析中,了解 data 的新旧程度对于做出明智的决策都至关重要。此 timestamp 有助于用户信任 data,并了解 dashboard 和 KPI 所涵盖的时间窗口。 为何重要 确保数据新鲜度的透明度,让用户了解流程分析的实时程度。 获取方式 这是一个元 data 字段,通常由 data 提取或 ETL 工具在 data 刷新成功结束时生成并填充。 示例 2023-10-27T02:00:00Z2023-10-28T02:00:00Z2023-10-29T02:00:00Z | |||
| 源系统 SourceSystem | data 来源的系统。 | ||
| 描述 识别生成事件数据的特定源系统实例。在复杂的系统架构中,一家公司可能针对不同地区或业务单元拥有多个 SAP S/4HANA 实例。 此属性对于数据治理和细分分析非常重要。它允许分析人员比较不同系统之间的流程绩效,或从单一、权威的来源隔离数据。 为何重要 为 data 来源提供关键背景,这对于 data 验证以及在不同系统环境之间比较流程非常重要。 获取方式 这通常是在 data 提取过程中添加的静态值,用于标识来源,例如 SAP 系统 ID (SAPSID)。 示例 S4H_PROD_EUS4H_PROD_NAS4H_DEV | |||
| 供应商名称 SupplierName | 与采购活动关联的供应商或卖方名称。 | ||
| 描述 此属性标识采购货物或服务的供应商。它通常与“已创建采购申请”和“已下达采购订单”等活动相关联。 供应商名称 (Supplier Name) 对于“供应商交付绩效”dashboard 至关重要。它允许对 data 进行过滤和分段,以比较不同供应商的准时交付率、交付周期和质量水平,这对于战略采购和供应商关系管理至关重要。 为何重要 支持按供应商进行绩效分析,这对于优化采购流程和评估供应商可靠性至关重要。 获取方式 供应商编号 (LIFNR) 存储在采购单据(如表 EKKN, EBAN)中。名称是从中央供应商主表 LFA1 中检索的。 示例 Global Components Inc.Advanced Materials LLCPrecision Parts Co. | |||
| 客户名称 CustomerName | 正在履行的订单所属客户的名称。 | ||
| 描述 此属性标识与销售订单及后续履行活动关联的终端客户。它为供应链流程的需求端提供背景。 在 Process Mining 中,按客户进行分析有助于识别大客户不同的履行模式或绩效水平。它用于诸如“送货证明滞后分析”之类的 dashboard 中,以查看某些客户是否始终延迟确认。 为何重要 支持按客户进行细分分析,揭示特定客户的行为、瓶颈或服务水平协议 (SLA) 表现。 获取方式 客户编号 (KUNNR) 存储在销售单据(如表 VBAK)中。名称是从中央客户主表 KNA1 中检索的。 示例 Retail Corp创新解决方案制造合作伙伴 | |||
| 客户要求的交货日期 RequestedDeliveryDate | 要求供应商交付货物的日期。 | ||
| 描述 这是采购订单中指定的交货日期,代表供应商的目标。它作为衡量实际交付绩效的基准。 此日期对于计算“供应商准时交付率”KPI 至关重要。通过比较实际收货日期与此请求日期,企业可以客观地衡量供应商是否履行了其承诺。 为何重要 这是用于计算“供应商准时交付率”KPI 的基准日期,因此对于供应商绩效管理至关重要。 获取方式 存在于采购订单项目表 EKPO 中,字段名为 EINDT(交货日期)。 示例 2023-05-20T00:00:00Z2023-06-15T00:00:00Z2023-07-01T00:00:00Z | |||
| 工厂 Plant | 发生该活动的制造或分销设施。 | ||
| 描述 工厂 (Plant) 是一个 SAP 组织单位,代表生产、存储或分销货物的地点。它为流程活动提供了地理或功能背景。 按工厂分析流程绩效是一项常见需求。它允许对不同运营站点的效率、吞吐量和合规性进行基准测试和比较,有助于识别最佳实践或需要改进的地点。 为何重要 提供用于分析的地理或组织维度,从而能够对不同设施的绩效进行比较。 获取方式 存在于许多单据项目表中,例如 VBAP(销售)、EKPO(采购)和 LIPS(交货)。该字段通常命名为 WERKS。 示例 100021003500 | |||
| 执行用户 ExecutingUser | 执行该活动的用户ID。 | ||
| 描述 此属性捕获执行给定活动(如创建采购订单或过账收货)的员工的 SAP 用户名或 ID。它将流程步骤与所涉及的人力资源联系起来。 按用户分析有助于了解工作量分配、识别培训需求并发现个人或团队之间的绩效差异。这对于合规性分析也很有价值,可以查看谁执行了关键流程步骤。 为何重要 将活动归因于特定用户,支持工作量分析、绩效对比以及对不合规操作的调查。 获取方式 存在于许多 SAP 表的“创建者”或“更改者”字段中,例如 EKKO(采购订单抬头)中的 ERNAM、LIKP(交货抬头)和 VBRK(发票抬头)。 示例 CBROWNJSMITHASINGH | |||
| 物料编号 MaterialNumber | 正在处理的产品或物料的唯一标识符。 | ||
| 描述 物料编号 (Material Number),通常称为 SKU,是 SAP 中特定产品的唯一代码。它将流程活动与正在制造、采购或运输的实物或数字货物联系起来。 此属性对于以产品为中心的分析至关重要。它有助于确定某些产品是否更容易出现质量问题、生产延迟或缺货。可以按物料过滤 dashboard,以调查特定产品线的绩效。 为何重要 支持产品级分析,以识别延迟或质量故障等流程问题是否集中在特定物料上。 获取方式 存在于大多数单据的项目级表中,例如销售订单的 VBAP、采购订单的 EKPO 和交货的 LIPS。该字段通常命名为 MATNR。 示例 FG-100-ARM-2034-BSA-5500 | |||
| 质量检验结果 QualityInspectionResult | 质量检验的结果,例如“合格”或“不合格”。 | ||
| 描述 此属性记录对生产或收到的货物进行的质量检查结果。结果决定了货物是否可以进入下一步,或者是否需要返工、退货或报废。 这是“质量控制不合格率”dashboard 和 KPI 的关键属性。分析故障的频率和原因有助于识别特定产品、供应商或生产线的系统性质量问题。 为何重要 直接支持质量相关 KPI 的计算,并帮助精准定位供应链中质量问题的根源。 获取方式 此信息通常存储在质量管理 (QM) 模块中。Data 可能来自 QALS 等检验批次表和 QAVE 中的用法决策代码。 示例 已通过未通过需要返工带偏差通过 | |||
| 处理时间 ProcessingTime | 在一项活动上实际投入工作的时间长度。 | ||
| 描述 处理时间 (Processing Time) 是指从活动开始时间到结束时间的计算时长。它代表流程步骤中的实际工作时间或“触碰时间”,而不是步骤之间的等待时间。 该指标是识别效率低下的基础。通过将处理时间从等待时间中分离出来,分析师可以确定延迟是由任务执行缓慢引起的,还是由部门或系统之间的长时间排队和交接延迟引起的。 为何重要 有助于区分实际工作时间与闲置等待时间,这对于识别流程延迟的真实来源至关重要。 获取方式 通过活动的 EndTime 减去 StartTime 计算得出 (EndTime - StartTime)。 示例 PT1H30MPT8HP2D | |||
| 承运商名称 CarrierName | 负责处理货运的运输公司或货运代理的名称。 | ||
| 描述 承运人名称 (Carrier Name) 标识负责在不同地点之间运输货物的物流服务提供商,例如从仓库到客户。 此属性对于“运输周期时间分析”dashboard 至关重要。它允许比较不同承运人的运输时间、成本和可靠性,从而实现更好的物流规划和承运人选择。 为何重要 支持按运输提供商进行绩效分析,这是优化物流成本和交付时间的关键。 获取方式 承运人 ID(货运代理)存储在运输单据中,例如表 VTTK(运输抬头)。名称是从 LFA1 等主数据表中检索的。 示例 DHL联邦快递马士基物流 | |||
| 是否延迟交付 IsLateDelivery | 一个布尔值标志,指示供应商交货是否晚于请求的交货日期。 | ||
| 描述 此计算标记提供了一个简单的真或假指标,说明交付是否准时。它是通过比较“已过账采购订单收货”活动的 timestamp 与“请求交付日期”属性得出的。 此属性简化了与供应商绩效相关的 dashboard 和 KPI 的创建。它允许快速过滤和聚合,以计算“供应商准时交付率”,并识别哪些供应商、物料或地区最常发生延迟。 为何重要 通过为每次交付提供清晰的二元结果,简化了供应商绩效分析,这对于“准时交付”KPI 至关重要。 获取方式 这是一个计算字段。逻辑为:IF ('Goods Receipt For PO Posted'.EventTime > PurchaseOrder.RequestedDeliveryDate) THEN True ELSE False。 示例 truefalse | |||
| 是否返工 IsRework | 用于标记某个活动或一系列活动是否代表返工的标识。 | ||
| 描述 此布尔属性标记了流程中重复早期步骤的活动,表示某种形式的返工或纠正。例如,如果“质量检验”之后是“已创建生产订单”步骤,然后又是另一个“质量检验”,则第二次检验可以标记为返工。 识别返工是了解流程效率低下和隐藏成本的关键。此标记有助于量化返工循环的频率和影响,支持“订单处理错误率”KPI 的计算,并突出需要改进流程的领域。 为何重要 通过明确识别和统计属于返工循环的活动,帮助量化流程的低效程度。 获取方式 这通常在 Process Mining 工具中通过识别同一 case 内重复的活动序列来计算。 示例 truefalse | |||
| 结束时间 EndTime | 表示活动完成的 timestamp,用于计算处理时间。 | ||
| 描述 End Time 标志着特定活动的完成。虽然开始时间 (EventTime) 表示活动何时开始,但 End Time 对于了解执行活动花费了多长时间至关重要,尤其是对于非瞬时活动。 在分析中,同时拥有开始和结束时间可以精确测量处理时间与等待时间。这有助于区分主动执行任务所花费的时间与等待下一步所花费的时间,这是识别效率提升机会的关键。 为何重要 支持精确计算活动处理时间,有助于区分增值工作和等待时间。 获取方式 可以从 SAP 中的状态更改推导得出。例如,开始是来自 JEST/JCDS 等表的“进行中”状态更新,结束是“已完成”状态更新。对于瞬时事件,EndTime 可能等于 StartTime。 示例 2023-04-15T11:30:00Z2023-04-18T14:05:00Z2023-04-22T09:00:00Z | |||
| 订单数量 OrderQuantity | 订单行项目中的物料数量。 | ||
| 描述 此属性指定销售订单或采购订单行项目中请求的物料单位数量。它提供了每笔交易的量化指标。 按数量分析有助于优先处理大批量订单,因为这些订单可能具有更大的业务影响。它还可以用于规范化其他指标(如计算单位成本),或了解订单规模如何影响处理时间。 为何重要 为交易提供量化背景,允许根据规模进行影响分析和 case 分段。 获取方式 存在于项目级表中,例如 EKPO(采购订单)中的 MENGE 或 VBAP(销售订单)中的 KWMENG。 示例 100500025 | |||
| 采购订单号 PurchaseOrderNumber | 采购订单 (PO) 单据的唯一标识符。 | ||
| 描述 采购订单号 (Purchase Order Number) 是用于向供应商订购材料的官方单据编号。它是供应链采购部分的关键标识符。 此属性允许深入研究采购流程。它用于“采购端到端周期时间”dashboard,并用于计算“供应商准时交付率”KPI,将申请、订单、收货和付款活动联系起来。 为何重要 作为钻取采购子流程并链接相关采购 event 的关键标识符。 获取方式 存在于采购订单抬头表 EKKO 和项目表 EKPO 中。字段名为 EBELN。 示例 450007819245000781934500078194 | |||
| 销售订单编号 SalesOrderNumber | 销售订单 (SO) 单据的唯一标识符。 | ||
| 描述 销售订单号 (Sales Order Number) 是确认向客户销售的官方单据编号。它是供应链“订单到现金”部分的关键标识符。 此属性对于跟踪特定客户订单的履行至关重要。它有助于将最初的客户请求与所有后续活动(如交货和开票)联系起来,支持订单履行交付周期分析。 为何重要 作为订单履行子流程的关键标识符,将客户需求与物流及财务结算关联起来。 获取方式 存在于销售订单抬头表 VBAK 和项目表 VBAP 中。字段名为 VBELN。 示例 100023451000234610002347 | |||
供应链管理活动
| 活动 | 描述 | ||
|---|---|---|---|
| 交货签收已确认 | 代表客户或承运人的正式确认,即已按规定收到货物。这通常通过在出库交货单中更新 POD 信息来记录。 | ||
| 为何重要 此活动是履行流程的最终结束。它对于准确开票、纠纷解决以及衡量交付周期的最后一段至关重要。 获取方式 这是一个显式 event。送货证明日期记录在交货抬头表(LIKP,字段 PODAT)或相关的 POD 表 (VLPOD) 中。 捕获 使用交货单据中的送货证明日期 (LIKP-PODAT)。 事件类型 explicit | |||
| 产出品 | 此活动代表货物制造已完成的确认。它通常记录为生产订单的收货,将成品移入库存。 | ||
| 为何重要 这标志着生产周期的结束。生产订单创建与此 event 之间的时间代表了制造交付周期,这是生产效率的关键指标。 获取方式 这可以通过物料单据过账(生产订单收货)显式捕获,也可以从生产订单的最终确认(AFRU 表)或状态更改为“已交付”中推断。 捕获 从生产订单的最终收货入库物料单据的过账日期或状态更改中推断。 事件类型 inferred | |||
| 发货出库已过账 | 此活动代表货物从仓库在法律上和物理上的离开。它会减少库存并过账销售成本,标志着订单的正式发货。 | ||
| 为何重要 这是一个关键里程碑,标志着“运输中”期间的开始。这是货物离开公司所有权开始交付的明确节点。 获取方式 这是创建一个物料单据的显式 event。timestamp 记录在物料单据抬头(MKPF,字段 BUDAT)中,并更新交货单据(LIKP,字段 WBSTK)中的货物移动状态。 捕获 使用与出库交货关联的发货材料单据中的过账日期 (MKPF-BUDAT)。 事件类型 explicit | |||
| 已创建销售订单 | 此活动标志着新销售订单的创建,正式记录了客户的货物需求。这是用户在系统中保存新销售订单单据时记录的显式 event。 | ||
| 为何重要 这是“订单到现金”流程的主要起点。分析从该 event 到其他 event 的时间,可以揭示整体订单履行交付周期并识别初始处理延迟。 获取方式 此 event 是显式记录的。可以在销售订单表的更改单据 (CDHDR/CDPOS) 中找到,或者使用销售订单抬头表(VBAK,字段 ERDAT)中的创建 timestamp。 捕获 对销售订单单据使用创建日期 (VBAK-ERDAT) 和时间 (VBAK-ERZET)。 事件类型 explicit | |||
| 采购订单已发布 | 标志着正式创建并向外部供应商发布所需物料的采购订单。此活动将采购申请转换为与供应商之间具有法律约束力的承诺。 | ||
| 为何重要 作为一个关键里程碑,此活动对于衡量供应商提前期和采购周期至关重要。它为评估供应商的准时交货表现提供了基准。 获取方式 这是在创建采购订单时记录的显式 event。创建 timestamp 存储在采购订单抬头表(EKKO,字段 AEDAT)中。 捕获 对采购订单使用单据创建日期 (EKKO-AEDAT)。 事件类型 explicit | |||
| 采购订单收货已过账 | 代表根据采购订单从供应商处实际收到原材料或货物。当货物在仓库或工厂接收时记录此 event。 | ||
| 为何重要 此活动完成了采购周期中的供应商交付部分。这对于计算供应商准时交付率和了解入库物流绩效至关重要。 获取方式 这是通过物料单据过账捕获的显式 event。event timestamp 位于物料单据抬头表(MKPF,字段 BUDAT)中。指向 PO 的链接位于行项目表 (MSEG) 中。 捕获 使用与采购订单关联的物料单据中的过账日期 (MKPF-BUDAT)。 事件类型 explicit | |||
| 创建外向交货 | 表示交货单据的创建,该单据授权向客户拣选和运送货物。此活动标志着流程从订单管理转为物流执行。 | ||
| 为何重要 这是启动实际履行流程的关键步骤。订单创建与交货创建之间的延迟可能表明存在计划或可用性问题。 获取方式 这是一个显式 event。创建 timestamp 记录在交货抬头表(LIKP,字段 ERDAT)中。 捕获 使用交货单据抬头中的创建日期 (LIKP-ERDAT) 和时间 (LIKP-ERZET)。 事件类型 explicit | |||
| 客户发票已创建 | 此活动标志着根据交付的货物或服务为客户创建开票单据。它启动了流程中最后的财务结算部分。 | ||
| 为何重要 此活动是分析开票周期时间的关键。交付确认与开票之间的延迟会对现金流产生负面影响。 获取方式 这是一个显式 event。创建 timestamp 记录在开票单据抬头表(VBRK,字段 ERDAT)中。 捕获 使用开票单据抬头中的创建日期 (VBRK-ERDAT)。 事件类型 explicit | |||
| 已创建请购单 | 此活动表示创建采购必要货物或原材料的内部请求。当库存不足以履行销售订单或低于再订货点时,通常会触发此活动。 | ||
| 为何重要 这是采购周期的第一步。跟踪其创建有助于识别启动采购时的延迟,并支持对端到端采购流程的分析。 获取方式 这是一个显式 event。创建 timestamp 记录在采购申请抬头表(EBAN,字段 BADAT)中。 捕获 对采购申请单据使用创建日期 (EBAN-BADAT)。 事件类型 explicit | |||
| 已执行质量检验 | 代表生产货物的质量控制检查已完成。检验结果(合格或不合格)记录在用法决策中。 | ||
| 为何重要 此活动对于监控产品质量和识别生产问题至关重要。高拒收率或较长的检验时间可能是重大的瓶颈。 获取方式 这是在对质量检验批次做出用法决策时捕获的显式 event。决策日期在 QALS 表(字段 PASTRTERM)或 QAVE 表中。 捕获 使用记录检验批次用法决策时的 timestamp(QALS/QAVE 表)。 事件类型 explicit | |||
| 已检查库存可用性 | 代表系统或手动检查,以确定所请求的项目是否有库存以履行销售订单。这通常是销售订单创建过程中的一个自动化步骤,但可能不会记录为独立的 event。 | ||
| 为何重要 了解订单与此检查之间的时间及其结果,有助于分析库存水平如何影响履行时间。此处的延迟通常会导致采购或生产活动。 获取方式 这通常不是一个显式 event。它可以从销售订单行项目表 (VBEP) 中第一个确认的计划行的创建,或从订单行项目内的状态更改中推断出来。 捕获 从销售订单计划行(VBEP 表)上的确认状态更新中推断。 事件类型 inferred | |||
| 拣货完成 | 此活动标志着从仓库收集出库货物的实际流程完成。在许多系统中,当交货单据的拣选状态更新时,此活动即被确认。 | ||
| 为何重要 高效的拣货对仓库吞吐量至关重要。追踪此活动有助于识别仓库作业中的瓶颈并衡量拣货绩效。 获取方式 这通常不是一个单一的独立 event,但可以从状态变化中推断出来。当交货行项目表(LIPS,字段 KOSTA)中的拣选状态设置为“C”(完全处理)时,即记录该 event。 捕获 当拣货状态 (LIPS-KOSTA) 更新为已完全拣货时,从变更单据中推断。 事件类型 inferred | |||
| 生产订单已创建 | 指示已创建生产订单,以制造销售订单所需的产成品。这是内部制造流程的正式开始。 | ||
| 为何重要 生产订单的创建标志着制造交付周期的开始。分析此项有助于识别需求信号与生产开始之间的延迟。 获取方式 这是一个显式 event。创建日期记录在生产订单抬头表(AUFK,字段 ERDAT)中。 捕获 使用订单抬头表中的创建日期 (AUFK-ERDAT)。 事件类型 explicit | |||
| 装运已创建 | 代表运输单据的创建,该单据将一个或多个交货单组合在一起进行运输规划。该单据包含承运人、路线和运输方式的详细信息。 | ||
| 为何重要 此活动是正式运输规划的开始。分析发货与运输完成之间的时间可以揭示运输流程的效率。 获取方式 这是记录在货运抬头表(VTTK,字段 ERDAT)中的显式 event。这是 LE-TRA 模块的一部分,可能并非所有组织都使用该模块。 捕获 使用运输单据抬头中的创建日期 (VTTK-ERDAT)。 事件类型 explicit | |||
| 货物已在目的地卸载 | 此活动表示在客户所在地实际卸货。此 event 可能不会在 SAP 中被显式跟踪,通常需要从承运人 data 或后续 event 中推断。 | ||
| 为何重要 这标志着旅程中运输阶段的结束。从发货到此节点的时间即为运输时间,这是物流优化的关键。 获取方式 这在核心 ERP 中很少是一个显式 event。它可以从承运人 EDI 消息、来自运输管理 (TM) 模块的 data 或送货证明单据的 timestamp(如果有)中推断出来。 捕获 从承运商状态更新(如 EDI 214)中推断,或使用签收证明 (POD) 时间戳作为近似值。 事件类型 inferred | |||
提取指南
步骤
- 前提条件:确保您的用户拥有访问所需 SAP S/4HANA 核心数据服务 (CDS) views 的充足权限。这通常需要由 SAP 安全团队分配特定角色。您还需要一个能够连接到 SAP HANA 数据库的 SQL 客户端,例如 DBeaver 或 SAP HANA Studio。
- 建立数据库连接:配置您的 SQL 客户端以连接到 SAP S/4HANA 数据库。您需要数据库服务器主机、端口(例如 3xx15,其中 xx 是实例编号)、数据库用户名和密码。
- 准备 SQL 查询:将本文档查询部分中提供的完整 SQL 查询复制到 SQL 客户端的编辑器中。此查询旨在从各种物流和销售模块中提取所有指定的活动。
- 设置提取参数:在运行查询之前,找到每个子查询中
WHERE子句内的占位符条件。您必须将'YourCompanyCode'替换为您正在分析的实际公司代码,并调整日期范围占位符(如'YYYY-MM-DD')以定义所需的提取周期。 - 执行查询:运行完整的 SQL 脚本。执行时间将取决于所选的日期范围和系统中的数据量。建议在非高峰时段运行,以尽量减少系统负载。
- 查看初步结果:查询完成后,在 SQL 客户端中快速浏览输出。检查行数是否合理,确保
LogisticsOrder、ActivityName和EventTime等列已填充,并确认出现了各种活动名称。 - 将数据导出为 CSV:从 SQL 客户端将整个结果集导出为 CSV 文件。选择 UTF-8 编码以避免特殊字符出现问题。
- 格式化以上传:确保最终 CSV 文件中的列标题与导入所需的属性名称完全匹配(例如
LogisticsOrder、ActivityName、EventTime)。如果按原样使用提供的 SQL 查询,则无需进一步的数据转换。
配置
- 前提条件:需要访问底层 SAP HANA 数据库。数据库用户必须对查询中引用的所有 CDS views 拥有
SELECT权限,包括但不限于 I_SalesOrderItem、I_PurchaseOrderItem、I_OutboundDeliveryItem、I_MaterialDocumentItem、I_ProductionOrder、I_QualityInspection、I_Shipment 和 I_BillingDocumentItem。 - 日期范围筛选:提供的查询包含日期范围筛选占位符,通常作用于创建日期字段(
CreationDate或DocumentDate)。初步分析时,建议选择 3 到 6 个月的时间段,以获得代表性数据并避免系统负载过高。 - 关键业务筛选:按特定组织单元筛选数据对于确保分析的相关性至关重要。查询已预置了
CompanyCode占位符。您还可以根据分析范围添加SalesOrganization、DistributionChannel或Plant等筛选器。 - 性能考量:这是一个涉及多个大型 CDS views 关联的复杂查询。执行时可能会消耗大量系统资源。请安排在非营业时间进行提取。对于极大数据集,建议按月分批次执行查询。
a 查询示例 sql
WITH SalesOrderLink AS (
SELECT DISTINCT
sd.SalesDocument AS SalesOrder,
pr.PurchaseRequisition AS PurchaseRequisition,
po.PurchaseOrder AS PurchaseOrder,
od.DeliveryDocument AS OutboundDelivery,
bd.BillingDocument AS BillingDocument
FROM I_SalesDocItemProcessFlow AS pf
LEFT JOIN I_SalesDocumentItem AS sd ON pf.PrecedingDocument = sd.SalesDocument AND pf.PrecedingDocumentItem = sd.SalesDocumentItem
LEFT JOIN I_PurchaseRequisitionItem AS pr ON pf.SubsequentDocument = pr.PurchaseRequisition AND pf.SubsequentDocumentItem = pr.PurchaseRequisitionItem
LEFT JOIN I_PurchaseOrderItem AS po ON pf.SubsequentDocument = po.PurchaseOrder AND pf.SubsequentDocumentItem = po.PurchaseOrderItem
LEFT JOIN I_OutboundDeliveryItem AS od ON pf.SubsequentDocument = od.DeliveryDocument AND pf.SubsequentDocumentItem = od.DeliveryDocumentItem
LEFT JOIN I_BillingDocumentItem AS bd ON pf.SubsequentDocument = bd.BillingDocument AND pf.SubsequentDocumentItem = bd.BillingDocumentItem
WHERE sd.SalesDocument IS NOT NULL
)
SELECT
so.SalesOrder AS "LogisticsOrder",
'Sales Order Created' AS "ActivityName",
so.CreationDate || ' ' || so.CreationTime AS "EventTime",
so.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
soi.Material AS "MaterialNumber",
soi.Plant AS "Plant",
soi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_SalesOrder AS so
JOIN I_SalesOrderItem AS soi ON so.SalesOrder = soi.SalesOrder
LEFT JOIN I_Customer AS cust ON so.SoldToParty = cust.Customer
WHERE so.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
so.SalesOrder AS "LogisticsOrder",
'Inventory Availability Checked' AS "ActivityName",
so.CreationDate || ' ' || so.CreationTime AS "EventTime",
so.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
soi.Material AS "MaterialNumber",
soi.Plant AS "Plant",
soi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_SalesOrder AS so
JOIN I_SalesOrderItem AS soi ON so.SalesOrder = soi.SalesOrder
LEFT JOIN I_Customer AS cust ON so.SoldToParty = cust.Customer
WHERE so.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Purchase Requisition Created' AS "ActivityName",
pr.CreationDate || ' ' || '00:00:00' AS "EventTime",
pr.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
pri.Material AS "MaterialNumber",
pri.Plant AS "Plant",
pri.DeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_PurchaseRequisition AS pr
JOIN I_PurchaseRequisitionItem AS pri ON pr.PurchaseRequisition = pri.PurchaseRequisition
JOIN SalesOrderLink sl ON pr.PurchaseRequisition = sl.PurchaseRequisition
WHERE pr.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND pr.CompanyCode = 'YourCompanyCode'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Purchase Order Issued' AS "ActivityName",
po.PurchaseOrderDate || ' ' || '00:00:00' AS "EventTime",
po.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
sup.SupplierName AS "SupplierName",
poi.Material AS "MaterialNumber",
poi.Plant AS "Plant",
poi.DeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_PurchaseOrder AS po
JOIN I_PurchaseOrderItem AS poi ON po.PurchaseOrder = poi.PurchaseOrder
LEFT JOIN I_Supplier AS sup ON po.Supplier = sup.Supplier
JOIN SalesOrderLink sl ON po.PurchaseOrder = sl.PurchaseOrder
WHERE po.PurchaseOrderDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND po.CompanyCode = 'YourCompanyCode'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Goods Receipt For PO Posted' AS "ActivityName",
md.DocumentDate || ' ' || md.CreationTime AS "EventTime",
md.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
sup.SupplierName AS "SupplierName",
mdi.Material AS "MaterialNumber",
mdi.Plant AS "Plant",
poi.DeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_MaterialDocumentHeader AS md
JOIN I_MaterialDocumentItem AS mdi ON md.MaterialDocument = mdi.MaterialDocument AND md.MaterialDocumentYear = mdi.MaterialDocumentYear
JOIN I_PurchaseOrderItem AS poi ON mdi.PurchaseOrder = poi.PurchaseOrder AND mdi.PurchaseOrderItem = poi.PurchaseOrderItem
LEFT JOIN I_Supplier AS sup ON poi.Supplier = sup.Supplier
JOIN SalesOrderLink sl ON poi.PurchaseOrder = sl.PurchaseOrder
WHERE md.DocumentDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND mdi.GoodsMovementType = '101' AND mdi.CompanyCode = 'YourCompanyCode'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Production Order Created' AS "ActivityName",
po.CreationDate || ' ' || po.CreationTime AS "EventTime",
po.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
po.Material AS "MaterialNumber",
po.ProductionPlant AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_ProductionOrder AS po
JOIN SalesOrderLink sl ON po.SalesOrder = sl.SalesOrder
WHERE po.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Goods Produced' AS "ActivityName",
md.DocumentDate || ' ' || md.CreationTime AS "EventTime",
md.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
mdi.Material AS "MaterialNumber",
mdi.Plant AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_MaterialDocumentHeader AS md
JOIN I_MaterialDocumentItem AS mdi ON md.MaterialDocument = mdi.MaterialDocument AND md.MaterialDocumentYear = mdi.MaterialDocumentYear
JOIN I_ProductionOrder AS po ON mdi.ManufacturingOrder = po.ManufacturingOrder
JOIN SalesOrderLink sl ON po.SalesOrder = sl.SalesOrder
WHERE md.DocumentDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND mdi.GoodsMovementType = '101'
UNION ALL
SELECT
qi.SalesOrder AS "LogisticsOrder",
'Quality Inspection Performed' AS "ActivityName",
qi.InspLotUsageDecisionDate || ' ' || qi.InspLotUsageDecisionTime AS "EventTime",
qi.InspLotUsageDecisionMadeByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
qi.Material AS "MaterialNumber",
qi.Plant AS "Plant",
NULL AS "RequestedDeliveryDate",
qi.InspLotUsageDecisionCode AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_QualityInspection AS qi
WHERE qi.InspLotUsageDecisionDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND qi.SalesOrder IS NOT NULL
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Outbound Delivery Created' AS "ActivityName",
od.CreationDate || ' ' || od.CreationTime AS "EventTime",
od.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Picking Completed' AS "ActivityName",
od.PickingDate || ' ' || od.PickingTime AS "EventTime",
od.LastChangedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.PickingDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND od.OverallPickingStatus = 'C'
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Goods Issue Posted' AS "ActivityName",
od.ActualGoodsMovementDate || ' ' || od.ActualGoodsMovementTime AS "EventTime",
od.LastChangedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.ActualGoodsMovementDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND od.OverallGoodsMovementStatus = 'C'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Shipment Created' AS "ActivityName",
sh.CreationDate || ' ' || sh.CreationTime AS "EventTime",
sh.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
NULL AS "MaterialNumber",
sh.ShippingPoint AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_Shipment AS sh
JOIN I_ShipmentDelivery AS sd ON sh.Shipment = sd.Shipment
JOIN SalesOrderLink sl ON sd.Delivery = sl.OutboundDelivery
WHERE sh.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Proof Of Delivery Confirmed' AS "ActivityName",
od.PODActualDate || ' ' || '00:00:00' AS "EventTime",
od.LastChangedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.PODActualDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND od.OverallPODStatus = 'C'
UNION ALL
SELECT
bdi.SalesDocument AS "LogisticsOrder",
'Customer Invoice Created' AS "ActivityName",
bd.BillingDocumentDate || ' ' || bd.CreationTime AS "EventTime",
bd.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
bdi.Material AS "MaterialNumber",
bdi.Plant AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_BillingDocument AS bd
JOIN I_BillingDocumentItem AS bdi ON bd.BillingDocument = bdi.BillingDocument
LEFT JOIN I_Customer AS cust ON bd.SoldToParty = cust.Customer
WHERE bd.BillingDocumentDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND bd.CompanyCode = 'YourCompanyCode' AND bdi.SalesDocument IS NOT NULL; 步骤
- 前提条件:确保您的用户拥有访问所需 SAP S/4HANA 核心数据服务 (CDS) views 的充足权限。这通常需要由 SAP 安全团队分配特定角色。您还需要一个能够连接到 SAP HANA 数据库的 SQL 客户端,例如 DBeaver 或 SAP HANA Studio。
- 建立数据库连接:配置您的 SQL 客户端以连接到 SAP S/4HANA 数据库。您需要数据库服务器主机、端口(例如 3xx15,其中 xx 是实例编号)、数据库用户名和密码。
- 准备 SQL 查询:将本文档查询部分中提供的完整 SQL 查询复制到 SQL 客户端的编辑器中。此查询旨在从各种物流和销售模块中提取所有指定的活动。
- 设置提取参数:在运行查询之前,找到每个子查询中
WHERE子句内的占位符条件。您必须将'YourCompanyCode'替换为您正在分析的实际公司代码,并调整日期范围占位符(如'YYYY-MM-DD')以定义所需的提取周期。 - 执行查询:运行完整的 SQL 脚本。执行时间将取决于所选的日期范围和系统中的数据量。建议在非高峰时段运行,以尽量减少系统负载。
- 查看初步结果:查询完成后,在 SQL 客户端中快速浏览输出。检查行数是否合理,确保
LogisticsOrder、ActivityName和EventTime等列已填充,并确认出现了各种活动名称。 - 将数据导出为 CSV:从 SQL 客户端将整个结果集导出为 CSV 文件。选择 UTF-8 编码以避免特殊字符出现问题。
- 格式化以上传:确保最终 CSV 文件中的列标题与导入所需的属性名称完全匹配(例如
LogisticsOrder、ActivityName、EventTime)。如果按原样使用提供的 SQL 查询,则无需进一步的数据转换。
配置
- 前提条件:需要访问底层 SAP HANA 数据库。数据库用户必须对查询中引用的所有 CDS views 拥有
SELECT权限,包括但不限于 I_SalesOrderItem、I_PurchaseOrderItem、I_OutboundDeliveryItem、I_MaterialDocumentItem、I_ProductionOrder、I_QualityInspection、I_Shipment 和 I_BillingDocumentItem。 - 日期范围筛选:提供的查询包含日期范围筛选占位符,通常作用于创建日期字段(
CreationDate或DocumentDate)。初步分析时,建议选择 3 到 6 个月的时间段,以获得代表性数据并避免系统负载过高。 - 关键业务筛选:按特定组织单元筛选数据对于确保分析的相关性至关重要。查询已预置了
CompanyCode占位符。您还可以根据分析范围添加SalesOrganization、DistributionChannel或Plant等筛选器。 - 性能考量:这是一个涉及多个大型 CDS views 关联的复杂查询。执行时可能会消耗大量系统资源。请安排在非营业时间进行提取。对于极大数据集,建议按月分批次执行查询。
a 查询示例 sql
WITH SalesOrderLink AS (
SELECT DISTINCT
sd.SalesDocument AS SalesOrder,
pr.PurchaseRequisition AS PurchaseRequisition,
po.PurchaseOrder AS PurchaseOrder,
od.DeliveryDocument AS OutboundDelivery,
bd.BillingDocument AS BillingDocument
FROM I_SalesDocItemProcessFlow AS pf
LEFT JOIN I_SalesDocumentItem AS sd ON pf.PrecedingDocument = sd.SalesDocument AND pf.PrecedingDocumentItem = sd.SalesDocumentItem
LEFT JOIN I_PurchaseRequisitionItem AS pr ON pf.SubsequentDocument = pr.PurchaseRequisition AND pf.SubsequentDocumentItem = pr.PurchaseRequisitionItem
LEFT JOIN I_PurchaseOrderItem AS po ON pf.SubsequentDocument = po.PurchaseOrder AND pf.SubsequentDocumentItem = po.PurchaseOrderItem
LEFT JOIN I_OutboundDeliveryItem AS od ON pf.SubsequentDocument = od.DeliveryDocument AND pf.SubsequentDocumentItem = od.DeliveryDocumentItem
LEFT JOIN I_BillingDocumentItem AS bd ON pf.SubsequentDocument = bd.BillingDocument AND pf.SubsequentDocumentItem = bd.BillingDocumentItem
WHERE sd.SalesDocument IS NOT NULL
)
SELECT
so.SalesOrder AS "LogisticsOrder",
'Sales Order Created' AS "ActivityName",
so.CreationDate || ' ' || so.CreationTime AS "EventTime",
so.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
soi.Material AS "MaterialNumber",
soi.Plant AS "Plant",
soi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_SalesOrder AS so
JOIN I_SalesOrderItem AS soi ON so.SalesOrder = soi.SalesOrder
LEFT JOIN I_Customer AS cust ON so.SoldToParty = cust.Customer
WHERE so.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
so.SalesOrder AS "LogisticsOrder",
'Inventory Availability Checked' AS "ActivityName",
so.CreationDate || ' ' || so.CreationTime AS "EventTime",
so.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
soi.Material AS "MaterialNumber",
soi.Plant AS "Plant",
soi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_SalesOrder AS so
JOIN I_SalesOrderItem AS soi ON so.SalesOrder = soi.SalesOrder
LEFT JOIN I_Customer AS cust ON so.SoldToParty = cust.Customer
WHERE so.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Purchase Requisition Created' AS "ActivityName",
pr.CreationDate || ' ' || '00:00:00' AS "EventTime",
pr.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
pri.Material AS "MaterialNumber",
pri.Plant AS "Plant",
pri.DeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_PurchaseRequisition AS pr
JOIN I_PurchaseRequisitionItem AS pri ON pr.PurchaseRequisition = pri.PurchaseRequisition
JOIN SalesOrderLink sl ON pr.PurchaseRequisition = sl.PurchaseRequisition
WHERE pr.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND pr.CompanyCode = 'YourCompanyCode'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Purchase Order Issued' AS "ActivityName",
po.PurchaseOrderDate || ' ' || '00:00:00' AS "EventTime",
po.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
sup.SupplierName AS "SupplierName",
poi.Material AS "MaterialNumber",
poi.Plant AS "Plant",
poi.DeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_PurchaseOrder AS po
JOIN I_PurchaseOrderItem AS poi ON po.PurchaseOrder = poi.PurchaseOrder
LEFT JOIN I_Supplier AS sup ON po.Supplier = sup.Supplier
JOIN SalesOrderLink sl ON po.PurchaseOrder = sl.PurchaseOrder
WHERE po.PurchaseOrderDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND po.CompanyCode = 'YourCompanyCode'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Goods Receipt For PO Posted' AS "ActivityName",
md.DocumentDate || ' ' || md.CreationTime AS "EventTime",
md.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
sup.SupplierName AS "SupplierName",
mdi.Material AS "MaterialNumber",
mdi.Plant AS "Plant",
poi.DeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_MaterialDocumentHeader AS md
JOIN I_MaterialDocumentItem AS mdi ON md.MaterialDocument = mdi.MaterialDocument AND md.MaterialDocumentYear = mdi.MaterialDocumentYear
JOIN I_PurchaseOrderItem AS poi ON mdi.PurchaseOrder = poi.PurchaseOrder AND mdi.PurchaseOrderItem = poi.PurchaseOrderItem
LEFT JOIN I_Supplier AS sup ON poi.Supplier = sup.Supplier
JOIN SalesOrderLink sl ON poi.PurchaseOrder = sl.PurchaseOrder
WHERE md.DocumentDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND mdi.GoodsMovementType = '101' AND mdi.CompanyCode = 'YourCompanyCode'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Production Order Created' AS "ActivityName",
po.CreationDate || ' ' || po.CreationTime AS "EventTime",
po.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
po.Material AS "MaterialNumber",
po.ProductionPlant AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_ProductionOrder AS po
JOIN SalesOrderLink sl ON po.SalesOrder = sl.SalesOrder
WHERE po.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Goods Produced' AS "ActivityName",
md.DocumentDate || ' ' || md.CreationTime AS "EventTime",
md.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
mdi.Material AS "MaterialNumber",
mdi.Plant AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_MaterialDocumentHeader AS md
JOIN I_MaterialDocumentItem AS mdi ON md.MaterialDocument = mdi.MaterialDocument AND md.MaterialDocumentYear = mdi.MaterialDocumentYear
JOIN I_ProductionOrder AS po ON mdi.ManufacturingOrder = po.ManufacturingOrder
JOIN SalesOrderLink sl ON po.SalesOrder = sl.SalesOrder
WHERE md.DocumentDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND mdi.GoodsMovementType = '101'
UNION ALL
SELECT
qi.SalesOrder AS "LogisticsOrder",
'Quality Inspection Performed' AS "ActivityName",
qi.InspLotUsageDecisionDate || ' ' || qi.InspLotUsageDecisionTime AS "EventTime",
qi.InspLotUsageDecisionMadeByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
qi.Material AS "MaterialNumber",
qi.Plant AS "Plant",
NULL AS "RequestedDeliveryDate",
qi.InspLotUsageDecisionCode AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_QualityInspection AS qi
WHERE qi.InspLotUsageDecisionDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND qi.SalesOrder IS NOT NULL
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Outbound Delivery Created' AS "ActivityName",
od.CreationDate || ' ' || od.CreationTime AS "EventTime",
od.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Picking Completed' AS "ActivityName",
od.PickingDate || ' ' || od.PickingTime AS "EventTime",
od.LastChangedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.PickingDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND od.OverallPickingStatus = 'C'
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Goods Issue Posted' AS "ActivityName",
od.ActualGoodsMovementDate || ' ' || od.ActualGoodsMovementTime AS "EventTime",
od.LastChangedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.ActualGoodsMovementDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND od.OverallGoodsMovementStatus = 'C'
UNION ALL
SELECT
sl.SalesOrder AS "LogisticsOrder",
'Shipment Created' AS "ActivityName",
sh.CreationDate || ' ' || sh.CreationTime AS "EventTime",
sh.CreatedByUser AS "ExecutingUser",
NULL AS "CustomerName",
NULL AS "SupplierName",
NULL AS "MaterialNumber",
sh.ShippingPoint AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_Shipment AS sh
JOIN I_ShipmentDelivery AS sd ON sh.Shipment = sd.Shipment
JOIN SalesOrderLink sl ON sd.Delivery = sl.OutboundDelivery
WHERE sh.CreationDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'
UNION ALL
SELECT
odi.SalesOrder AS "LogisticsOrder",
'Proof Of Delivery Confirmed' AS "ActivityName",
od.PODActualDate || ' ' || '00:00:00' AS "EventTime",
od.LastChangedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
odi.Material AS "MaterialNumber",
odi.Plant AS "Plant",
odi.RequestedDeliveryDate AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_OutboundDelivery AS od
JOIN I_OutboundDeliveryItem AS odi ON od.OutboundDelivery = odi.OutboundDelivery
LEFT JOIN I_Customer AS cust ON od.SoldToParty = cust.Customer
WHERE od.PODActualDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND od.OverallPODStatus = 'C'
UNION ALL
SELECT
bdi.SalesDocument AS "LogisticsOrder",
'Customer Invoice Created' AS "ActivityName",
bd.BillingDocumentDate || ' ' || bd.CreationTime AS "EventTime",
bd.CreatedByUser AS "ExecutingUser",
cust.CustomerName AS "CustomerName",
NULL AS "SupplierName",
bdi.Material AS "MaterialNumber",
bdi.Plant AS "Plant",
NULL AS "RequestedDeliveryDate",
NULL AS "QualityInspectionResult",
'SAP S/4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate"
FROM I_BillingDocument AS bd
JOIN I_BillingDocumentItem AS bdi ON bd.BillingDocument = bdi.BillingDocument
LEFT JOIN I_Customer AS cust ON bd.SoldToParty = cust.Customer
WHERE bd.BillingDocumentDate BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD' AND bd.CompanyCode = 'YourCompanyCode' AND bdi.SalesDocument IS NOT NULL; 步骤
- 前提条件:确保您在 SAP S/4HANA 系统中拥有开发人员密钥和必要的权限,以创建和执行 ABAP 程序(访问事务代码 SE38),并能够读取 VBAK、LIKP、EKKO 和 MKPF 等供应链相关表。
- 创建程序:使用事务代码
SE38打开 ABAP 编辑器。输入新程序的名称(例如Z_PM_SCM_EXTRACTION),然后点击“创建”。提供描述性标题,并将程序类型设置为“可执行程序”。 - 插入代码:从下方的“查询”部分复制完整的 ABAP 代码,并将其粘贴到新程序的 ABAP 编辑器中。
- 定义文本元素:导航至 转到 > 文本元素 > 选择文本。激活所有建议的选择屏幕标签,确保用户界面清晰易懂。
- 激活程序:按 CTRL+S 保存,然后按 CTRL+F3 激活程序(或使用工具栏中的激活图标)。解决由于系统特定配置可能产生的任何语法错误。
- 执行程序:按 F8 或使用“直接处理”按钮运行程序。随后会出现一个选择屏幕,供您筛选待提取的数据。
- 设置提取参数:在选择屏幕上,指定销售订单创建日期的范围。强烈建议同时按特定的公司代码或销售组织进行筛选,以控制数据量。输入 SAP 应用服务器上输出文件的完整路径。
- 后台运行:对于覆盖多个月的大型数据集,务必在后台执行程序以防止事务超时。从菜单中选择 程序 > 后台执行 并安排作业。
- 检索数据文件:程序执行完成后,使用事务代码
AL11导航到您指定的应用服务器目录。找到生成的文件,并使用事务代码CG3Y将其下载到本地机器。 - 准备上传:确保下载的文件为纯文本格式(如以逗号或分号分隔的 CSV),并使用 UTF-8 编码。该文件现在可以上传到 Process Mining 工具中了。
配置
- 选择日期范围 (S_ERDAT):这是最关键的筛选器。它根据销售订单的创建日期(
VBAK-ERDAT)定义初始选择的时间窗口。建议从 3 到 6 个月等较短的时间段开始,以确保数据量可控。 - 销售组织 (S_VKORG):可选筛选器,用于将数据提取限制在特定的销售组织。这有助于针对特定的业务单元或区域进行分析。
- 公司代码 (S_BUKRS):可选筛选器,用于限制特定公司代码的数据。强烈建议使用此筛选器以缩小数据范围并提高系统性能。
- 输出文件路径 (P_FILE):SAP 应用服务器上保存最终事件日志文件的全路径。执行程序的账户必须拥有该目录的写入权限。示例:
/usr/sap/trans/tmp/scm_event_log.csv。 - 执行模式:对于少量测试提取,可以在前台运行程序。对于大规模数据提取,必须进行后台处理,以避免超时并减轻系统在高峰时段的负载。
- 系统权限:执行报表的用户需要对所有相关表具有读取权限,包括但不限于 VBAK、VBAP、EKKO、EKPO、MSEG、MKPF、LIKP、LIPS、VBRK、AUFK、QAVE、KNA1 和 LFA1。
a 查询示例 abap
REPORT Z_PM_SCM_EXTRACTION.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
PARAMETERS: p_file TYPE string LOWER CASE DEFAULT '/usr/sap/trans/tmp/scm_event_log.csv'.
SELECT-OPTIONS: s_erdat FOR sy-datum OBLIGATORY,
s_vkorg FOR vbak-vkorg,
s_bukrs FOR vbak-bukrs.
*&---------------------------------------------------------------------*
*& Data Type Definitions
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
LogisticsOrder TYPE vbeln_va,
ActivityName TYPE string,
EventTime TYPE string,
SourceSystem TYPE sysysid,
LastDataUpdate TYPE string,
ExecutingUser TYPE ernam,
SupplierName TYPE name1_gp,
CustomerName TYPE name1_gp,
MaterialNumber TYPE matnr,
Plant TYPE werks_d,
RequestedDeliveryDate TYPE vdatu,
QualityInspectionResult TYPE string,
END OF ty_event_log.
*&---------------------------------------------------------------------*
*& Data Declarations
*&---------------------------------------------------------------------*
DATA: lt_event_log TYPE TABLE OF ty_event_log,
ls_event_log TYPE ty_event_log,
lv_sysid TYPE sysysid,
lv_last_update TYPE string.
*&---------------------------------------------------------------------*
*& START-OF-SELECTION
*&---------------------------------------------------------------------*
START-OF-SELECTION.
lv_sysid = sy-sysid.
CONCATENATE sy-datum sy-uzeit INTO lv_last_update.
" Select base data: Sales Orders
SELECT h~vbeln, h~erdat, h~erzet, h~ernam, h~kunnr, h~bukrs, h~vdatu, i~posnr, i~matnr, i~werks
INTO TABLE @DATA(lt_so)
FROM vbak AS h
INNER JOIN vbap AS i ON h~vbeln = i~vbeln
WHERE h~erdat IN @s_erdat
AND h~vkorg IN @s_vkorg
AND h~bukrs IN @s_bukrs.
IF lt_so IS INITIAL.
MESSAGE 'No sales orders found for the given criteria.' TYPE 'I'.
RETURN.
ENDIF.
" Select related documents using Document Flow (VBFA)
SELECT *
INTO TABLE @DATA(lt_vbfa)
FROM vbfa
FOR ALL ENTRIES IN @lt_so
WHERE vbelv = @lt_so-vbeln
AND posnv = @lt_so-posnr.
" Collect all unique document numbers
DATA: lt_vbeln_pr TYPE RANGE OF banfn,
lt_vbeln_po TYPE RANGE OF ebeln,
lt_vbeln_dn TYPE RANGE OF vbeln_vl,
lt_vbeln_gi TYPE RANGE OF mblnr,
lt_vbeln_auf TYPE RANGE OF aufnr,
lt_vbeln_inv TYPE RANGE OF vbeln_vf,
lt_vbeln_shp TYPE RANGE OF tknum.
LOOP AT lt_vbfa INTO DATA(ls_vbfa).
CASE ls_vbfa-vbtyp_n.
WHEN 'H'. " Purchase Requisition
APPEND ls_vbfa-vbeln TO lt_vbeln_pr.
WHEN 'K'. " Purchase Order
APPEND ls_vbfa-vbeln TO lt_vbeln_po.
WHEN 'J'. " Delivery
APPEND ls_vbfa-vbeln TO lt_vbeln_dn.
WHEN 'R'. " Goods Movement (GI)
APPEND ls_vbfa-vbeln TO lt_vbeln_gi.
WHEN 'L'. " Production Order
APPEND ls_vbfa-vbeln TO lt_vbeln_auf.
WHEN 'M'. " Invoice
APPEND ls_vbfa-vbeln TO lt_vbeln_inv.
WHEN '8'. " Shipment
APPEND ls_vbfa-vbeln TO lt_vbeln_shp.
ENDCASE.
ENDLOOP.
SORT lt_vbeln_pr. DELETE ADJACENT DUPLICATES FROM lt_vbeln_pr.
SORT lt_vbeln_po. DELETE ADJACENT DUPLICATES FROM lt_vbeln_po.
SORT lt_vbeln_dn. DELETE ADJACENT DUPLICATES FROM lt_vbeln_dn.
SORT lt_vbeln_gi. DELETE ADJACENT DUPLICATES FROM lt_vbeln_gi.
SORT lt_vbeln_auf. DELETE ADJACENT DUPLICATES FROM lt_vbeln_auf.
SORT lt_vbeln_inv. DELETE ADJACENT DUPLICATES FROM lt_vbeln_inv.
SORT lt_vbeln_shp. DELETE ADJACENT DUPLICATES FROM lt_vbeln_shp.
" Select detailed data for each document type
SELECT banfn, badat, ernam FROM eban INTO TABLE @DATA(lt_eban) FOR ALL ENTRIES IN @lt_so WHERE bnfpo = @lt_so-posnr AND banfn IN @lt_vbeln_pr.
SELECT ebeln, aedat, ernam, lifnr FROM ekko INTO TABLE @DATA(lt_ekko) WHERE ebeln IN @lt_vbeln_po.
SELECT vbeln, erdat, erzet, ernam, kodat, wadat_ist, podat FROM likp INTO TABLE @DATA(lt_likp) WHERE vbeln IN @lt_vbeln_dn.
SELECT mblnr, mjahr, budat, usnam FROM mkpf INTO TABLE @DATA(lt_mkpf) WHERE mblnr IN @lt_vbeln_gi.
SELECT mblnr, mjahr, zeile, bwart, lfbnr, ebeln, aufnr FROM mseg INTO TABLE @DATA(lt_mseg) FOR ALL ENTRIES IN @lt_mkpf WHERE mblnr = @lt_mkpf-mblnr AND mjahr = @lt_mkpf-mjahr.
SELECT aufnr, erdat, ernam FROM aufk INTO TABLE @DATA(lt_aufk) WHERE aufnr IN @lt_vbeln_auf.
SELECT prueflos, vdatum, vcode FROM qave INTO TABLE @DATA(lt_qave) FOR ALL ENTRIES IN @lt_so WHERE aufnr IN @lt_vbeln_auf.
SELECT vbeln, erdat, erzet, ernam FROM vbrk INTO TABLE @DATA(lt_vbrk) WHERE vbeln IN @lt_vbeln_inv.
SELECT tknum, erdat, erzet FROM vttk INTO TABLE @DATA(lt_vttk) WHERE tknum IN @lt_vbeln_shp.
SELECT kunnr, name1 FROM kna1 INTO TABLE @DATA(lt_kna1) FOR ALL ENTRIES IN @lt_so WHERE kunnr = @lt_so-kunnr.
SELECT lifnr, name1 FROM lfa1 INTO TABLE @DATA(lt_lfa1) FOR ALL ENTRIES IN @lt_ekko WHERE lifnr = @lt_ekko-lifnr.
" Assemble Event Log
LOOP AT lt_so INTO DATA(ls_so).
CLEAR ls_event_log.
READ TABLE lt_kna1 INTO DATA(ls_kna1) WITH KEY kunnr = ls_so-kunnr BINARY SEARCH.
ls_event_log-LogisticsOrder = ls_so-vbeln.
ls_event_log-SourceSystem = lv_sysid.
ls_event_log-LastDataUpdate = lv_last_update.
ls_event_log-CustomerName = ls_kna1-name1.
ls_event_log-MaterialNumber = ls_so-matnr.
ls_event_log-Plant = ls_so-werks.
ls_event_log-RequestedDeliveryDate = ls_so-vdatu.
" 1. Sales Order Created
ls_event_log-ActivityName = 'Sales Order Created'.
CONCATENATE ls_so-erdat ls_so-erzet INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_so-ernam.
APPEND ls_event_log TO lt_event_log.
" 2. Inventory Availability Checked (proxy event)
ls_event_log-ActivityName = 'Inventory Availability Checked'.
CONCATENATE ls_so-erdat ls_so-erzet INTO ls_event_log-EventTime. " Using SO creation time as a proxy
ls_event_log-ExecutingUser = ls_so-ernam.
APPEND ls_event_log TO lt_event_log.
" Find related documents for this SO item
LOOP AT lt_vbfa INTO ls_vbfa WHERE vbelv = ls_so-vbeln AND posnv = ls_so-posnr.
CASE ls_vbfa-vbtyp_n.
WHEN 'H'. " 3. Purchase Requisition Created
READ TABLE lt_eban INTO DATA(ls_eban) WITH KEY banfn = ls_vbfa-vbeln.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Purchase Requisition Created'.
CONCATENATE ls_eban-badat '000000' INTO ls_event_log-EventTime. " PR has no time field
ls_event_log-ExecutingUser = ls_eban-ernam.
APPEND ls_event_log TO lt_event_log.
ENDIF.
WHEN 'K'. " 4. Purchase Order Issued
READ TABLE lt_ekko INTO DATA(ls_ekko) WITH KEY ebeln = ls_vbfa-vbeln.
IF sy-subrc = 0.
READ TABLE lt_lfa1 INTO DATA(ls_lfa1) WITH KEY lifnr = ls_ekko-lifnr BINARY SEARCH.
ls_event_log-ActivityName = 'Purchase Order Issued'.
CONCATENATE ls_ekko-aedat '000000' INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_ekko-ernam.
ls_event_log-SupplierName = ls_lfa1-name1.
APPEND ls_event_log TO lt_event_log.
ENDIF.
WHEN 'L'. " 6. Production Order Created
READ TABLE lt_aufk INTO DATA(ls_aufk) WITH KEY aufnr = ls_vbfa-vbeln.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Production Order Created'.
CONCATENATE ls_aufk-erdat '000000' INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_aufk-ernam.
APPEND ls_event_log TO lt_event_log.
" 8. Quality Inspection Performed
READ TABLE lt_qave INTO DATA(ls_qave) WITH KEY prueflos = ls_vbfa-vbeln. " Approximation linking lot to order
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Quality Inspection Performed'.
CONCATENATE ls_qave-vdatum '000000' INTO ls_event_log-EventTime.
ls_event_log-QualityInspectionResult = ls_qave-vcode.
APPEND ls_event_log TO lt_event_log.
CLEAR ls_event_log-QualityInspectionResult.
ENDIF.
ENDIF.
WHEN 'J'. " 9. Outbound Delivery Created
READ TABLE lt_likp INTO DATA(ls_likp) WITH KEY vbeln = ls_vbfa-vbeln.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Outbound Delivery Created'.
CONCATENATE ls_likp-erdat ls_likp-erzet INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_likp-ernam.
APPEND ls_event_log TO lt_event_log.
" 10. Picking Completed
IF ls_likp-kodat IS NOT INITIAL.
ls_event_log-ActivityName = 'Picking Completed'.
CONCATENATE ls_likp-kodat '120000' INTO ls_event_log-EventTime. " Using Picking Date as proxy
APPEND ls_event_log TO lt_event_log.
ENDIF.
" 14. Proof Of Delivery Confirmed
IF ls_likp-podat IS NOT INITIAL.
ls_event_log-ActivityName = 'Proof Of Delivery Confirmed'.
CONCATENATE ls_likp-podat '000000' INTO ls_event_log-EventTime.
APPEND ls_event_log TO lt_event_log.
ENDIF.
ENDIF.
WHEN 'M'. " 15. Customer Invoice Created
READ TABLE lt_vbrk INTO DATA(ls_vbrk) WITH KEY vbeln = ls_vbfa-vbeln.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Customer Invoice Created'.
CONCATENATE ls_vbrk-erdat ls_vbrk-erzet INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_vbrk-ernam.
APPEND ls_event_log TO lt_event_log.
ENDIF.
WHEN '8'. " 12. Shipment Created
READ TABLE lt_vttk INTO DATA(ls_vttk) WITH KEY tknum = ls_vbfa-vbeln.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Shipment Created'.
CONCATENATE ls_vttk-erdat ls_vttk-erzet INTO ls_event_log-EventTime.
APPEND ls_event_log TO lt_event_log.
ENDIF.
ENDCASE.
ENDLOOP.
" Find material movements (MSEG) not directly in VBFA
" 5. Goods Receipt For PO Posted
LOOP AT lt_mseg INTO DATA(ls_mseg_po) WHERE ebeln IN (SELECT ebeln FROM ekpo WHERE banfn IN (SELECT banfn FROM eban WHERE vbeln = ls_so-vbeln) ) AND bwart = '101'.
READ TABLE lt_mkpf INTO DATA(ls_mkpf_po) WITH KEY mblnr = ls_mseg_po-mblnr mjahr = ls_mseg_po-mjahr.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Goods Receipt For PO Posted'.
CONCATENATE ls_mkpf_po-budat '000000' INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_mkpf_po-usnam.
APPEND ls_event_log TO lt_event_log.
ENDIF.
ENDLOOP.
" 7. Goods Produced
LOOP AT lt_mseg INTO DATA(ls_mseg_pp) WHERE aufnr IN (SELECT aufnr FROM afpo WHERE kdauf = ls_so-vbeln) AND bwart = '101'.
READ TABLE lt_mkpf INTO DATA(ls_mkpf_pp) WITH KEY mblnr = ls_mseg_pp-mblnr mjahr = ls_mseg_pp-mjahr.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Goods Produced'.
CONCATENATE ls_mkpf_pp-budat '000000' INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_mkpf_pp-usnam.
APPEND ls_event_log TO lt_event_log.
ENDIF.
ENDLOOP.
" 11. Goods Issue Posted
LOOP AT lt_mseg INTO DATA(ls_mseg_gi) WHERE lfbnr IN (SELECT vbeln FROM lips WHERE vgbel = ls_so-vbeln) AND bwart = '601'.
READ TABLE lt_mkpf INTO DATA(ls_mkpf_gi) WITH KEY mblnr = ls_mseg_gi-mblnr mjahr = ls_mseg_gi-mjahr.
IF sy-subrc = 0.
ls_event_log-ActivityName = 'Goods Issue Posted'.
CONCATENATE ls_mkpf_gi-budat '000000' INTO ls_event_log-EventTime.
ls_event_log-ExecutingUser = ls_mkpf_gi-usnam.
APPEND ls_event_log TO lt_event_log.
ENDIF.
ENDLOOP.
ENDLOOP.
" Remove duplicate events for the same case
SORT lt_event_log BY LogisticsOrder ActivityName EventTime.
DELETE ADJACENT DUPLICATES FROM lt_event_log COMPARING LogisticsOrder ActivityName EventTime.
" Write data to file
DATA: lt_output TYPE TABLE OF string.
APPEND 'LogisticsOrder,ActivityName,EventTime,SourceSystem,LastDataUpdate,ExecutingUser,SupplierName,CustomerName,MaterialNumber,Plant,RequestedDeliveryDate,QualityInspectionResult' TO lt_output.
LOOP AT lt_event_log INTO ls_event_log.
DATA(lv_line) = |
{ ls_event_log-LogisticsOrder },
{ ls_event_log-ActivityName },
{ ls_event_log-EventTime },
{ ls_event_log-SourceSystem },
{ ls_event_log-LastDataUpdate },
{ ls_event_log-ExecutingUser },
{ ls_event_log-SupplierName },
{ ls_event_log-CustomerName },
{ ls_event_log-MaterialNumber },
{ ls_event_log-Plant },
{ ls_event_log-RequestedDeliveryDate },
{ ls_event_log-QualityInspectionResult }|
.
REPLACE ALL OCCURRENCES OF ',' IN lv_line WITH ' '.
REPLACE ALL OCCURRENCES OF REGEX '\s+' IN lv_line WITH '' LEADING.
CONDENSE lv_line.
APPEND lv_line TO lt_output.
ENDLOOP.
cl_gui_frontend_services=>gui_download(
EXPORTING
filename = p_file
filetype = 'ASC'
CHANGING
data_tab = lt_output
EXCEPTIONS
OTHERS = 24
).
IF sy-subrc <> 0.
MESSAGE 'Error downloading file.' TYPE 'E'.
ELSE.
MESSAGE |File downloaded successfully to { p_file }| TYPE 'S'.
ENDIF.