In this blog I will explain how to create new variant for PO FPM component configuration. Also, will show you how to call this new variant based on custom logic. This can be used, if we need to display different buttons/tabs in PO screen when accessed from different places.

 

  1. Go to SE80, go to component FPM_OIF_COMPONENT and expand component configuration node and select configuration ZENH_SAPSRM_WDCC_PO_PURCH ( In my case I already had created a custom variant with delegation to standard configutaion)

img1.jpg

2. Click on ‘Start Configurator’. This will open up configuration screen in a browser

2.png

 

3. Click on ‘Change’ button. You will see a pop-up asking for transport request. Select the existing request or create a new one.

4. Click on ‘Copy’ button and select ‘Variant’

4.png

5. A new pop-up window asking for new variant name will appear on the screen

5.png

6. Click on ‘Copy’.

7. All mainview and subview IDs have ‘_1’ appended at the end

 

Mainview ‘Header’

6.png

 

Subview ‘Notes and Attachments’

7.png

 

8. In general we don’t have to change these IDs, but in case of PO, we faced an issue with PO item details button. Below error appears when we click on ‘Details’ button at item level.

8.png

Because of this reason, we had to change the mainview ID from PO_ITM_1 to PO_ITM

 

9.png

 

9. To hide a button from the screen, select the button and choose ‘Is not visible’ option from ‘Visibility’ dropdown.

10.png

10. Finally click on ‘Save’.

 

How to call the new variant from ABAP code:

Create an implicit enhancement in method HANDLE_VIEW_SWITCH_VISIBILITY of class /SAPSRM/CL_FPM_OVRIDE_OIF and call method SET_VARIANT’ of interface IF_FPM_OIF ( mo_fpm_oif variable in the method ).

 

 

Thanks for taking time and reading the blog.

In this Blog I am going to talk to about, how to interrupt the standard FPM actions and induce our custom logic and then continue with the execution of standard code. Instead of just explaining the methodology, I would like to state an imaginary requirement and explain the methodology as we fulfill the requirement. Here is the most amazing requirement you have ever heard

 

When we click on EDIT button on PO screen, user should get a pop-up which will have some check boxes, each referring to a particular field of PO. Once the user selects some check box and clicks on OK button, corresponding field and label should be removed from the screen. Below is screen shot of how it should look

 

edit button.JPG

 

Now on a high level, we should know which code gets triggered when we click on EDIT button, enhance it and include the code to generate a pop-up screen. Also when we click on OK button execute whatever logic we want to execute and then let the standard code get execute.

 

How to figure out the code that gets executed when we click on EDIT button:

 

The header buttons in PO screen are not part of any particular webdynpro component. This makes it difficult to debug these actions. We have to go to the corresponding AppCC component ( refer to my blog to know more about AppCC ( Dynamically Modifying Purchase order FPM in SRM7 using custom AppCC) and debug the component controller method OVERRIDE_EVENT_OIF to figure out what code gets executed when we click on EDIT button. Below are the details

 

- control first goes to the statement  wd_this->mo_oif_helper->override_event_oif( ). Here mo_oif_helper refers to class /SAPSRM/CL_FPM_OVRIDE_OIF.

 

- once inside the method OVERRIDE_EVENT_OIF of class /SAPSRM/CL_FPM_OVRIDE_OIF, control goes to the statement

 

mo_ident_mapper->handle_event(

            EXPORTING io_event = mo_fpm_oif->mo_event ).

 

Here mo_ident_mapper refers to class /SAPSRM/CL_CH_WD_IDEN_MAP_PO. Inside the method handle_event is the code related to respective action.

 

How to generate a pop-up dialog box:

 

To do this, first we enhance the AppCC component and create a View ( POP_VIEW), a  window (POP_WIN) and embed the view inside the window. Also, add two check box with descriptions as shown in the above screen shot ( I assume reader knows how create view, window and check boxes, so i am not going to explain that in detail here ).

 

enhwdconf.JPG

Layout of the view

layout.JPG

 

Create two context attributes and bind them to 'Checked' property of the check-box

 

context.JPG

 

Once we have everything ready, we go to the method  HANDLE_EVENT method of class  /SAPSRM/CL_CH_WD_IDEN_MAP_PO, create an implicit enhancement and insert the below code.

 

DATA lo_window_manager TYPE REF TO if_wd_window_manager.

  DATA lo_api_component  TYPE REF TO if_wd_component.

  DATA lo_api_controller TYPE REF TO if_wd_controller.

  DATA lo_window         TYPE REF TO if_wd_window.

  *check if the event is EDIT

  IF  io_event->mv_event_id = 'FPM_EDIT'.

*check if pop up is required

    IF zcl_popup=>popup_req EQ 'X'.

 

 

      lo_api_controller  =  mo_wd_component_controller->wd_get_api( ).

 

 

      CALL METHOD lo_api_controller->get_component

        RECEIVING

          component = lo_api_component.

 

*get access to window manager

      lo_window_manager = lo_api_component->get_window_manager( ).

 

*create window

      lo_window         = lo_window_manager->create_window(

      window_name            = 'POP_WIN'

      title                  = 'Please selct...'

      message_display_mode   = if_wd_window=>co_msg_display_mode_selected

      close_button           = abap_false

      button_kind            = if_wd_window=>co_buttons_ok

      message_type           = if_wd_window=>co_msg_type_none

      default_button         = if_wd_window=>co_button_ok

      ).

 

 

* Set the height and width here

      lo_window->set_window_size( width = '20%' height = '15%' ).

      lo_window->open( ).

      EXIT.

    ENDIF.

  ENDIF.

To your surprise, most important piece of code in the above code is 'EXIT' statement. If we don't exit from the method after raising the pop up, what happens is, we get the pop-up BUT system continues with the afterwards code and removes the pop-up from the screen. So, we will not be able to select any check box on the pop-up. In order for pop-up to stay on the screen, till we select something on the screen and click on OK button, we have to exit the method. But there is a catch here... If we exit the method,  we are skipping the actual code related to EDIT action. So, we have to somehow re trigger the action EDIT, once we are done with check box selection on pop-up ( Just to keep the suspense alive, I will come back to this later )

 

I have created a class with name ZCL_POPUP and added three static attributes as shown below

 

staticclass.JPG

Here POPUP_REQ attribute is used to check, if pop-up needs to be created or not ( by default it is set to 'X'). Attributes CHECK1 and CHECK2 are used to capture the selection made by the user on pop-up screen.

 

Let's look at what happens in the view POP_VIEW...

 

In WDDOMODIFYVIEW method,  we use the below code to assign an action to button OK on pop-up

 

  DATA:l_api TYPE REF TO if_wd_view_controller,

       l_window_ctlr TYPE REF TO if_wd_window_controller,

       l_popup TYPE REF TO if_wd_window.

 

 

  l_api = wd_this->wd_get_api( ).

  l_window_ctlr = l_api->get_embedding_window_ctlr( ).

 

 

  IF l_window_ctlr IS BOUND.

    l_popup = l_window_ctlr->get_window( ).

 

 

    l_popup->subscribe_to_button_event(

       button = if_wd_window=>co_button_ok

       action_name = 'OK'

       action_view = l_api

       is_default_button = abap_true ).

 

 

  ENDIF.

 

we also add an event with name OK, this creates an event handler with name ONACTIONOK in methods tab of the view POP_VIEW. In the action handler we write the below code

 

DATA: lo_fpm TYPE REF TO if_fpm.

  DATA lo_el_context TYPE REF TO if_wd_context_element.

  DATA ls_context TYPE wd_this->element_context.

  DATA lv_check1 TYPE wd_this->element_context-check1.

  DATA lv_check2 TYPE wd_this->element_context-check2.

 

 

*clear static attribute popup_req

 

  CLEAR zcl_popup=>popup_req.

 

* get element via lead selection

  lo_el_context = wd_context->get_element( ).

 

 

* read context attributes check1 and check2

  lo_el_context->get_attribute(

    EXPORTING

      name =  `CHECK1`

    IMPORTING

      value = lv_check1 ).

 

 

  lo_el_context->get_attribute(

     EXPORTING

       name =  `CHECK2`

     IMPORTING

       value = lv_check2 ).

 

*set the static variables 

  zcl_popup=>check1 = lv_check1.

  zcl_popup=>check2 = lv_check2.

 

*Get rererence to current FPM instance

  lo_fpm = cl_fpm_factory=>get_instance( ).

 

*Trigger the EDIT action again 

  CALL METHOD lo_fpm->raise_event_by_id

    EXPORTING

      iv_event_id = 'FPM_EDIT'.

 

Here we are reading the context attributes CHECK1 and CHECK2 and store the values in static attributes of the class ZCL_POPUP. Then using raise_event_by_id method we are re triggering event FPM_EDIT ( suspense is over now..   )

 

Now to Hide the PO number and PO name fields from the overview, we can use the BADI WD_BADI_DOMODIFYVIEW. Create an implementation with below filter

 

badifilter.JPG

 

Inside the method IF_WD_BADI_DOMODIFYVIEW~WDDOMODIFYVIEW, write below code

 

DATA : lo_ref TYPE REF TO cl_wd_transparent_container.

 

  lo_ref ?= view->get_element( 'LEFT_CONTAINER' ).

 

  IF zcl_popup=>check1 EQ 'X'.

 

    IF lo_ref IS NOT INITIAL.

      lo_ref->remove_child( id = 'PO_NUMBER_LABEL' ).

      lo_ref->remove_child( id = 'PO_NUMBER' ).

    ENDIF.

 

  ENDIF.

 

 

  IF zcl_popup=>check2 EQ'X'.

 

    IF lo_ref IS NOT INITIAL.

      lo_ref->remove_child( id = 'PO_NAME_LABEL' ).

      lo_ref->remove_child( id = 'PO_NAME' ).

    ENDIF.

 

  ENDIF.

 

 

Here based on values of static attributes CHECK1 and CHECK2 of class ZCL_POPUP, we conditionally remove PO number / PO name fields from the PO screen

 

DEMO:

 

User clicks on EDIT button on PO screen, which triggers a pop-up that has two check boxes on it. User selects both the check boxes and clicks on OK button.

clickok.JPG

After OK button is clicked, PO number and PO name fields are removed from the overview screen.

 

pofinal.JPG

 

I am sure that there might be a better solution for this and  I sincerely welcome all the suggestions from readers.

 

Finally, I would like to thank Matteo Montalto  for his invaluable contribution towards this blog.

This is in continuation of the blog http://scn.sap.com/community/web-dynpro-abap/floorplan-manager/blog/2012/04/08/dynamically-modifying-purchase-order-fpm-in-srm7-using-custom-appcc I had writen about customising standard PO screen ( Adding custom MAIN / SUBVIEWS and changing standard MAIN / SUBVIEWs) in SRM7. In this blog I will talk about how do we access PO details in Custom subview that we had added in previous blog.

 

Here is the screenshot of how the screen looks after making changes accrording to the previous blog

 

poscreen.JPG

 

I have added an input field to the view of component YTEST. Now I would like to access the PO description and display it in the input field. To achieve this we need to access the FPM instance inside the WDDOINIT method of YTEST compoenent controller and access the attribute MO_APP_PARAMETER of interface IF_FPM. Once we have the reference to this attribute ( which is of type IF_FPM_PARAMETER) we can use GET_VALUE( ) method to read different parameter values. Below is the sample code on how to read the PO GUID

 

* Instantiate the FPM Manager

     DATA: lo_fpm TYPE REF TO if_fpm,

           lo_appdata type ref to IF_FPM_PARAMETER,

           lv_value type string,

           lv_guid type CRMD_ORDERADM_H-GUID,

           ls_header type BBP_PDS_PO_HEADER_D.

*access the attribute containing different parameters

     lo_fpm = cl_fpm_factory=>get_instance( ).

     lo_appdata = lo_fpm->MO_APP_PARAMETER.

*get the po guid

CALL METHOD lo_appdata->get_value

   EXPORTING

     iv_key   = 'SAPSRM_BOID'

   IMPORTING

     ev_value = lv_value.

 

lv_guid = lv_value.

*once we have the GUID we can access all the details of the PO   

CALL FUNCTION 'BBP_PD_PO_GETDETAIL'

  EXPORTING

    I_GUID                           = lv_guid

  IMPORTING

    E_HEADER                         = ls_header.

 

After getting the PO header details in ls_header, set the context attribute which is binded to the input field to ls_header-description. See the code below ( this code can be generated by code wizard)

 

  DATA lo_nd_node TYPE REF TO if_wd_context_node.

   DATA lo_el_node TYPE REF TO if_wd_context_element.

   DATA ls_node TYPE wd_this->element_node.

   DATA lv_ponumber TYPE wd_this->element_node-ponumber.

 

* navigate from <CONTEXT> to <NODE> via lead selection

   lo_nd_node = wd_context->get_child_node( name = wd_this->wdctx_node ).

 

* get element via lead selection

   lo_el_node = lo_nd_node->get_element( ).

 

* set single attribute

   lo_el_node->set_attribute(

     name =  `PODESCR`

     value = ls_header-description).

 

fillinput.JPG

I have listed down below different application parameters that are available for us to access. Unfortunately there is no description available for each of the parameters. If you want to know the value that each parameter holds at runtime, you have to debug and see it. To do that put an external breakpoint  at statement

'lt_app_params = LO_APPLICATION_INFO->GET_APPLICATION_PARAMETERS( ). '

inside the method INITIALIZE_APP_PARAMETERS of class CL_FPM_FLOORPLAN_ASSIST

Here is the list of parameter names

 

Name of the parameter
SAPSRM_ACTION
SAPSRM_BOID
SAPSRM_BOSUBTYPE
SAPSRM_BOTYPE
SAPSRM_CA_TAB
SAPSRM_CONTACTID
SAPSRM_DOC_NUMBER
SAPSRM_ITEMID
SAPSRM_KW_ID
SAPSRM_MODE
SAPSRM_NWBC_HTML
SAPSRM_PARENT_BOID
SAPSRM_PCDLOCATION
SAPSRM_PORTALBASEURL
SAPSRM_PROCESSTYPE
SAPSRM_PROGRESS_SHM_ID
SAPSRM_PS
SAPSRM_TEMPLATEID
SAPSRM_TX_CONTEXT_ID
SAPSRM_VIEW_SWITCH
SAPSRM_WIID
SRM_TEMPLATE

 

If you are wondering how we are able to access FPM instance inside our custom component methods, here is a brief explanation.

 

*access the attribute containing different parameters

     lo_fpm = cl_fpm_factory=>get_instance( ).

 

The above static method call enables us to get a reference to the FPM instance, eventhough we did not explicitly create an instance of class CL_FPM. So where did it get instantiated in the first place? To understand it we need to go inside componentcontroller WDDOINIT method of  component FPM_OIF_COMPONENT ( This is the core component underlying most of the FPM applications in SRM7) . In this method, below code creates an object for CL_FPM

 

CREATE OBJECT wd_this->mr_fpm

     EXPORTING

       io_floorplan  = wd_this->mr_oif_api

       io_controller = wd_this.

 

Initialization of IDR component and AppCC component is also done inside the WDDOINIT method.

 

The constructor method of the class CL_FPM stores the instance in global private static attribute GO_INSTANCE. FPM message manager is also instantiated inside the constructor method. The static method GET_INSTANCE   reads this attribute and returns it as returning parameter. So in short, the FPM instance is available to all the UIBB components.

 

I hope this blog brings in in-depth understanding of how to access business object details inside custom UIBBs. Thanks for taking time and reading my blog.

 

thanks,

sankar.

This blog is intended for ABAP webdynpro developers working in SRM7 with good knowledge on FPM.  Most of the requirements we encounter in projects involves modifying web ui components. Almost all of the applications in SRM are built based on ABAP webdynpro FPM. Modifying FPM based applications is bit different than modifying normal ABAP webdynpro applications. In the coming sections we will see different methods of achieving this.

 

If you are not familiar with webdynpro go through the below links first to get a hang of ABAP webdynpro

 

http://fuller.mit.edu/web_dynpro/WebDynproABAPpart1.pdf

http://fuller.mit.edu/web_dynpro/WebDynproABAPpart2.pdf

http://fuller.mit.edu/web_dynpro/WebDynproABAPpart3.pdf

 

If you are familiar with ABAP webdynpro but not with FPM go through the below docs and elearning material first.

 

http://www.****************/Tutorials/WebDynproABAP/FloorPlanManager/Page1.htm

 

http://www.****************/Tutorials/WebDynproABAP/FloorPlanManager/GAF2.htm

 

go through the below excellent e learning material on SDN.

http://wiki.sdn.sap.com/wiki/display/WDABAP/eLearning+Tutorials+-+Floorplan+Manager+for+Web+Dynpro+ABAP

 

after the above tutorial download the developer guide from the link below

http://scn.sap.com/docs/DOC-26081

 

Ok... enough of material.. let's get into some action now....

 

Basically there are three ways of modifying the PO FPM elements depending on the requirement.

 

1. If you want to hide/remove  MAIN/SUBVIEWS or indivudual UIBBs contained in them and you want to make these changes visible across all roles then enhance the standard component configuration and make the necessary changes.

 

2. If you want hide/remove fields with in specific UIBB ( for example you want to hide PO number  field in 'Overview* tab ) based on some logic.  you can use WD_BADI_DOMODIFYVIEW BADI, create an implementation with filters  component  '/SAPSRM/WDC_PO_DOFC_OV_HD ' and view  'V_PO_DOFC_OV_GN_HD '  and write the below code (to get the component and view name , right click on the field in web ui and go to 'more field help')

 

DATA : lo_ref TYPE REF TO cl_wd_transparent_container.

 

   lo_ref ?= view->get_element( 'LEFT_CONTAINER' ).

   IF lo_ref IS NOT INITIAL.

 

     lo_ref->remove_child( id = 'PO_NUMBER_LABEL' ).

     lo_ref->remove_child( id = 'PO_NUMBER' ).

 

   ENDIF.

 

3. If you want to hide/remove/add  MAIN / SUBVIEWS based on some logic, then you have to follow the method I mentioned below.

 

First let's look at the standard purchase order display screen and understand the difference components and configurations that it uses.

 

Login with the employee role and go to shopping area->My Pos POWL query where you will see bunch of POs. Open any of the PO by clicking on it. Right click on any of the tabs ( Overview, Header, Approval etc., ) and go the 'More field help' of the UI element. You will see below information

 

Header 1Header 2
Application /SAPSRM/WDA_L_FPM_OIF
Webdynpro componentFPM_OIF_COMPONENT
Window Information FPM_WINDOW
View InformationCNR_VIEW
Configuration ID/SAPSRM/WDCC_FPM_OIF_PO_PURCH


 

Now go to component FPM_OIF_COMPONENT from SE80 and locate the application /SAPSRM/WDA_L_FPM_OIF. This application will have different application configurations associated with it.  We need to figure out which application configuration is getting called at run time. To know this we need to go to PFCG and see the Employee role, go to 'display purchase order' webdynpro application and click on details button.

pfcg.JPG

 

Now double click on application configuration /SAPSRM/WDAC_I_FPM_OIF_PO_PURCH and select 'Start Configurator', which will take you to application configuration browser window. Click on 'Other funcitons' dropdown button and select create enhancement. This will open up a pop up window asking for the name of new configuration, description and package. Enter a configuration name starting with Z or Y and click OK

 

newappconfig.JPG

 

click on 'Create' button to go to the individual component configuration view. The component configuration that is currently used by application is displayed there.

 

compconfig.JPG

we need to create an enhancement for this component configuration as well and use it in the apllication configuration enhancement. To create enhancement for component configuration /SAPSRM/WDCC_FPM_OIF_PO_PURCH, expand the component configuraiton section of FPM_OIF_COMPONENT and locate the configuration /SAPSRM/WDCC_FPM_OIF_PO_PURCH. start the configurator and select 'create enhancemnet' from the 'other functions' button dropdown. Enter any name starting with Z or Y and select OK. save the configuration. Now replace /SAPSRM/WDCC_FPM_OIF_PO_PURCH with the Z component configuration that we just created

 

newcompconfig.JPG

After this is done click on 'go to compoent configuration' and select 'change' -> 'global settings'. you will see under 'application specific parameters' , webdynpro component and confguration used for AppCC.

appcc.JPG

we need to create our own custom AppCC component by copying the standard WD component /SAPSRM/WDC_FPM_OIF_CONF and component configuration /SAPSRM/WDCC_FPM_APPCC_PO_PURCH. Go to se80 and create both ( configuration can not be copied. so just look at the standard configration /SAPSRM/WDCC_FPM_APPCC_PO_PURCH and creata Z  configuration similar to it ).

 

 

Once we have created the custom AppCC component and configuration, replace the standard AppCC component and configuration with custom ones.

 

appccchange.JPG

Ok... we are done with the enhancement part . As we have created a custom AppCC component, we can now add/remove main/subviews as we want. let's look at a simple scenario.

 

The requirement is to change the name of the 'Header' mainview to 'Header after change' and remove the subview 'Budget' from the mainview 'Header' and also add a new subview with name ' FPM is Cool' which holds a custom component ( YTEST ) as an UIBB.

 

The above requirement can be achived by just changing the custom component configuration ZENH_SAPSRM_WDCC_PO_PURCH that we had created earlier. But what if we need to do that based on some logic, we need a place to write the code. This is where the interface method OVERRIDE_EVENT_OIF of AppCC component comes into picture. Go to the component controller of component  ' ZWDC_FPM_OIF_COMP ' and open the method OVERRIDE_EVENT_OIF' and write the below code at the end.

 

  TYPES:

     BEGIN OF ty_s_uibb,

            component            TYPE string,

            interface_view       TYPE string,

            config_id            TYPE wdy_config_id,

            config_type          TYPE wdy_config_type,

            config_var           TYPE wdy_config_var,

            needs_stretching     TYPE fpm_needs_stretching,

            location             TYPE fpm_location,

            index                TYPE fpm_index,

          END OF ty_s_uibb .

   DATA: ls_uibb TYPE ty_s_uibb,

             lt_uibb TYPE STANDARD TABLE OF ty_s_uibb .

   ls_uibb-component = 'YTEST'.

   ls_uibb-interface_view = 'YTEST'.

   APPEND ls_uibb TO lt_uibb.

   CASE io_oif->mo_event->mv_event_id.

     WHEN 'FPM_START'.

       TRY.

*rename the main view Header to Header after change

         CALL METHOD io_oif->rename_mainview

           EXPORTING

             iv_variant_id  =  'PO_PUR'

             iv_mainview_id =  'PO_HDR'

             iv_new_name    =  'Header After Change'

*remove subview 'Budget' under main view Header            .

           CALL METHOD io_oif->remove_subview

             EXPORTING

               iv_variant_id  = 'PO_PUR'

               iv_mainview_id = 'PO_HDR'

               iv_subview_id  = 'Budget'.

 

add subview FPM is coll in Header mainview

           CALL METHOD io_oif->add_subview

             EXPORTING

               iv_variant_id   = 'PO_PUR'

               iv_mainview_id  = 'PO_HDR'

               iv_subview_id   = 'mysubview'

               iv_subview_name = 'FPM is Cool'

               it_uibb         = lt_uibb.

         CATCH cx_fpm_floorplan .

       ENDTRY.

   ENDCASE.

 

This is how PO screen looks after the code change. Header description is changed, 'Budget' subview is removed and there is a new subview with name ' FPM is Cool' added.

fpmafterchange.JPG

If you now click on subview 'FPM is Cool', you can see the custom component YTEST ( I had created a simple component YTEST with single button and some text)

fpmcool.JPG

 

NOTE: The other option to achieve the above functionality would be to create a post-exit for OVERRIDE_EVENT_OIF method of component controller for WD component  /SAPSRM/WDC_FPM_OIF_CONF and write the code in the post-exit.

 

I hope this blog will be of some help to ABAP webdynpro developers working in SRM 7.

 

Thank you so much for reading the blog

 

thanks,

sankara rao bhatta.

Filter Blog

By author: By date:
By tag: