ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SAP IDOC实现PO自动转SO:从配置到ABAP开发完整指南

SAP IDOC实现PO自动转SO:从配置到ABAP开发完整指南 你有没有遇到过这种情况客户不是在你的SAP系统里直接下单而是从他们自己的ERP里发来一张采购订单然后销售助理照着邮件里的PO在VA01里一行一行地敲成销售订单。订单行项目少还好说碰上几十行的PO敲到下班眼睛都花了数量、单价、物料号一不小心就串行。等你发现货发多了或者价格录错了已经是几天之后的事。这种场景在B2B供应链里太常见了。客户发采购订单你这边要生成销售订单两边系统如果靠人工搬运效率低、错误多、还追不了责。解决思路是用IDOCIntermediate Document中间文档做系统间数据交换客户系统把采购订单数据推过来SAP收到后自动创建销售订单。这玩意儿配置起来其实并不复杂难的是把整条链路的逻辑理顺。这篇文章我把从IDOC类型定义、消息类型、端口、伙伴参数配置到入站ABAP处理、BAPI生成销售订单、状态码回写、高频踩坑这一整套流程完整拆开讲。标题说5分钟那是我在客户现场把坑都排干净之后的速度新手第一次搞照着这篇文章走半天内跑通没问题。1. 一张客户采购订单为什么要绕道进SAP1.1 业务场景与痛点PO转SO到底解决什么问题先说清楚业务链路。假设你是一家制造业公司的SAP管理员客户用他们的SAP或者Oracle系统给你发采购订单你需要在自家里创建对应的销售订单来触发后续的排产、发货、开票流程。人工处理这套流程有三个痛点第一时效性差。客户PO来了销售助理不可能实时盯着邮箱订单多的时候积压半天很正常交付周期被白白压缩。第二准确性没保障。一个人对着两个界面来回比对几十个行项目录入下来不出错的概率很低。尤其物料编码、价格条件、交货日期这些字段只要错一个后面MRP跑出来的结果就是错的。第三无法追溯。人工录入的单子出了问题只能问人没有系统日志可查。到底是客户传错了还是录入错了扯皮能扯一个星期。IDOC方案解决的就是这三点。客户系统把PO数据以固定格式推过来SAP自动接收、自动创建销售订单全程有日志、有状态码、可重试、可追责。1.2 自动化方案对比IDOC、RFC、BDC和中间件怎么选很多刚接触SAP集成的朋友会问实现PO自动转SO不是有RFC、BAPI、甚至BDC录屏吗为什么非要用IDOC方案技术特点适用场景主要缺点RFC/BAPI同步调用调用方实时等待返回结果外部系统需要立刻知道SO是否创建成功依赖双方系统同时在线网络抖动就失败BDC录屏模拟屏幕操作批量过账一次性数据迁移没有接口协议无结构化日志出错难定位不推荐做长期接口IDOC异步消息发送方发出后不等待接收方后台处理跨系统长期集成、量大、需要审计配置链路多初次上手有一定理解成本中间件/ESB通过第三方平台转换数据格式再入SAP多系统异构集成字段映射复杂多一层架构实施成本高简单说如果你想做一个长期跑、数据量大、还要能追踪问题来源的接口IDOC是SAP生态里最正统的选择。异步传输机制决定了发送方发完就完事不占用会话SAP这边处理失败了还能重置状态重新处理。相比同步RFC调用对网络波动和系统短暂故障的容忍度高得多不需要双方系统时刻保持连接。1.3 为什么选自定义IDOC类型而不是标准ORDERSSAP自带标准采购订单消息类型ORDERS以及对应的IDOC基本类型ORDERS01、ORDERS02等。理论上可以直接复用但实际项目中我一般建议谨慎使用。标准ORDERS类型字段非常多E1EDK01、E1EDP01这些标准段里几十个字段真正用得到的可能就十几个。外部系统对接时对方一看这么多字段直接懵了不知道哪些必填、哪些选填。而且标准类型如果后续被SAP标准增强或Oss note影响你很难控制变数。自定义IDOC类型的好处在于只保留双方约定好的字段外部系统对接简单清晰SAP端处理逻辑也直观。缺点是需要自己维护段结构和数据元素。对于PO转SO这种业务字段量不大自定义类型的性价比很高。本文的配置流程就基于自定义IDOC类型展开。2. 理解IDOC的运行链路从发送到落地的每个环节2.1 一条IDOC的完整旅程是什么样的配置之前脑子里必须有一条完整的链路图。IDOC从发送到最终在SAP里生成销售订单要经过这些环节发送方系统生成IDOC数据写入数据库表EDIDC是控制记录EDID4是数据记录。根据端口配置将IDOC发送出去。端口就像邮筒定义了把这个信封投到哪个通道。接收方系统通过RFC端口收到IDOC写入自己的EDIDC/EDID4表。根据伙伴参数文件WE20中的配置找到对应的入站处理程序功能模块。功能模块解析IDOC数据调用BAPI_SALESORDER_CREATEFROMDAT2创建销售订单。处理完成后把IDOC状态码更新到EDIDS表比如53表示成功51表示出错。注意这里有个关键点接收方收到IDOC后并不是立刻执行处理程序而是把IDOC先落库再通过后台作业或入站触发器调用功能模块。这也是IDOC异步处理的核心价值——即使SAP系统正好在跑重型报表IDOC数据也不会丢处理可以排队。2.2 四个核心对象IDOC类型、消息类型、端口、伙伴参数这四个对象是IDOC配置的基石很多人配到一半卡住就是因为没搞懂它们各自管什么。IDOC类型IDOC Type定义数据的结构格式。比如ZPO_SO_RECEIVER这个IDOC类型里包含哪些段Segment、每个段里有哪些字段。这相当于两个人约定的表格格式A列是采购订单号B列是行号C列是物料编码。消息类型Message Type说明这条消息是什么业务含义比如ZPO_TO_SO就是“采购订单转销售订单”。一个IDOC类型可以被多个消息类型引用反过来消息类型也可以分配多个IDOC类型。端口Port定义数据传输的通道。SAP支持事务性RFC端口、文件端口、CPI端口等。在两个SAP系统之间用事务性RFC端口最省事直接填目标系统的RFC目标名SM59里配置的逻辑系统。伙伴参数Partner Profile定义双方系统的身份和消息规则。对于入站方向要指定消息类型对应的入站处理功能模块对于出站方向要指定接收方系统、端口等。可以这么类比IDOC类型是信封里的表格格式消息类型是信封上的业务标签端口是邮局通道伙伴参数是寄件人和收件人的地址。四个对象缺一个送信流程就走不通。2.3 为什么这些对象必须成套配置我在项目实施中见过最典型的问题是刚入门的顾问在WE20里配了伙伴参数但忘了把消息类型分配给IDOC类型结果IDOC到达后系统直接报错。或者端口配了出站却忘记在伙伴参数里指定消息类型对应的出站处理程序。原因就是没有把四个对象当成一个整体来看。配置顺序建议是先规划好IDOC类型和段结构WE30/WE31。再建消息类型WE81并把消息类型分配给IDOC类型WE82。配置端口WE21。最后维护伙伴参数WE20入站时指定功能模块。如果还要触发后续的确认回执才需要配置流程代码和输出类型。顺序反了就会出现“对象存在但关联关系断裂”的诡异问题排查起来特别耗时间。3. 配置实操从新建IDOC类型到合作伙伴参数全流程3.1 配置前的数据规划与字段清单动手配置前先跟业务确认清楚客户传过来的采购订单有哪些字段是必填的、哪些是选填的映射到销售订单的哪些字段。这一步看起来不重要实际上决定了你后来写ABAP要处理多少脏数据。以我常用的自定义IDOC类型ZPO_SO_RECEIVER为例段结构分为抬头段和行项目段段名称用途关键字段示例Z1EEDK01采购订单抬头采购订单号、采购订单日期、客户编号、销售组织、分销渠道、销售订单类型Z1EEDP01采购订单行项目行号、物料号、数量、单位、单价、工厂、交货日期注意客户编号在SAP S/4HANA新版本里推荐使用BP业务伙伴概念客户主数据维护在CVP客户-供应商集成功能下。如果你们公司启用了BP那就把BP号作为客户编号字段如果还是传统SD模块的客户主数据用KUNNR字段。3.2 创建段和IDOC类型WE31与WE30第一步用事务代码WE31创建段。输入段名Z1EEDK01进入维护界面后添加字段。段字段可以直接录入SAP数据元素比如采购订单号可以用BSTKT采购订单号物料号用MATNR客户号用KUNNR。如果SAP标准数据元素不够用用SE11自己创建数据元素。这里不展开SE11的操作但记住一个原则能用标准数据元素就用标准的自定义太少反而增加维护成本。WE31里把段保存激活后进入WE30创建IDOC类型。初始屏幕输入IDOC类型名ZPO_SO_RECEIVER点击“创建”系统会弹出基础类型的创建界面。把刚才建好的段Z1EEDK01和Z1EEDP01依次添加到类型树里。如果行项目段会重复出现多次一行一条数据把段的“最小次数”和“最大次数”设置成1和999这样一条IDOC里可以容纳多行项目。这里有个细节值得注意段在WE31里定义之后在WE30里添加时系统会自动生成一个以数字后缀开头的段实例比如E1Z1EEDK01这是正常现象因为IDOC类型的段名必须唯一。不要看到前缀变化就以为配错了。3.3 定义消息类型并分配WE81与WE82用WE81创建消息类型输入ZPO_TO_SO描述为“采购订单转销售订单”保存即可。然后进WE82把消息类型和IDOC类型关联起来。维护方向选“入站”和“出站”都勾上IDOC类型选ZPO_SO_RECEIVER。不确定的话两个方向都分配后续只在需要的方向上配置伙伴参数即可。有些SAP版本里WE81创建的消息类型会自动出现在WE82的候选列表里但关联关系不会自动生成必须手动分配。这一步漏了后面在WE20里配置伙伴参数时会发现消息类型根本选不上。3.4 配置RFC端口WE21事务代码WE21进入端口维护界面。创建端口类型选“事务性RFC端口”系统会要求维护RFC目标。RFC目标一般在SM59里预先配置好这里直接引用。如果对方也是SAP系统RFC目标要连接到对方的逻辑系统上。如果对方是非SAP系统通常通过中间件比如BOOMI、CPI、MuleSoft来调用SAP的RFC/BAPI函数创建IDOC此时端口配置要根据中间件的连接方式调整。端口名称可以起得直白一点比如ZPORT_PO_TO_SO方便后面在伙伴参数里一眼识别。3.5 维护合作伙伴参数WE20WE20是整个配置链路里最关键也最容易出错的一步。对于入站方向伙伴类型一般选“逻辑系统LS”或“客户KU”。如果发送方是客户的SAP系统用LS如果发送方是客户业务伙伴用KU。实务中两个SAP系统对接用LS最常见。输入伙伴编号后进入“入站参数”区域添加一条消息类型ZPO_TO_SO处理程序类型选“功能模块”处理功能模块填Z_INBOUND_PO_TO_SO这个是后面要写的ABAP函数名。对于出站方向如果你的SAP系统还需要向对方回传销售订单确认信息可以在出站参数里维护伙伴类型选LS伙伴编号填目标系统消息类型ZPO_TO_SO输出类型选“IDOC”端口选ZPORT_PO_TO_SO包大小按需填。不做出站就不需要配。保存后这条链路就通了对方系统发来消息类型为ZPO_TO_SO的IDOCSAP根据伙伴参数找到功能模块Z_INBOUND_PO_TO_SO去处理。3.6 流程代码与输出控制什么时候需要WE41/WE42如果是SAP系统内部通过“消息控制”来触发IDOC比如采购订单确认后自动发IDOC给供应商那还需要配置流程代码Process Code和输出类型。但本文的场景是外部系统主动推送PO数据过来属于入站推式Inbound Push不涉及输出控制。流程代码更多用在出站场景。如果你后续要做“销售订单创建后自动回传给客户”的功能再去看WE41出站流程代码和NACE输出类型配置。刚开始做PO转SO不要贪多把入站链路跑通比什么都强。4. 创建销售订单的ABAP处理逻辑从IDOC数据到销售订单4.1 入站处理功能模块怎么写IDOC的DATA结构拆解配置做好了没有处理程序IDOC到了也只是躺着不动。我们要写一个入站功能模块Z_INBOUND_PO_TO_SO挂在WE20伙伴参数的入站处理程序上。SAP IDOC入站功能模块的接口是固定的两个标准参数参数名类型说明INPUT_METHODEDIDC输入方式一般用4后台处理MASS_PROCESSINGEDIDC是否批量处理传入后通过标准函数IDOC_INBOUND_ASYNCHRONOUS或直接读表来获取IDOC数据。常见的写法是先在FUNCTION POOL里声明标准IDOC结构然后用IDOC_DATA表接收段数据。处理逻辑拆分三步读控制记录EDIDC确认IDOC方向、消息类型、伙伴编号。遍历数据记录EDID4根据段名SEGNAM把抬头段和行项目段分别拆出来。拼装BAPI_SALESORDER_CREATEFROMDAT2的输入结构。4.2 核心代码框架BAPI_SALESORDER_CREATEFROMDAT2的封装调用创建销售订单最常用的是标准BAPI_SALESORDER_CREATEFROMDAT2相比老版本的CREATEFROMDAT1它对抬头、项目、计划行、条件等结构支持得更完整。核心代码框架如下示例值已脱敏FUNCTION Z_INBOUND_PO_TO_SO. DATA: ls_idoc_control TYPE edidc, lt_idoc_data TYPE TABLE OF edid4, ls_e1edk01 TYPE z1eedk01, ls_e1edp01 TYPE z1eedp01. DATA: ls_header_in TYPE bapisdh1, ls_header_inx TYPE bapisdh1x, lt_item_in TYPE TABLE OF bapisditm, lt_item_inx TYPE TABLE OF bapisditmx, lt_return TYPE TABLE OF bapiret2, ls_so_number TYPE bapivbeln-vbeln. * 1. 读取IDOC数据标准函数IDOC_INBOUND_ASYNCHRONOUS会填充内表 LOOP AT lt_idoc_data INTO DATA(ls_segment). CASE ls_segment-segnam. WHEN Z1EEDK01. MOVE ls_segment-sdata TO ls_e1edk01. WHEN Z1EEDP01. MOVE ls_segment-sdata TO ls_e1edp01. 每读到一个行项目段就填充一条BAPI行项目 DATA(ls_item) VALUE bapisditm( itm_number ls_e1edp01-posnr material ls_e1edp01-matnr target_qty ls_e1edp01-quantity plant ls_e1edp01-plant ). APPEND ls_item TO lt_item_in. ENDCASE. ENDLOOP. * 2. 填充抬头数据 ls_header_in VALUE bapisdh1( doc_type ls_e1edk01-doctype 销售订单类型如OR sales_org ls_e1edk01-salesorg distr_chan ls_e1edk01-distrchan division ls_e1edk01-division sold_to ls_e1edk01-kunnr purch_no ls_e1edk01-bstkd 对应客户采购订单号 ). * 3. 调用BAPI CALL FUNCTION BAPI_SALESORDER_CREATEFROMDAT2 EXPORTING order_header_in ls_header_in IMPORTING salesdocument ls_so_number TABLES return lt_return order_item_in lt_item_in. * 4. 判断BAPI返回 READ TABLE lt_return TRANSPORTING NO FIELDS WITH KEY type E. IF sy-subrc 0. CALL FUNCTION BAPI_TRANSACTION_COMMIT. 更新IDOC状态为成功 PERFORM update_idoc_status USING ls_idoc_control 53. ELSE. CALL FUNCTION BAPI_TRANSACTION_ROLLBACK. 记录错误日志IDOC保持错误状态后续可重置重跑 PERFORM update_idoc_status USING ls_idoc_control 51. ENDIF. ENDFUNCTION.这段代码就是主干框架。实际项目中还要补销售订单的抬头文本、行项目文本、价格条件、计划行交货日期等数据。注意计划行数据如果要维护需要填充BAPI表ORDER_SCHEDULES_IN和ORDER_SCHEDULES_INX否则系统可能默认按物料主数据里的计划行配置处理。4.3 状态码回写与错误日志IDOC能不能重跑就看这里IDOC处理完必须回写状态码否则IDOC会一直停留在已接收未处理的状态出了问题也没法重跑。SAP标准做法是调用函数IDOC_STATUS_WRITE来写入状态记录状态码的意义状态码含义处理建议53处理成功无需再动保留日志备查51处理失败错误排查后调用IDOC重置再重新处理64等待入站功能模块处理正常中间状态错误排查时的关键经验在BAPI返回错误信息时一定要把lt_return的完整内容写到自定义日志表或者应用日志SLG1里。IDOC状态表只记录了一个成败标志真正的错误原因都在BAPI返回结构里。不写日志出了问题你只能去翻BAPI调试器效率极低。我在项目里习惯建一张自定义日志表ZIDOC_LOG字段包括IDOC编号、采购订单号、销售订单号、状态、错误消息、创建时间。每次入站处理结束都写一条记录后续追查问题、对账都非常方便。5. 实测验证与高频踩坑WE02状态、字段映射及其余细节5.1 模拟发送一条IDOCWE19测试工具与状态检查配置全部完成、ABAP程序也激活了接下来就是验证。推荐两种方式第一用WE19测试工具。在WE19里输入IDOC类型ZPO_SO_RECEIVER系统会生成一条空的IDOC记录你在段视图里手工填上测试数据然后点“标准入站处理”直接触发功能模块。这种方式不用等外部系统真正发数据非常适合单步调试。第二如果你已经和外部系统联调让对方真实推送一条PO过来。数据到达后用WE02查看IDOC列表输入IDOC编号或时间段查询。双击一条IDOC进去可以看到控制记录和数据记录。测试时重点看两个地方IDOC状态是否从30已接收变成53成功或者51失败。如果没有变化去SE37里对Z_INBOUND_PO_TO_SO按F8单步执行看卡在哪一步。5.2 我实际遇到的高频问题伙伴参数、字段映射和主数据PO转SO这个接口配置本身半小时能搞定真正耗时间的是各种业务主数据和字段映射问题。列出我踩过的坑问题现象常见原因解决办法IDOC到后停在30状态不触发功能模块WE20入站参数没配处理程序或方向配错检查入站伙伴参数确认消息类型和功能模块挂接WE20里消息类型下拉为空WE82没做消息类型-IDOC类型关联回WE82做关联分配BAPI报“销售订单类型不存在”自定义销售订单类型未在VOV8里配置在VOV8为对应销售范围激活订单类型BAPI报“客户主数据未定义”客户编号字段映射错或客户主数据缺少销售范围用XD03/BP检查客户在对应销售组织、分销渠道下是否有效相同采购订单号重复创建销售订单没有按采购订单号做去重处理在BAPI调用前用VBAK-VGBEL参照采购订单号查一遍是否已存在数量单位不一致导致数量错误采购订单单位与销售订单基本单位不一致在BAPI里维护目标单位或让外部系统按基本单位传价格没带出来条件记录VK11缺失或没有维护价格主数据检查条件记录BAPI里可以传自定义价格条件覆盖特别提醒去重这个坑。接口上线初期偶发网络重发客户系统同一张PO传了两次结果SAP里生成了两张销售订单发货发重复了。后来在程序里加了按“客户编码客户采购订单号行号”的查重逻辑才把这个隐患堵住。5.3 上线前的验收清单除了流程通还要测什么流程能跑通只是第一步上线前这几项必须测异常场景测试对方传了一张不存在的物料号IDOC状态是否为51错误日志是否清晰重复处理测试同一张PO发两次第二次系统是否会拒绝行项目边界测试50行、100行的POBAPI响应时间和IDOC处理是否正常主数据变更测试客户主数据被冻结或者物料被冻结后接口报错是否合理。断网重连测试RFC端口临时不可用IDOC会积压在发送方恢复后是否能自动补发。第5条在跨系统对接时尤其重要。IDOC的异步机制保证了发送方不会因为接收方临时宕机而丢数据但前提是发送方把IDOC成功落库了。真遇到极端情况还是要靠端口监控作业和状态报表来兜底。最后说点实话。这篇文章标题写“5分钟搞定”真按这个准备去客户现场实施新手第一次可能还是要折腾大半天。5分钟是建立在把段结构、字段映射、主数据问题全部想清楚的基础上——配置只是抄作业真正花时间的是搞清楚业务到底要什么、对方系统能传什么、SAP这边哪些字段必须收到值。只要这三点梳理清楚了后面的配置和代码都是顺水推舟的事。IDOC这套机制学会了不光能做PO转SO供应商发货通知、发票回传、客户主数据同步都是同一个套路定结构、配伙伴、写处理函数。把这篇文章里的链路吃透再遇到类似接口需求就不会怵了。
返回列表