关于改造维护工单BAPI_ALM_ORDER_MAINTAIN用于生产订单组件批量修改

本文主要是介绍关于改造维护工单BAPI_ALM_ORDER_MAINTAIN用于生产订单组件批量修改,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、研究背景

1.1、业务背景

 由于销售、研发、工艺等需要频繁变更,导致工单中组件需要频繁的进行变更,修改组件的物料,数量,库存地点,工序等内容。

1.2、技术痛点

为了满足要求,使用了函数:CO_XT_COMPONENT_ADD和CO_XT_COMPONENT_CHANGE用于组件的新增和修改,使用CO_XT_COMPONENTS_DELETE用于组件的批量删除。

痛点1:新增和修改函数,每次只能更改一行组件,而且无法按照订单维度,批量修改组件,只能按照组件维度,多次调用函数,每一次都需要提交保存一遍工单,效率很慢。

痛点2:项目中在工单修改保存时,调用了同步接口推送工单到MES,且MES必须返回成功结果,工单修改才允许保存。受接口+网络影响,工单保存效率很慢。

痛点3:受制于同步接口等原因,导致工单保存时耗时较长,且一直保持着对工单的锁定状态。而批导程序紧接着处理第二行同一工单的组件数据,就会导致出现工单锁表报错。

2、改造BAPI

2.1、BAPI现状

维护订单的BAPI:BAPI_ALM_ORDER_MAINTAIN,拥有丰富的工单修改字段,然而对于生产订单限制修改,只允许修改维护订单。

另外,经过测试,还有反冲强制取物料主数据内容导致不能指定;组件分配报错问题;组件分配BOM行号重新被指定问题等,需要逐一进行修改。

2.1.1、反冲被默认

在原逻辑中,有赋默认值的函数,里面根据物料主数据对传入的反冲标识做了更改

 调用子例程

 在以下代码处修改了传入的反冲标识

2.1.2、组件分配

在工单中,工序可以通过主数据带入工艺路线,也可以直接在工单前台手工创建。

问题在于,当在CO02手工创建时,与CA01创建的工序不一样,缺少了部分字段值,最主要的序列字段为空

导致组件分配给30工序后,前台查看组件出现报错,或组件全部丢失,最终判定都是因为序列PLNFL字段为空导致

2.1.3、BOM行项目

标准程序中,会根据要分配的工序,查找已经存在分配给该工序的组件,获取这些组件的最大BOM号,+10获得最新BOM号。

如果当前分配的工序,没有存在已经分配给该工序的组件,则直接+10得到最新BOM号0010。

例如:将0030行分配给20工序,而现有的两个工序都是10,没有20工序的组件,则BOM号0030行分配完之后,BOM号将变为0010

2.1.4、工单类型限制

 该BAPI只能修改维护订单,不能修改其他类型工单

2.2、增强改造(未采用)

第一次改造,使用了代码修改器,修改原有逻辑,如下所示:

跳过反冲默认

跳过订单类型限制

但是最终感觉太多的地方要修改,并且从未来持续优化功能的角度出发,写大量的代码片段不是一件好事情,且四代增强也要花很多时间调试,因此打算放弃改源码,而直接做代码拷贝。参考2.3自定义BAPI

2.3、自定义BAPI

 根据多次的源码调试,找到程序运行相关的函数、包含文件等,依次进行代码的复制,过程不做过多说明,结果如下:

1、需要复制的函数组及函数,将IBAPI_ALM_ORDER复制为ZBAPI_ALM_ORDER,其余同理

2、ZBAPI_C_DEFAULT_VALUES_01 修改反冲标识

3、LZBAPI_ALM_ORDER_PROCESSINGF10

在AFVC表中,序列PLNFL为空,但是序列APLFL有值,可以使用

在程序中为PLNFL赋值,解决组件分配报错

4、LZBAPI_CF03

注释掉BOM号递增逻辑

5、ZBAPI_H_ORDER_READ

去掉对生产订单的限制

另外在标准逻辑调用过程中上下文需要做修改的程序可以参考3、修改路径图。

3、修改路径图

4、参考源码

调用BAPI代码示例:

"--------------------@斌将军--------------------
LOOP AT lt_alv INTO DATA(ls_alv) GROUP BY ls_alv-aufnr.REFRESH:lt_methods[],lt_component[],lt_componentup[],lt_return[].CLEAR:lv_rspos.CLEAR:ls_methods.ls_methods-refnumber  = 1.ls_methods-method = 'SAVE'.ls_methods-objectkey = ls_alv-aufnr.APPEND ls_methods TO lt_methods.LOOP AT GROUP ls_alv ASSIGNING FIELD-SYMBOL(<fs_alv>).READ TABLE gt_resb INTO gs_resb WITH KEY aufnr = <fs_alv>-aufnrrspos = <fs_alv>-rspos BINARY SEARCH.IF sy-subrc EQ 0."修改逻辑IF gs_resb-xloek = 'X'.<fs_alv>-icon = icon_led_red.<fs_alv>-log = <fs_alv>-log && '项目已删除,不允许修改'.MODIFY gt_alv FROM <fs_alv>.CONTINUE.ENDIF.IF gs_resb-enmng > abs( gs_alv-bdmng ).<fs_alv>-icon = icon_led_red.<fs_alv>-log = <fs_alv>-log && '修改的数量小于已提货数,不允许修改'.MODIFY gt_alv FROM <fs_alv>.CONTINUE.ELSE.lv_rspos = lv_rspos + 1.CLEAR:ls_component.
*          ls_component-item_number = gs_alv-posnr.    "BOMls_component-reserv_no = gs_resb-rsnum.    "预留号ls_component-res_item = gs_resb-rspos.    "预留项目ls_component-material = <fs_alv>-idnrk.    "物料编码ls_component-requirement_quantity = <fs_alv>-bdmng."数量
*          ls_component-plant = gs_alv-werks.IF <fs_alv>-lgort IS NOT INITIAL.ls_component-stge_loc = <fs_alv>-lgort."存储地点ENDIF.ls_component-batch = <fs_alv>-charg."批次号ls_component-req_date = <fs_alv>-bdter."组件的需求日期IF <fs_alv>-rgekz IS NOT INITIAL.ls_component-backflush = 'X'."反冲标识ELSE.ls_component-backflush = ''."反冲标识ENDIF.ls_component-special_stock = <fs_alv>-sobkz."特殊库存ls_component-activity = gs_resb-vornr."操作/活动编号APPEND ls_component TO lt_component.CLEAR:ls_componentup.
*          ls_componentup-item_number = 'X'.                  "BOMls_componentup-material = 'X'.                  "物料编码ls_componentup-requirement_quantity = 'X'."数量
*          ls_componentup-plant = 'X'.IF <fs_alv>-lgort IS NOT INITIAL.ls_componentup-stge_loc = 'X'."存储地点ENDIF.ls_componentup-batch = 'X'."批次号ls_componentup-req_date = 'X'."组件的需求日期ls_componentup-backflush = 'X'."反冲标识ls_componentup-special_stock = 'X'."特殊库存APPEND ls_componentup TO lt_componentup.CLEAR:ls_methods.ls_methods-refnumber = lv_rspos.                "参照组件编号ls_methods-objecttype = 'COMPONENT'.    "组件ls_methods-method = 'CHANGE'.                "修改ls_methods-objectkey = <fs_alv>-aufnr.          "订单号ls_methods-objectkey+12(4) = gs_resb-rspos.          "预留行APPEND ls_methods TO lt_methods."组件分配IF <fs_alv>-vornr IS NOT INITIAL.lv_rspos = lv_rspos + 1.CLEAR:ls_component.ls_component-reserv_no = gs_resb-rsnum.    "预留号ls_component-res_item = gs_resb-rspos.    "预留项目ls_component-activity = <fs_alv>-vornr."新分配的工序APPEND ls_component TO lt_component.CLEAR:ls_componentup.ls_componentup-activity = 'X'.APPEND ls_componentup TO lt_componentup.CLEAR:ls_methods.ls_methods-refnumber = lv_rspos.                "参照组件编号ls_methods-objecttype = 'COMPONENT'. "组件ls_methods-method = 'REASSIGN'. "重新分配ls_methods-objectkey = <fs_alv>-aufnr.          "订单号ls_methods-objectkey+12(4) = gs_resb-rspos.          "预留行APPEND ls_methods TO lt_methods.ENDIF.ENDIF.ELSE."新增逻辑lv_rspos = lv_rspos + 1.CLEAR:ls_component.ls_component-item_number = <fs_alv>-posnr.    "BOMls_component-material = <fs_alv>-idnrk.    "物料编码ls_component-requirement_quantity = <fs_alv>-bdmng."数量ls_component-plant = <fs_alv>-werks."工厂ls_component-stge_loc = <fs_alv>-lgort."存储地点ls_component-batch = <fs_alv>-charg."批次ls_component-req_date = <fs_alv>-bdter."组件的需求日期IF <fs_alv>-rgekz IS NOT INITIAL.ls_component-backflush = 'X'."反冲标识ELSE.ls_component-backflush = ''."反冲标识ENDIF.ls_component-special_stock = <fs_alv>-sobkz."特殊库存ls_component-activity = <fs_alv>-vornr."工序ls_component-item_cat = 'L'."项目类别APPEND ls_component TO lt_component.CLEAR:ls_componentup.ls_componentup-item_number = 'X'.                  "BOMls_componentup-material = 'X'.                  "物料编码ls_componentup-requirement_quantity = 'X'."数量ls_componentup-plant = 'X'."工厂ls_componentup-stge_loc = 'X'."存储地点ls_componentup-batch = 'X'."批次ls_componentup-req_date = 'X'."组件的需求日期ls_componentup-backflush = 'X'."反冲标识ls_componentup-special_stock = 'X'."特殊库存ls_componentup-activity = 'X'."工序ls_componentup-item_cat = 'X'."项目类别APPEND ls_componentup TO lt_componentup.CLEAR:ls_methods.ls_methods-refnumber = lv_rspos.                "参照组件编号ls_methods-objecttype = 'COMPONENT'.      "组件ls_methods-method = 'CREATE'.       "创建ls_methods-objectkey = <fs_alv>-aufnr.          "订单号APPEND ls_methods TO lt_methods.ENDIF.ENDLOOP.READ TABLE gt_afko INTO DATA(ls_afko) WITH KEY aufnr = ls_alv-aufnr BINARY SEARCH.IF sy-subrc EQ 0.CALL FUNCTION 'T350_READ'EXPORTINGauart         = ls_afko-auartEXCEPTIONSno_t350_entry = 1OTHERS        = 2.* override buffered table T350ASSIGN ('(SAPLINST)T350') TO <t350>.IF sy-subrc = 0.<t350>-auart = ls_afko-auart.ENDIF.ENDIF."调用ZBAPICALL FUNCTION 'ZBAPI_ALM_ORDER_MAINTAIN'TABLESit_methods      = lt_methodsit_component    = lt_component[]it_component_up = lt_componentup[]return          = lt_return.CLEAR:lv_check,lv_message.LOOP AT lt_return INTO ls_return WHERE type CA 'AEX'.lv_check = 'E'.lv_message = lv_message && ls_return-message.CLEAR:ls_return.ENDLOOP.IF lv_check = 'E'.CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.ls_alv-icon = icon_led_red.ls_alv-log = lv_message.ELSE.CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'EXPORTINGwait = 'X'.ls_alv-icon = icon_led_green.ls_alv-log = '添加成功'.ENDIF.MODIFY gt_alv FROM ls_alv TRANSPORTING icon log WHERE aufnr = ls_alv-aufnrAND xloek = ''AND item = 'X'AND icon <> icon_led_red.CLEAR:ls_alv.ENDLOOP.
"--------------------@斌将军--------------------   

5、补充说明

5.1、并行工序组件分配研究

对读者提出的该BAPI改造后是否能进行并行工序组件分配进行了研究。

在组件分配过程中,程序调用了函数CO_BT_READ_MASTER_SEQUENCE,通过工单编号,查询对应的序列信息

但是函数中通过常量限制了序列为0,即只查找标准顺序,不查找并行顺序

导致获取的序列值为000000,

导致查询AFVC数据时,获取到标准顺序0的工序,而不是并行顺序1的工序

综上所述,认为直接使用该函数无法进行并行工序的组件分配。

但是源代码逻辑已经梳理很清晰,想必稍加改造,例如直接抛内存传值,查询对应的并行顺序的工序,应该就可以解决问题。

读者有兴趣可自行研究一下。

定期更文,欢迎关注

这篇关于关于改造维护工单BAPI_ALM_ORDER_MAINTAIN用于生产订单组件批量修改的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/412073

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,

如何在运行时修改serialVersionUID

优质博文:IT-BLOG-CN 问题 我正在使用第三方库连接到外部系统,一切运行正常,但突然出现序列化错误 java.io.InvalidClassException: com.essbase.api.base.EssException; local class incompatible: stream classdesc serialVersionUID = 90314637791991

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理,在有一定基础认识的前提下,通过阅读kubelet源码,对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管理(pod生命周期管理) 监听apiserver的容器事件 容器的创建、删除(CRI) 容器的网络的创建与删除

火语言RPA流程组件介绍--浏览网页

🚩【组件功能】:浏览器打开指定网址或本地html文件 配置预览 配置说明 网址URL 支持T或# 默认FLOW输入项 输入需要打开的网址URL 超时时间 支持T或# 打开网页超时时间 执行后后等待时间(ms) 支持T或# 当前组件执行完成后继续等待的时间 UserAgent 支持T或# User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器

android系统源码12 修改默认桌面壁纸--SRO方式

1、aosp12修改默认桌面壁纸 代码路径 :frameworks\base\core\res\res\drawable-nodpi 替换成自己的图片即可,不过需要覆盖所有目录下的图片。 由于是静态修改,则需要make一下,重新编译。 2、方法二Overlay方式 由于上述方法有很大缺点,修改多了之后容易遗忘自己修改哪些文件,为此我们采用另外一种方法,使用Overlay方式。