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!*
Comments (14)
Jun 23, 2009
Wentao Pan says:
Melanie, Very well written and helpful article. I was able to follow your examp...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
Jul 06, 2009
Wolfgang Mayer says:
Hi, very good blog; do you have information on how to solve it when the entries...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
Aug 25, 2009
Melanie Lauber says:
Hi Wentao, Hi Wolfgang, Thank you for commenting my article. It's good to know ...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
Jan 19, 2010
Duarte Melim says:
Hi Melanie, first of all, thank you, your article has made some concepts a bit ...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
Jan 26, 2010
Lucas Ignacio Alvarez says:
Hi Melanie, Do you know how to include a z-table in a CASE View? We only ...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
Feb 15, 2010
Kapil Patil says:
Hi Melanie, You have written a very good blog. I am also working on...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
Apr 20, 2010
Jaya Nair says:
Hi Melanie, I was looking for some explantion where in i can create a custom As...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.
Feb 03, 2011
Rambabu Ramineni says:
Melanie, Thanks for the wonderful blog. I am able to achieve the results with y...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
Feb 03, 2011
Gregor Wolf says:
Hi Rambabu, the biggest advantage of the WebUI Framework is that you can use en...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
Feb 22, 2011
Markus Reich says:
Hi, thx for this guid, I followed every step, but my view doesn't show up in BP...Hi,
thx for this guid, I followed every step, but my view doesn't show up in BPHeadOverview configuration?
Markus
Feb 24, 2011
Gregor Wolf says:
Hi Markus, have you added your view to the BPHeadOverview view area in the Runt...Hi Markus,
have you added your view to the BPHeadOverview view area in the Runtime Repository?
Best regards
Gregor
Sep 26, 2011
sub_dan says:
Hi Melanie i have a question where do you get or where you declare this va...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
Nov 30, 2011
Ludek Vondruska says:
Hi, thanks for good tutorial, it helped very much. I did'nt have any problem w...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
Regards
Feb 07
Erick Aragon Zepeda says:
Hi. I have a problem with steep 3 Create View & Context Nodes, when I type ...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?