ARTICLE DETAIL

资讯详情

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

基于MB_MIGO_BADI的SAP MIGO屏幕增强实现与调试指南

基于MB_MIGO_BADI的SAP MIGO屏幕增强实现与调试指南 1. 从需求说起为什么MIGO要做屏幕增强做SAP MM的顾问和开发迟早会碰到这么一类需求用户在MIGO做收货、发货、转储的时候光靠标准字段根本不够用非要额外录入一些自定义信息比如质检报告号、供应商批次、自定义的入库备注、甚至几个业务上自己定义的附加字段。标准界面又不让随便改最干净的做法就是做屏幕增强。MIGO这个事务码在SAP系统里是一个典型的复合事务它把收货、发货、退货、转储这些货物移动场景全部收在一个界面里。早期版本里分别叫MB1A、MB1B、MB1C这些事务码后来统一到MIGO里。正因为界面统一、逻辑复杂它不像VA01、ME23N那样有相对固定的屏幕结构随便找个隐式增强点就能挂字段。MIGO的增强需要通过专门的BADI来实现也就是题目标题里提到的MB_MIGO_BADI用SE19事务码创建增强实现。我最早碰到这个需求的时候也在网上翻过很多资料但大部分都比较零散。有的帖子讲了BADI接口里的方法但没讲怎么把子屏幕挂上去有的贴了代码但没讲为什么那样子写遇到报错也不知道怎么查。这篇就把我从创建增强实现、写子屏幕、挂载、到调试和传输的完整过程捋一遍尽量把每一步背后的原因也讲清楚。这篇内容主要面向有一定ABAP基础、打算在MIGO上做自定义字段的开发和顾问。如果你只是做配置或者业务运维看个大概思路就好如果你要真的落地代码建议把SE19和BADI的用法先熟悉一下然后照着后面的步骤做。2. SE19创建增强实现的关键步骤2.1 事务代码准备屏幕增强的入口是SE19这个事务码专门用来创建BADI的增强实现跟SE18查看/维护BADI定义是一对。SE19创建出来的东西本质上是给某个BADI写一个具体的实现类系统会在运行到增强点时调用这个类里的方法。进入SE19之后界面会让你填增强点名称和增强实现名称。这里有一个非常容易搞错的点增强点名称填的是BADI定义名也就是MB_MIGO_BADI但如果你只是想在行项目级别做校验或赋值实际上填MB_MIGO_ITEM_BADI更合适。这两个名字看着像但作用范围不一样增强点名称作用范围常用场景MB_MIGO_BADI抬头级、行项目级都会经过包含抬头和方法较多需要控制抬头字段、或需要同时处理抬头和行项目MB_MIGO_ITEM_BADI专门针对行项目处理的BADI只需要对行项目附加字段、校验、赋值大部分在MIGO行项目里加几个自定义字段的需求用MB_MIGO_ITEM_BADI就够了。不过标题里明确提到了MB_MIGO_BADI这两个在实际创建时路径几乎一样方法名也高度重合区别主要在接口里方法的触发时机。为了稳妥起见如果你不确定就先用MB_MIGO_BADI然后挂载子屏幕处理逻辑时用GOITEM参数来访问行项目数据。2.2 指定增强点和实现类SE19界面上输入增强点MB_MIGO_BADI然后点创建系统会弹出来让你确认实现类名称。这个类名可以自己命名一般建议用ZCL_IM_MB_MIGO_BADI这种格式一看就知道是MIGO增强用的。如果系统报错说增强点不存在多半是当前客户端没有激活相关业务组件或者你输错了名字。创建完之后SE19的界面上会有几个页签常见的有接口属性屏幕增强等。如果是MB_MIGO_BADI你会在接口页签看到IF_EX_MB_MIGO_BADI里面包含的方法比较多常用的有LINE_DELETE删除行项目时调用适合做删除前的检查。LINE_MODIFY行项目内容发生变化时调用数量、批次、库位变化等。POST_DOCUMENT凭证过账完成之后调用适合写日志或者触发后续逻辑。PBO_UPDATEPBO阶段调用适合设置界面显示状态、刷新自定义字段值。PBO_DETAIL进入明细页签时调用逻辑跟PBO_UPDATE类似。PAI_UPDATEPAI阶段调用适合在用户输入之后读取自定义字段值并做处理。HEADER_CHECK检查抬头数据一般做校验用。ITEM_CHECK检查行项目数据做校验用。RESETMIGO界面重置清空行项目时调用需要把自定义字段也清掉。实际做屏幕增强最核心的是PBO_UPDATE、PAI_UPDATE和POST_DOCUMENT。前两个用于控制自定义子屏幕的数据进出最后一个用于把附加信息保存到自定义表里。如果你的增强点选的是MB_MIGO_ITEM_BADI界面上的方法会少一些主要就是LINE_DELETE、LINE_MODIFY、POST_DOCUMENT、PBO_UPDATE、PBO_DETAIL、PAI_UPDATE、ITEM_CHECK、RESET等够用了。2.3 方法选择与激活选好方法后每个方法里都有一些参数比如MB_MIGO_BADI的PBO_UPDATE方法有一个IM_GOITEM参数类型是GOITEM里面包含了当前行项目的字段结构物料号、工厂、库存地点、数量、批次、移动类型等都可以从这里取出来。这个GOITEM结构是MIGO增强里的核心数据载体。在实现方法时只需要双击方法名进入代码编辑器补上自己的逻辑。写代码之前建议先看一下同方法的较多示例代码尤其注意一个细节BADI方法里的传参是IM_开头的是输入、CH_开头的是可修改、EX_开头是异常或输出不能乱改方向不然语法检查过不去。全部实现类代码写完之后回到SE19主界面点激活按钮。如果激活时提示增强实现未分配到增强项目说明这个BADI所在的增强点还没有被激活需要先去SPRO里激活相关业务功能或者使用事务码SE19创建之后再去SE18验证一下BADI在系统中的状态。2.4 关于增强项目与传输请求这里要专门提一下增强项目。BADI在标准系统里可能没有被直接激活某些业务功能需要显式开启后才运行。特别是MB_MIGO_BADI如果做了增强但运行没生效先看看是不是系统里对应的业务功能没激活。正常情况下SAP标准系统默认是激活的但不同版本、不同行业解决方案下会有差异。所有新建的类、方法代码和屏幕程序都记得放进传输请求里。很多新手在DEV系统里跑得好好的一传输到QAS就发现增强不生效十有八九是漏传了实现类相关请求。增强实现一般是绑定在请求里的但子屏幕程序是另一个独立的对象很容易忘。3. 子屏幕开发真正的屏幕增强3.1 子程序与屏幕规划BADI方法本身主要负责逻辑处理但如果用户要在MIGO界面上看到你加的字段就需要通过子屏幕Subscreen的方式挂载到MIGO的界面上。第一步先创建一个独立的程序用来存放自定义屏幕。我习惯用ZMM_MIGO_SCR这种名字一眼就知道是干嘛的。这个程序可以是普通Report程序也可以是没有TITLE的Module Pool关键是要能维护一个屏幕。屏幕创建之后进入屏幕布局器Screen Painter按实际业务需要放字段。字段可以是自建表的字段也可以是程序全局变量。比如说要加一个质量备注字段就在程序里定义一个变量DATA: gv_zremark TYPE zmm_migo-zremark. 自定义备注字段然后在屏幕上摆放一个带标签的输入框绑定这个变量。屏幕的一般布局建议不要放太多字段因为MIGO本来就很复杂额外加的字段只要够用就行字段命名要清晰后续维护成本低。3.2 屏幕在SE19里的挂载方式创建好子屏幕程序后回到SE19的增强实现界面。这里需要找到屏幕增强相关的按钮或页签不同版本叫法不太一样有的叫Screen Exit有的直接叫子屏幕点进去之后里面会列出这个BADI支持的附加屏幕挂载点。在MB_MIGO_BADI的标准设计里系统预留了抬头和行项目两个挂载位置。把程序名和屏幕号填进去对应的位置就会在MIGO界面上生成一个新的Tab页比如附加或者增强页签。用户切到那个页签时就能看到你自定义屏幕的内容。有一点需要留意挂载的子屏幕有可能会在MIGO的多个场景里都显示收货、发货、转储都会显示。如果只希望某一种移动类型显示就需要在PBO逻辑里根据当前的移动类型一般可以从MIGO_DYNP_PROC或传入的参数里拿到去做动态控制。3.3 数据传递GOITEM怎么用子屏幕需要的当前行项目数据从GOITEM结构里取。比如我想在自定义屏幕中显示当前行的物料号和批次在BADI的PBO_UPDATE方法里写METHOD pbo_update. DATA: ls_goitem TYPE goitem. 将当前行项目数据传入自定义屏幕的全局变量 MOVE-CORRESPONDING im_goitem TO ls_goitem. gv_matnr ls_goitem-matnr. 物料号 gv_charg ls_goitem-charg. 批次 gv_werks ls_goitem-werks. 工厂 ENDMETHOD.这里的gv_matnr、gv_charg、gv_werks需要定义在子屏幕程序里作为全局变量并且屏幕上的字段绑定这些变量。为什么不是直接在子屏幕的PBO里读表因为MIGO界面上的行项目数据很多是内存中尚未持久化的比如用户改了数量还没保存直接去读数据库表根本不靠谱。通过GOITEM拿到的是MIGO当前界面内存中的行项目数据这才符合业务实际。反过来用户如果在自定义屏幕上输入了内容希望在过账时保存就需要在PAI_UPDATE方法里把屏幕字段的值写入到自定义存储表或者直接返回给MIGO后续处理逻辑。比如METHOD pai_update. 用户输入的质量备注保存到自定义表 MODIFY zmm_migo_doc FROM gv_zremark. ENDMETHOD.当然更合理的做法是在POST_DOCUMENT里处理因为POST_DOCUMENT可以拿到过账成功后的物料凭证号和年度便于关联保存。3.4 一个典型的自定义字段保存流程举个例子业务需求是MIGO采购订单收货时用户需要输入一个收货备注过账后这个备注要能跟物料凭证关联起来。完整的实现链路是SE19创建MB_MIGO_BADI的增强实现比如ZMM_MIGO_ZREMARK。创建子屏幕程序ZMM_MIGO_SCR屏幕9001上放一个字段GV_ZREMARK。在SE19的屏幕增强里把程序ZMM_MIGO_SCR、屏幕9001挂载到行项目附加页签。在PBO_UPDATE里把当前行项目的单据号码、行号、物料号写入子屏幕程序的全局变量同时读取自定义表如果有历史输入过显示在屏幕输入框里。在PAI_UPDATE里接收GV_ZREMARK的值保存到内存变量里用BACKEND_MEMORY或者程序间传递的方式让POST_DOCUMENT能够读到。在POST_DOCUMENT里根据传入的物料凭证号把内存中的备注写入自定义表ZMM_MIGO_DOC。第5步的程序间传值是个关键点。因为BADI实现类和子屏幕程序是两个不同的ABAP对象不能直接互相访问对方的全局变量。常用的传值方式有三种调用EXPORT ... TO MEMORY ID .../IMPORT ... FROM MEMORY ID ...用内存ID传值简单直接。把值存在一个全局的ABAP内存区域里用GET/SET PARAMETER传递。如果变量不多直接定义一个公共的类比如ZCL_MIGO_HELPER用静态属性来传递。我实际项目中用得最多的是前两种因为它们不依赖额外开发对象传值快也不会因为激活顺序导致类找不到。3.5 子屏幕上的字段联动逻辑自定义屏幕上如果不止一个字段经常会遇到联动需求。比如选择了某个自定义类型备注字段是否必填或者根据物料启用批次的情况控制供应商批次号字段是否可输。联动逻辑放在子屏幕自己的PBO/PAI里最合适不要去BADI里处理。子屏幕程序的PBO里判断当前GV_MATNR对应的物料是否启用批次然后设置字段属性PROCESS BEFORE OUTPUT. MODULE status_9001.在STATUS_9001里MODULE status_9001 OUTPUT. CLEAR: field1_active. 根据物料类别控制增强字段显示 SELECT SINGLE maktx INTO gv_maktx FROM makt WHERE matnr gv_matnr AND spras sy-langu. IF gv_werks IS NOT INITIAL. field1_active 1. 可输入 ELSE. field1_active 0. 禁止输入 ENDIF. ENDMODULE.子屏幕的PBO放在BADI的PBO_UPDATE之后触发还是之前触发不同版本会有细微差别但不需要过度纠结。只要记住一点需要读取GOITEM数据的逻辑放BADI方法里需要控制屏幕本身显示状态的逻辑放子屏幕程序的PBO里两边通过内存ID传值基本不会出大问题。4. 常见问题排查与避坑实录4.1 BADI不生效增强实现类激活了代码也写了但MIGO进去就是看不到自定义页签也不走BADI方法。这个现象出现频率最高。首先检查BADI是否被调用最简单的方法是在方法第一行打一个短文本日志或者用MESSAGE BADI Called TYPE I弹窗仅测试时用。如果弹窗都没出来说明BADI实例根本没触发。常见原因有几个MB_MIGO_BADI在系统里存在多个增强实现且被标记为多次使用Multiple Use。如果别的实现里逻辑报错可能影响整体调用。系统里有过滤器Filter限制。查看BADI定义时如果某个过滤器设有值而当前上下文不匹配就不会触发。这个在标准BADI里很少但自己定义过增强的话要留意。增强项目没激活。SE19创建的时候如果提示需要激活业务功能没激活就直接用了系统不会调用。排查顺序建议SE18检查增强点过滤器 - SE19确认实现已激活 - 代码里写日志确认调用 - 最后再查业务功能开关。4.2 增强字段值不刷新另外一个高发问题是第一次进入MIGO时自定义字段显示正常但切换行项目或者更改行项目后自定义字段不跟着变。比如点第一行时显示物料A点第二行还显示物料A。原因通常是对PBO_UPDATE方法的理解偏差。PBO_UPDATE是在PBO阶段被调用的但它不是只针对当前行它可能在界面刷新时被调用多次也可能因为GUI状态没刷新而不调用。解决办法是把字段刷新逻辑放在子屏幕自己的PBO里不要只依赖BADI的PBO方法。在MIGO界面切换行项目时系统本身会刷新细节页签子屏幕的PBO就会再次执行趁这个时机去内存里取当前行的数据重新赋值给显示字段这样刷新才可靠。如果还是有问题看看是不是子屏幕被MIGO缓存了。MIGO的界面大量使用Tabstrip激活状态没变的时候子屏幕可能不会重绘。可以在子屏幕的PBO里无条件执行CLEAR gv_matnr.这样至少保证每次进入新的上下文时字段是干净的不会显示上一行的残留数据。4.3 MIGO检查导致物料锁定网络上关于SAP MIGO检查导致物料锁定的讨论很热这也是做MIGO增强时容易踩的雷。物料锁定本质上是因为MIGO过账时系统在更新物料库存、物料凭证之前会对物料主数据加锁尤其涉及批次、序列号时锁的范围会更广。如果在BADI的LINE_MODIFY或ITEM_CHECK方法里写了读物料主数据的逻辑而且读取的方式或者事务没有正确处理锁有可能会让物料在MIGO检查阶段就被挂起后续别的用户再操作同一物料时就提示物料被锁定。这不是BADI自身的问题但增强代码会放大锁定的概率。建议在BADI的预检查阶段LINE_MODIFY/ITEM_CHECK只做轻量级校验避免大的跨表查询。不要直接ENQUEUE任何物料锁除非你非常清楚自己在做什么。如果确实需要读取物料主数据用BAPI_MATERIAL_GET_DETAIL这类函数但尽可能在POST_DOCUMENT之后处理那时候库存更新已经完成锁也释放了。4.4 增强字段没保存有的项目做完屏幕增强界面上字段也显示出来了输入内容也没报错但过账之后数据就是没落库。这种情况要检查字段值是否在PAI阶段成功传递给了BADI实现类如果用的是内存传值先看ID对不对。POST_DOCUMENT方法里的保存逻辑是否执行了这个方法在过账成功后会被调用但如果前面有校验失败过账根本不会成功自然就不会执行。自定义表写入有没有做COMMIT在BADI实现里通常不建议做额外的COMMIT WORK因为标准逻辑后面还会提交。但如果你在POST_DOCUMENT里写的是独立自定义表并且前面的写入没有提交可能要去看一下是否有其他COMMIT把事务所级别的事务处理影响了。最常见的还是传值丢失。输入时在屏幕程序里保存时在BADI类里中间的转存环节一旦出问题字段就丢了。建议在POST_DOCUMENT方法里先写一条日志表记录下通过内存取到的值看看是否为空就知道是传递环节还是存储环节出问题了。4.5 ATC检查与S/4升级如果你用的是S/4 HANA或者准备升级到S/4现在做ABAP增强基本绕不开ATCABAP Test Cockpit检查。BADI实现类的代码质量直接决定传输能否通过。建议在代码里严格遵守S/4的规范不要直接修改数据库表MODIFY dbtab除非必要能通过VALUE #( )给结构赋值的就用新语法。SELECT语句指定字段列表不要用SELECT *。避免使用END-OF-SELECTION这种过时的事件BADI方法里本来也不用这个。禁止使用HIDE、CURSOR这些老掉牙的写法。在HANA环境下性能检查也会更严格。如果子屏幕字段绑定的数据需要频繁查询建议建索引或者用缓存不要每次PBO都全表查。5. 扩展思考屏幕增强还能怎么玩MB_MIGO_BADI能做的不只是加几个字段。掌握了挂载子屏幕的方法之后延伸出来的玩法还挺多的第一可以做行项目级别的审批备注。比如超量收货时需要强制填写超收原因不填就不让过账。这个可以在LINE_MODIFY或PAI_UPDATE里判断数量与采购订单剩余量的差异然后检查自定义字段是否有值没有就报错。第二可以做移动类型联动控制。比如某些移动类型下禁用人工作废、自动带出库位或批次。这在PBO_UPDATE里根据移动类型设置子屏幕字段的显示/可输状态非常方便。第三可以结合条码扫描。MIGO收货时用扫码枪扫入条码把条码内容解析后填充到自定义子屏幕的字段里再通过BADI把解析结果回传给MIGO的行项目数据。很多工厂特别是汽车零部件行业和电子行业都爱这么干。第四可以做过账后动作。比如过账成功后自动打印标签、调用打印服务、或者把物料凭证信息推送写到外部接口表。这个在POST_DOCUMENT里处理就可以传入参数里有物料凭证号和年度很好用。总的来说MIGO屏幕增强的核心套路就是SE19创建增强实现 自建子屏幕程序 BADI方法逻辑处理 内存传值。把这四步串联起来绝大多数MIGO附加字段需求都能解决。我在实际项目里还有一个习惯所有MIGO增强的代码里都会在关键节点写入自定义日志表记录物料凭证号、移动类型、自定义字段内容、操作人、操作时间方便出问题后追溯。这个习惯帮我省了不少事特别是后来业务方说数据怎么跟想象中的不一样的时候查一下日志马上就能定位是增强模块写错了还是业务操作本身触发了不合理的流程。另外写在最后的一个小经验如果同一个系统里有很多历史增强实现建议在类名里带上业务含义比如ZCL_IM_MIGO_QUALITY、ZCL_IM_MIGO_TRACE而不是全部叫ZCL_IM_MB_MIGO_BADI。不然五年后接手的人打开SE19看到一排重名类似的类心态会崩的。
返回列表