Monday, 6 May 2024

Fiori PO Approver app Accept and Reject button customization from ECC backend

Many time there are custom requirements for which it requires the need of creating Enhancement in standard SAP functionality.

Overview: PO Approvers are maintained in Release Strategy. Once the PO is generated it is set to be approved by PO approvers based on the levels maintained in PPOME structure. Only then the PO will be set to 03 status in EKKO.

Pre-requisite: All the roles and authorization must be given to the approvers to access the PO Approval Tile in SAP Fiori.

Requirement: If the approver find the PO is incorrect, he will reject the PO. The rejection of PO must contain the rejection text. Since the Text is an optional there comes up the challenge to make it mandatory.

Fiori PO Approver app Accept and Reject button customization from ECC backend

Solution: 

There are many ways to do this 

1. Doing changes in Front-End using BTP/WEB IDE.

2. Making it mandatory from ECC

I chose the 2nd method since there was some issue in licensing the BTP and it was not configured correctly.

Making it mandatory from ECC

My PO tile looks like this 

Fiori PO Approver app Accept and Reject button customization from ECC backend

When the approver click on the Reject button , he must enter the Rejection note. If he doesn't then the PO should not be rejected.

Fiori PO Approver app Accept and Reject button customization from ECC backend

SAP has provided only few objects which can be modified without the BTP framework. PO Approval is one of it. The main thing to note and find the Odata.

How to find the OData which will can be used for my development?

You can find the OData from going to Fiori tile -> Do Frontend debugging-> Refresh the page-> Navigate to Network Tab -> Find Path starting with key words /sap/opu/odata

In my case the OData is GBAPP_POAPPROVAL
/sap/opu/odata/SAP/GBAPP_POAPPROVAL

Fiori PO Approver app Accept and Reject button customization from ECC backend

You can also find it through the XML file 

Fiori PO Approver app Accept and Reject button customization from ECC backend

Now you have the Standard OData name, it must be implemented so that it could connect with the backend system by providing the system name in External system. 

Odata Implementation: The ODATA deployment is Central HUB . We have separate GW systems for hosting Fiori Tiles.

Tcode : /n/iwfnd/maint_service

Fiori PO Approver app Accept and Reject button customization from ECC backend

Fiori PO Approver app Accept and Reject button customization from ECC backend

Fiori PO Approver app Accept and Reject button customization from ECC backend

Now one must get 200 response after connecting it with backend system. 
Tcode : /n/iwfnd/gw_client

Fiori PO Approver app Accept and Reject button customization from ECC backend

Till now OData is successfully configured. Now its time to find the BADI in ECC system to implement. 

Let me directly jump to the method which would be required to implement.
The method is Change SET_DECISION method

Fiori PO Approver app Accept and Reject button customization from ECC backend

Here the SAP Standard documentation is pretty clear about the way of processing. You can go through it.

Fiori PO Approver app Accept and Reject button customization from ECC backend

Accept : iv_decision = 1.
Reject : iv_decision  = 2.
If you want nothing should happen mark ev_decision_processed = 'X'. 

METHOD IF_GBAPP_EX_APV_PO_RDP~CHANGE_SET_DECISION.
" Standard Documentation: Do not delete

* This method can be used to enable execution of a workitem
* without updating a purchase order. The customer should
* implement the method and call a corresponding function to execute
* the workitem followed by COMMIT WORK.
* To avoid update of the purchase order, it is necessary to set the
* output parameter EV_DECISION_PROCESSED to 'X'.
* Preventing update of a document can be necessary, if the customer
* uses his own workflow where update of purchase order takes place
* in a separate background workflow step.
  IF iv_decision EQ 2.
    IF iv_rejection_text IS INITIAL.
      ev_decision_processed = 'X'.
    ELSE.
      DATA : t_return TYPE STANDARD TABLE OF  BAPIRET2.
      CALL FUNCTION 'ZFIORI_PO_APPROVAL_REJ_CHG' IN UPDATE TASK
        EXPORTING
          iv_ebeln = iv_pc_number
        TABLES
          t_return = t_return.
      COMMIT WORK.
    ENDIF.
  ENDIF.
ENDMETHOD.

As per my requirement if the approver accept I should not check anything and simply make it happen, hence I have not done anything with iv_decision = 1. If you want, you can add your custom requirement under it. 

For me I have marked ev_decision_processed = 'X', if rejection text/ note in not provided.
I have used a Update Task FM because these were the async call hence the system was giving dump while updating the EKKO. So as to correct this I have divided it in 2 Logical unit. A wait of 5 secs have introduced so that the previous task gets over.

Fiori PO Approver app Accept and Reject button customization from ECC backend

FUNCTION zfiori_po_approval_rej_chg.
*"----------------------------------------------------------------------
*"*"Update Function Module:
*"
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(IV_EBELN) TYPE  EBELN
*"  TABLES
*"      T_RETURN STRUCTURE  BAPIRET2
*"----------------------------------------------------------------------
*"*"Update Function Module:
  WAIT UP TO 5 SECONDS.
  DATA: lr_po           TYPE REF TO cl_po_header_handle_mm,
        ls_bapi         TYPE bapiret2,
        l_result        TYPE mmpur_bool,
        lv_procstat     TYPE ekko-procstat,
        ls_document     TYPE mepo_document.
  CONSTANTS: lc_status TYPE ekko-procstat VALUE '08',
             lc_set_status TYPE ekko-procstat VALUE '03',
             lc_process TYPE char16 VALUE 'PO_PROCESS',
*             lc_trtyp TYPE char1 VALUE 'VER',
*             lc_trtyp TYPE char1 VALUE 'V',
             lc_ind TYPE char40 VALUE 'RELEASE',
             lc_tcode TYPE SY-TCODE VALUE 'ME29N'.


  SELECT SINGLE procstat FROM ekko INTO lv_procstat WHERE ebeln =  iv_ebeln.
  IF lv_procstat EQ lc_status.
*  prepare creation of PO instance
    ls_document-process     = 'PO_PROCESS'.
    ls_document-trtyp       = 'VER'.
    ls_document-doc_key(10) = iv_ebeln.
    ls_document-initiator-initiator = 'RELEASE'.

    CREATE OBJECT lr_po.
    lr_po->for_bapi = 'X'.
    lr_po->po_initialize( ls_document ).
    lr_po->set_po_number( iv_ebeln ).

    CALL FUNCTION 'MEPO_DOC_READ'
      EXPORTING
        im_ebeln                       = iv_ebeln
        im_tcode                       = lc_tcode"'ME29N'
        im_trtyp                       = ls_document-trtyp
*    IM_ID                          =
        im_document                    = ls_document
*   IM_NO_MESSAGING                =
*   IM_NO_MESSAGE_REQ              =
*   IM_NO_AUTHORITY                =
* EXCEPTIONS
*   DOC_NUMBER_MISSING             = 1
*   TRANSACTION_CODE_MISSING       = 2
*   TRANSACTION_TYPE_MISSING       = 3
*   INVALID_CALL                   = 4
*   OTHERS                         = 5
              .
    IF sy-subrc <> 0.
* Implement suitable error handling here
    ENDIF.
    DATA : ex_data  LIKE  mepoheader.
    CALL FUNCTION 'MEPO_DOC_HEADER_GET'
      IMPORTING
        ex_ekko = ex_data.

    IF cl_process_state_mm=>is_allowed(
                     im_bstyp   = ex_data-bstyp
                     im_state   = ex_data-procstat
                     im_process = cl_process_state_mm=>c_pr_reset_rej )
                                                          EQ mmpur_no.
      MESSAGE e806(mepo) WITH ex_data-procstat RAISING failed.
    ENDIF.
    ex_data-procstat = cl_process_state_mm=>c_active.
    lr_po->set_data( ex_data ).

    UPDATE ekko SET procstat = lc_set_status WHERE ebeln EQ iv_ebeln.
*    UPDATE ekko SET PROCSTAT = ex_data-procstat where ebeln eq iv_ebeln.
  ENDIF.

ENDFUNCTION.

No comments:

Post a Comment