Sample ABAP coding for enhancing the Logistics Workplace in NF-e Inbound
This blog will provide a sample coding for the implementation of BAdI
Determination of Custom UI for Logistics Workplace for Inbound NF-e’s. You use this BAdI to replace the existing user interface (UI) of the process step
Prepare Goods Receipt Posting with a custom Web Dynpro UI.
Implementing the BAdI ‘Determination of Custom UI for Logistics Workplace’
The BAdI uses interface /XNFE/IF_BADI_GET_CUSTOM_UI. The system calls this interface with the GET_CUSTOM_UI method and here you can make known your custom UI component to the NFE Framework. You can determine different UI components depending on the import parameters
- CNPJ,
- process type, or
- process step.
Although we only support one step (Prepare Goods Receipt Posting) at the moment, the
process step is import parameter of the BAdI (because maybe in future we support other steps).
The following is an example of this method in the implementing class of the enhancement implementation; let us call our component Z_INBOUND_DELIV:
METHOD /xnfe/if_badi_get_custom_ui~get_custom_ui.
* use this UI only for process type 'Normal Purchasing'
IF iv_procstep = 'GRMMCHCK' AND iv_proctyp = 'NORMPRCH'.
ev_component = 'Z_INBOUND_DELIV'.
ev_component_window = 'MAIN'.
ev_component_plug = 'DEFAULT'.
ENDIF.
ENDMETHOD.
Enhancing the NF-e Logistics Workplace
On the Logistics Workplace screen you can select a NF-e and choose Execute Process Step > Prepare Goods Receipt Posting, if the NF-e processing status allows it. On the
Prepare Goods Receipt Posting screen you can set the status for the NF-e and return to the
NF-e Logistics Workplace. With our custom UI (below the
Set Status buttons) we want to offer the possibility to change data of the inbound delivery in ERP before setting the status of the step:
Create a new Web Dynpro component
To visualize the data of the inbound delivery from the ERP data base we will use an editable ALV table. The implementation presented here uses a copy of the sample component
WDT_FLIGHTLIST_EDIT in package
SWDP_DEMO_TUTORIALS as starting point.
To read the delivery data from the ERP data base we use function
BAPI_DELIVERY_GETLIST. The relevant output table, which returns the item data of the deliveries, is et_delivery_item with structure BAPIDLVITEM (we use the copy structure INBOUND_DELIV_STY).
To store the delivery data create node NODE_DELIVERY_ITEM based on dictionary structure INBOUND_DELIV_STY in the context of the component controller and choose the fields which you want to show in the ALV table:
Set table editable
Then this ALV is configured to make column
Shelf Life Expiration or Best-Before Date (
VFDAT) editable. Therefore we need to enhance method WDDOINIT of view ResultView:
METHOD wddoinit .
DATA:
lo_cmp_usage TYPE REF TO if_wd_component_usage,
lo_interfacecontroller TYPE REF TO iwci_salv_wd_table,
lv_value TYPE REF TO cl_salv_wd_config_table,
lr_column TYPE REF TO cl_salv_wd_column,
lr_column_settings TYPE REF TO if_salv_wd_column_settings,
lr_input_field TYPE REF TO cl_salv_wd_uie_input_field.
lo_cmp_usage = wd_this->wd_cpuse_alv( ).
IF lo_cmp_usage->has_active_component( ) IS INITIAL.
lo_cmp_usage->create_component( ).
ENDIF.
lo_interfacecontroller = wd_this->wd_cpifc_alv( ).
lv_value = lo_interfacecontroller->get_model( ).
lv_value->if_salv_wd_table_settings~set_read_only( abap_false ).
lv_value->if_salv_wd_table_settings~set_selection_mode( cl_wd_table=>e_selection_mode-none ).
lv_value->if_salv_wd_table_settings~set_visible_row_count( '5' ).
lv_value->if_salv_wd_table_settings~set_fixed_table_layout( abap_true ).
lv_value->if_salv_wd_std_functions~set_pdf_allowed( abap_false ).
lv_value->if_salv_wd_std_functions~set_export_allowed( abap_false ).
lv_value->if_salv_wd_std_functions~set_edit_append_row_allowed( abap_false ).
lv_value->if_salv_wd_std_functions~set_edit_check_available( abap_false ).
lv_value->if_salv_wd_std_functions~set_edit_delete_row_allowed( abap_false ).
lv_value->if_salv_wd_std_functions~set_edit_insert_row_allowed( abap_false ).
lv_value->if_salv_wd_std_functions~set_filter_complex_allowed( abap_false ).
lv_value->if_salv_wd_std_functions~set_filter_filterline_allowed( abap_false ).
lr_column_settings ?= lv_value.
lr_column = lr_column_settings->get_column( 'VFDAT' ).
CREATE OBJECT lr_input_field
EXPORTING
value_fieldname = 'VFDAT'.
lr_column->set_cell_editor( lr_input_field ).
ENDMETHOD.
Create a method to get the data from ERP
Your custom Web Dynpro component needs to implement the Web Dynpro interface
/XNFE/IF_CUSTOM_UI with the 3 methods:
- STEP_DATA. This method transfers the step-relevant import parameters
- IS_INNFEHD - NF-e header,
- IT_NFEASSIGN - the corresponding assignment table,
- IV_XML - the XML data
into your custom UI. The method is called by the NFE Framework every time the custom UI is loaded.
We use this method in the component controller to fill node
NODE_DELIVERY_ITEM:
METHOD step_data .
TYPES:
BEGIN OF bapidlvbuffercontrol,
bypassing_buffer TYPE char1,
head_status TYPE xfeld,
head_partner TYPE xfeld,
item TYPE xfeld,
item_status TYPE xfeld,
doc_flow TYPE xfeld,
ft_data TYPE xfeld,
hu_data TYPE xfeld,
serno TYPE xfeld,
END OF bapidlvbuffercontrol,
BEGIN OF bapidlv_range_vbeln,
sign TYPE bapisign,
option TYPE bapioption,
deliv_numb_low TYPE char10,
deliv_numb_high TYPE char10,
END OF bapidlv_range_vbeln.
DATA:
lo_nd_node_delivery_item TYPE REF TO if_wd_context_node,
lt_delivery_item TYPE TABLE OF inbound_deliv_sty,
ls_range_vbeln TYPE bapidlv_range_vbeln,
lt_range_vbeln TYPE TABLE OF bapidlv_range_vbeln,
ls_dlv_data_control TYPE bapidlvbuffercontrol,
ls_nfeassign LIKE LINE OF it_nfeassign,
lv_delnumber TYPE /xnfe/delnum,
lt_return TYPE bapiret2_tab,
ls_return LIKE LINE OF lt_return.
wd_this->ms_innfehd = is_innfehd.
wd_this->mt_nfeassign = it_nfeassign.
wd_this->mv_xml = iv_xml.
*--- Get system for RFC call
CALL FUNCTION '/XNFE/READ_RFC_DESTINATION'
EXPORTING
iv_logsys = is_innfehd-logsys
IMPORTING
ev_rfcdest = wd_this->mv_rfcdest
EXCEPTIONS
no_dest_found = 1.
IF sy-subrc = 1.
RETURN.
ENDIF.
READ TABLE it_nfeassign INTO ls_nfeassign INDEX 1.
IF sy-subrc = 0.
lv_delnumber = ls_nfeassign-delnumber.
ls_dlv_data_control-bypassing_buffer = 'X'.
ls_dlv_data_control-item = 'X'.
ls_range_vbeln-sign = 'I'.
ls_range_vbeln-option = 'EQ'.
ls_range_vbeln-deliv_numb_low = lv_delnumber.
COLLECT ls_range_vbeln INTO lt_range_vbeln.
* read the delivery data from the data base
CALL FUNCTION 'BAPI_DELIVERY_GETLIST' DESTINATION wd_this->mv_rfcdest
EXPORTING
is_dlv_data_control = ls_dlv_data_control
TABLES
it_vbeln = lt_range_vbeln
et_delivery_item = lt_delivery_item
return = lt_return
EXCEPTIONS
communication_failure = 1
system_failure = 2.
IF sy-subrc IS NOT INITIAL.
RETURN.
ENDIF.
IF lt_return IS NOT INITIAL.
LOOP AT lt_return INTO ls_return
WHERE type EQ 'E' OR type EQ 'A' OR type EQ 'X'.
EXIT.
ENDLOOP.
ENDIF.
ENDIF.
* fill ALV
lo_nd_node_delivery_item = wd_context->get_child_node( name = wd_this->wdctx_node_delivery_item ).
lo_nd_node_delivery_item->bind_table( lt_delivery_item ).
ENDMETHOD.
- ACTION_BACK_IS_ALLOWED. If you managed to recognize that there are unsaved data on the UI you can enter this status in the return parameter RV_IS_ALLOWED ("Navigation Allowed?").
But at least you should return True, the worst that can happen is that unsaved data are lost and the user has to enter them again.
METHOD action_back_is_allowed .
rv_is_allowed = 'X'.
ENDMETHOD.
- ACTION_SET_STATUS_IS_ALLOWD. Here you should return True with the return parameter RV_IS_ALLOWED ("Navigation Allowed?"), if the last update of ERP was successful, otherwise False.
Remark: It is advisable with 'Set status to OK' to call ERP to check that the ID is complete, i.e. Sloc entered, batch, manufacturing date. Otherwise, when Goods Receipt fails, the user cannot go back to 'Prepare Goods Receipt'.
So the proposal is, to just call the functionality of method ONACTIONSAVE again in this Interface method and return the result:
METHOD action_set_status_is_allowd .
rv_is_allowed = wd_this->save( ).
ENDMETHOD.
Save Changes
Now we can see the delivery data and change the expiration date in the editable column of VFDAT. So implement a save button called
Change Data to save the user changes to the database in view ResultView.
Implement method ONACTIONSAVE
Implement an event handler method ONACTIONSAVE for the
Change Data button with the following functionality:
- Get actual/changed content of the delivery table
- Update DB
- Display a success message.
To update the existing delivery we use function WS_DELIVERY_UPDATE in ERP. The relevant input table for confirming the data from delivery item is VBPOK_TAB of structure VBPOK. The error or success message is displayed in the message area.
METHOD onactionsave .
wd_comp_controller->save( ).
ENDMETHOD.
METHOD save .
DATA: node_node_deliverytab TYPE REF TO if_wd_context_node,
elem_node_deliverytab TYPE REF TO if_wd_context_element,
lt_sdelivery TYPE if_layoutview=>elements_node_delivery_item,
ls_sdelivery LIKE LINE OF lt_sdelivery,
lv_rfcdest TYPE rfcdest,
lv_out TYPE string,
vbkok_ls TYPE vbkok_sty,
vbpok_ls TYPE vbpok_sty,
vbpok_lt TYPE TABLE OF vbpok_sty INITIAL SIZE 0,
prot_ls TYPE prott_sty,
prot_lt TYPE TABLE OF prott_sty INITIAL SIZE 0,
ls_error TYPE string.
* get error message manager
DATA: l_current_controller TYPE REF TO if_wd_controller,
l_message_manager TYPE REF TO if_wd_message_manager.
l_current_controller ?= wd_this->wd_get_api( ).
CALL METHOD l_current_controller->get_message_manager
RECEIVING
message_manager = l_message_manager.
* navigate from <CONTEXT> to <NODE_deliveryTAB> via lead selection
node_node_deliverytab
= wd_context->get_child_node( name = `NODE_DELIVERY_ITEM` ).
* save data to database
lv_rfcdest = wd_comp_controller->mv_rfcdest.
* get data from context node <NODE_deliveryTAB>
node_node_deliverytab->get_static_attributes_table(
IMPORTING table = lt_sdelivery ).
* read the changed data
CLEAR: vbpok_lt.
LOOP AT lt_sdelivery INTO ls_sdelivery.
vbkok_ls-vbeln_vl = ls_sdelivery-vbeln.
vbkok_ls-vbeln = ls_sdelivery-vbeln.
* Positions
vbpok_ls-vbeln_vl = ls_sdelivery-vbeln.
vbpok_ls-posnr_vl = ls_sdelivery-posnr.
vbpok_ls-vbeln = ls_sdelivery-vbeln.
vbpok_ls-posnn = ls_sdelivery-posnr.
vbpok_ls-lfimg = ls_sdelivery-lfimg.
vbpok_ls-vfdat = ls_sdelivery-vfdat.
vbpok_ls-kzvfdat = 'X'.
APPEND vbpok_ls TO vbpok_lt. CLEAR vbpok_ls.
ENDLOOP.
**** update the existing delivery ...
CALL FUNCTION 'WS_DELIVERY_UPDATE' DESTINATION lv_rfcdest
EXPORTING
vbkok_wa = vbkok_ls
"#EC ENHOK
commit = 'X'
delivery = ls_sdelivery-vbeln
TABLES
vbpok_tab = vbpok_lt
"#EC ENHOK
prot = prot_lt
"#EC ENHOK
EXCEPTIONS
error_message = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
INTO ls_error.
CALL METHOD l_message_manager->report_error_message
EXPORTING
message_text = ls_error.
ELSE.
CLEAR prot_ls.
LOOP AT prot_lt INTO prot_ls.
MESSAGE ID prot_ls-msgid TYPE prot_ls-msgty NUMBER prot_ls-msgno
WITH prot_ls-msgv1 prot_ls-msgv2 prot_ls-msgv3 prot_ls-msgv4
INTO ls_error.
CALL METHOD l_message_manager->report_error_message
EXPORTING
message_text = ls_error.
ENDLOOP.
IF prot_ls IS INITIAL.
rv_is_allowed = 'X'.
CONCATENATE 'Data has been modified successfully in system' lv_rfcdest INTO lv_out SEPARATED BY space.
"#EC NOTEXT
CALL METHOD l_message_manager->report_success
EXPORTING
message_text = lv_out.
ENDIF.
ENDIF.
ENDMETHOD.
Test the Web Dynpro Application
The result will look like the following:
Display the changed inbound delivery in the ERP system with transaction VL33N: