ARTICLE DETAIL

资讯详情

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

SAP PP生产订单批量修改:BAPI_PRODORD_CHANGE实战指南

SAP PP生产订单批量修改:BAPI_PRODORD_CHANGE实战指南 1. 为什么是 BAPI_PRODORD_CHANGE从手工 CO02 到批量刷新的效率差距1.1 生产订单主数据修改的典型业务场景先说说我遇到的具体场景。去年年中排产调整计划员手里压了五十多张生产订单全部要做三件事订单数量从 800 调整到 1200、基本开始日期整体顺延一周、部分工序的工作中心从 M1020 换到 M1030。如果靠 CO02 一张张打开、找页签、改字段、保存再处理各种弹窗确认平均一张订单五到八分钟五十张就是四五个小时而且人一疲劳就容易改错订单号。更麻烦的是这种需求不是一次性的。每个月排产变动、客户交期变化、BOM 版本切换都会带来成批的生产订单主数据变更。生产订单在 SAP PP 里的定位非常特殊它从物料主数据、工艺路线、BOM 复制数据生成一旦生成后就自成一套执行主数据——抬头数据、工序数据、组件需求数据全都固化在订单里。所以“刷新 PP 主数据”这个说法落到生产订单场景核心就是改三块抬头字段数量、日期、类型、工序字段工作中心、控制码、组件字段物料、数量。BAPI_PRODORD_CHANGE 就是 SAP 专门为这类修改场景提供的标准接口。它支持通过参数传入修改值一次性完成抬头、工序、组件的更新并且内置了订单状态检查、数量单位校验、排程联动等逻辑。对于熟悉 ABAP 的开发或者搞 PP 的顾问来说把这个 BAPI 吃透批量刷主数据这件事就能从几小时的机械体力活压缩到几十秒的报表运行。1.2 BAPI 与 BDC、直接改底表的取舍做 PP 主数据刷新常用的有三条技术路线标准 BAPI、BDC 录屏、直接 UPDATE 底表。我做了个对比表方便后面选型时直接参考技术路线稳定性维护成本风险等级适用场景BAPI_PRODORD_CHANGE高接口有完整返回信息低参数结构稳定低内置校验标准的抬头、工序、组件字段修改BDC 录屏CO02/COHV中依赖屏幕顺序和弹窗高界面一变就要重录中容易录错字段有增强字段、标准 BAPI 覆盖不到的界面操作直接 UPDATE 底表无校验数据一致性靠自觉高需要自己维护所有联动极高不推荐几乎没有除非是数据修复应急我见过不少项目里开发图省事直接 UPDATE AUFK、AFPO、RESB结果修改数量后组件需求不同步、日期改了不排程、工序改了状态怪怪的最后全都要擦屁股。BAPI 背后走的是一整套 CO 模块业务逻辑包含了状态管理、排程更新、可用性检查和必要的历史记录这些是裸 UPDATE 给不了的。另外要提一个很容易混淆的点如果你们用的是流程行业的生产订单PP-PI对应的修改 BAPI 是 BAPI_PROC_ORD_CHANGE参数设计跟 BAPI_PRODORD_CHANGE 很像但面向的订单类别不同字段逻辑也不同。日常写程序时一定要确认订单类别离散制造和流程制造别用串了。2. 调用前必须吃透的参数骨架IN、INX 与 RETURN 的联动关系2.1 核心参数结构解析BAPI_PRODORD_CHANGE 的常用参数不算复杂分成三组定位参数、修改值参数、返回参数。参数类型作用NUMBER导入参数字符串传入生产订单号是 BAPI 定位订单的依据ORDER_HEADER_IN导入参数结构体订单抬头的新值如总数量、基本开始/结束日期ORDER_HEADER_INX导入参数结构体抬头更新标志标记哪些字段真正参与更新ORDER_OPERATION_IN导入参数内表工序的新值如工作中心、控制码ORDER_OPERATION_INX导入参数内表工序更新标志ORDER_COMPONENT_IN导入参数内表组件的新值如物料、数量ORDER_COMPONENT_INX导入参数内表组件更新标志RETURN表参数BAPIRET2 标准返回结构里面是成功、警告、错误消息IN 和 INX 成对出现这是 BAPI 家族非常典型的设计。IN 里放的是“我要改成什么值”INX 里放的是“哪些字段要改”。系统处理时只有 INX 中打了更新标志的字段才会进入后续业务逻辑IN 里传了值但 INX 没打勾基本等于白传。SAP 这样设计是为了让同一个接口既能承载部分更新也能承载全量更新不至于每次都把整张订单的字段都塞进去。不过这类接口因为参数多刚上手的人特别容易在赋值阶段漏字段。我的建议是写之前先 SE11 看一下 bapi_pp_order_header_in、bapi_pp_order_operation_in、bapi_pp_order_component_in 这些结构的字段清单按订单修改需求勾出必填项再动手写代码能省掉后面一大半调试时间。2.2 INX 更新标志BAPI 不生效的第一嫌疑BAPI_PRODORD_CHANGE 的 INX 结构里有个非常关键的字段叫 FLAG这个字段是总开关。按照 SAP 的 BAPI 文档要修改抬头数据时必须先把 INX-FLAG 置为 X 或 U然后再把需要修改的具体字段如 TOTAL_QUANTITY、BASIC_START_DATE也置为 X。否则 BAPI 可能只返回正常消息实际却一行数据都没动这种“静默失败”最让人头疼。写成代码就是下面这样DATA: ls_header_in TYPE bapi_pp_order_header_in, ls_header_inx TYPE bapi_pp_order_header_inx, lt_return TYPE STANDARD TABLE OF bapiret2. DATA(lv_order) 10010658. 生产订单号 先让总开关生效 ls_header_inx-flag X. ls_header_inx-total_quantity X. 再给新值 ls_header_in-total_quantity 1200. CALL FUNCTION BAPI_PRODORD_CHANGE EXPORTING number lv_order order_header_in ls_header_in order_header_inx ls_header_inx TABLES return lt_return.有一次我在测试环境里改订单数量RETURN 全部是 S 类型成功消息但回查 AFKO/or 用 CO03 打开看数量纹丝不动排查了半天才发现是 INX-FLAG 没置位。从那以后我总结了一条铁律只要遇到“BAPI 返回成功但数据没变”第一反应不是查业务逻辑而是先检查 INX 里的更新标志有没有打全十次里有八次都是这个问题。对于工序和组件同样存在 FLAG 字段而且内表中每一行都要设置。比如要改五道工序的工作中心那五行的 INX 都要有 FLAG不能只在其中一行上打标。2.3 RETURN 结果判断与 COMMIT 时机RETURN 是 BAPIRET2 标准表结构字段不多但判断逻辑要严谨。TYPE 字段是最核心的S 表示成功、E 表示错误、W 表示警告、I 表示信息、A 表示异常中止。日常代码里可以这样处理DATA: ls_return LIKE LINE OF lt_return, lv_has_error TYPE abap_bool. LOOP AT lt_return INTO ls_return WHERE type E OR type A. lv_has_error abap_true. WRITE: / 错误:, ls_return-message. ENDLOOP. IF lv_has_error abap_true. CALL FUNCTION BAPI_TRANSACTION_ROLLBACK. ELSE. CALL FUNCTION BAPI_TRANSACTION_COMMIT. ENDIF.W 警告要单独看情况。有些警告只是提示“日期已根据工厂日历自动调整”不影响结果但有些警告背后可能是数量精度四舍五入、单位换算丢失等实质问题。我的习惯是W 先记录到日志里最终再人工复核不会直接当成成功处理。COMMIT 时机这里必须强调BAPI 本身不会自动提交数据库修改必须在业务逻辑全部跑完后显式调用 BAPI_TRANSACTION_COMMIT。如果你忘了调用结束后数据回滚一切白做。反过来如果过程中有错误必须调用 BAPI_TRANSACTION_ROLLBACK否则数据库锁一直捏在当前会话里后面同订单的修改全都卡死。很多“BAPI 没生效”的求助帖最后查到就是没 COMMIT 或者没 ROLLBACK。还有一点很实用不要把 COMMIT 写在被公共调用的封装函数内部最好由最外层调用方统一控制这样批量场景下才能灵活决定提交节奏。3. 动态刷新 PP 主数据的四个实战模板数量、日期、工序、组件3.1 模板一批量调整订单数量生产订单数量是 PP 主数据里被调得最频繁的字段客户改订单量、销售预测变动都会导致排产数量调整。修改本身不复杂但有一个单位问题必须提前搞清楚BAPI 里的 TOTAL_QUANTITY 是订单总数量通常基于基本计量单位不是订单单位。如果基本单位是 KG订单单位是 PC你直接按 PC 数量往上传结果可能差一截。示例代码一次性处理多张订单TYPES: BEGIN OF ty_order_qty, order_number TYPE aufnr, new_qty TYPE menge_d, END OF ty_order_qty. DATA: lt_orders TYPE STANDARD TABLE OF ty_order_qty, ls_header_in TYPE bapi_pp_order_header_in, ls_header_inx TYPE bapi_pp_order_header_inx, lt_return TYPE STANDARD TABLE OF bapiret2, lv_error TYPE abap_bool. lt_orders VALUE #( ( order_number 10010658 new_qty 1200 ) ( order_number 10010659 new_qty 800 ) ( order_number 10010660 new_qty 1500 ) ). LOOP AT lt_orders INTO DATA(ls_order). CLEAR: ls_header_in, ls_header_inx, lt_return, lv_error. ls_header_inx-flag X. ls_header_inx-total_quantity X. ls_header_in-total_quantity ls_order-new_qty. CALL FUNCTION BAPI_PRODORD_CHANGE EXPORTING number ls_order-order_number order_header_in ls_header_in order_header_inx ls_header_inx TABLES return lt_return. LOOP AT lt_return INTO DATA(ls_return) WHERE type E OR type A. lv_error abap_true. WRITE: / 订单, ls_order-order_number, 失败:, ls_return-message. ENDLOOP. IF lv_error abap_true. CALL FUNCTION BAPI_TRANSACTION_ROLLBACK. ELSE. CALL FUNCTION BAPI_TRANSACTION_COMMIT. ENDIF. ENDLOOP.这里我特意用了每张订单单独 COMMIT 的方式而不是攒一批再提交。原因很简单五十张订单里有一张失败我不想让它拖累其余四十九张的成功提交单独提交后失败的订单单独补处理就行。后面第五章我会专门讲大批量下的提交节奏选择。3.2 模板二批量顺延基本日期排产调整日期调整比数量调整要复杂一层因为生产订单之间存在下级订单、物料可用性、产能分配等联动关系BAPI 内部会做排程重算。修改日期常用的字段是基本开始日期 BASIC_START_DATE 和基本结束日期 BASIC_END_DATE这两个字段在 bapi_pp_order_header_in 里都有。如果业务上用的是计划日期则对应 PLANNED_START_DATE 和 PLANNED_END_DATE到底改哪一组要问清楚业务口径。顺延一周的通用写法DATA: ls_header_in TYPE bapi_pp_order_header_in, ls_header_inx TYPE bapi_pp_order_header_inx, lt_return TYPE STANDARD TABLE OF bapiret2. DATA(lv_order) 10010658. DATA(lv_days) 7. 读取订单当前日期 DATA: ls_order_detail TYPE bapi_pp_order_detail. CALL FUNCTION BAPI_PRODORD_GET_DETAIL EXPORTING number lv_order IMPORTING order_detail ls_order_detail TABLES return lt_return. ls_header_inx-flag X. ls_header_inx-basic_start_date X. ls_header_inx-basic_end_date X. ls_header_in-basic_start_date ls_order_detail-basic_start_date lv_days. ls_header_in-basic_end_date ls_order_detail-basic_end_date lv_days. CALL FUNCTION BAPI_PRODORD_CHANGE EXPORTING number lv_order order_header_in ls_header_in order_header_inx ls_header_inx TABLES return lt_return.如果能直接拿到目标日期就不必先 GET_DETAIL按业务规则算好日期传进去即可。需要注意工厂日历和假期日历会影响排程结果。比如你把开始日期填到了休息日BAPI 内部会自动校正到下一个工作日但 RETURN 里大概率只给个 W 警告不会在 E 消息里等你。所以日期批量刷新完建议再调用一次 BAPI_PRODORD_GET_DETAIL 核对实际排程结果否则日期差一天的事后面排产时会很尴尬。3.3 模板三工序维度的动态更新工序数据在生产订单里是最容易和工艺路线脱节的部分。业务上常见的是工作中心调整、控制码调整比如从自动确认改成手工确认、工序标准工时更新。BAPI_PRODORD_CHANGE 里对应的是 ORDER_OPERATION_IN 和 ORDER_OPERATION_INX 两张内表每次要修改的工序以 OPERATION 字段工序号为定位键。举个例子把订单 10010658 的工序 0020 的工作中心从 M1020 改为 M1030DATA: ls_op_in TYPE bapi_pp_order_operation_in, ls_op_inx TYPE bapi_pp_order_operation_inx, lt_op_in TYPE STANDARD TABLE OF bapi_pp_order_operation_in, lt_op_inx TYPE STANDARD TABLE OF bapi_pp_order_operation_inx, lt_return TYPE STANDARD TABLE OF bapiret2. DATA(lv_order) 10010658. ls_op_in-operation 0020. ls_op_in-work_center M1030. APPEND ls_op_in TO lt_op_in. ls_op_inx-operation 0020. ls_op_inx-flag X. ls_op_inx-work_center X. APPEND ls_op_inx TO lt_op_inx. CALL FUNCTION BAPI_PRODORD_CHANGE EXPORTING number lv_order TABLES order_operation_in lt_op_in order_operation_inx lt_op_inx return lt_return.这里有个细节ORDER_OPERATION_INX 里的 OPERATION 不是更新标志而是定位键用来告诉 BAPI 到底要更新哪一道工序。所以即使你只想改工作中心OPERATION 这一格也得填写否则后面全乱套。另外工序是否有过确认记录会直接影响可修改性。如果工序已经做了部分确认、报工甚至入库再改工作中心或控制码系统大概率会报错或者只允许改特定字段。遇到这种情况先把工序相关的确认数据理清再决定是改订单还是走红冲返工流程。3.4 模板四组件BOM 展开结果的增减生产订单的组件数据是从 BOM 展开复制的里面可以增加非 BOM 物料也可以调整已有组件的数量。BAPI 里对应 ORDER_COMPONENT_IN 和 ORDER_COMPONENT_INX组件行的定位键是 ITEMBOM 项目号。比如把组件项目 0010 的物料数量从 20 调整到 30DATA: ls_comp_in TYPE bapi_pp_order_component_in, ls_comp_inx TYPE bapi_pp_order_component_inx, lt_comp_in TYPE STANDARD TABLE OF bapi_pp_order_component_in, lt_comp_inx TYPE STANDARD TABLE OF bapi_pp_order_component_inx, lt_return TYPE STANDARD TABLE OF bapiret2. DATA(lv_order) 10010658. ls_comp_in-item 0010. ls_comp_in-material M-1001. ls_comp_in-quantity 30. APPEND ls_comp_in TO lt_comp_in. ls_comp_inx-item 0010. ls_comp_inx-flag X. ls_comp_inx-quantity X. APPEND ls_comp_inx TO lt_comp_inx. CALL FUNCTION BAPI_PRODORD_CHANGE EXPORTING number lv_order TABLES order_component_in lt_comp_in order_component_inx lt_comp_inx return lt_return.组件更新最容易踩的坑是物料主数据的可用性检查。你把数量往上调系统会立刻做 ATP 检查库存不够直接 E 错误。这在某些场景下是好事能防止超卖欠料但在批量刷新时也意味着大量订单会因缺料中断。所以组件批量更新前建议先跑一次物料可用性检查把库存不足的物料提前筛出来再决定是改数量还是改供货计划。另外注意ORDER_COMPONENT_IN 里如果只传 ITEM、MATERIAL、QUANTITY其他字段不会动如果你把 MATERIAL 也当成新值传了相当于把组件物料整个换掉逻辑完全不一样容易引发 BOM 一致性问题操作前一定要想清楚业务含义。4. 实测高频踩坑与完整排查链路4.1 改完数量后组件数量没联动这个问题我在多个项目里被问到过。业务人员的预期是生产订单数量从 800 改成 1200组件需求应该自动跟着放大但 BAPI_PRODORD_CHANGE 默认并不会做这件事。组件的需求数量来自 BOM 展开时按订单数量换算的结果修改订单数量后是否需要重新展开 BOM、以什么规则展开是由订单类型里的 BOM 展开参数控制的不是必然行为。我在代码里处理时通常会先 BAPI_PRODORD_GET_DETAIL 读出订单当前 BOM 组件明细和比例关系再按新订单数量计算每个组件的新需求数量最后通过 ORDER_COMPONENT_IN 批量传回去。计算时务必注意数量精度和舍入方式SAP 的组件数量换算可能涉及分母分子BOM 数量关系直接乘除很容易出现小数点后一堆数字。这时候可以用 SAP 标准的舍入逻辑或者跟业务确认后按物料主数据的舍入参数来做。4.2 状态问题订单已技术性关闭BAPI 静默不更新生产订单状态对可修改性影响极大。常见状态包括CRTD 已创建、REL 已释放、PCNF 部分确认、PDLV 部分交货、TECO 技术性完成、DLFL 删除标记。BAPI_PRODORD_CHANGE 内部会检查订单状态很多情况下RL 状态的订单允许改数量和日期但 TECO 状态的订单基本锁死。踩过最坑的一次计划员在系统里把几十张订单误操作成 TECO然后让我们跑批量刷新。BAPI 返回一部分 S、一部分 EE 的消息写得很泛翻订单状态才发现全是 TECO。此时有两个处理方向如果订单没有实际完成需要先让计划员做“取消技术性完成”的操作解除 TECO 后再跑 BAPI如果已经发生大量报工和收货那就不是刷新主数据的问题而是要走订单重开或返工的流程了。建议在批量刷新代码里增加一道状态预检读取订单系统状态提前把 TECO、DLFL 的订单拎出来直接跳过并输出告警日志而不是等 BAPI 一个个报错。4.3 锁冲突与并发修改BAPI_PRODORD_CHANGE 在处理订单时是带锁的锁类型通常是排他锁锁对象可以从 SM12 里看到。批量场景下最容易出事的是循环内重复处理同一张订单或者外部系统同时通过其他渠道改同一张订单。前者是程序逻辑问题后者是并发设计问题。我在实际项目里遇到过这样的事一个后台程序循环调用 BAPI不小心把订单号列表里的重复项没过滤掉结果 BAPI 拿到锁之后自己又去碰同一个订单直接死锁整个 JOB 挂住。排查了半天才发现是因为内表里有重复订单号。后来的处理很简单循环前用 SORT DELETE ADJACENT DUPLICATES 去重同时在循环内记录锁处理状态遇到锁冲突的订单使用 ROLLBACK 释放锁并记录下来不至于一个订单卡死整批任务。如果一定要做并发安全可以用函数 ENQUEUE_ENQUEUE 自己先在订单层加业务锁处理完再 DEQUEUE但通常生产场景单点和队列控制已经够用不必过度设计。4.4 完整排查链路从 RETURN 到 SQL 追踪我把排查 BAPI_PRODORD_CHANGE 不生效或报错的步骤整理成了一条固定链路团队里新人照着走基本都能自己解决问题先看 RETURN 表里有没有 E 或 A 类型消息。有错误就先解决错误消息不要看别的。如果 RETURN 全绿但数据没变检查 INX 更新标志是否齐全FLAG 是否置位。这一步能解决大半“静默失败”。用 BAPI_PRODORD_GET_DETAIL 回读订单当前值跟目标值对比确认是不是被其他逻辑覆盖了。检查订单系统状态和用户状态TECO、DLFL、锁标记都可能挡住修改。如果以上都正常但仍异常在 SE37 里用调试模式单步执行 BAPI看内部 Function Module 在哪一步报错重点看它抛出的异常类消息。还定位不了就用 ST05 开启 SQL 追踪确认 BAPI 执行后到底更新了哪些表、更新值是否符合预期。这套链路看起来简单但遇到真正诡异的问题时能帮你快速收敛。尤其是第 5 步很多顾问一遇到 BAPI 问题就抓瞎其实 SE37 调试是最好用的武器。5. 稳定性优化与扩展思路批量提交、自定义字段与混合调用5.1 大批量场景的 COMMIT 节奏与内存控制大批量刷新时COMMIT 的节奏决定了任务的成败和时长。每张订单单独 COMMIT优点是单点失败不影响其他订单缺点是频繁提交会有性能损耗攒一批再 COMMIT性能更好但其中一张失败会导致一批回滚复杂度和风险都上去了。我的经验是分档处理一百张以内、订单之间有独立性的用每张订单单独 COMMIT逻辑简单出问题好定位上千张的场景按五十到一百张一组提交失败的一组单独重跑同时把每张订单的入参快照保存到自定义日志表方便追溯。这个方案在几个项目里跑得都很稳。BAPI 内部要做不少业务校验实际耗时比想象中大。有些复杂订单单次调用可能接近一秒五千张订单跑完就是五千秒别指望在线同步跑应该做成后台 JOB 分批执行同时用 SPOOL 或者自定义日志表记录每批的执行结果。否则用户在前台等半个小时体验非常差。5.2 自定义增强字段的更新思路标准 BAPI 的参数结构是固定的遇到生产订单上有自定义字段比如订单抬头增加了一个“项目批次号”BAPI_PRODORD_CHANGE 就不够用了。这时候有三种常见补救方案。第一种是增强 BAPI。通过 MOD 或 BADI 在 BAPI 的 Update 逻辑里把自定义字段的写库逻辑接进去技术门槛高而且升级有风险不是所有项目都愿意做。第二种是 BAPI 扩展表更新。先用 BAPI_PRODORD_CHANGE 完成标准字段更新再调用自定义 Function Module 或者直接对扩展表做维护。这个方案工作量小但要注意自定义字段有没有参与状态检查、有没有被其他逻辑引用如果只是“存着给人看”的字段问题不大如果参与可用性计算就必须慎重。第三种是用 BDC 录 CO02 整屏操作。自定义字段如果在屏幕上存在用 BDC 反而能一步到位。BDC 的问题是屏幕顺序和弹窗变化频繁维护成本高但对于少数带增强字段的界面场景这是最实用的兜底方案。我个人倾向第二种前提是和业务确认清楚自定义字段的用途。只做信息记录就简单处理如果字段参与排程、计算或下游接口传输务必先把联动逻辑理清否则修改不一致很容易在 MRP 结果里留下隐患。5.3 组合调用创建、修改、释放一条龙BAPI_PRODORD_CHANGE 在实际项目中很少单独独舞经常要和它的兄弟们组合使用。最典型的组合是BAPI_PRODORD_CREATE 创建订单BAPI_PRODORD_CHANGE 做批量调整最后 BAPI_PRODORD_RELEASE 释放订单。比如排产员在 MRP 跑完后生成一批计划订单转成生产订单后需要批量修改数量和日期再统一释放下发车间这个流程用 BAPI 组合做非常顺。组合调用时有一个很重要的顺序问题先 RELEASE 再 CHANGE还是先 CHANGE 再 RELEASE大多数业务场景下先修改再释放更合理——释放后订单进入执行状态部分字段会被锁定能改的空间变小。有些项目里有特殊要求需要订单释放后再改少量字段那就必须和相关模块确认清楚哪些字段放开修改。组合调用的代码结构大致是这样DATA: lt_return TYPE STANDARD TABLE OF bapiret2, lv_order TYPE aufnr. 1. 创建生产订单 CALL FUNCTION BAPI_PRODORD_CREATE EXPORTING order_header_in ls_header_in_main IMPORTING number lv_order TABLES return lt_return. CHECK lv_order IS NOT INITIAL. 2. 修改抬头数量 CALL FUNCTION BAPI_PRODORD_CHANGE EXPORTING number lv_order order_header_in ls_header_in order_header_inx ls_header_inx TABLES return lt_return. 3. 释放生产订单 CALL FUNCTION BAPI_PRODORD_RELEASE EXPORTING order_number lv_order IMPORTING return ls_return_release. 4. 统一提交 CALL FUNCTION BAPI_TRANSACTION_COMMIT.这类组合调用还有一个隐藏价值它把人工在 CO01/CO02/CO02 释放按钮上的点击操作变成了结构化、可追溯的程序逻辑排产调整的整个操作轨迹都留在了日志里出了问题翻代码和日志就能还原现场比让人凭记忆解释“我当时点了什么”靠谱得多。就我自己的经验来说把 BAPI_PRODORD_CHANGE 吃透的最大收益并不是省那几小时点击操作而是让 PP 主数据的批量刷新从“靠人肉保证准确”变成“靠逻辑保证一致”。每次跑完批量刷新把成功、失败、警告三类清单输出成报表再核对几笔关键数据基本就能放心交给业务。最后再分享一个小习惯批量程序里最好保留一份入参快照表记录日期时间、操作人、订单号、修改前值和修改后值这能让事后审计和问题追溯省一大半力气。
返回列表