09-29-2020 3:31 PM
I've added a field to CI_EKPODB and CI_EKPODBX and am trying to update it in a Z* implementation of ME_PROCESS_PO_CUST.
I first placed it in method POST, but found other questions here indicating that it should be placed in CHECK.
However neither resulted in the field being updates in EKPO when saving the PO in ME22N.
My code is below. I hope somebody here can tell me what else I need to do to make this work.
DATA lt_items TYPE purchase_order_items.
DATA ls_item TYPE purchase_order_item.
DATA lt_lines TYPE mmpur_t_textlines.
DATA ls_line TYPE mmpur_textlines.
DATA ls_data_old TYPE mepoitem.
DATA ls_data_new TYPE mepoitem.
DATA ls_datax_old TYPE mepoitemx.
DATA ls_datax_new TYPE mepoitemx.
DATA lv_text TYPE text100.
DATA ls_ekpo TYPE ekpo.
DATA: l_parent TYPE REF TO cl_po_header_handle_mm,
l_model_entry TYPE mmpur_model_type,
l_model TYPE REF TO if_model_mm.
DATA lo_item TYPE REF TO cl_po_item_handle_mm.
FIELD-SYMBOLS: <fs> TYPE any.
lt_items = im_header->get_items( ).
LOOP AT lt_items INTO ls_item.
CLEAR lv_text.
lo_item ?= ls_item-item.
CALL METHOD lo_item->if_longtexts_mm~get_text
EXPORTING
im_tdid = 'F90'
IMPORTING
ex_textlines = lt_lines.
IF lt_lines[] IS NOT INITIAL.
LOOP AT lt_lines INTO ls_line.
IF lv_text IS INITIAL.
lv_text = ls_line-tdline(100).
ELSE.
lv_text = |{ lv_text } { ls_line-tdline(100) }|.
ENDIF.
IF strlen( lv_text ) = 100.
EXIT.
ENDIF.
ENDLOOP.
CALL METHOD lo_item->get_data
IMPORTING
ex_data = ls_data_old.
CALL METHOD lo_item->get_datax
IMPORTING
ex_data = ls_datax_old.
ls_data_new = ls_data_old.
ls_data_new-zzvendortext = lv_text.
CALL METHOD lo_item->set_data
EXPORTING
im_data = ls_data_new.
CALL METHOD lo_item->check_badi_datax
EXPORTING
im_data_old = ls_data_old
im_data_new = ls_data_new
im_datax_old = ls_datax_old
IMPORTING
ex_datax_new = ls_datax_new.
CALL METHOD lo_item->set_datax
EXPORTING
im_data = ls_datax_new.
mmpur_dynamic_cast l_parent lo_item->my_parent.
mmpur_dynamic_cast l_model lo_item.
READ TABLE l_parent->my_recheck_queue WITH KEY model = l_model TRANSPORTING NO FIELDS.
IF NOT sy-subrc IS INITIAL.
l_model_entry-model = l_model.
APPEND l_model_entry TO l_parent->my_recheck_queue.
ENDIF.
ENDIF. "lt_lines[] is not initial
ENDLOOP. "lt_items
09-30-2020 12:46 PM
Could you try to execute 'ls_data_new-zzvendortext = lv_text.' only once, wrapping this statement and following ones if a 'IF ls_data_new-zzvendortext <> lv_text. ... ENDIF.'.
NB: If that works, try to comment some of the call following 'lo_item->set_data[x]' as they may no longer be required.
09-30-2020 12:57 PM
Hi Raymond,
I don't completely understand what you mean by executing the code only once. What I'm doing is check if the long text for each item has been changed en updating the zzvendortext field with the first 100 characters of the long text. I will try to comment the code after the set_datax and see what happens.
Update: commenting the last part still did not help. EKPO still was not updated after save.
09-30-2020 3:08 PM
In the code posted, you don't seem to check if the text has changed, you only check if there is some text. Maybe some code is missing in the post?
09-30-2020 3:19 PM
I've added an IF statement around the code after ls_data_new = ls_data_old untill the end, but I made no difference. When I modify the long text in ME22N and save the PO. EKPO is still not updated in the DB.
09-30-2020 4:19 PM
Try
LOOP AT lt_items INTO ls_item.
CLEAR lv_text.
CALL METHOD ls_item-item->if_longtexts_mm~get_text
EXPORTING
im_tdid = 'F90'
IMPORTING
ex_textlines = lt_lines.
IF lt_lines[] IS NOT INITIAL.
LOOP AT lt_lines INTO ls_line.
IF lv_text IS INITIAL.
lv_text = ls_line-tdline(100).
ELSE.
lv_text = |{ lv_text } { ls_line-tdline(100) }|.
ENDIF.
IF strlen( lv_text ) GE 100.
EXIT.
ENDIF.
ENDLOOP.
CALL METHOD ls_item-item->get_data
IMPORTING
ex_data = ls_data_old.
ls_data_new = ls_data_old.
CALL METHOD ls_item-item->get_datax
IMPORTING
ex_data = ls_datax_old.
" Do your stuff
ls_data_new-zzvendortext = lv_text.
" Did you actually do smth
IF ls_data_new NE ls_data_old.
CALL METHOD ls_item-item->set_data
EXPORTING
im_data = ls_data_new.
ENDIF. " ls_data_new NE ls_data_old
ENDIF. "lt_lines[] is not initial
ENDLOOP. "lt_items
09-30-2020 4:31 PM
See the new code below, but unfortunately no difference in result when checking EKPO using SE16 after changing the text and saving the results.
METHOD if_ex_me_process_po_cust~check .
DATA lt_items TYPE purchase_order_items.
DATA ls_item TYPE purchase_order_item.
DATA lt_lines TYPE mmpur_t_textlines.
DATA ls_line TYPE mmpur_textlines.
DATA ls_data_old TYPE mepoitem.
DATA ls_data_new TYPE mepoitem.
DATA ls_datax_old TYPE mepoitemx.
DATA ls_datax_new TYPE mepoitemx.
DATA lv_text TYPE text100.
DATA ls_ekpo TYPE ekpo.
DATA: l_parent TYPE REF TO cl_po_header_handle_mm,
l_model_entry TYPE mmpur_model_type,
l_model TYPE REF TO if_model_mm.
DATA lo_item TYPE REF TO cl_po_item_handle_mm.
FIELD-SYMBOLS: <fs> TYPE any.
lt_items = im_header->get_items( ).
LOOP AT lt_items INTO ls_item.
CLEAR lv_text.
lo_item ?= ls_item-item.
CALL METHOD lo_item->if_longtexts_mm~get_text
EXPORTING
im_tdid = 'F90'
IMPORTING
ex_textlines = lt_lines.
IF lt_lines[] IS NOT INITIAL.
LOOP AT lt_lines INTO ls_line.
IF lv_text IS INITIAL.
lv_text = ls_line-tdline(100).
ELSE.
lv_text = |{ lv_text } { ls_line-tdline(100) }|.
ENDIF.
IF strlen( lv_text ) = 100.
EXIT.
ENDIF.
ENDLOOP.
CALL METHOD lo_item->get_data
IMPORTING
ex_data = ls_data_old.
CALL METHOD lo_item->get_datax
IMPORTING
ex_data = ls_datax_old.
ls_data_new = ls_data_old.
IF ls_data_new-zzvendortext <> lv_text.
ls_data_new-zzvendortext = lv_text.
CALL METHOD lo_item->set_data
EXPORTING
im_data = ls_data_new.
* CALL METHOD lo_item->check_badi_datax
* EXPORTING
* im_data_old = ls_data_old
* im_data_new = ls_data_new
* im_datax_old = ls_datax_old
* IMPORTING
* ex_datax_new = ls_datax_new.
*
* CALL METHOD lo_item->set_datax
* EXPORTING
* im_data = ls_datax_new.
*
* mmpur_dynamic_cast l_parent lo_item->my_parent.
* mmpur_dynamic_cast l_model lo_item.
* READ TABLE l_parent->my_recheck_queue WITH KEY model = l_model TRANSPORTING NO FIELDS.
* IF NOT sy-subrc IS INITIAL.
* l_model_entry-model = l_model.
* APPEND l_model_entry TO l_parent->my_recheck_queue.
* ENDIF.
ENDIF."zzvendortext <> lv_text
ENDIF. "lt_lines[] is not initial
ENDLOOP. "lt_items
ENDMETHOD. "IF_EX_ME_PROCESS_PO_CUST~CHECK
10-01-2020 7:46 AM
Hi Raymond,
I tried your code, after needing to make some changes. You're using methodes IF_PURCHASE_ORDER_ITEM_MM~GET_DATA and IF_PURCHASE_ORDER_ITEM_MM~SET_DATA. of class CL_PO_ITEM_HANDLE_MM while I used GET_DATA and SET_DATA that didn't come from an interface. The main reason I did this is that in IF_PURCHASE_ORDER_ITEM_MM~SET_DATA the program didn't pass the check code.
CHECK l_parent->my_ibs_firewall_on EQ mmpur_yes OR
l_parent->my_cust_firewall_on EQ mmpur_yes.<br>
Do I have to implement one of the other methods to ensure one of these fields is set to mmpur_yes, or is is this just a case of SAP doesn't update the fields in CI_EKPODB. I did find a note (663650) that solved this for the header and CI_EKKODB, but didn't find a corresponding one for CI_EKPODB.
10-01-2020 12:17 PM
Could you temporary set the ch_failed to abap_true, and check on screen if your zz field is updated by the BAdI.
Could you add a check such as
if im_header->is_changeable( ) = abap_true.
Else did you try to set the flag custom yourself (it's a public attribute)
cl_po ?= im_header.
cl_po->my_cust_firewall_on = 'X'.
What's your version of SAP?
10-01-2020 12:53 PM
Hi Raymond,
I set ch_failed to abap_true before my get_items statement.
Tried adding
CHECK ls_item-item->is_changeable( ) = abap_true.
as the first line after the loop at lt_items into ls_item. But activating gave that the method was unknown. Did do the setting of the firewall variable.
Also about the zz field. This is not a field we show on screen in ME22N. The field was added for use in a CDS view in which we do not want the entire SO10 long text but just the first 100 characters of the long text.
When testing these changes though it appears setting the ch_failed to appears makes it so that the PO isn't saved when I press save.
I'm wondering now if I shouldn't move everything to the POST method and look for or create an appropriate FM to update EKPO there, what's your opinion on this?
10-02-2020 10:22 AM
The failed flag was intended to check if the field was actually updated, but as it's not displayed you have to debug for this. (remove the failed flag after test...
Did you try the 'set the cust fireflag yourself' option?
10-02-2020 10:36 AM
Hi Raymond,
I tried the following. In debugging I set ch_failed to X before going into the loop. However is stayed that way after the loop was finished.
LOOP AT lt_items INTO ls_item.
lo_po ?= im_header.
lo_po->my_ibs_firewall_on = 'X'.
CLEAR lv_text.
CALL METHOD ls_item-item->if_longtexts_mm~get_text
EXPORTING
im_tdid = 'F90'
IMPORTING
ex_textlines = lt_lines.
IF lt_lines[] IS NOT INITIAL.
LOOP AT lt_lines INTO ls_line.
IF lv_text IS INITIAL.
lv_text = ls_line-tdline(100).
ELSE.
lv_text = |{ lv_text } { ls_line-tdline(100) }|.
ENDIF.
IF strlen( lv_text ) GE 100.
EXIT.
ENDIF.
ENDLOOP.
CALL METHOD ls_item-item->get_data
RECEIVING
re_data = ls_data_old.
ls_data_new = ls_data_old.
* CALL METHOD ls_item-item->get_datax
* IMPORTING
* ex_data = ls_datax_old.
* " Do your stuff
ls_data_new-zzvendortext = lv_text.
* " Did you actually do smth
IF ls_data_new NE ls_data_old.
CALL METHOD ls_item-item->set_data
EXPORTING
im_data = ls_data_new.
ENDIF. " ls_data_new NE ls_data_old
ENDIF. "lt_lines[] is not initial
ENDLOOP. "lt_items