Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

ME_PROCESS_PO_CUST saving CI_EKPODB field

ArthurParisius
Contributor
0 Kudos

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
11 REPLIES 11

raymond_giuseppi
Active Contributor
0 Kudos

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.

ArthurParisius
Contributor
0 Kudos

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.

raymond_giuseppi
Active Contributor
0 Kudos

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?

ArthurParisius
Contributor
0 Kudos

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.

raymond_giuseppi
Active Contributor
0 Kudos

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

ArthurParisius
Contributor
0 Kudos

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

ArthurParisius
Contributor
0 Kudos

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.

raymond_giuseppi
Active Contributor
0 Kudos

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?

ArthurParisius
Contributor
0 Kudos

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?

raymond_giuseppi
Active Contributor
0 Kudos

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?

ArthurParisius
Contributor
0 Kudos

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