物料BOM修改的函数 CSAI_BOM_MAINTAIN的BUG
曾经用CSAI_BOM_MAINTAIN 修改BOM,当BOM项目存在长文本需要写入,且BOM项目很多时,发现此函数修改完成后,长文本内容对应的BOM项目与我们实际传入的错位了。
(也许是我们传值有错误?如果是请联系微信)
例如:我们需要BOM项目40项的长文本内容是T1……,第50项目需要删除,项目60的长文本内容是T2……,项目70的长文本为 T3……,
此时发现调用函数完成后,文本内容T3……跑到项目60上去了。
恼火了一阵子,决定调试原代码如下:
form t_ltx_itm_modify 中的loop at lt_ltx_itm 处理,并不能保证 pointer = t_stpob中排除掉vbkz = 'D'后的行索引。
假设t_stpob的数据如下
行索引 |
BOM项目 |
物料号 |
字段VBKZ |
1 |
40 |
A1 |
|
2 |
50 |
A2 |
D |
3 |
60 |
A3 |
|
4 |
70 |
A4 |
|
假设t_ltx_itm的数据如下
pointer |
文本内容 |
1 |
T1 (对应BOM项目40) |
3 |
T2 (对应BOM项目60) |
4 |
T3 (对应BOM项目70) |
根据原代码当循环t_stpob到第2行时,VBKZ = 'D',form t_ltx_itm_modify中的逻辑是先删除t_ltx_itm中pointer = 2的,(此时可能有等于2的也可能没有),再将大于2的递减,即原pointer = 3的将修改为pointer = 2,原pointer = 4的将修改为pointer = 3,修改后的t_ltx_item数据如下
pointer |
文本内容 |
1 |
T1 |
2 |
T2 |
3 |
T3 |
我们本来是要将文本T2写到BOM项目60上,T3写到BOM项目70上,经以上处理后,T2的pointer= 2,对应t_stpob的50项目,写到了BOM项目50上,但50项目被删除 ,所以没有写入,而T3的pointer = 3,对应t_stpob的60项目,则写到了60项目上。
因此,我们将form t_ltx_itm_modify 中的loop at lt_ltx_itm语句注释掉,此处没有增强,是修改原代码。
由于接下来的 loop at itstpoi 中 l_tabix_stpo = l_tabix_stpo + 1,是递加的,是在
itstpoi-fldel is initial 的情况下,如下图。
所以要保证t_ltx_itm中的 pointer = l_tabix_stpo,必须对t_ltx_itm中的pointer 重新计算序号。在增强点ES_SAPLCSAI处实施新的处理代码。
由于在form t_ltx_itm_modify中,我们修改原代码后,t_ltx_itm中保留的数据是在t_stpob中vbkz <> ‘D’的,也就是itstpoi-fldel is initial的,所以我们只要将t_ltx_itm中的pointer按先后顺序编写就行(前提是在传t_ltx_item时,是按t_stpob的项目的先后顺序)。
data:begin of ls_poin,
pointer type CSLTX_ITM_02-pointer,
end of ls_poin.
data lt_poin like STANDARD TABLE OF ls_poin.
MOVE-CORRESPONDING t_ltx_itm[] to lt_poin[].
delete ADJACENT DUPLICATES FROM lt_poin COMPARING pointer.
data l_err type c.
loop at t_ltx_itm.
read TABLE lt_poin with key pointer = t_ltx_itm-pointer TRANSPORTING NO FIELDS.
if sy-subrc = 0.
t_ltx_itm-pointer = sy-tabix. "pointer 应对应内表 itstpoi 中 字段 fldel is initial
后的递加
modify t_ltx_itm.
else.
l_err = 'X'.
exit.
endif.
endloop.
IF L_ERR = 'X'.
PERFORM appl_log_write_single_message USING 'E'
'Z001'
037
'' '' '' '' .
* Exit API Log
PERFORM appl_log_exit USING 'CSAI_BOM_CREATE'
CHANGING hlp_subrc.
* Dequeue all Locks
CALL FUNCTION 'DEQUEUE_ALL'.
RAISE error.
ENDIF.