ARTICLE DETAIL

资讯详情

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

告别 CO48 BDC:我用 AI 拆开 SAP 标准代码,把计划订单“部分转单”封装成了一个可复用类

告别 CO48 BDC:我用 AI 拆开 SAP 标准代码,把计划订单“部分转单”封装成了一个可复用类 告别 CO48 BDC我用 AI 拆开 SAP 标准代码把计划订单“部分转单”封装成了一个类一次真实的 SAP PP 重构实践不调用BAPI_PRODORD_CREATE不使用BAPI_PRODORD_CHANGE也不再依赖 CO48/CO02 的屏幕 BDC而是沿用 SAP 标准订单内存和保存链路实现计划订单可重复部分转换、增强字段传递、无弹窗处理和工单日期锁定。前言真正危险的不是 BDC 能不能跑而是它什么时候突然不能跑有部分SAP标准功能没有对应的BAPI或者BAPI不好用时我们就会进行BDC开发CALL TRANSACTION XXX USING gt_bdcdata MODE N.这些程序可能已经稳定运行多年但它们始终存在一些共同风险依赖具体屏幕号、字段名和 OKCODESAP 升级、补丁或屏幕增强后可能失效弹窗、警告和用户参数可能改变 BDC 流程很难准确控制事务提交和回滚错误经常只能从 BDC 消息表中拼接排查困难批量处理时性能和稳定性都不理想。本次需求看似只是“不要用 BDC 调用 CO48”实际涉及计划订单、生产订单、标准内存缓冲、更新任务、日期排程、增强字段和多次部分转换等多个环节。最终我们在 AI 辅助下完成了一个类ZCL_PP_PLORD_CONV_CO48并提供测试程序ZTEST_CO48本文记录整个分析思路、最终架构以及值得复用的方法论。一、业务场景一个计划订单需要多次部分转单需求不是简单地把计划订单一次性转成生产订单而是支持输入计划订单输入本次转换数量输入生产订单开始和结束日期同一个计划订单可以多次部分转换每次产生一张新的生产订单原计划订单保留剩余数量剩余计划订单日期按输入值更新自定义 AUFK 增强字段随新订单一起保存不允许用 CO48 BDC不使用BAPI_PRODORD_CREATE自己重建标准逻辑不使用BAPI_PRODORD_CHANGE做创建后的二次修改普通警告和确认弹窗自动继续真正禁止转换的错误仍然终止。这意味着不能只找一个“能创建生产订单”的接口而必须尽量复用 CO48 原本的标准逻辑。二、为什么没有直接使用生产订单创建 BAPI最容易想到的方案通常是读取计划订单再调用BAPI_PRODORD_CREATE创建生产订单。但这样做的本质是重新实现 CO48计划订单组件如何转移预留如何处理部分转换后的剩余数量如何计算计划订单何时修改或删除订单类型如何确定工艺路线、BOM、生产版本和能力需求如何处理临时订单号如何替换为正式订单号标准状态、结算规则和增强何时执行。自己重新拼这些逻辑很难与 CO48 保持一致。另一个方案是在创建后调用BAPI_PRODORD_CHANGE修改日期和增强字段。但在实际系统中创建提交尚未完全结束时后续 BAPI 可能读不到刚创建的工单容易出现数据库提交时序问题。因此本次设计遵循一个核心原则不重新发明生产订单创建逻辑而是找到 CO48 真正使用的标准业务内核。三、AI 在这次开发中真正发挥了什么作用这次 AI 的价值不只是生成 ABAP 代码而是协助完成了大量人工分析工作读取 CO48 相关标准程序和函数组追踪计划订单转换的标准调用链查找函数的真实参数和异常定义分析订单内存缓冲与数据库保存的边界对照现有程序ZPPU077的业务逻辑分析跨程序子例程ZPPU001-FRM_CO02的实际行为定位确认弹窗为什么无法被普通 no-dialog 标志抑制检查语法、激活状态和 ATC 结果根据实际测试现象继续反查标准源码。传统方式下这类分析通常需要反复进入 SE80、SE37、SAT、调试器和 Where-Used List。AI 配合 ADT Remote Filesystem/MCP 后可以快速完成“搜索—阅读—推理—验证”的闭环。但必须强调AI 的结论不能只靠记忆或猜测。涉及未发布的 SAP 标准函数时每一个函数签名和关键分支都应该以当前系统源码为准。四、最终使用的标准内存调用链经过对 CO48 标准代码的分析最终采用了下面的链路读取并锁定 PLAF │ ▼ CO_SD_PLANNED_ORDER_CONVERT │ ├─ 在 CO 标准内存中生成生产订单 ├─ 转移组件、工艺和相关订单数据 └─ 返回临时订单号及订单内存结构 │ ▼ MD_PLANNED_ORDER_CHANGE 或 MD_DELETE_PLANNED_ORDER_DIA │ ▼ MD_POST_PLANNED_ORDERS │ ▼ CO_BI_AFPO_UPD │ ▼ 锁定生产订单日期可选 │ ▼ CO_ZV_ORDER_POST │ ▼ COMMIT WORK AND WAIT │ ▼ 读取 AUFK、AFKO、AFPO、PLAF 验证结果这里最重要的是生产订单和计划订单的修改先保存在 SAP 标准内存缓冲中然后通过标准保存函数统一落库。这比“创建后再调用另一个 BAPI 修改”更接近 CO48 的原始事务模型。五、类接口如何设计类对外只暴露一个主要方法METHODS convert_partial IMPORTING iv_plnum TYPE plaf-plnum iv_quantity TYPE plaf-gsmng iv_start_date TYPE plaf-psttr iv_finish_date TYPE plaf-pedtr iv_auart TYPE aufk-auart OPTIONAL is_aufk_ext TYPE zpp_s_aufk OPTIONAL is_aufkx_ext TYPE zpp_s_aufkx OPTIONAL iv_lock_dates TYPE abap_bool DEFAULT abap_false EXPORTING ev_aufnr TYPE aufk-aufnr ev_remaining_qty TYPE plaf-gsmng ev_auart TYPE aufk-auart et_return TYPE tt_return.调用方只需要提供计划订单号本次转换数量开始日期结束日期可选订单类型AUFK 增强字段是否强制锁定生产订单日期。类内部负责锁定计划订单校验剩余数量自动确定订单类型处理标准转换处理增强内存更新或删除原计划订单保存生产订单提交和回滚验证最终结果。这样以后业务程序不需要在每次调用前重新拼一遍增强字段、日期和提交逻辑。六、同一计划订单如何支持多次部分转换多次部分转换的关键不是限制计划订单“只能用一次”而是每次都读取数据库中的当前剩余数量SELECT SINGLE * FROM plaf INTO ls_plaf_db WHERE plnum iv_plnum. ev_remaining_qty ls_plaf_db-gsmng - iv_quantity.转换标志根据剩余数量决定IF ev_remaining_qty 0. ls_plaf_conv-umskz T. 部分转换 ELSE. ls_plaf_conv-umskz E. 最后一次转换 ENDIF.如果仍有剩余数量则通过标准计划订单修改逻辑保留原计划订单如果数量已全部转换则通过标准删除逻辑删除计划订单。同时必须先对计划订单加锁防止两个会话同时转换同一个剩余数量CALL FUNCTION ENQUEUE_EMPLAFE EXPORTING plnum iv_plnum _scope 2 _wait X.七、增强字段如何一次封装现有系统通过增强在订单保存阶段读取自定义结构is_aufk_ext TYPE zpp_s_aufk is_aufkx_ext TYPE zpp_s_aufkx类将增强字段写入现有增强约定使用的内存区域EXPORT a is_aufk_ext b is_aufkx_ext q iv_quantity TO DATABASE indx(zp) ID lv_id. EXPORT a is_aufk_ext TO MEMORY ID ZAUFK.订单保存结束后必须清理DELETE FROM DATABASE indx(zp) ID lv_id. FREE MEMORY ID ZAUFK. FREE MEMORY ID ZAUFKX.这样调用方只负责填充结构不再关心增强在哪个保存节点读取。需要特别注意当前数据库内存键包含用户名。如果同一 SAP 用户并发执行多笔转换存在互相覆盖的可能因此批量并发前应重新设计更细粒度的键。八、为什么设置 no-dialog 后仍然会弹“物料不可用”最开始我们在标准转换前调用CALL FUNCTION DIALOG_SET_NO_DIALOG.它能抑制遵循 SAP 通用 Dialog 状态的窗口但测试时仍然出现了“物料不可用是否继续转换”的确认框。继续追踪标准源码后发现该窗口来自CO_UP_CONVERT_CHECK_AVAIL这个函数没有读取通用 no-dialog 状态而是直接判断IF sy-binpt IS INITIAL. CALL FUNCTION POPUP_WITH_3_BUTTONS_TO_CHOOSE. ELSE. antwort 1. ENDIF.因此类只在调用转换内核的极小范围内暂时设置lv_binpt_before sy-binpt. sy-binpt abap_true. CALL FUNCTION CO_SD_PLANNED_ORDER_CONVERT. sy-binpt lv_binpt_before.异常路径同样恢复原值。这使标准逻辑对以下确认自动采用“继续”物料不可用产能不可用生产资源/工具不可用。但如果后台配置明确规定“不允许转换”标准仍然发出 E 类错误并终止。也就是说我们绕过的是确认不是业务禁止规则。修改SY-BINPT属于依赖标准实现细节的技术手段应严格限制作用范围并纳入升级回归测试。九、计划订单日期为什么需要兜底更新原程序已经遇到过一个实际问题调用BAPI_PLANNEDORDER_CHANGE返回成功但受到 MRP 日期逻辑影响数据库中的计划订单日期有时没有变成期望值。因此类在提交后重新读取PLAFSELECT SINGLE plnum gsmng psttr pedtr FROM plaf INTO CORRESPONDING FIELDS OF ls_plaf_after WHERE plnum iv_plnum.如果数量正确但日期没有生效则执行受控兜底UPDATE plaf SET psttr iv_start_date pedtr iv_finish_date WHERE plnum iv_plnum.直接更新标准表不是首选方案因此只有在标准更新已经执行、提交后重新验证仍不一致时才使用并返回警告信息。十、生产订单日期如何替代 CO02 BDC原逻辑创建订单后会调用另一个程序中的子例程PERFORM frm_co02 IN PROGRAM zppu001 USING lv_aufnr pv_pedtr pv_psttr IF FOUND.进一步分析发现FRM_CO02本质仍是 CO02 BDC给屏幕写入CAUFVD-GSTRP 开始日期 CAUFVD-GLTRP 结束日期 CAUFVD-TERKZ 3当前类新增了LOCK_ORDER_DATES直接在订单首次保存前完成同样的业务意图METHOD lock_order_dates. CALL FUNCTION CO_BT_CAUFV_READ_WITH_KEY EXPORTING aufnr_act iv_aufnr IMPORTING caufvd_exp ls_caufvd. ls_caufvd-gstrp iv_start_date. ls_caufvd-gltrp iv_finish_date. ls_caufvd-terkz 3. CALL FUNCTION CO_BT_CAUFV_PUT EXPORTING caufvd_imp ls_caufvd index ls_caufvd-indbt. ENDMETHOD.随后保存时明确禁止再次排程CALL FUNCTION CO_ZV_ORDER_POST EXPORTING no_dialog abap_true no_gui_message abap_true flg_no_scheduling iv_lock_dates.标准源码确认FLG_NO_SCHEDULING会传入保存阶段的CHECK_SCHEDULING。因此写回订单头缓冲的日期不会在最终保存时再次被标准排程覆盖。这比 CO02 BDC 有几个明显优势不依赖屏幕号和 OKCODE不需要等待订单第一次提交不需要第二次进入 CO02创建和日期锁定处于同一个保存链路不依赖跨程序FORM错误可以直接通过类返回。需要注意这种方式锁定的是订单头基本日期。由于禁止再次排程工序、能力需求和组件需求日期可能仍保留转换期间生成的结果。如果业务要求所有底层日期整体移动则应该执行标准重新排程而不是使用TERKZ 3。十一、Demo 程序测试程序提供以下输入计划订单号转换数量开始日期结束日期可选生产订单类型必填增强字段AUFK-ZQTPMC是否锁定生产订单日期。核心调用示例DATA: lo_converter TYPE REF TO zcl_pp_plord_conv_co48, lv_aufnr TYPE aufk-aufnr, lv_remaining TYPE plaf-gsmng, lv_auart TYPE aufk-auart, lt_return TYPE zcl_pp_plord_conv_co48tt_return, ls_aufk_ext TYPE zpp_s_aufk, ls_aufkx_ext TYPE zpp_s_aufkx. ls_aufk_ext-zqtpmc zqtpmc. CREATE OBJECT lo_converter. lo_converter-convert_partial( EXPORTING iv_plnum p_plnum iv_quantity p_qty iv_start_date p_begda iv_finish_date p_endda iv_auart p_auart is_aufk_ext ls_aufk_ext is_aufkx_ext ls_aufkx_ext iv_lock_dates p_lockd IMPORTING ev_aufnr lv_aufnr ev_remaining_qty lv_remaining ev_auart lv_auart et_return lt_return ).十二、推荐测试清单不要只验证“是否生成了订单”至少应覆盖以下场景。1. 正常部分转换输入数量小于当前PLAF-GSMNG成功产生生产订单原计划订单仍存在剩余数量正确新订单AFPO-PSMNG正确。2. 同一计划订单重复部分转换连续转换两次或多次每次产生不同生产订单每次都基于最新剩余数量最后一次转换后计划订单被删除。3. 增强字段检查AUFK-ZQTPMC检查其他ZPP_S_AUFK/ZPP_S_AUFKX字段验证失败或回滚后内存是否清理。4. 日期锁定输入与原计划订单差异较大的日期检查AFKO-GSTRP检查AFKO-GLTRP检查AFKO-TERKZ检查 CO03 工序日期和能力需求日期是否符合业务预期。5. 不可用性确认制造物料短缺场景验证不出现确认弹窗验证订单仍保留缺料状态配置明确禁止转换时确认仍返回错误。6. 异常与并发数量大于剩余数量计划订单已被其他用户锁定生产版本或订单类型缺失同一计划订单并发转换更新任务失败时检查 SM13/ST22。十三、这类方案的风险边界本方案使用了多个 SAP 未发布的内部函数例如CO_SD_PLANNED_ORDER_CONVERT CO_BT_CAUFV_READ_WITH_KEY CO_BT_CAUFV_PUT CO_BI_AFPO_UPD CO_ZV_ORDER_POST它们不是稳定的公共 APISAP 不保证跨版本兼容。因此必须接受以下事实SAP 升级或 Support Package 后需要回归测试不同 ECC/S/4HANA 版本的函数参数和内部逻辑可能不同不能只复制网络示例必须读取目标系统的真实源码和签名应保留完整错误日志和结果验证应限制类的业务范围不要把内部函数包装成无限通用的“万能订单接口”。不过与依赖屏幕的 BDC 相比这种方案至少直接复用了标准业务内核减少了对 UI 的耦合也更容易进行自动化检查和问题定位。十四、可复用的方法论用 AI 重构系统中的 BDC有了这次经验系统里其他 BDC 程序都值得重新评估。可以采用下面的步骤找出 BDC 对应的标准事务和业务目标读取事务主程序、函数组和保存逻辑找到屏幕背后的业务函数或类区分公共 API、内部 API、内存缓冲和更新任务记录所有隐式上下文如 ABAP Memory、SPA/GPA 参数和全局标志明确 COMMIT/ROLLBACK 的责任边界将最小必要的标准链路封装为业务类对照原事务进行数据结果验证建立升级后的回归测试清单最后再考虑替换原生产程序。并不是所有 BDC 都能安全地改成内部函数调用。如果找不到稳定的业务入口或者标准逻辑严重依赖 Dynpro 状态保留 BDC 可能仍然是现实选择。AI 可以显著降低标准代码阅读和调用链追踪成本但最终判断仍要依赖当前系统源码实际业务配置可重复测试结果对事务一致性的验证。结语这次改造最大的收获并不是找到了一个“神秘函数”替代 CO48而是形成了一套更可靠的解决问题方式先让 AI 帮助理解 SAP 标准事务真正做了什么再决定如何封装不要让 AI 根据函数名字猜业务更不要把一个 BDC 简单替换成另一个不完整的 BAPI。最终得到的不是一段孤立代码而是一个相对清晰的业务边界外部程序只负责提供计划订单、数量、日期和增强字段类负责标准转换、内存保存、提交、异常处理和结果验证原业务程序可以在测试充分后逐步替换未来 SAP 升级时也有明确的回归测试入口。系统里那些“多年不敢动”的 BDC也许正适合用同样的方法重新审视。自开发标准类 zcl_pp_plord_conv_co48 部分转单演示增强字段
返回列表