Registration

Dear SAP Community Member,
In order to fully benefit from what the SAP Community has to offer, please register at:
http://scn.sap.com
Thank you,
The SAP Community team.
Skip to end of metadata
Go to start of metadata

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 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 Available 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!*

15 Comments

  1. Guest

    Melanie,

    Very well written and helpful article. I was able to follow your example and successfully invoke an external web service call from BP ui page. Thank you for sharing and documenting the details.

    A comment on step 9, Display data. One simple configuration is all that's needed to show table contents without any bsp coding. Open the view from Component Structure Browser (I am using CRM 7.0 where things are renamed slightly). Instead of opening the .htm page from the View Structure tab, click the Configuration tab.  Create a new configuration. Here you will see all fields from structure ZBP_FAVS_S listed in the left pane under Availabe Fields. Select and add them to the Displayed Fields in the right pane. Save the configuration. That's it.

    Regards,

    Wentao 

  2. Hi,

    very good blog; do you have information on how to solve it when the entries in the table have to be changeable? Changes should be saved as soon as the business partner is saved.

    Regards

    Wolfgang

  3. Guest

    Hi Wentao, Hi Wolfgang,

    Thank you for commenting my article. It's good to know that my sharing helps others.

    I have been on holiday so far, hence the late respond.

    Thanks Wentao for your tip about my step 9. I was fighting with it for a while and once I just couldn't spend more time I decided to go deep into the coding and do my own workaround. I always hoped to figure out how to do it without code-changes.

    Concerning your question Wolfgang: I have unfortunatelly not worked with changeable tables as we use ours only to display data. But what I do know is that there is a BAdI which is called whenever a partner is saved: PARTNER_UPDATE. Although I cannot say for sure if this is the correct way to go. I used this BAdI to automatically add a partner function to every account that is created.

     Regards,

    Melanie

  4. Guest

    Hi Melanie,

    first of all, thank you, your article has made some concepts a bit clearer for me.

    I'd like to implement your solution, but on the appointment page, and the information i want to show would still depend on the bp account inserted in the appointment details, component BT126H_APPT.

    Could you tell me how different would Step 3 have to be to make it work? I mean, what BOL entity would I use?

    My aim is to show an opportunities table, the same that appears in the BP page, but in the appointments page.

     Thank you for any help,

    Best Regards, 

    Duarte

  5. Guest

    Hi Melanie,

     Do you know how to include a z-table in a CASE View? We only want to display de info that is updated in the CRM. We are on a CRM 6.0.

    Thanks in advance!!

    Lucas

  6. Hi Melanie,

     You have written a very good blog.

    I am also working on a similar scenario in CRM 7.0, i have to display change documents on the satus field in the overview screen in a new 'z' view. 

    I have followed all the steps mentioned by you. My view is getting displayed and lazy mode.

    But the data is not getting displayed in the View.

    Please could you provide your valuable advice. 

    Regards,

    K

  7. Guest

    Hi Melanie,

    I was looking for some explantion where in i can create a custom Assignment block for Accounts.
    Your explantion to this satisfy my requirement... I followed all the steps in your WIKI  'How to display a z-table in an assignment block ' But facing some problems.

    My assignment block does not get refreshed when a new account is opened.
    How to debug and find out whether the view is receiving the BP number.
    I am new to MVC concept so i think i am lost ..... is there any thing else we need to do .....also if your explanation had screen shots on every step , then it would be more clear.

    Hope you see this reply and get back with some suggestions.

  8. Guest

    Melanie,

    Thanks for the wonderful blog. I am able to achieve the results with your blog. I have one question, We are creating the custom component view directly in the standard BSP in Runtime Repository Editor. It is a core modification right, So what kind of problem we will get while support pack updates ?

    Thanks

  9. Hi Rambabu,

    the biggest advantage of the WebUI Framework is that you can use enhancements instead of modifications. An upgrade or support pack should not affect your enhancements.

    Best regards
    Gregor

  10. Hi,

    thx for this guid, I followed every step, but my view doesn't show up in BPHeadOverview configuration?

    Markus

  11. Hi Markus,

    have you added your view to the BPHeadOverview view area in the Runtime Repository?

    Best regards
    Gregor

  12. Guest

    Hi Melanie i have a question
    where do you get  or where you declare this variables
    best regards
    Hi Melanie i have a question

    where do you get  or where you declare this variables

    ZL_ZBP_FAVS_ZBPFAVORITES_IMPL=>gv_destination

    best regards

  13. Guest

    Hi,

    thanks for good tutorial, it helped very much.

    I did'nt have any problem with page layout, I sipmly used following tag

    <chtmlb:configCellerator id="Table" table="//ZBP_FAVS/Table" width="100%"/>

    to sub_dan:

    Yes, this this a little bug, however you can declare your own variable

    data: LV_DESTINATION type SCMC_RFCDEST

    Regards

  14. Former Member

    Hi.

    I have a problem with steep 3 Create View & Context Nodes, when I type BOL Entity BuilHeader shows a PopUp  with the next message

    "Error BOL Entity BOL entity BuilHeader does not exist"

    I do´nt know what happend, the search help in field BOL Entity doesnt show entries.

    ¿Some idea?

  15. Guest

    @Erick Aragon Zepeda

    If you still have the same problem, see http://scn.sap.com/thread/3233424 which should help you.