
Some time ago I created a document to show how can display some custom data in a SRM document adding a custom button and calling a custom WebDynpro:
http://scn.sap.com/docs/DOC-25271
But this example only shows how to display some data, not how to update the data. In this new document we’re going to see other way to do it and with the possibility to update the data when you are editing the document.
Other posibilities |
---|
If you only want to add custom fields to your document you can follow this document: http://scn.sap.com/docs/DOC-25692 If you want to extend a document with only a custom table at item and/or header level you can use this one: http://scn.sap.com/docs/DOC-28602 |
In this new example we’re going to create a custom table to save some data related with the items of our SRM document. You can enhance this solution adding other tables or custom fields.
1. First thing to do is create a custom table to store the data
We have as Key fields the following fields:
- OBJECT_ID: Id of the SRM Document.
- NUMBER_INT: Id of the SRM Document item.
- CUSTOM_POS: A counter with the “sub-item” number.
In this case, as example, we have the fields Quantity and Unit.
We’re going to create also a table type for this table:
2. Function Group to save and retrieve the data
We are going to use a FG to get, set and save the data. The reason for this is that while the caller program of any FM in this FG is alive the data stored in the include TOP is alive.
So we can store temporary data in the TOP and use any FM in this FG to retrieve or save the data from our custom WebDynpro but also from the badis BBP_DOC_CHANGE_BADI, BBP_DOC_CHECK_BADI, BBP_DOC_SAVE_BADI, etc.
Goto SE80 and create a FG ZZCUSTOM_DATA. Go to the include TOP and create the internal table to store the data.
Create the following function modules:
2.1 Function Module ZZCUSTOM_DATA_SELECT
We will use this FM to select the data stored in the database.
ZZCUSTOM_DATA_SELECT |
---|
FUNCTION ZZCUSTOM_DATA_SELECT. |
2.2 Function Module ZZCUSTOM_DATA_GET
We will use this FM to get the data related with one of the document items.
ZZCUSTOM_DATA_GET |
---|
FUNCTION zzcustom_data_get. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" REFERENCE(IV_NUMBER_INT) TYPE CRMT_ITEM_NO *" EXPORTING *" REFERENCE(ET_CUSTOM_DATA) TYPE ZZCUSTOM_DATA_T *"---------------------------------------------------------------------- FIELD-SYMBOLS: <ls_custom_data> TYPE zzcustom_data. LOOP AT gt_custom_data ASSIGNING <ls_custom_data> WHERE number_int EQ iv_number_int. APPEND <ls_custom_data> TO et_custom_data. ENDLOOP. ENDFUNCTION. |
2.3 Function Module ZZCUSTOM_DATA_SET
We will use this FM to update the data stored in our TOP include.
ZZCUSTOM_DATA_SET |
---|
FUNCTION zzcustom_data_set. ASSIGNING <ls_custom_data>.
|
2.4 Function Module ZZCUSTOM_DATA_SAVE
We will use this FM to save the data in database.
ZZCUSTOM_DATA_SAVE |
---|
FUNCTION zzcustom_data_save. *"-------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" REFERENCE(IV_OBJECT_ID) TYPE CRMT_OBJECT_ID_DB *"-------------------------------------------------------------------- * Delete old data, in case some item was deleted: DELETE FROM zzcustom_data WHERE object_id EQ iv_object_id. * Insert the data updated; INSERT zzcustom_data FROM TABLE gt_custom_data. ENDFUNCTION. |
3. Creating the custom WebDynpro
Goto SE80 and create the Web Dynpro Component ZZCUSTOM_DATA.
3.1 Go to the Component Controller and create an interface node INFO with the following attributes:
We will use this interface node to pass some data from the standard component.
3.2 Create also a table node to store the custom data:
3.3 Get and save the data
We are going to get the data every time the window is opened and set the data every time the window is closed.
Map the nodes created in the component controller within the window context:
Go to the method WDDOONOPEN of the window and add the following code:
With this we obtain the data related with one of the items every time the window is opened.
WDDOONOPEN |
---|
method WDDOONOPEN . DATA: ls_info TYPE wd_this->element_info, lo_nd_info TYPE REF TO if_wd_context_node, lo_el_info TYPE REF TO if_wd_context_element, lo_nd_custom_data TYPE REF TO if_wd_context_node, lt_custom_data TYPE wd_this->elements_custom_data. * Get the info passed through the interface node; lo_nd_info = wd_context->get_child_node( name = wd_this->wdctx_info ). lo_el_info = lo_nd_info->get_element( ). lo_el_info->get_static_attributes( IMPORTING static_attributes = ls_info ). * Select the data stored in the database; CALL FUNCTION 'ZZCUSTOM_DATA_SELECT' EXPORTING iv_object_id = ls_info-object_id. * Get the data for this item; CALL FUNCTION 'ZZCUSTOM_DATA_GET' EXPORTING iv_number_int = ls_info-number_int IMPORTING et_custom_data = lt_custom_data. lo_nd_custom_data = wd_context->get_child_node( name = wd_this->wdctx_custom_data ). lo_nd_custom_data->bind_table( new_items = lt_custom_data set_initial_elements = abap_true ). endmethod. |
Add the following code in the method WDDOEXIT:
With this we update the internal table we have as a "buffer" in the include TOP of our FG.
WDDOEXIT |
---|
DATA: ls_info TYPE wd_this->element_info, lt_custom_data TYPE wd_this->elements_custom_data, lo_nd_custom_data TYPE REF TO if_wd_context_node, lo_nd_info TYPE REF TO if_wd_context_node, lo_el_info TYPE REF TO if_wd_context_element. * lo_nd_custom_data = wd_context->get_child_node( name = wd_this->wdctx_custom_data ). lo_nd_custom_data->get_static_attributes_table( IMPORTING table = lt_custom_data ). lo_nd_info = wd_context->get_child_node( name = wd_this->wdctx_info ). lo_el_info = lo_nd_info->get_element( ). lo_el_info->get_static_attributes( IMPORTING static_attributes = ls_info ). CALL FUNCTION 'ZZCUSTOM_DATA_SET' EXPORTING iv_number_int = ls_info-number_int CHANGING ct_custom_data = lt_custom_data. |
3.4 Go to the Main View and create a table to display the data:
First you need to map the nodes in the context.
Create the table and a toolbar with two buttons to add and remove rows. Create an action for each button.
Create also an input field to display the item number and check the property READ_ONLY of this field.
Bind the property READ_ONLY of the table with the attribute READ_ONLY we have in the context:
In this way we control when the table will be editable depending on the value of this attribute.
Bind the property VISIBLE of the toolbar with the Inverse of the attribute READ_ONLY to not display the toolbar when we enter in Display mode:
Add the following code to the action ADD_ROW:
ONACTIONADD_ROW |
---|
METHOD onactionadd_row . DATA: ls_info TYPE wd_this->element_info, ls_custom_data TYPE wd_this->element_custom_data, lt_custom_data TYPE wd_this->elements_custom_data, lo_nd_info TYPE REF TO if_wd_context_node, lo_nd_custom_data TYPE REF TO if_wd_context_node, lo_el_info TYPE REF TO if_wd_context_element. lo_nd_custom_data = wd_context->get_child_node( name = wd_this->wdctx_custom_data ). lo_nd_custom_data->get_static_attributes_table( IMPORTING table = lt_custom_data ). lo_nd_info = wd_context->get_child_node( name = wd_this->wdctx_info ). lo_el_info = lo_nd_info->get_element( ). lo_el_info->get_static_attributes( IMPORTING static_attributes = ls_info ). * Add an initial row; ls_custom_data-object_id = ls_info-object_id. ls_custom_data-number_int = ls_info-number_int. APPEND ls_custom_data TO lt_custom_data. lo_nd_custom_data->bind_table( new_items = lt_custom_data set_initial_elements = abap_true ). ENDMETHOD. |
And to the action REMOVE_ROW
ONACTIONREMOVE_ROW |
---|
method ONACTIONREMOVE_ROW .
|
4 Adding the button to the standard component
We are going to create a new button at the SC item level.
You can also use the same custom component to show a popup in other docuents, PO, RFx, etc.
Create a new SC and check the technical help to find the standard webdynpro component:
In this case we can see the component /SAPSRM/WDC_UI_SC_DOTC_BD.
4.1 Go to that component and create a new Enhancent point
4.2 Add as Used Component our custom component
4.3 Go to the view V_SC_DOTC_BASIC and Add the used component
4.4 Map the interface node INFO in the context
4.5 Add a new button to the table toolbar to call our component and create an action to it
4.6 Adding code to the button
we are going to show a popup with our component. To do that we are going to use the Code wizard:
We need to pass to our component some data through the interface node, like the item number or the display mode, this the entire code of the button:
ONACTIONZZCUSTOM_DATA |
---|
METHOD onactionzzcustom_data . ls_info TYPE wd_this->element_info, lt_set TYPE wdr_context_element_set, lo_api_controller TYPE REF TO if_wd_controller,
* case you don't modify nothing but the custom data; |
5 Saving the data
At this point you can use the button and you can display and modify the custom data:
But we need to save this data in the database, to do that we are going to use the badi BBP_DOC_SAVE_BADI.
5.1 Create a new implementation of the badi
Set the filter value for the Shopping Cart
Call the FM we’ve created to save the data
SAVE BADI |
---|
DATA: lv_action TYPE /sapsrm/pdo_action_type, lo_tran_context TYPE REF TO /sapsrm/if_transaction_context, ls_header TYPE bbp_pds_header. lo_tran_context = /sapsrm/cl_transaction_context=>/sapsrm/if_transaction_context~get_instance( ) . lv_action = lo_tran_context->get_current_action( ). IF lv_action EQ 'ORDER' OR lv_action EQ 'SAVE'. EXPORTING ENDIF. |
Now you can save the data. If you save the document and enter in display mode you can see you cannot modify the data. You can only modify the data if you enter in Edit mode.
You can enhance this solution adding other custom tables or custom fields to the custom webdynpro and creating the proper FM in the FG.
You can add some validation when you are saving the document creating an implementation of the badi BBP_DOC_CHECK_BADI and using the FM to get the data we have in our FG.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.