关于sap:SAP订单上Shipping抬头和行项目字段的持久化实现原理

29次阅读

共计 4237 个字符,预计需要花费 11 分钟才能阅读完成。

It is known that we can maintain shipping data for order header and order item separately.
For example, suppose when I have maintained the following data, what happens when save button is clicked?


First all links to this service order is retrieved by function module CRM_GET_ALL_LINKS which works based on database table CRMD_LINK.

The link data has the following format:


The persistence of shipping data is done in function module CRM_SHIPPING_SAVE_OB:

The header guid together with all link data is put into the generic function module CRM_ORDER_UPDATE_TABLES_DETERM, which will calculate current change mode (insert, update or delete) by comparing object buffer with database buffer.


In this example, the determined change are two update operations as expected.


Now let’s write a standalone report to perform the change on both header and item shipping data and try to interpret these two changes by our own code.

REPORT crms4_change_shipping.

PARAMETERS: inh     TYPE crmd_shipping-incoterms2 OBLIGATORY DEFAULT 'header',
            ini     LIKE inh OBLIGATORY DEFAULT 'item',
            srvo_id TYPE crmd_orderadm_h-object_id OBLIGATORY DEFAULT '8000000111'.

DATA: lv_srvo_guid      TYPE crmd_orderadm_h-guid,
      lt_changed_fields TYPE crmt_input_field_tab,
      ls_changed_fields LIKE LINE OF lt_changed_fields,
      lt_orderadm_i     TYPE TABLE OF crmd_orderadm_i,
      lt_shipping       TYPE crmt_shipping_comt,
      ls_shipping       LIKE LINE OF lt_shipping.

START-OF-SELECTION.

  SELECT SINGLE * INTO @DATA(ls_header) FROM crmd_orderadm_h WHERE object_id = @srvo_id.

  IF sy-subrc <> 0.
    WRITE:/ 'Service order not found for id:', srvo_id.
    RETURN.
  ENDIF.

  lv_srvo_guid = ls_header-guid.

  SELECT SINGLE guid INTO @DATA(lv_item_guid) FROM crmd_orderadm_i
     WHERE header = @lv_srvo_guid.

  IF sy-subrc <> 0.
    WRITE:/ 'No item found for service order:', srvo_id.
    RETURN.
  ENDIF.

  SELECT * INTO TABLE @DATA(lt_link) FROM crmd_link WHERE
   (guid_hi = @lv_srvo_guid OR guid_hi = @lv_item_guid) AND
    objtype_set = '12'.

  SELECT * INTO TABLE @DATA(lt_shipping_db) FROM crmd_shipping
     FOR ALL ENTRIES IN @lt_link WHERE guid = @lt_link-guid_set.

  IF lines(lt_shipping_db) <> 2.
    WRITE:/ 'corrupted shipping data'.
    RETURN.
  ENDIF.

  READ TABLE lt_link ASSIGNING FIELD-SYMBOL(<head_link>) WITH KEY
     objtype_hi = '05'.
  IF sy-subrc <> 0.
    WRITE:/ 'header data does not exist'.
    RETURN.
  ENDIF.

  READ TABLE lt_shipping_db ASSIGNING FIELD-SYMBOL(<head>) WITH KEY
    guid = <head_link>-guid_set.
  <head>-incoterms2 = inh.
  MOVE-CORRESPONDING <head> TO ls_shipping.
  ls_shipping-ref_guid = lv_srvo_guid.
  ls_shipping-ref_kind = 'A'.
  INSERT ls_shipping INTO TABLE lt_shipping.

  ls_changed_fields-ref_guid = <head_link>-guid_hi.
  ls_changed_fields-ref_kind = 'A'.
  ls_changed_fields-objectname = 'SHIPPING'.
  APPEND 'INCOTERMS2' TO ls_changed_fields-field_names.
  APPEND ls_changed_fields TO lt_changed_fields.

  READ TABLE lt_link ASSIGNING FIELD-SYMBOL(<item_link>) WITH KEY
     objtype_hi = '06'.
  IF sy-subrc <> 0.
    WRITE:/ 'item data does not exist'.
    RETURN.
  ENDIF.

  READ TABLE lt_shipping_db ASSIGNING FIELD-SYMBOL(<item>) WITH KEY
    guid = <item_link>-guid_set.
  <item>-incoterms2 = ini.
  MOVE-CORRESPONDING <item> TO ls_shipping.
  ls_shipping-ref_guid = lv_item_guid.
  ls_shipping-ref_kind = 'B'.
  INSERT ls_shipping INTO TABLE lt_shipping.

  CLEAR: ls_changed_fields.
  ls_changed_fields-ref_guid = <item_link>-guid_hi.
  ls_changed_fields-objectname = 'SHIPPING'.
  ls_changed_fields-ref_kind = 'B'.
  APPEND 'INCOTERMS2' TO ls_changed_fields-field_names.
  INSERT ls_changed_fields INTO TABLE lt_changed_fields.

  CALL FUNCTION 'CRM_ORDER_MAINTAIN'
    EXPORTING
      it_shipping       = lt_shipping
    CHANGING
      ct_input_fields   = lt_changed_fields
    EXCEPTIONS
      error_occurred    = 1
      document_locked   = 2
      no_change_allowed = 3
      no_authority      = 4.

  IF sy-subrc <> 0.
    WRITE: / 'error during quantity change'.
    RETURN.
  ENDIF.

Execute the report, specify new incoterms for header and item:

And use the following code to capture the change:

DATA: lt_update TYPE crmt_shipping_du_tab,
        lt_insert TYPE crmt_shipping_du_tab,
        lt_delete TYPE crmt_shipping_du_tab,
        lt_guid   TYPE crmt_object_guid_tab.

  DO 2 TIMES.
    CLEAR: lt_guid.
    IF sy-index = 1.
      APPEND <head>-guid TO lt_guid.
    ELSE.
      APPEND <item>-guid TO lt_guid.
    ENDIF.
    CALL FUNCTION 'CRM_ORDER_UPDATE_TABLES_DETERM'
      EXPORTING
        iv_object_name       = 'SHIPPING'
        iv_field_name_key    = 'GUID'
        it_guids_to_process  = lt_guid
        iv_header_to_save    = lv_srvo_guid
      IMPORTING
        et_records_to_insert = lt_insert
        et_records_to_update = lt_update
        et_records_to_delete = lt_delete.

    READ TABLE lt_update ASSIGNING FIELD-SYMBOL(<update>) INDEX 1.
    IF <update> IS ASSIGNED.
      CASE sy-index.
        WHEN 1.
          WRITE:/ |changes on header, new incoterms: {<update>-incoterms2}| COLOR COL_GROUP.
        WHEN 2.
          WRITE:/ |changes on item, new incoterms: {<update>-incoterms2}| COLOR COL_KEY.
      ENDCASE.
    ENDIF.
  ENDDO.

And you will see the output, the change is detected correctly as expected.

要获取更多 Jerry 的原创文章,请关注公众号 ” 汪子熙 ”:

正文完
 0