Monday 29 June 2020

SAP ABAP Programming Model for FIORI- List Report Application (Part 2)

This is the second blog in this series. You can refer to the first blog in the below link:

SAP ABAP Programming Model for FIORI- List Report Application (Part 1)

In this blog we will be looking into BOPF part to enable the Determination, Validation and Action in our Fiori List report Application:

Let’s proceed with this tutorial. In last blog we have created a Transaction CDS on SPFLI Table.

Go to the CDS View and click on the highlighted dot, and then the link for the Generated BOPF Object as shown in below image:

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification


BOPF Path

The Generated Business Object will look as below. Click on ‘Go to Root Node’:

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

In the root Node we can see option to Navigate for Determination, Action and Validation

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

BOPF Root Node

Determination: It can be use to determine some value at runtime. In our case we are using it to generate the Primary key value at runtime.

To create a new Determination, click on the Determination link in above image and then click on ‘New’ Button.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

Give the name, description and Category as given below. (Ignore the error, I am receiving it as I have already created it)

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

Once created click on ‘Triggers Configured’ and enable it for create and update. You can also see the generated class for this determination where we will be writing our code:


SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

Now go into the generated class and write the below code:

class ZCL_IDEMO_D_CALCULATEKEYVALUES definition
  public
  inheriting from /BOBF/CL_LIB_D_SUPERCL_SIMPLE
  final
  create public .
public section.
  methods /BOBF/IF_FRW_DETERMINATION~EXECUTE
    redefinition .
protected section.
private section.
ENDCLASS.

CLASS ZCL_IDEMO_D_CALCULATEKEYVALUES IMPLEMENTATION.
  METHOD /bobf/if_frw_determination~execute.

    "Read data with the given keys (typed with combined type table)
    DATA lt_data TYPE ztidemo_ddl_spfli.
    "Call retrieve method of BOPF Framework
    io_read->retrieve(
      EXPORTING
        iv_node                 = is_ctx-node_key   " uuid of node name
        it_key                  = it_key            " keys given to the determination
      IMPORTING
        eo_message              = eo_message        " pass message object
        et_data                 = lt_data           " itab with node data
        et_failed_key           = et_failed_key     " pass failures
    ).
    IF eo_message IS NOT BOUND.
      eo_message = /bobf/cl_frw_factory=>get_message( ).
    ENDIF.

"Select Data from DB Table
    SELECT FROM spfli
      FIELDS carrid, MAX( connid ) AS max
      GROUP BY carrid
      INTO TABLE @DATA(lt_max_item).


    " Assign numbers to each newly created item and trigger the modification in BOPF
    LOOP AT lt_data REFERENCE INTO DATA(lr_data).
      IF lr_data->connid IS INITIAL.
"As the field is read only it will be always Initial in our case
        READ TABLE lt_max_item WITH KEY carrid = lr_data->parent_key REFERENCE INTO DATA(lr_max_item).
        IF sy-subrc = 0.
          lr_max_item->max = lr_max_item->max + 10.
        ELSE.
"Assign an Incremented value. In real case scenario we can get the new number from number range "function
          APPEND INITIAL LINE TO lt_max_item REFERENCE INTO lr_max_item.
          lr_max_item->max = lr_data->parent_key.
          lr_max_item->max = lt_max_item[ carrid = 'AA' ]-max + 1 .
          lr_max_item->carrid = 'AA'.
        ENDIF.

        " Fill leading zeros for ALPHANUM field on database
        lr_data->carrid = lr_max_item->carrid.
        lr_data->connid = |{ lr_max_item->max ALPHA = IN }|.
        lr_data->arrtime = sy-uzeit.
        lr_data->deptime = sy-uzeit.

        io_modify->update(
              EXPORTING
                iv_node           = is_ctx-node_key    " uuid of node
                iv_key            = lr_data->key       " key of line
                is_data           = lr_data            " ref to modified data
                it_changed_fields =
                      VALUE #( ( zif_idemo_ddl_spfli_c=>sc_node_attribute-zidemo_ddl_spfli-carrid )
                                                      (   zif_idemo_ddl_spfli_c=>sc_node_attribute-zidemo_ddl_spfli-connid )
                                                      (   zif_idemo_ddl_spfli_c=>sc_node_attribute-zidemo_ddl_spfli-arrtime )
                                                      (   zif_idemo_ddl_spfli_c=>sc_node_attribute-zidemo_ddl_spfli-deptime )
                                                      (   zif_idemo_ddl_spfli_c=>sc_node_attribute-zidemo_ddl_spfli-fltype )
                                                    )
        ). "Here you have to pass all the field name which you change or passing value
     ENDIF.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

Similarly create a new Validation by clicking on the Validation link under the root node. You can refer below image for the generated Validation:

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

BOPF Validation 

Validation: Validation are use to validate the Input Screen data.

In our case we are validating the Country From Field.

I have created a Message class with below messages

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

Message Class

Go to the generated validation class and write down the below code:

CLASS zcl_idemo_v_validatecountry DEFINITION
  PUBLIC
  INHERITING FROM /bobf/cl_lib_v_supercl_simple
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    METHODS /bobf/if_frw_validation~execute
        REDEFINITION .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS ZCL_IDEMO_V_VALIDATECOUNTRY IMPLEMENTATION.
  METHOD /bobf/if_frw_validation~execute.
    " Internal tab for Header Data
    " Created using reference to Generated Table Type
    DATA(lt_head) = VALUE ztidemo_ddl_spfli( ).
    " Get Header Data row under process
    io_read->retrieve(
    EXPORTING
    iv_node = is_ctx-node_key " Node Name
    it_key = it_key " Key Table
    IMPORTING
    et_data = lt_head " Data Return Structure
    ).
    " Instantiate Message Object if not bound
    IF eo_message IS NOT BOUND.
      eo_message = /bobf/cl_frw_factory=>get_message( ).
    ENDIF.
    "Loop the fetched records
    LOOP AT lt_head REFERENCE INTO DATA(lr_head).
      " Validate
      DATA ls_msg TYPE symsg.
      "If Country From is blank raise an error
      IF lr_head->countryfr IS INITIAL.
        ls_msg-msgty = 'E'.
        ls_msg-msgid = 'ZBOPF'.
        ls_msg-msgno = '000'.
      ELSE.
        "If entered Country is not valid raise an error
        SELECT COUNT(*) FROM t005 INTO @DATA(lv_count) WHERE land1 = @lr_head->countryfr.
        IF  lv_count = 0.
          ls_msg-msgty = 'E'.
          ls_msg-msgid = 'ZBOPF'.
          ls_msg-msgno = '001'.
        ENDIF.
      ENDIF.

      " Add Message
      IF NOT ls_msg IS INITIAL.
        eo_message->add_message(
        EXPORTING
        is_msg = ls_msg " Message
        iv_node = is_ctx-node_key " Node
        iv_key = lr_head->key " Instance key
        ).

        "Below step is important to stop the flow when error occurs
        DATA ls_key TYPE /bobf/s_frw_key.
        ls_key-key = lr_head->key.

        APPEND ls_key TO et_failed_key.

      ENDIF.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

In Case if Validation fails, the create or update process will not get complete and error will appear on the FIORI App screen as shown below:

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

Validation Errors

Finally we will be adding the Action to our BOPF:

Action: Usually we use it to perform some activity based on some event which cannot be handled in create, update or delete methods.

In our case we are creating a new record by referring to the selected one. The Action button is added to the UI view with the help of annotation mentioned in the Metadata Extension view for SPFLI.

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

To create a Action we need to navigate to the root node for the generated Business Object of SPFLI (Shown in the image earlier) and click on the Action link.

Click on the ‘New’ Button in next page and create new Action referring to the below Image.(Note that the Action Name should match to the dataAction Value mentioned in the Metadata Extension view file).

SAP ABAP Tutorial and Material, SAP ABAP Guides, SAP ABAP Learning, SAP ABAP Prep, SAP ABAP Certification

After the Action is created go to the generated class and write down the below code:

CLASS zcl_idemo_a_copy DEFINITION
  PUBLIC
  INHERITING FROM /bobf/cl_lib_a_supercl_simple
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    METHODS /bobf/if_frw_action~execute
        REDEFINITION .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_idemo_a_copy IMPLEMENTATION.

  METHOD /bobf/if_frw_action~execute.
    DATA: lr_head_ref TYPE REF TO data.

    DATA(lt_head) = VALUE ztidemo_ddl_spfli( ).
    DATA ls_head_ref TYPE zsidemo_ddl_spfli.

    " Retrieve the data from the Node
    io_read->retrieve(
    EXPORTING
    iv_node = is_ctx-node_key
    it_key = it_key
    IMPORTING
    et_data = lt_head
     ).

    "Copy the data from retrieved node
    LOOP AT lt_head REFERENCE INTO DATA(lr_head).
      ASSIGN lr_head->* TO FIELD-SYMBOL(<fs_head>).

      ls_head_ref-carrid = <fs_head>-carrid.
      "Increase the connection id by 10 to avoid the primary key violation error
      ls_head_ref-connid = <fs_head>-connid + 10.
      "Date and time cannot be kept blank else the OData Metadata will fail to load
      ls_head_ref-arrtime = sy-uzeit.
      ls_head_ref-deptime = sy-uzeit.
      ls_head_ref-countryfr = <fs_head>-countryfr.
      "Copy field data
      CREATE DATA lr_head_ref TYPE zsidemo_ddl_spfli.
      ASSIGN lr_head_ref->* TO FIELD-SYMBOL(<fs_head_ref>).
      IF <fs_head_ref> IS ASSIGNED.
        <fs_head_ref> = ls_head_ref.
      ENDIF.

      "Create Record
      io_modify->create(
            EXPORTING
                iv_node = is_ctx-node_key
                is_data = lr_head_ref
            IMPORTING
                ev_key = DATA(lv_copy_key)
            ).

    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

So here we are completed with this blog. We have successfully added the Determination, Validation and Action Node behavior to our BOPF. In the next blog we will see how to finally consume this view as a Fiori Application using SAP WebIDE.

No comments:

Post a Comment