cancel
Showing results for 
Search instead for 
Did you mean: 
Subscribe

Hi everyone,

I'm currently in the process of implementing a RAP action. This action makes several calls, both through traditional function modules and via RAP objects:

DATA lt_create_materialdocumet_head TYPE TABLE FOR CREATE I_MaterialDocumentTP.
DATA lt_create_materialdocumet_item TYPE TABLE FOR CREATE I_MaterialDocumentTP\_MaterialDocumentItem.
DATA lt_create_matdocitem_sernum    TYPE TABLE FOR CREATE I_MaterialDocumentItemTP\_SerialNumber.

[...]

lt_create_materialdocumet_head = VALUE #(
          ( %cid              = 'CID1'
            GoodsMovementCode = if_goodsmvt=>goodsmvt_code_06
            PostingDate       = sy-datum
            DocumentDate      = sy-datum
            %control          = VALUE #( GoodsMovementCode = cl_abap_behv=>flag_changed
                                         PostingDate       = cl_abap_behv=>flag_changed
                                         DocumentDate      = cl_abap_behv=>flag_changed ) ) ).

      lt_create_materialdocumet_item = VALUE #(
          ( %CID_ref = 'CID1'
            %target  = VALUE #( ( %cid                = 'CID_ITEM1'
                                  Plant               = COND #( WHEN ls_equipment-Plant IS NOT INITIAL
                                                                THEN ls_equipment-Plant
                                                                ELSE ls_equipment-MaintenancePlanningPlant )
                                  Material            = ls_equipment-Material
                                  StorageLocation     = ls_equipment-StorageLocation
                                  GoodsMovementType   = '551' " Goods issue for scrapping (no order reference)
                                  QuantityInEntryUnit = 1
                                  QuantityInBaseUnit  = 1
                                  MaterialBaseUnit    = ls_equipment-ProductionOrderQuantityUnit
                                  EntryUnit           = ls_equipment-ProductionOrderQuantityUnit
                                  " IsCompletelyDelivered must NOT be set for mvt type 551 (no order reference)
                                  " - it would trigger M7264 as the system expects a reservation/order context
                                  %control            = VALUE #(
                                      Plant               = cl_abap_behv=>flag_changed
                                      Material            = cl_abap_behv=>flag_changed
                                      StorageLocation     = cl_abap_behv=>flag_changed
                                      GoodsMovementType   = cl_abap_behv=>flag_changed
                                      QuantityInEntryUnit = cl_abap_behv=>flag_changed
                                      QuantityInBaseUnit  = cl_abap_behv=>flag_changed
                                      MaterialBaseUnit    = cl_abap_behv=>flag_changed
                                      EntryUnit           = cl_abap_behv=>flag_changed ) ) ) ) ).

      IF ls_equipment-SerialNumber IS NOT INITIAL.
        lt_create_matdocitem_sernum = VALUE #(
            ( %CID_ref = 'CID_ITEM1'
              %target  = VALUE #( ( %cid         = 'CID_SER1'
                                    SerialNumber = ls_equipment-SerialNumber
                                    %control     = VALUE #( SerialNumber = cl_abap_behv=>flag_changed ) ) ) ) ).
      ENDIF.

      MODIFY ENTITIES OF i_materialdocumenttp
             ENTITY MaterialDocument
             CREATE FROM lt_create_materialdocumet_head
             CREATE BY \_MaterialDocumentItem
             FROM lt_create_materialdocumet_item

             ENTITY MaterialDocumentItem
             CREATE BY \_SerialNumber
             FROM lt_create_matdocitem_sernum

             FAILED   DATA(ls_create_failed)
             REPORTED DATA(ls_create_reported).

      " Handle failed and reported messages for material document header
      IF ls_create_failed-MaterialDocument IS NOT INITIAL.
        APPEND VALUE #( Equipment = ls_equipment-Equipment ) TO failed-equipment.
      ENDIF.

      IF ls_create_reported-MaterialDocument IS NOT INITIAL.
        reported-equipment = VALUE #( BASE  reported-equipment
                                      FOR ls_repo IN ls_create_reported-MaterialDocument
                                      ( %tky = CORRESPONDING #( ls_equipment  )
                                        %msg = ls_repo-%msg ) ).
      ENDIF.

      " Handle failed and reported messages for material document item
      IF ls_create_failed-MaterialDocumentItem IS NOT INITIAL.
        APPEND VALUE #( Equipment = ls_equipment-Equipment ) TO failed-equipment.
      ENDIF.

      IF ls_create_reported-MaterialDocumentItem IS NOT INITIAL.
        reported-equipment = VALUE #( BASE  reported-equipment
                                      FOR ls_repo_item IN ls_create_reported-MaterialDocumentItem
                                      ( %tky = CORRESPONDING #( ls_equipment  )
                                        %msg = ls_repo_item-%msg ) ).
      ENDIF.


      DATA lv_object TYPE j_objnr.
      lv_object = ls_equipment-MaintObjectInternalID.

      CALL FUNCTION 'STATUS_CHANGE_EXTERN'   "<--- 'E0011'
        EXPORTING  objnr               = lv_object
                   user_status         = lc_status_int
        EXCEPTIONS object_not_found    = 1
                   status_inconsistent = 2
                   status_not_allowed  = 3
                   OTHERS              = 4.

       DATA lt_status type standard table of jstat.
       lt_status = VALUE #( ( stat = 'I0320' ) ). "Deactivate

      CALL FUNCTION 'STATUS_CHANGE_INTERN'
        EXPORTING
          OBJNR               = lv_object
        TABLES
          STATUS              = lt_status
        EXCEPTIONS
          OBJECT_NOT_FOUND    = 1
          STATUS_INCONSISTENT = 2
          STATUS_NOT_ALLOWED  = 3
          OTHERS              = 4
		  
[...]

A central commit is performed within the RAP save sequence. This results, in this case, in the equipment being set to the Deactivated status before the goods movement could be posted. The latter is no longer possible with an inactive equipment. Afterwards, since the commit to the RAP Object call fails, a rollback is triggered, causing all changes to be lost.

How should multiple action be handled in RAP, that are affected by each other? Is only way to call multiple actions in succession?

Thanks in advance,

Lukas

 

View Entire Topic
aravindhan2529
Participant
0 Likes

Hi Lukas,

One way to look at this is that LUW (Logical Unit of Work) is the transactional boundary for a set of related changes.

In your case, the intended flow would be:

RAP Action

Create Material Document
+
Change Equipment Status

Same RAP LUW

RAP Save Sequence

If successful → Commit
If something fails → Rollback

The important point is that both changes should participate in the same transactional lifecycle if they are expected to succeed or fail together.

This is why I would avoid adding COMMIT WORK between the operations. RAP controls the transaction and the final commit.

The main point I would check in your case is whether STATUS_CHANGE_EXTERN / STATUS_CHANGE_INTERN can safely participate in the RAP LUW. If they perform their own database or update processing, that is likely where the transactional issue comes from.

Hope this helps.

Regards,

Aravindhan Chandran🍀

lukasmetzger
Participant
0 Likes

Hi Aravindhan,

Thank you very much for the detailed feedback. 😊 I completely understand the part about the LUW of RAP and the dependency of the calls.

In my scenario, where I rely on the use of function modules, how would the optimal structure look like? When using multiple action calls, since each has its own self-contained LUW, the advantage of using Fiori Elements will be lost, and I would have to build a custom action.

Is there another option here that I’m overlooking if no released RAP objects are available?

Thanks again,
Lukas