ALV Tree Simple Report (Multiple orders => Single Delivery)
We had an interesting requirement to combine multiple orders (belonging to a single ship-to party) into a single delivery note. This can be achieved using standard transaction ‘VL10’ but the custom requirement was to only be able to combine the orders that had a similar payment type. Payment type is a custom field in the Sales Order (in our case VBAK-ZPAYM_TYPE) which can be either Cash, Credit Card, Debit Card or so on.
In this blog post, I’ll show how I used ALV tree for displaying orders belonging to Ship-to in a hierarchical form.
Why ALV tree?
To display the orders which could be combined/ bundled together into a single Delivery Note, ALV tree seemed to be the perfect option for the hierarchy with the Ship-to Party being the Parent node and the orders with the same Ship-to Party to be the children nodes.
While developing this report I referred to SAP Standard reports “SALV_DEMO_TREE* “which are of great help.
All the data that is needed is fetched. We have a type ‘ty_final’ which has Ship-to Party, Ship-to Name, Sales order, time, Material, Qty, Unit, Payment type, Delivery and others. In order to combine multiple orders into a single Delivery note, the Order Combination flag (VBKD-KZAZU) of the Sales Order must be set. Hence, we select only those orders.
This is how the Order Combination screen looks like
Creation of tree structure:
Step 1. Create an instance of ALV tree (go_tree). The table needs to be empty at this point (gt_final1 is empty)
DATA: gt_final1 TYPE TABLE OF ty_final, go_tree TYPE REF TO cl_salv_tree. * Create ALV tree TRY. cl_salv_tree=>factory( IMPORTING r_salv_tree = go_tree CHANGING t_table = gt_final1 ). CATCH cx_salv_error. LEAVE LIST-PROCESSING. ENDTRY.
Step 2. Set the heading for the report
DATA: lo_settings TYPE REF TO cl_salv_tree_settings. lo_settings = go_tree->get_tree_settings( ). lo_settings->set_hierarchy_header( ‘Ship-to’ ). lo_settings->set_hierarchy_tooltip( ‘Ship-to’ ). lo_settings->set_header( ‘Order Combination Report’ ).
Step 3. Register LINK_CLICK event
DATA: lo_events TYPE REF TO cl_salv_events_tree. lo_events = go_tree->get_event( ). SET HANDLER go_create->on_link_click FOR lo_events.
Step 4. The building blocks of an ALV tree are called nodes.
The Ship-to Party is a parent node and the Orders are the children nodes.
Supply the data and build the hierarchy
LOOP AT gt_final ASSIGNING <ls_final>. * Check if there is a change in Ship-to or Payment type * in which case a new folder needs to be created IF <ls_final>-kunwe NE ls_prev-kunwe OR <ls_final>-zpaym_type NE ls_prev-zpaym_type. * Get the Ship-to text CLEAR lv_text. CONCATENATE ‘Ship to’ <ls_final>-kunwe <ls_final>-name1 INTO lv_text SEPARATED BY space. * Here we get the key to the Ship-to node, we will use it for Orders * belonging to this Ship-to * Create new folder for Ship-to lv_kunwe_key = go_create->add_tree_node( iv_text = lv_text ). ENDIF. * Keep changing the flag to get alternate background color * Changing colors as Order no. changes IF ls_prev-vbeln NE <ls_final>-vbeln. IF lv_set_style IS INITIAL. lv_set_style = abap_true. ELSE. lv_set_style = abap_false. ENDIF. ENDIF. * Add new item in the folder * Add the node with the relevant data * Here we give the key to the Ship-to node, this way the Order * becomes the child of the Ship-to node go_create->add_tree_node( iv_nkey = lv_kunwe_key is_data = <ls_final> iv_set_type = if_salv_c_item_type=>checkbox iv_set_style = lv_set_style ). * Store the current line as "previous" for further processing ls_prev = <ls_final>. ENDLOOP.
Below is the code along with comments for method ADD_TREE_NODE.
The idea is to distinguish between orders by changing background colors with changing Sales Orders, to set a text for Ship-to Node, to create a button at Ship-to node Delivery Column, and create checkboxes at Sales Order nodes.
METHOD add_tree_node. *--------------------------------------------------------- * Add a node to the ALV tree *--------------------------------------------------------- DATA: lo_nodes TYPE REF TO cl_salv_nodes, lo_node TYPE REF TO cl_salv_node, lo_item TYPE REF TO cl_salv_item, lo_item_delivery TYPE REF TO cl_salv_item. lo_nodes = go_tree->get_nodes( ). * We use the standard method to add the node TRY. lo_node = lo_nodes->add_node( related_node = iv_nkey relationship = if_salv_c_node_relation=>last_child data_row = is_data collapsed_icon = '@5F@' "space expanded_icon = '@5F@' "space text = iv_text ). CATCH cx_salv_msg. LEAVE LIST-PROCESSING. ENDTRY. * We provided text only for Ship-to node. * The below code will set the text of the node (viz. Ship-to 12345 ABC Org.) * Set the text for the node IF iv_text IS NOT INITIAL. lo_node->set_text( iv_text ). ENDIF. * In order to distinguish between Orders, we set different background colors. * The below code sets blue color as background IF iv_set_style IS NOT INITIAL. lo_node->set_row_style( if_salv_c_tree_style=>emphasized_b ). ENDIF. lo_item = lo_node->get_hierarchy_item( ). IF iv_nkey IS INITIAL. * For the Ship-to node, we take the Delivery column and set it to Button TRY. lo_item_delivery = lo_node->get_item( 'DELIVERY' ). CATCH cx_salv_msg. EXIT. ENDTRY. lo_item_delivery->set_type( if_salv_c_item_type=>button ). lo_item_delivery->set_value( ‘Delivery Creation’ ). ELSE. * For the order nodes, we get the entire row and Set it as editable checkbox lo_item->set_type( if_salv_c_item_type=>checkbox ). lo_item->set_editable( abap_true ). * Set the data of the node lo_node->set_data_row( is_data ). lo_nodes->expand_all( ). ENDIF. * Return the node key rv_nkey = lo_node->get_key( ). ENDMETHOD. "add_tree_node
Once the orders are selected, and the corresponding “Delivery Creation” button is clicked, it is a link_click event for which we have the below method.
METHODS: on_link_click FOR EVENT link_click
We have registered an event for this method (step 3 in create tree structure)
METHOD on_link_click. *--------------------------------------------------------- * Method when the user clicks on Link or button *--------------------------------------------------------- DATA: lo_nodes TYPE REF TO cl_salv_nodes, lo_node TYPE REF TO cl_salv_node. lo_nodes = go_tree->get_nodes( ). * Get the parent node TRY. lo_node = lo_nodes->get_node( node_key ). CATCH cx_salv_msg. EXIT. ENDTRY. go_create->create_delivery( lo_node ). ENDMETHOD. "on_link_click
Delivery Creation Logic
The BAPI used for the delivery creation was BAPI_OUTB_DELIVERY_CREATE_SLS.
The method CREATE_DELIVERY is explained below.
The idea is to loop at all the nodes, and get the orders that were selected and pass them to the BAPI. Once the delivery is created, we display it in the ‘Delivery’ column corresponding to the sales orders
METHOD create_delivery. *--------------------------------------------------------- * Create the delivery from the selected Orders *--------------------------------------------------------- DATA: lt_nodes TYPE salv_t_nodes, lo_item TYPE REF TO cl_salv_item, lo_data TYPE REF TO data, lv_delivery TYPE vbeln_vl, lv_number TYPE vbnum, lt_sales_orders TYPE STANDARD TABLE OF bapidlvreftosalesorder, lt_created_items TYPE STANDARD TABLE OF bapidlvitemcreated, lt_return TYPE STANDARD TABLE OF bapiret2. FIELD-SYMBOLS: <ls_nodes> TYPE salv_s_nodes, <ls_data> TYPE ty_final, <ls_orders> TYPE bapidlvreftosalesorder, <ls_items> TYPE bapidlvitemcreated. * Get the entire subtree TRY. lt_nodes = io_node->get_subtree( ). CATCH cx_salv_msg. EXIT. ENDTRY. * Here we will loop at all the nodes, find the ones that were selected * and pass those orders to BAPI for Delivery creation LOOP AT lt_nodes ASSIGNING <ls_nodes>. * Get the item details lo_item = <ls_nodes>-node->get_hierarchy_item( ). * Get the node data if it is checked IF lo_item->is_enabled( ) = abap_true AND lo_item->is_checked( ) = abap_true. lo_data = <ls_nodes>-node->get_data_row( ). ASSIGN lo_data->* TO <ls_data>. IF sy-subrc EQ 0. * Get the sales order and item APPEND INITIAL LINE TO lt_sales_orders ASSIGNING <ls_orders>. <ls_orders>-ref_doc = <ls_data>-vbeln. <ls_orders>-ref_item = <ls_data>-posnr. ENDIF. ENDIF. ENDLOOP. * Call the BAPI for Delivery Creation CALL FUNCTION 'BAPI_OUTB_DELIVERY_CREATE_SLS' IMPORTING delivery = lv_delivery num_deliveries = lv_number TABLES sales_order_items = lt_sales_orders created_items = lt_created_items return = lt_return. SORT lt_created_items BY ref_doc ref_item. IF lv_delivery IS NOT INITIAL. CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'. ELSE. CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. ENDIF. * Next, loop at the nodes and display the delivery LOOP AT lt_nodes ASSIGNING <ls_nodes>. lo_item = <ls_nodes>-node->get_hierarchy_item( ). IF lo_item->is_checked( ) = abap_true. lo_item->set_checked( abap_false ). lo_data = <ls_nodes>-node->get_data_row( ). ASSIGN lo_data->* TO <ls_data>. IF sy-subrc EQ 0. * Set the delivery READ TABLE lt_created_items ASSIGNING <ls_items> WITH KEY ref_doc = <ls_data>-vbeln ref_item = <ls_data>-posnr BINARY SEARCH. IF sy-subrc EQ 0. <ls_data>-delivery = <ls_items>-deliv_numb. <ls_nodes>-node->set_data_row( <ls_data> ). ENDIF. ENDIF. * Disable the checkbox if the delivery is created, IF <ls_data>-delivery IS NOT INITIAL. lo_item->set_enabled( abap_false ). lo_item->set_icon( '@0V\QOK@' ). "OK ENDIF. ENDIF. ENDLOOP. ENDMETHOD. "create_delivery
The purpose was to show how one can create a basic report using ALV tree.
I have implemented other functionalities of ALV tree which makes this report quite user friendly. Some of these enhancements are:
- Expand/ Collapse all the nodes in a single button click
- Select/ unselect all the nodes in a single button click
- Navigate to the created Delivery
- Display error log in case an order cannot be delivered
- Reset button in case of error and resolve error by navigating to order with error
And the best part is all these can be implemented with only a few lines of code, but makes the report look more appealing. If you wish to see the above mentioned points, please check this post.
I hope this blog post helps you and makes you explore more about ALV tree. 😊
Please let me know in the comments if you liked this post and wish to see the enhancements I made.