How to display a z-table in an assignment block

Description

You have a z-table in your ERP system which you would like to display on the CRM WebUI in its own Assignment Block. Let's say this table even depends on one of the objects of CRM; the Business Partner (henceforth called just partner or BP).
This guide describes step by step a possible way to do this. Please note that there might be other, easier ways and what is described below is what I found out and it worked for me so I thought it could work for others too.

Technical data

Before I start a development, I always like to know all the technical data and write them down so I don't have to look them up all the time during developing.
I said before this z-table has data which belongs to partners. This means I have to find out the Overview Page for the BP details display - there we will eventually add our assignment block.

Component: BP_HEAD
View:      BPHEADOverview

Development Step-by-Step

1. Create a Structure and Table type

We need a structure and a table type in the CRM system which look the exact same as the table in the ERP system. Let's assume this table in the ERP system contains the favorite color, meal and sport of a partner (not saying that makes much sense but it's easier if we have an example). So the structure could look something like this:

Component Description
MANDT Client
PARNR Partner Number
COLOR Favorite Color
MEAL Favorite Meal
SPORT Favorite Sport
Structure:  ZBP_FAVS_S
Table type: ZBP_FAVS_TAB

2. Create Component & Window

To add a new, custom assignment block must we create our own component (with a window) and view. This is done in the BSP Component Workbench - transaction BSP_WD_CMPWB.
Type in a suitable name for the Component and choose create (also remove the Enhancement Set, if existing). Follow the instructions and name the Window.

Component: ZBP_FAVS
Window:    MainWindow

3. Create View & Context Nodes

Display the newly created component and and in the tree on the left side right-click on View and choose Create View.Do changes in following steps of the wizard:

  • Define Name: type in a suitable name for the view
  • Add Model Node: because the data from the z-table is dependent on the BP we have to add a Context Node which has the corresponding BOL entity. The Business Partner header data has the BOL entity BuilHeader. Add the model node PARTNER with that BOL Entity.
  • Add Value Node: we need a value node for our z-table (which will become a node for a table in Select View Type). Simply type a name for the node.
  • Add Model Attributes to Model Node: here we decide which attributes of the partner (header data) we would like to have. In our case we only need the partner number. Add it with the plus-icon.
  • Add Value Attributes to Context Node: here we have to add every component (field) of our table. This is best done with the plus-icon. Choose the correct Context Node (the Value Node for the z-table) and type in the structure we created in Step 1. Press enter, mark all attributes and add them.
  • Select View Type: choose View Type "Table View" and the Context Node we created for the z-table in Add Value Node.

Finish the wizard.

View:          ZBPFavorites
Context Nodes: PARTNER (Model Node with BOL Entity BuilHeader)
               ZBP_FAVS (Value/Table Node like Structure ZBP_FAVS_S

4. Set Runtime Repository

The tree to the left side in the Component Workbench can display different things. The normal one is Browse Component Structure. In order to change the Runtime Repository click on Runtime Repository Editor and after click on the edit-icon. We have to do three steps:

  • Add View to Window: Open the Window node, find your window, right click on it and choose Add View. Select the view you created in Step 3.
  • Add Window to Component Interface: Open the Component Interface node, right click on Interface View and choose Add. Select your Window and View.
  • Add Component Usage: Open the Component Usages node, right click on Component Usage and choose Add Interface View. Select the Interface View you added above.

Save the Runtime Repository with the disc-icon.

5. Bind Model Node with Component Controller

Go back to  Browse Component Structure.
The Model Context Node we created in Step 3 now needs to be bound to the Component Controller. This will make sure that when our z-component is called all the attributes from the BOL entity are passed to our node.
Double click on Component Controller, right click on Context Node and choose Create. Follow the wizard and create the same Model Node as in Step 3 (preferably also with the same name).

Context Nodes: PARTNER (Model Node with BOL Entity BuilHeader)

Double click the View we've created in Step 3. Open the node Context and double click on the Context Implementation Class. Locate the method CREATE_PARTNER (Model Node) and go into its coding. Add the binding to the Component Controller at the end of the method as shown below:

Context Class: ZL_ZBP_FAVS_ZBPFAVORITES_CTXT
Method:        CREATE_PARTNER
 * data binding with Component Controller 'PARTNER'
   owner->do_context_node_binding(
            iv_controller_type  = cl_bsp_wd_controller=>co_type_component
            iv_target_node_name = 'PARTNER'
            iv_node_2_bind      = partner ).

6. Create refresh Event for dependent Value Node

Our table is dependent on the partner - therefore do we need to create an Event that refreshes the table display whenever the partner changes.
Double click the view, open the nodes Context and Context Node, open the Table Node ZBP_FAVS and double click its Implementation Class. Go into edit mode and add a new method called ON_NEW_FOCUS. Open the method-attributes (puzzle-piece-icon) and tick "Event Handler for" (see the box below). Go to the Parameters and add the parameters of the Event by clicking on the icon with the small blue square. We leave the coding empty for now.

Impl. Class: ZL_ZBP_FAVS_ZBPFAVORITES_CN01
Method:      ON_NEW_FOCUS (Event Handler)
Event Class: CL_BSP_WD_COLLECTION_WRAPPER
Event:       NEW_FOCUS
Parameters:  FOCUS_BO (Importing - Type Ref To - IF_BOL_BO_PROPERTY_ACCESS)

Now we have to call this Event Handler. Go into the Context Class (just like in Step 5) and open the coding of method CREATE_ZBP_FAVS (Value/Table Node). Add the call of method ON_NEW_FOCUS depending on the Model Node as shown below:

Context Class: ZL_ZBP_FAVS_ZBPFAVORITES_CTXT
Method:        CREATE_ZBP_FAVS
* dependent node settings
  coll_wrapper = partner->get_collection_wrapper( ).
  TRY.
      entity ?= coll_wrapper->get_current( ).
    CATCH cx_sy_move_cast_error.
  ENDTRY.
  IF entity IS BOUND.
    zbp_favs->on_new_focus( focus_bo = entity ).
  ENDIF.

7. Get data from the ERP System

Now our component is ready to be filled with data. So we have to create a RFC function module in the ERP system which later will be called from the CRM system.
The only two parameters needed are the Partner Number (as importing) and the table with the favorite things (as exporting). Code a simple SELECT statement which gets the data from the database table.

Function Module: Z_CRM_GET_FAVS_FOR_BP (Remote Enabled)
Import:          IV_PARTNER (Type - BU_PARTNER)
Export:          ET_FAVS (Type - ZBP_FAVS_TAB)

8. Fill the Table Node with data

The next step is to get the data from the ERP system into the CRM. We do this in the Event Handler method ON_NEW_FOCUS which we created in Step 6 (so that every time the partner is changed, the new data from the ERP system is selected). Following coding is a possible way to do it:

data: lr_wrapper     type ref to  cl_bsp_wd_collection_wrapper, " BP collection wrapper
        lr_entity      type ref to  if_bol_bo_property_access,    " wrapper entity
        lv_bp_nr       type         string,     " BP (business partner) number as string
        lv_partner     type         bu_partner, " BP number in correct format (for RFC call)

        ls_smof_erpsh  type         smof_erpsh, " structure of the RFC destination

        lr_col         type ref to  if_bol_bo_col,        " collection to fill node ZBP_FAVS
        lr_valuenode   type ref to  cl_bsp_wd_value_node, " value nodes to fill a collection
        lr_tabline     type ref to  zbp_favs_s,   " table line reference to fill value node
        lt_favs        type         zbp_favs_tab, " local table with data from ERP-table ZBP_FAVS
        ls_favs        type         zbp_favs_s.   " local structure of table above

* get partner entity and partner number
  try.
      lr_entity ?= focus_bo.
    catch cx_sy_move_cast_error.
      return.
  endtry.
  lv_bp_nr = lr_entity->get_property_as_string( 'BP_NUMBER' ).
  if lv_bp_nr is initial. " no partner...
    return. "...return without selection
  endif.

* get RFC destination of ERP system, if needed
  if ZL_ZBP_FAVS_ZBPFAVORITES_IMPL=>gv_destination is initial.
    call function 'CRM_GET_ERP_SYSTEM'
*     exporting
*       iv_rfcdest    =
*       iv_siteid     =
     importing
       es_smof_erpsh = ls_smof_erpsh.
    if sy-subrc = 0 and ls_smof_erpsh-rfcdest is not initial.
      ZL_ZBP_CUCL_ZCURRENCYCLAU_IMPL=>gv_destination = ls_smof_erpsh-rfcdest.
    endif.
  endif.

* get favorite things for partner
  lv_partner = lv_bp_nr.  " call RFC function in ERP system
  call function 'Z_CRM_GET_FAVS_FOR_BP'
    destination ZL_ZBP_CUCL_ZCURRENCYCLAU_IMPL=>gv_destination
    exporting
      iv_partner = lv_partner
    importing
      et_favs    = lt_favs
    exceptions
      others     = 4.
  if sy-subrc <> 0.
    " should never happen
  endif.

* create collection object to transfer data
  create object lr_col
    type
      cl_crm_bol_bo_col.

* loop through all found data...
  loop at lt_favs into ls_favs.
    "...create line object
    create data lr_tabline.
    "...create value object with current line for colleciton
    create object lr_valuenode
      exporting
        iv_data_ref = lr_tabline.
    "...set current line data
    lr_valuenode->set_properties( ls_favs ).
    "...add current line to collection
    lr_col->add( lr_valuenode ).
  endloop.

* set collection
  me->set_collection( lr_col ).

9. Display data

Unfortunately we're not done yet. I don't know why, but the standard created HTML-page doesn't display the Table Node we filled with a data collection in Step 8. Therefore I programmed my own workaround.
Go to the HTML-page which is located under View Layout. Double click to get into the HTML editor.
Please note: the html-table you'll find in the coding below _considers the user's Layout settings_ but it's not the official coding - just something I figured out myself.

View (HTML): ZBPFavorites.htm
<%@page language="abap"%>
<%@ extension name="htmlb" prefix="htmlb"%>
<%
* data definitions *****************************************************
  data: lr_wrapper         type ref to   cl_bsp_wd_collection_wrapper,
        lr_entity          type ref to   if_bol_bo_property_access,

        lt_favs            type          zbp_favs_tab,
        ls_favs            type          zbp_favs_s,

        lv_value           type          string.

  field-symbols: <fs_favs> type          any.


* fill local Currency Clause table *************************************
  " get collection wrapper
  lr_wrapper = zcucl->get_collection_wrapper( ).
  if lr_wrapper is bound.
    " get first entity...
    lr_entity = lr_wrapper->get_first( ).
    "...then loop through all entities
    while lr_entity is bound.
      " Partner number
      assign component 'PARNR' of structure ls_favs to <fs_favs>.
      try.
          lv_value = lr_entity->get_property_as_string( 'PARNR' ).
        catch cx_sy_conversion_error .
      endtry.
      <fs_favs> = lv_value.
      " Color
      assign component 'COLOR' of structure ls_favs to <fs_favs>.
      try.
          lv_value = lr_entity->get_property_as_string( 'COLOR' ).
        catch cx_sy_conversion_error .
      endtry.
      <fs_favs> = lv_value.
      " Meal
      assign component 'MEAL' of structure ls_favs to <fs_favs>.
      try.
          lv_value = lr_entity->get_property_as_string( 'MEAL' ).
        catch cx_sy_conversion_error .
      endtry.
      <fs_cucl> = lv_value.
      " Sport
      assign component 'SPORT' of structure ls_favs to <fs_favs>.
      try.
          lv_value = lr_entity->get_property_as_string( 'SPORT' ).
        catch cx_sy_conversion_error .
      endtry.
      <fs_favs> = lv_value.

      " add favorites to local table
      append ls_favs to lt_favs.

      " get next entity
      lr_entity = lr_wrapper->get_next( ).
    endwhile.

  endif.
%>

<%
* display BP Favorites table **************************************************
%>
<table class="th-tv th-tv-table">
<%
  loop at lt_favs into ls_favs.
    if sy-tabix = 1.
%>
  <!-- table header -->
  <thead class="th-tv-header">
    <tr>
      <!--<th class="th-clr-cel th-tx-header1"><%= otr(ZCRM/Partner) %></th>-->
      <th class="th-clr-cel th-tx-header1"><%= otr(ZCRM/Color) %></th>
      <th class="th-clr-cel th-tx-header1"><%= otr(ZCRM/Mail) %></th>
      <th class="th-clr-cel th-tx-header1"><%= otr(ZCRM/Sport) %></th>
    </tr>
  <!-- end of table header -->
  </thead>
  <!-- table body -->
  <tbody>
<%
    endif.
%>
  <tr>
    <td class="th-ip-td1 th-tv-cel-txt"><%= ls_favs-color %></td>
    <td class="th-ip-td1 th-tv-cel-txt"><%= ls_favs-mail %></td>
    <td class="th-ip-td1 th-tv-cel-txt"><%= ls_cucl-sport %></td>
  </tr>
<%
    if sy-tabix = sy-tfill.
%>
  <!-- end of table body -->
  </tbody>
<%
    endif.
  endloop.

  if sy-subrc <> 0.
%>
  <tr>
    <td class="th-tv-noresult">
      <img src="images/infoMessage.gif" border="0"> <span><%= otr(ZCRM/noResults) %></span>
    </td>
  </tr>
<%
  endif.
%>
</table>

10. Add assignment block to Overview page

As our last step, we need to add our z-component to the Overview page of the Business Partner. Go to the BSP Component Workbench - transaction BSP_WD_CMPWB and display component BP_HEAD.
First we have to make our z-component available in this component. Go to the Runtime Repository Editor and choose edit mode. Open ViewSets, ViewSet BP_HEAD/BPHEADOverview and ViewArea OverviewPage. Right-Click on the ViewArea and choose Add View. Type in the z-component as BSP-Application and choose the correct View. Save the Runtime Repository with the disc-icon.
Go back to the Component Structure, locate View BPHEADOverview and double click it. Change into the Configuration tab and select the Configuration with your Role Key (or copy the configuration to your Role Key). At the right side under Avaiable Assignment Blocks you'll now see our z-component. Mark it and add it with the arrow pointing right to the Displayed Assignment Blocks. Give it a suitable Title and choose the Load Option.
*And once you saved the configuration, you're done!*

Labels

crm crm Delete
webui webui Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.