The aim of this blog is to show how you can make your own planning and scheduling system as an add-in into your SAP or at least the first step: building order net for particular order-position-schedule combination or in other words order status report known from the transaction MD04.
Like many other companies, our plant has been struggling with the delivery performance and other problems, which can be solved by various sorts of APS (Advance Planning and Scheduling Systems) such as APO from SAP and others add-ons. After examining and testing various solutions, we decided to make our own as an add-in in our SAP environment. As mentioned earlier, the first step and key for following planning and scheduling operations are building order net table.
Here is the code using function module MD_SALES_ORDER_STATUS_REPORT, following by a recursive method GET_LINE for building the desire result table.
REPORT zjarda. PARAMETERS: p_delnr TYPE mdps-del12, p_delps TYPE delps, p_delet TYPE delet. CLASS lcl_main DEFINITION. PUBLIC SECTION. CLASS-METHODS: main. METHODS: constructor IMPORTING i_ioel TYPE ioel. PRIVATE SECTION. TYPES:BEGIN OF t_itab. TYPES: rsnum TYPE ioel-rsnum, rspos TYPE ioel-rspos, etenr TYPE ioel-etenr, level TYPE i, matnr TYPE matnr, mng01 TYPE menge13, delnr TYPE del12, " delnr for dispositons element / MRP element number nxtrs TYPE rsnum, "Number of Reservation/Dependent Requirement key TYPE salv_de_node_key."Number of Reservation/Dependent Requirement TYPES END OF t_itab. CLASS-DATA: lt_ioel TYPE TABLE OF ioel, lt_onet TYPE TABLE OF t_itab, ls_onet TYPE t_itab, lo_ioel TYPE REF TO lcl_main, lt_delkz TYPE TABLE OF char2, lv_key TYPE salv_de_node_key VALUE 1, go_tree TYPE REF TO cl_salv_tree, lo_nodes TYPE REF TO cl_salv_nodes, lo_node TYPE REF TO cl_salv_node, columns TYPE REF TO cl_salv_columns, lt_itab TYPE TABLE OF t_itab, key TYPE salv_de_node_key. DATA: ioel TYPE ioel. METHODS get_line. CLASS-METHODS get_ioel. CLASS-METHODS get_net. CLASS-METHODS display. CLASS-METHODS get_nodes. ENDCLASS. CLASS lcl_main IMPLEMENTATION. METHOD main. get_ioel( ). get_net( ). display( ). ENDMETHOD. METHOD get_ioel. CALL FUNCTION 'MD_SALES_ORDER_STATUS_REPORT' EXPORTING edelet = p_delet edelkz = 'VC' " 'VC' for Orders, for other value see value range on domain delkz in dictonary edelnr = p_delnr edelps = p_delps * EPLSCN = 000 " if needed you can use Planning Scenario * AVAILABILITY_CHECK = ' ' * NO_SAVETY_STOCK = ' ' * DATA_IN_MEMORY = ' ' * MEMORY_ID = 'PLHS' * EMATNR = ' ' ewerks = '013' " your plant * EBERID = ' ' * EMDPS = nodisp = 'X' "otherwise it would be displayed * I_IGNORE_MTOLD = ' ' * I_PROFID = ' ' * I_REP_REFRESH = ' ' * IS_PROFILE = * IT_VBEP_KEYS = * NO_COMMIT_WORK = ' ' * IMPORTING * ET_MLDELAY = * ET_RTREE_SEL = TABLES iioelx = lt_ioel * EXCEPTIONS * ERROR = 1 * OTHERS = 2 . IF sy-subrc <> 0. * Implement suitable error handling here ENDIF. ENDMETHOD. METHOD get_net. * the first level contains elements for satisfying primary requirements * the conection goes like this: *ioel-rsnum = p_delnr. *ioel-rspos = p_delps. *ioel-etenr = p_delet. LOOP AT lt_ioel ASSIGNING FIELD-SYMBOL(<fs_ioel>) WHERE rsnum = p_delnr AND rspos = p_delps AND etenr = p_delet AND sobes IS NOT INITIAL " we are interested only in not satisfied requirements AND ( delkz = 'FE' OR delkz = 'PA' OR delkz = 'BE' OR delkz = 'LE' OR delkz = 'LA' OR delkz = 'BA' OR delkz = 'WB' OR delkz = 'SA'). " check your own delkz MOVE-CORRESPONDING <fs_ioel> TO ls_onet. ls_onet-level = 0. ls_onet-key = lv_key. APPEND ls_onet TO lt_onet. CREATE OBJECT lo_ioel EXPORTING i_ioel = <fs_ioel>. lo_ioel->get_line( ). " for lower levels CLEAR: lo_ioel, ls_onet. ENDLOOP. ENDMETHOD. METHOD constructor. ioel = i_ioel. ENDMETHOD. METHOD get_line. * here we are looking through lower levels, which are connecting in this way: * ioel-nxtrs of upper element = ioel-rsnum of lower element LOOP AT lt_ioel ASSIGNING FIELD-SYMBOL(<fs_ioel>) WHERE rsnum = ioel-nxtrs AND sobes IS NOT INITIAL " we are interested only in not satisfied requirements AND ( delkz = 'FE' OR delkz = 'PA' OR delkz = 'BE' OR delkz = 'LE' OR delkz = 'LA' OR delkz = 'BA' OR delkz = 'WB' OR delkz = 'SA'). " check your own delkz READ TABLE lt_onet ASSIGNING FIELD-SYMBOL(<fs_upper>) WITH KEY nxtrs = <fs_ioel>-rsnum. MOVE-CORRESPONDING <fs_ioel> TO ls_onet. ls_onet-level = <fs_upper>-level + 1. lv_key = lv_key + 1. ls_onet-key = lv_key. APPEND ls_onet TO lt_onet. CREATE OBJECT lo_ioel EXPORTING i_ioel = <fs_ioel>. lo_ioel->get_line( ). " for lower levels CLEAR: lo_ioel, ls_onet. ENDLOOP. ENDMETHOD. METHOD display. IF go_tree IS NOT BOUND. TRY. cl_salv_tree=>factory( IMPORTING r_salv_tree = go_tree CHANGING t_table = lt_itab ). CATCH cx_salv_error. FREE go_tree. ENDTRY. ENDIF. get_nodes( ). columns = go_tree->get_columns( ). columns->set_optimize( abap_true ). go_tree->display( ). ENDMETHOD. METHOD get_nodes. lo_nodes = go_tree->get_nodes( ). LOOP AT lt_onet INTO ls_onet. READ TABLE lt_onet ASSIGNING FIELD-SYMBOL(<fs_upper>) WITH KEY nxtrs = ls_onet-rsnum. IF sy-subrc = 0. key = <fs_upper>-key. ENDIF. TRY. lo_node = lo_nodes->add_node( related_node = key relationship = cl_gui_column_tree=>relat_first_child ). lo_node->set_data_row( ls_onet ). CATCH cx_salv_msg. ENDTRY. CLEAR ls_onet. ENDLOOP. ENDMETHOD. ENDCLASS. START-OF-SELECTION. lcl_main=>main( ).
- The result is the internal table LT_IOEL which can be used as a data source for displaying in the tree with the class CL_SALV_TREE – see the picture
- Or it can be used as a base for building and scheduling capacity requirements in your own way. This can be followed by displaying these requirements – see pictures.
As you can see SAP function modules and classes can be extremely helpful to build your own APS with your own functionalities and logic. I hope, you will find it useful.