Friday, 29 December 2023

How to get stock on posting date: manually and programmatically

Sometimes for planning purposes we need to get logistics stocks by plant/storage location/material for the specific date. In the blog I will describe some ways to solve the problem depending on version of SAP NetWeaver.

Manual approach via tcode MB5B


Transaction MB5B could help us to read stocks. Tcode could be find via menu path Logistics -> Materials Management -> Inventory Management -> Environment -> Stock -> MB5B – Stock for Posting Date. As we could see from the screenshot below there are also some others useful transactions in the menu path.

How to get stock on posting date: manually and programmatically
Pict1. Path to MB5B in standard menu

Transaction MB5B launches report RM07MLBD. The report collects the stocks according to selection criteria, where among others we could specify Material, Plant, Storage Location.

The MB5B shows zero-stocks by default. If we do not need zero-stocks we should uncheck checkbox Without Opening Stock; Without Closing Stock.

How to get stock on posting date: manually and programmatically
Pict.2 Exclude zero stocks

As a result the system provides us with abap list with several columns with important and accurate data.

How to get stock on posting date: manually and programmatically
Pict.3 ABAP list resutl in MB5B

So, to get stock on the specific date we need to fill in selection criteria and launch the report. In the table below I have provided short description with technical names for the selection criteria.

Parameter’s name Tech.name   Comment 
Material Number
(multi)
MATNR If not specified – no restriction by the field.
Company Code
(multi) 
BUKRS  For the sake of efficient launch it is recommended to specify. 
Plant
(multi) 
WERKS   
Storage Location
(multi) 
LGORT   
Selection Date
(multi) 
BUDAT   
Radiobutton group Stock type  LGBST
BWBST
SBBST 
I will choose option Storage Loc/Batch Stock (field LGBST)

List Scope

uncheck option
Without Opening Stock; Without Closing Stock

PA_WDZER

PA_NDZER 
Fields PA_NDZER иand PA_NDZER I will uncheck.

For more details about the report we can use F1 or help inside the report.

How to get stock on posting date: manually and programmatically
Pict.4 Documentation in MB5B from the selection screen

Also there are plenty of comments inside the report

How to get stock on posting date: manually and programmatically
Pict.5 Comments inside MB5B

So we can get stocks on the specific date (or period) via transaction MB5B manually. The report works in the following way: system reads quantity on the closing moment of the previous logistic period and then reads all material movements according to selection criteria; after that calculates total quantity with pluses and minuses. And of course the system takes into account different batches, stock types and different movement types.

But could we get the stocks programmatically? Yes. of course

Solution#1. Reading stocks via custom report as copy of RM07MLBD


The easiest way to read stock – is to copy RM07MLBD  into custom report and export data to memory. The custom class (which will launch the report) should import from memory the result and the stocks on the specific posting date are received accurately.

Advantage of the solution: we avoid doing any changes or enhancement inside standard code and we could add custom logic without any risk to impact standard report.

Disadvantage: in case of upgrade of report RM07MLBD  we need to replicate the changes also manually.

My realization of the solution could be found here. However I will highlight some moments:

1. the report RM07MLBD  uses locally defined structure inside. But for export/import to/from memory it is more convenient to use global structure. So we need to move data from internal table bestand (here is the result list of the report) to internal table with global type.

How to get stock on posting date: manually and programmatically

2. We need to add parameter to the report, that was the signal to report to export to memory. The report-copy could be like that.

How to get stock on posting date: manually and programmatically

3. SUBMIT REPORT is in the separate class which is also validate the selection criteria. The report is dealing with material movements and usually there are many movements – validation will helps to avoid unnecessary system’s overloading. In my realization export/import is doing by class in the following way.

Solution#2. Reading stocks via RM07MLBD directly (modern system versions)


In more modern versions the report RM07MLBD  was upgraded (among many others reports) and it already does have the parameter to export data into memory. So we have standard solution just like solution#1. However the option was done not for business needs but for unit test needs (I do not know, but maybe somebody has plan to remove it, but please do not do that)

Let us see some parts of the report.

1. Parameter P_AUT in report RM07MLBD (=transaction MB5B). The parameter is primary for unit testing but it gives us possibility to export the result data to memory.

How to get stock on posting date: manually and programmatically

2. The exporting to memory and memory id.

If the parameter P_AUT is checked – the system will not show the result by will export the data to memory.

How to get stock on posting date: manually and programmatically

3. Global table type STOCK_INVENTORY_TT and global structure STOCK_INVENTORY_S which are used for memory exporting/importing.

How to get stock on posting date: manually and programmatically

So, we could use standard approach for export to memory as we have done that in Solution #2. Example of code for solution #2 I have provided here.

Solution#3. Reading stocks RM07MLBD via EXPORT TO SPOOL


Any report which is using ABAP-list we could forward to spool and after that read data from spool. We could send data to spool via construction below

SUBMIT rm07mlbd EXPORTING LIST TO MEMORY.

With parameters it would look like that

    SUBMIT rm07mlbd EXPORTING LIST TO MEMORY
                     WITH bukrs IN lt_rng_bukrs
                     WITH werks IN is_sel_criteria-werks_rng
                     WITH lgort IN is_sel_criteria-lgort_rng
                     WITH matnr IN is_sel_criteria-matnr_rng
                     WITH budat IN is_sel_criteria-budat_rng
                     WITH bwbst EQ abap_true " valuated stock
                     WITH pa_sumfl EQ abap_true " Non-Hierarchical
                     WITH pa_wdzer EQ abap_true " without opening stock; without closing stock (mat withno movemetns)
                     AND RETURN
                     .
To read the result we need to use functions LIST_FROM_MEMORY, LIST_TO_ASCI и LIST_FREE_MEMORY. They are standard functions but inside themselves using memory ID %_LIST . This kind of solution I have provided here.

Disadvantage of the solution is additional parsing from string types into target types. It could take some time.

Advantages of the solution are cross-versions and the fact that the solution could be applied to ANY report that using ABAP list.

Solution#4. Using enhancement inside MB5B (report RM07MLBD)


The report RM07MLBD consists from subroutines and it gives the possibility to use enhancements technique. We should pay attention to the following parts of the report for enhancement

How to get stock on posting date: manually and programmatically
Pict.11 Subroutine listumfang where it is possible to add enhancement

How to get stock on posting date: manually and programmatically
Pict.12 Enhancement SPOT inside MB5B

Enhancements are widely described on sap wiki and here (author: Oleg Tochenyuk).

Advantage: you could avoid report copy.

Disadvantage: you should use enhancement carefully; as Linux-CLI says: with great power comes great responsibility.

Solution#5. Read stocks data via CDS (S/4 HANA version)


In S/4 HANA version we have CDS C_MaterialStockByKeyDate. For the solution I have also provided sample on github.

    SELECT *
      FROM C_MaterialStockByKeyDate( P_Language = @sy-langu, P_KeyDate = @lv_key_date )
      WITH PRIVILEGED ACCESS
      WHERE Plant IN @is_sel_criteria-werks_rng
        AND StorageLocation IN @is_sel_criteria-lgort_rng
        AND Material IN @is_sel_criteria-matnr_rng
        INTO TABLE @lt_stock_on_date
      .
 
I also would like to highlight:

1. the CDS C_MaterialStockByKeyDate works like MB5B: all documents are read and then system sum up and groups values.
2. In MB5B we could read stocks for period, but in CDS on the specific date only. Of course we could create some custom CDS above the C_MaterialStockByKeyDate but with help of the CDS only by date not by period.
3. MB5B shows quantity and amount of the stock; in CDS – quantity only.

Useful logistics’ CDS are in table below and also could be checked here.

CDS Description 
I_MATERIALDOCUMENTHEADER_2 Material Document Header
I_MaterialDocumentItem_2   Material Document Item 
I_MaterialStock   Material Stock 
I_MaterialStock_2   Material Stock 
C_MaterialStockActual  Total Actual Stock Quantity
C_MaterialStockByKeyDate  Material Stock at posting date 

No comments:

Post a Comment