
1 问题重述

物料编号 601-027019 在物料主数据更新时出现如下错误:不能更改估价分类,选择“显示错误”
通过搜索相关的问题,能够更改评估分类的几个条件:
-
该物料本期和上期都是零库存。物料有库存,不能变更评估分类和计划价格
-
采购有未清订单(相关采购订单都已打上删除标记)
-
相关生产订单已关闭
2 网上搜知识
SAP 那些事-技巧篇-19-如何修改物料主数据的评估类
首先明确一点,SAP 中只要有业务交易发生,主数据核心字段的修改就变得比较困难,因此主数据核心主数据最好是一次性维护正确,一次性维护正确,一次性维护正确!评估类修改的步骤如下:
先判断是否需通过修改物料类型修改评估类(MMAM),这种情况是指物料类型选择错误导致评估类也错误,此时可以通过 MMAM 修改物料类型来修改评估类。
如果不能通过 MMAM 修改评估类,直接需要通过 MM02 修改评估类,常规步骤如下:
相关的未清采购订单的处理,需标记删除。
相关的未清生产订单的处理,需标记删除。
库存价值调整为 0,当期交易的话可冲销相关移动来实现,前期已有的交易则需要把库存转移到中间科目,修改完毕后,再转回来。
修改消息 OMT4(MM-326/327,低于 4.6B 版本则需通过代码修改消息)类型为警告,默认消息类型为错误,目的是如果存在未清采购订单和未清的生产订单,消息为警告。
修改评估类(批量修改可使用 MASS 或 MM17,单个修改 MM02)
总结:有库存肯定是不能修改的,库存必须清零,根据 SAP 官方说法,未清采购订单和生产订单是需要处理或打删除标记的,但从测试来看,不打删除标记也是可以的(个人认为如果采购订单和生产订单没做任何物料移动,是无需打删除标记的;或者说所有订单均已关闭,即相关采购订单已全部发票校验,生产订单已全部 TECO),SAP 也说这个消息是可以修改为警告的(可参考 note:160970 )。因此通常的修改方法为库存清零(可通过程序开发或 LSMW,从财务角度来说,也必须清零,否则科目怎么会更换为新的库存科目),修改评估类(可通过程序或 LSMW 或 MM17 ),库存恢复(LSMW 或开发程序),库存清零和库存恢复建议使用移动类型 562 和 561 。
另外需注意特殊库存(销售订单库存和项目库存),特殊库存如果不单独设置评估类,其使用的评估类和非限制库存一致,但如果只修改表 MBEW 的评估类,特殊库存评估类不会自动修改,如 EBEW 销售订单库存,这个评估类也需要手工修改才行。
3 问题分析
但是针对本次业务场景的物料 601-027019 的评估类在两个系统是一致的,都为 7100。
后续跟 MM 顾问在确认问题的时候,发现这个物料在 3 月份的时候更改过物料的评估类。一开始这个物料在前台 PLM 系统第一次下发的数据,会默认一个值,我估计这个值经过 MDC 传给 SAP 的评估类是 3000。所以后续他们在业务出错的时候,在 3 月 18 号将 3000 的评估类更改为了 7100:
在 SAP 端也是将库存清掉,更改过来的报文:

4 问题解决
现在只能通过打断点,去程序 ZWJMDT001 找问题了。
发现问题出现的代码在 FORM frm_deserialize_data 当中这段逻辑中:
LOOP AT ls_material-mbew INTO DATA(ls_input_mbew).
MOVE-CORRESPONDING ls_input_mbew TO ls_mbew .
IF ls_mbew-eklas IS INITIAL."如果销售订单评估分类空 那么用评估类替代
ls_mbew-eklas = ls_mbew-bklas.
ENDIF.
ls_mbew-matnr = gs_mara-matnr.
APPEND ls_mbew TO gt_mbew.
IF ls_mbew-bwkey = '2901' AND gs_mdc001-zswitch = 'X'.
LOOP AT gt_mdc002 INTO gs_mdc002.
ls_mbew-bwkey = gs_mdc002-werks.
APPEND ls_mbew TO gt_mbew.
ENDLOOP.
ENDIF.
ENDLOOP.
-
问题点一:首先销售订单评估分类为空,用评估类替代,刚好这个物料在 MDC 传过来的数据没有销售订单评估类,而 SAP 的销售订单评估分类为空。就把 7100 赋值给了 eklas 这个字段。在 SAP 系统中,这个物料在 1020 工厂下的系统内的值为空,在接口调用过程中,被赋值了,经过确认,这个物料可以直接在前台维护销售订单评估类,所以将这个值更改为 7100。
-
问题点二:接口同时也会去更改上年的同步分类,按理说这个字段不应该在接口中进行更改的。

字段 VJBKL 上年的评估类在 1020 是 3000,在这次接口改为 7100 了:

问题就出现在设置默认值这段程序,接口中有些字段虽然没改,但其实被这段程序把所有的值都给赋值了:
LOOP AT gt_mbew ASSIGNING <fs_mbew>.
CLEAR lv_mbew_exit.
** 确定价格控制
READ TABLE gt_marc INTO DATA(ls_marc) WITH KEY matnr = <fs_mbew>-matnr werks = <fs_mbew>-bwkey BINARY SEARCH.
IF sy-subrc = 0.
ELSE.
CLEAR ls_marc.
ENDIF.
READ TABLE lt_marc_db INTO ls_marc_db WITH KEY matnr = <fs_mbew>-matnr werks = <fs_mbew>-bwkey BINARY SEARCH.
IF sy-subrc = 0.
ELSE.
CLEAR ls_marc_db.
ENDIF.
IF ls_marc-beskz IS INITIAL AND ls_marc_db-beskz IS NOT INITIAL.
ls_marc-beskz = ls_marc_db-beskz.
ENDIF.
IF ls_marc-sobsl IS INITIAL AND ls_marc_db-sobsl IS NOT INITIAL.
IF p_head-source NE 'MDC'. "add xt on 211201
ls_marc-sobsl = ls_marc_db-sobsl.
ENDIF.
ENDIF.
READ TABLE lt_mbew_db TRANSPORTING NO FIELDS WITH KEY matnr = <fs_mbew>-matnr bwkey = <fs_mbew>-bwkey BINARY SEARCH.
IF sy-subrc = 0.
lv_mbew_exit = 'X'.
ENDIF.
PERFORM frm_determine_vprsv USING ls_marc lv_mbew_exit CHANGING <fs_mbew>.
IF <fs_mbew>-vprsv = 'S'.
<fs_mbew>-mlast = '3'.
ENDIF.
IF <fs_mbew>-vprsv = 'V'.
<fs_mbew>-mlast = '2'.
ENDIF.
* IF sy-datum+0(6) = '202109'.
<fs_mbew>-vmvpr = <fs_mbew>-vprsv."控制标识
<fs_mbew>-vjvpr = <fs_mbew>-vprsv."
<fs_mbew>-vmbkl = <fs_mbew>-bklas."评估类
<fs_mbew>-vjbkl = <fs_mbew>-bklas.
<fs_mbew>-vmpei = <fs_mbew>-peinh."前期价格单位
<fs_mbew>-vjpei = <fs_mbew>-peinh."去年价格单位
* ENDIF.
* gs_maw1-wbkla = <fs_mbew>-bklas.
ENDLOOP.
其中这段语句就是问题:<fs_mbew>-vmbkl = <fs_mbew>-bklas."评估类,将上年期间的评估类也被重新赋值了,这个就是本次接口报错的原因。
同时,这段代码还会更改前期价格单位,去年价格单位等等,也不知道这样改是否符合 SAP 真实业务逻辑。
因为业务场景比较复杂,不可能一下子能将这段代码改掉,因此,我也是把这个字段在接口中手动改为 3000,然后 BAPI 没有报错了,如下图:

最终效果:

但是实际上,这段接口还是没有解决相应的问题,问题就在于前面的人将赋值不同物料的视图结构代码写的太通用了,但是没有数据校验。
参考文档

575

被折叠的 条评论
为什么被折叠?



