The BRF+ output determination framework is available for Inventory Management in S/4HANA. However, the traditional NACE/NAST output determination process still fully works and can be used in the same way as in ECC systems. When troubleshooting issues related to this output determination technology, SAP Note 426554 is an essential reference for analysis.
This blog is divided into two parts. The first part demonstrates, through a practical example, how to review and complete Checklist 1 from SAP Note 426554 to ensure that all required configurations are correctly maintained. The second part provides a detailed explanation of the system process flow, including debugging points that can help troubleshoot issues related to the classic output determination process.
Image/data in this Blog Post is from SAP internal systems, sample data, or demo systems. Any resemblance to real data is purely coincidental.
⠀
The example used here was executed on an old SAP ERP system running SAP_APPL package level 605. It consists of an initial entry of stock post on MIGO transaction using movement type 561 with an individual slip for output type WE01.
The MM-IM customizing can be reached using SPRO transaction, IMG path: ‘Materials Management' → ‘Inventory Management and Physical Inventory', but for short, transaction OLMB will be used to access the subfolders of that path.
1. Output type to be generated
For this example we want to use a WE01 output type with Individual Slip.
2. Form and Print program
The Form, Print Program and Form Routine assigned to the output type to be used can be checked on path OMLB → ‘Output Determination' → ‘Assign Forms and Programs':
- Program: SAPM07DR
- Form Routine: ENTRY_WE01
- Form: WESCHEINVERS1
Transaction M706 or transaction NACE + Application ‘ME', selecting the output type and then clicking on ‘Processing Routines' will show the same result and can also be used as alternate paths for further information such as access sequences, condition tables, condition record key fields, etc.
3. Access Sequence and Condition Table
The standard Access Sequence range is from 0001 to 0007 and can be consulted using path OMLB → ‘Output Determination' → ‘Maintain Output Types' or transaction M706 and then double-click on the output type that you wish to check, in this case output type WE01:
Double-click on the Access Sequence number will lead us to a screen where double-clicking the folder ‘Accesses' will show us our condition table (standard range from 070 to 075):
Inventory management uses B tables for the condition records, so table 72 corresponds to database table B072.
The subfolder ‘Fields' corresponds to the key fields that will be used on the condition table (item 6.) and will be mapped into the communication structures KOMKBME and KOMPBME:
- Access Sequence: 0003
- Condition table: 72 (B072 in SE16)
- Key fields:
- VGART – KOMKBME – Trans./Event Type
- WEVER – KOMKBME – Print Version
- KZDRU – KOMPBME – Print item
4. Transaction used
We are using transaction MIGO to post the 561, on the MIGO screen we are selecting the print version 1 for the ‘Individual Slip' (according to the F1 – Help for the field in MIGO):
The operation ‘Goods Receipt' + ‘Others' with movement type 561 assigns the transaction code ‘MIGO_GI' for the header of the material document and in table T158, the transaction event type ‘WA' is assigned to that transaction.
- Transaction: MIGO_GI
- Print Version (WEVER): 1 (Individual Slip)
- Transaction Event Type (VGART): WA
5. Movement Type
Under the path OLMB → ‘Print Control' → ‘Maintain Print Indicator for Goods Receipt Documents' we can see the print item (KZDRU) assigned to the movement type 561:
This indicator can also be checked on OMJJ transaction:
- Movement type: 561
- Print Item (KZDRU): 1
6. Condition Record key fields
On Item 3. we found the key fields for the condition record select:
- VGART – KOMKBME – Trans./Event Type
- WEVER – KOMKBME – Print Version
- KZDRU – KOMPBME – Print item
On Itens 4. and 5. we found the values for those fields:
- VGART – KOMKBME – Trans./Event Type = WA
- WEVER – KOMKBME – Print Version = 1
- KZDRU – KOMPBME – Print item = 1
Now we need to check if there is a Condition Record for those values based on the Condition Table. To do this, we can use transaction NACE or path OLMB → ‘Output Determination' → ‘Maintain Conditions' → ‘Display Condition: Inventory Mgmt' with the output type WE01:
If a condition record is found, the information we need from it is the Transmission time-spot (VSZTP) or Dispatch Time under the field ‘Date/Time'.
Alternatively, this information can be found using the B table for the condition number found and then using the condition record number (KNUMH) in table NACH.
- Transmission time-spot of the condition record (VSZTP) = 4 (Send immediately (when saving the application)).
7. Print Indicator
For the print indicator, since we are posting the movement on MIGO, the flag is marked on the header:
8. Output Record
To check the output record status, we have to open the material document posted in MIGO using the operation ‘Display' → ‘Material Document' and then click on ‘Display outputs':
9. Printer
When displaying the output created in MIGO transaction, you can check the communication method for the printer selected:
1. Form DRUCK_PRUEFEN (MM07MFD0)
In this form, we check the RM07M structure for the Print Indicator (XNAPR) to confirm if the Print Version set on MIGO (WVERS1, WVERS2 or WVERS3) needs to be saved on MKPF. The version is updated on MKPF-WEVER field.
IF NOT RM07M-WVERS1 IS INITIAL.
MKPF-WEVER = 1.
T158-WEVER = 1.
ENDIF.
IF NOT RM07M-WVERS2 IS INITIAL.
MKPF-WEVER = 2.
T158-WEVER = 2.
ENDIF.
[...]
In this form we also set the XNAPR flag based on the NDR parameter of the user in case the goods movement was posted via BAPI/Idoc:
* Nachlesen Parameter NDR, wenn Verarbeitung über MB_CREATE -----------*
IF NOT XMBWL IS INITIAL.
IF NOT PR_UNAME IS INITIAL.
PRINT_UNAME = PR_UNAME.
ENDIF.
IF PR_PRINT IS INITIAL.
SELECT SINGLE * FROM USR05 WHERE BNAME = PRINT_UNAME
AND PARID = 'NDR'.
IF SY-SUBRC IS INITIAL.
RM07M-XNAPR = USR05-PARVA.
ELSE.
CLEAR RM07M-XNAPR.
ENDIF.
ELSEIF PR_PRINT = 1.
RM07M-XNAPR = X.
ELSEIF PR_PRINT = 2.
CLEAR RM07M-XNAPR.
ENDIF.
ENDIF.
*---------
If the Print Indicator is not set, we clear the default print version so the system don't find any condition, not generating any slip. But the whole process for its determination is executed. It's not possible to skip the output determination, only to make sure it will not yield any results if not needed.
IF RM07M-XNAPR IS INITIAL.
CLEAR T158-WEVER.
ENDIF.
ENDFORM.
For the example we are running, RM07M-XNAPR is set to X since we marked the flag in MIGO and the version is defined as 1 for both MKPF-WEVER and T158-WEVER because RM07M-WVERS1 is X, corresponding to version 1 (Individual Slip).
2. Form BUCHEN_NUMMERNVERGABE (MM07MFB9)
Here's where the call for the forms KOPFDIALOGSTRUKTUR_FUELLEN, POSIDIALOGSTRUKTUR_FUELLEN and MESSAGING occurs to build the communication structure for the header, item and then trigger the actual output determination, respectively:
PERFORM kopfdialogstruktur_fuellen USING space. "<<< Build KOMKBME
LOOP AT xmseg.
xindex = sy-tabix.
xmseg-mblnr = xmkpf-mblnr.
IF xmseg-lgpla IS INITIAL AND NOT xmseg-xblvs IS INITIAL.
xmseg-lgpla = xmkpf-mblnr.
ENDIF.
IF xmseg-lfbnr IS INITIAL AND ( xmseg-kzbew = b OR t158-kzbew = b ).
LOOP AT lfbnr WHERE zeile = xmseg-zeile.
xmseg-lfbnr = xmkpf-mblnr.
ENDLOOP.
ENDIF.
MODIFY xmseg INDEX xindex.
READ TABLE xvm07m INDEX xmseg-zeile.
PERFORM posidialogstruktur_fuellen USING space. "<<< Build KOMPBME
PERFORM messaging USING space. "<<< Output determination
3. Form KOPFDIALOGSTRUKTUR_FUELLEN (MM07MFN0)
Here we have the call to the function COMMUNICATION_AREA_KOMKBME from SD area to fill the communication structure KOMKMBME with the information from the header of the material document (MKPF) like the Transaction Event Type (MKPF-VGART) and the Print Version (MKPF-WEVER).
This structure is used along with KOMPBME to define the condition table based on the access sequence on SD_COND_ACCESS function later in the process.
CALL FUNCTION 'COMMUNICATION_AREA_KOMKBME'
EXPORTING
MSG_MKPF = NMKPF
MSG_T158 = T158
MSG_PR_UNAME = PRINT_UNAME
TABLES
TAB_PART = PART.
Inside the function we can check the data returned to the imported structure KOMKBME:
4. Form POSIDIALOGSTRUKTUR_FUELLEN (MM07MFN0)
Like the previous form, we call the function COMMUNICATION_AREA_KOMPBME to fill the communication structure KOMPBME with the information of the items for the material document (MSEG) like the Print Item (T156-KZDRU) from Movement Type (MSEG-BWART), Plant (MSEG-WERKS), Storage Location (MSEG-LGORT), etc.
CALL FUNCTION 'COMMUNICATION_AREA_KOMPBME'
EXPORTING
MSG_MSEG = NMSEG
MSG_T156 = T156
MSG_VM07M = NVM07M
MSG_MKPF = MKPF
TABLES
TAB_PART = PART.
Inside of it we can check also check the return on structure KOMPBME:
5. Form MESSAGING (MM07MFN0)
This is where the actual output determination occurs based on all the information gathered previously and stored in KOMKBME and KOMPBME structures.
The condition technique from SD area is used for the determination of the condition table based on the access sequence determined by the key fields of the selected output.
The function MESSAGING starts the process by calling Form Routine COND_ACCESS_ME (LV61BMES) since the NACE application for the inventory management output is ME.
* do condition access if form already exists
PERFORM (L_CONDITION_FORM) IN PROGRAM SAPLV61B USING APPLIKATION
SCHEMA
IF FOUND.
* L_CONDITION_FORM = COND_ACCESS_ME
6. Form COND_ACCESS_ME (LV61BMES)
The internal tables KOMT1 e KOMT2 are filled in Form KONDITIONSVORSTEP(SAPLV61B).
KOMT1 will be filled with the output types configured for Inventory Management (KAPPL = ‘ME'). The column KOZGF corresponds to the access sequence linked to the output types in column KSCHL:
KOMT2 will be filled with the condition tables for each access sequence. The correspondence in MM-IM is 1:1.
When both tables are filled, we start a nested loop on them by calling the forms XNAST_AUFBAUEN_AUS_KOMT1 (LV61BF0X) and NACHRICHTENSTATUS_SCHREIBEN (LV61BF0N).
7. Form NACHRICHTENSTATUS_SCHREIBEN (LV61BF0N)
In this form we execute the call to the condition technique function SD_COND_ACCESS:
* start condition technique - find message type
CALL FUNCTION 'SD_COND_ACCESS'
EXPORTING
application = komt1-kappl
condition_type = komt1-kschl
header_comm_area = header_comm
position_comm_area = item_comm
prestep = ' '
protocol_access = protocol_access
read_only_one_record = 'X'
t682i_i = t682i
koprt_i = koprt
sdprothead_i = g_sdprothead
IMPORTING
condition_is_purely_header = headkz
TABLES
condition_records = kondtab
EXCEPTIONS
field_is_initial = 8
not_read_unqualified = 2
read_but_not_found = 4.
8. Function SD_COND_ACCESS
Inside this function, we will run the form SEL_KONDTAB:
* do access
PERFORM sel_kondtab TABLES condition_records
USING t682i_i
application
condition_type
date
prestep
read_only_one_record
protocol_access
protocol_date
sdprothead_i
koprt_i
condition_in_memory_internal
call_modus
read_all_prestep
CHANGING condition_is_purely_header
condition_is_in_memory.
On that form, we loop through the key fields of the access sequence to check if they are filled. With that information, we perform a dynamic select on the condition table inside T681-KOTAB together with the key field values inside CODING_TAB internal table.
Since the select is dynamic, we do not know the exact point where it will be executed in SEL_KONDTAB form, so in order to check it we can place a breakpoint in the statement below and go from there:
IF se_memory_internal EQ no OR se_t682i-gzugr NE 'B'. "<<< Breakpoint here
h_subrc = 4.
IF se_prestep = yes OR
se_read_only_one_record = yes.
IF t681-ksdat IS INITIAL.
IF se_read_all_prestep IS INITIAL.
SELECT * FROM (t681-kotab) APPENDING TABLE
UP TO 1 ROWS
WHERE kappl = se_kappl
AND kschl = se_kschl
AND (coding_tab).
h_subrc = sy-subrc.
ELSE.
SELECT * FROM (t681-kotab) APPENDING TABLE
WHERE kappl = se_kappl
AND kschl = se_kschl
AND (coding_tab).
ENDIF.
The statement below in form NACHRICHTENSTATUS_SCHREIBEN checks if the condition record number (XKNUMH) was found by the SEL_KONDTAB select (sy-subrc = 0 returned):
IF xknumh NE space.
*nach-kschl = space.
xsubrc = 1.
READ TABLE xnach WITH KEY key-knumh = xknumh BINARY SEARCH.
IF sy-subrc NE 0.
If the system found the record number, an entry is added to internal table XNAST.
9. Form BUCHEN_AUSFUEHREN (MM07MFB9)
In this form we can check XNAST table to confirm the entries built into it before the system starts the update tasks.
10. Form PROGRAMM_AUFRUFEN (RSNAST00) (UPDATE MODE)
It is not possible to debug the print program SAPM07DR because the same is executed in update task by the call below in Form PROGRAMM_AUFRUFEN (RSNAST00), also executed in update task:
perform (tnapr-ronam) in program (tnapr-pgnam) using returncode
us_screen
if found.
For our example, TNAPR-RONAM = ENTRY_WE01 and TNAPR-PGNAM = SAPM07DR.
Those are the main points of the old output determination process run by Inventory Management, if the output is not triggered for some reason when the document is posted, those points can be useful to find out what information was missing and adjust the customizing accordingly.
⠀



