Tuesday, 19 January 2021

ABAP RAP : Enabling custom actions with a dialog for additional input fields

Prerequisites:

◉ Knowledge on ABAP Restful Application Programming

◉ Knowledge on Entity Manipulation Language (EML)

◉ [Optional] Hands on exercises in Open SAP course https://open.sap.com/courses/cp13.

This blog gives you an idea to develop a custom action with a dialog for additional input fields that are needed based on scenario.

◉ Use case:

     ◉ There is a purchase contract that needs to be extended to next year by buyer.

◉ Business logic:

     ◉ Only extend those validities which are running on existing valid to

          ◉ [i.e. continue business with same supplier].

     ◉ Don’t touch items which are older than existing valid to.

          ◉ [i.e. no need to continue business with this supplier]

In my example: 

Old valid to: Jun 30, 2021

New valid to: Dec 31, 2021

Item #10 runs on Jun 30,2021 hence it is expected to extend till Dec 31, 2021

Item #20 ends on Mar 31, 2021 hence it is not expected to touch.

SAP ABAP Tutorial and Material, SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Preparation

Click the button Extend and to see results on Object page and item page

SAP ABAP Tutorial and Material, SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Preparation

SAP ABAP Tutorial and Material, SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Preparation

Implementation steps:


1. Create a data model with Header (Parent), Item (Child), Conditions (Grand Child) having fields “Valid from”, “Valid to “.

2. Create an abstract CDS entity with required input fields.

@EndUserText.label: 'Abstract entity to extend the validity'
@Metadata.allowExtensions: true
define abstract entity ZRK_A_Doc_Extend 
 // with parameters parameter_name : parameter_type 
  {
    extend_till : /dmo/end_date;
    comments : abap.string( 300 );
    
}

3. Enrich the entity with UI annotations such as labels.

@Metadata.layer: #CORE
annotate entity ZRK_A_Doc_Extend
    with 
{
   @EndUserText.label: 'New validity to:'
   extend_till; 
   @EndUserText.label: 'Enter your comments:'
   comments;
    
}

4. In Behavior Definition, define action “extendDoc” with parameter using the abstract entity created in step#2.

action extendDoc parameter ZRK_A_Doc_Extend result [1] $self;

SAP ABAP Tutorial and Material, SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Preparation

5. Implement the core ABAP logic for extend in Behavior Pool Class

METHOD extendDoc.

    DATA : lt_update_doc  TYPE TABLE FOR UPDATE zrk_i_doc_head.
    DATA(lt_keys) = keys.
    DATA(lv_today) = cl_abap_context_info=>get_system_date( ).

    LOOP AT lt_keys ASSIGNING FIELD-SYMBOL(<fs_key>).

      IF <fs_key>-%param-extend_till < lv_today.

        APPEND VALUE #( %tky                = <fs_key>-%tky ) TO failed-head.

        APPEND VALUE #( %tky                = <fs_key>-%tky
                        %msg                = new_message(  id       = 'ZRK_CM_DOC'
                                                            number   = '001' " Document cannot be extended into the past
                                                            severity = if_abap_behv_message=>severity-error )
                        %element-ValidTo = if_abap_behv=>mk-on ) TO reported-head.

        DELETE lt_keys.

      ELSE.
        DATA(lv_new_valid_to) = <fs_key>-%param-extend_till.
      ENDIF.

    ENDLOOP.

    " Once the validations are passed, proceed with extending document.
    CHECK lt_keys IS NOT INITIAL.

    READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
        ENTITY Head
        FIELDS ( ValidFrom ValidTo )
        WITH CORRESPONDING #( keys )
        RESULT DATA(lt_doc_head).

    CHECK lt_doc_head IS NOT INITIAL.

    LOOP AT lt_doc_head ASSIGNING FIELD-SYMBOL(<fs_head>).

      " Capture old valid to
      DATA(lv_old_valid_to) = <fs_head>-ValidTo.

      " Read items from entity
      READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
          ENTITY Head BY \_Items
          FIELDS ( ValidFrom ValidTo )
          WITH VALUE #( ( %tky = <fs_head>-%tky ) )
          RESULT DATA(lt_items).

      " Loop through items that are running on old valid to
      LOOP AT lt_items ASSIGNING FIELD-SYMBOL(<fs_item>)
                            WHERE ValidFrom LE lv_old_valid_to
                               AND ValidTo GE lv_old_valid_to.

        " Modify item with new valid to
        <fs_item>-ValidTo = lv_new_valid_to.

        " Read conditions from entity
        READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
            ENTITY Items BY \_Conds
            FIELDS ( ValidFrom ValidTo )
            WITH VALUE #( ( %tky = <fs_item>-%tky ) )
            RESULT DATA(lt_conds).

            LOOP AT lt_conds ASSIGNING FIELD-SYMBOL(<fs_conds>)
                                    WHERE ValidFrom LE lv_old_valid_to
                                     AND ValidTo GE lv_old_valid_to..

              <fs_conds>-ValidTo = lv_new_valid_to.

            ENDLOOP.

            " Modify conditions entity
            MODIFY ENTITIES OF zrk_i_doc_head IN LOCAL MODE
                ENTITY Conds
                UPDATE FIELDS ( ValidTo )
                WITH CORRESPONDING #( lt_conds ).

      ENDLOOP.

      " Modify Items entity
      MODIFY ENTITIES OF zrk_i_doc_head IN LOCAL MODE
            ENTITY Items
            UPDATE FIELDS ( ValidTo )
            WITH CORRESPONDING #( lt_items ).

    ENDLOOP.

    " Modify header entity
    MODIFY ENTITIES OF zrk_i_doc_head IN LOCAL MODE
        ENTITY Head
        UPDATE
        FIELDS ( ValidTo )
        WITH VALUE #( FOR <fs_doc> IN lt_doc_head
                        ( %tky = <fs_doc>-%tky
                          validTo = COND #( WHEN lv_new_valid_to IS NOT INITIAL
                          THEN lv_new_valid_to
                          ELSE <fs_doc>-ValidTo )  ) )
        REPORTED DATA(lt_update_reported).

    reported = CORRESPONDING #( DEEP lt_update_reported ).

    " Return result to UI
    READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
        ENTITY Head
        ALL FIELDS
        WITH CORRESPONDING #( keys )
        RESULT lt_doc_head.

    result = VALUE #( FOR <fs_doc_head> IN lt_doc_head ( %tky = <fs_doc_head>-%tky
    %param = <fs_doc_head> ) ).

  ENDMETHOD.

6. Position the Action button on List Report and Object Page using annotations.

  @UI: {

  lineItem: [
      { type: #FOR_ACTION,  dataAction: 'ExtendDoc' , label: 'Extend' , position: 90 } ] ,

  identification : [
      { type: #FOR_ACTION,  dataAction: 'ExtendDoc' , label: 'Extend' , position: 90 } ]
  }

No comments:

Post a Comment