Enterprise Resource Planning Blogs by Members
Gain new perspectives and knowledge about enterprise resource planning in blog posts from community members. Share your own comments and ERP insights today!
cancel
Showing results for 
Search instead for 
Did you mean: 
Waruna
Participant

Introduction


The purpose of this blog series is to share my experience with developing optimized inventory aging reports with the valuation for all stocks such as

  • Batch Stocks

  • Special Stocks with Vendor

  • Sales Order Stock

  • Special Stocks from Vendor


I have used proxy objects given by SAP S/4HANA in the form of CDS views and ABAP Managed Database Procedure (AMDP Classes) to process data through the S/4HANA system within 2 or 3 minutes. Logics has been implemented with less than 500 lines of code without even a single data processing loop. I would like to split this knowledge into multiple blog posts with this first post for the Batch Stocks aging.

The first part describes the implementation of the Selection Screen through the Module Pool program.
The next part describes the Implementation of the Inventory Aging Process in Eclipse as an AMDP class.
The last part describes the calling of the AMDP Class through the Selection Screen and Generate the Output ALV

So let’s start the ball rolling.

What You Should Already Have:


Before you start developing an inventory aging report, you should have Installed ABAP Development Tools (ADT) and a basic knowledge of:

Install ABAP Development Tools (ADT)

Stock Tables and Stock Types

SAP S/4HANA: Inventory Management Tables New Simplified Data Model (NSDM)

ABAP Managed Database Procedure

SAP CDS views Demystification

1. Implementation of the Selection Screen


Go to transaction code SE80 (Object Navigator), select the object category as Program, and enter the program name. ZMM_INVENTORY_AGE is given here for my example.


Hit the enter key on the program name and click Yes in the program creation dialog box as follows.


Next, make sure to check "Create with TOP Include" checkbox in the given program creation dialog box as follows.


Next, type the program name with _TOP for the "top include name" in the given input box as follows.



 

 

 

 

 


Next, Click Save on the program attribute window leaving the default values as follows. Initially, I created the program as module pool program.


Next, Select the appropriate package and click on save as follows.


Next, Create or select existing transportable workbench request for the development and continue until program creation is done as follows.


The generated initial program will be displayed as follows.


Next, double-click on the program name in the object list to open the ABAP Code and click on the Display Change button on the toolbar as follows. The source code will be changed as editable.


Next, insert a new include ZMM_INVENTORY_AGE_SEL for the selection screen include, below to the top include as following
*&---------------------------------------------------------------------*
*& Module Pool ZMM_INVENTORY_AGE
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*

INCLUDE ZMM_INVENTORY_AGE_TOP . " Global Data
INCLUDE ZMM_INVENTORY_AGE_SEL . " Selection Screen
* INCLUDE ZMM_INVENTORY_AGE_O01 . " PBO-Modules
* INCLUDE ZMM_INVENTORY_AGE_I01 . " PAI-Modules
* INCLUDE ZMM_INVENTORY_AGE_F01 . " FORM-Routines

 

Next, double-click on the include name ZMM_INVENTORY_AGE_SEL to create the object. Click Yes on the given dialog boxes until the Save dialog and click on Save. It is required to give the package name in the next window and select the transportable workbench request to complete the task. previously created transportable workbench request should be given.


Newly added include will be shown in the object list as follows.


Next double-click on include ZMM_INVENTORY_AGE_TOP  and need to change the PROGRAM as REPORT in the code as follows. then click on save.
*&---------------------------------------------------------------------*
*& Include ZMM_INVENTORY_AGE_TOP - Module Pool ZMM_INVENTORY_AGE
*&---------------------------------------------------------------------*
REPORT ZMM_INVENTORY_AGE.

Next double-click on the main program name ZMM_INVENTORY_AGE and click on Goto -> Attributes as follows.


Next, it is needed to change the Attributes Type to Executable program as follows. Click on save and then continue. Otherwise, it is not possible to run the program to display the selection screen.


Next, double-click on the main program name ZMM_INVENTORY_AGE and activate the entire program. The program should be activated without any errors.



Next, add the following code line to include ZMM_INVENTORY_AGE_TOP and activate that include individually.
TABLES : mara, t001k, mard.

Modified include ZMM_INVENTORY_AGE_TOP should be as follows.
*&---------------------------------------------------------------------*
*& Include ZMM_INVENTORY_AGE_TOP - Module Pool ZMM_INVENTORY_AGE
*&---------------------------------------------------------------------*
REPORT ZMM_INVENTORY_AGE.

TABLES : mara, t001k, mard.

The above tables are used to implement the selection screen.

Next, Add the following code to include ZMM_INVENTORY_AGE_SEL. Check (Ctrl+F2) the program to verify that there are no errors with the added code.
*&---------------------------------------------------------------------*
*& Include ZMM_INVENTORY_AGE_SEL
*&---------------------------------------------------------------------*
SELECTION-SCREEN : BEGIN OF BLOCK bk1 WITH FRAME TITLE TEXT-001.
PARAMETERS : p_comp TYPE t001k-bukrs.

SELECT-OPTIONS : s_mat FOR mara-matnr,
s_plant FOR t001k-bwkey NO-DISPLAY.

PARAMETERS : p_plant TYPE t001k-bwkey.

SELECT-OPTIONS : s_loc FOR mard-lgort,
s_mtt FOR mara-mtart.
SELECTION-SCREEN : END OF BLOCK bk1.

SELECTION-SCREEN : BEGIN OF BLOCK bk2 WITH FRAME TITLE TEXT-002.
PARAMETERS : p_date TYPE matdoc-bldat DEFAULT sy-datum .

SELECTION-SCREEN SKIP.

SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(30) TEXT-003.
PARAMETERS: p_age1(3) DEFAULT '1',
p_age2(3) DEFAULT '2',
p_age3(3) DEFAULT '3',
p_age4(3) DEFAULT '4',
p_age5(3) DEFAULT '',
p_age6(3) DEFAULT ''.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN : END OF BLOCK bk2.

Now you can activate the entire program. To activate the entire program double-click on the main program name ZMM_INVENTORY_AGE before activating. Otherwise, double-click on the main program and right-click to get the context menu on it. The program can be activated by clicking on the activate option on the context menu. The program should be activated without any errors.

Now the program can be run for the test screen by clicking direct processing or pressing shortcut key F8. Make it a point to double-click on the main program ZMM_INVENTORY_AGE before directly processing it.


The selection screen will be displayed as follows.


Next, change the selection screen labels in Text Elements -> Selection Text tab as follows and activate the program.



Next, add the frame titles TEXT-001, TEXT-002  and TEXT-003  in Text Elements -> Text Symbols tab as follows and activate the program.


The selection screen will be displayed as follows.


Next, add the below codes to filter Plant based on the selected Company.

Add the below code to the end of Include ZMM_INVENTORY_AGE_TOP as follows and activate the program.
TYPES: BEGIN OF ty_bwkey,
bwkey TYPE t001k-bwkey,
name1 TYPE t001w-name1,
END OF ty_bwkey.

DATA : it_return TYPE STANDARD TABLE OF ddshretval,
wa_dynpread TYPE dynpread,
it_dynpread TYPE TABLE OF dynpread,
it_bwkey TYPE STANDARD TABLE OF ty_bwkey.

Add the below code to the end of Include ZMM_INVENTORY_AGE_SEL as follows and activate the program.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_plant.

CLEAR: it_return,it_bwkey,s_plant.

wa_dynpread-fieldname = 'P_COMP'.
APPEND wa_dynpread TO it_dynpread.

CALL FUNCTION 'DYNP_VALUES_READ'
EXPORTING
dyname = sy-repid
dynumb = sy-dynnr
TABLES
dynpfields = it_dynpread.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.

READ TABLE it_dynpread INTO wa_dynpread INDEX 1.

IF wa_dynpread-fieldvalue IS NOT INITIAL.
SELECT k~bwkey w~name1 INTO TABLE it_bwkey
FROM t001k AS k
INNER JOIN t001w AS w
ON k~bwkey = w~werks
WHERE bukrs = wa_dynpread-fieldvalue.
ELSE.
SELECT k~bwkey w~name1 INTO TABLE it_bwkey
FROM t001k AS k
INNER JOIN t001w AS w
ON k~bwkey = w~werks.
ENDIF.

CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = 'BWKEY'
value_org = 'S'
TABLES
value_tab = it_bwkey
return_tab = it_return.

IF sy-subrc = 0.
IF it_return IS NOT INITIAL.
READ TABLE it_return INTO DATA(wa_return) INDEX 1.

IF wa_return-fieldval IS NOT INITIAL.
p_plant = wa_return-fieldval.

s_plant-low = p_plant.
s_plant-sign = 'I'.
s_plant-option = 'EQ'.

APPEND s_plant.
ELSE.
LOOP AT it_bwkey INTO DATA(wa_plant).

s_plant-low = wa_plant-bwkey.
s_plant-sign = 'I'.
s_plant-option = 'EQ'.

APPEND s_plant.
ENDLOOP.
ENDIF.
ENDIF.
ENDIF.

Next, add the below code to the end of Include ZMM_INVENTORY_AGE_SEL as follows to disable the date input field and activate the program.
AT SELECTION-SCREEN OUTPUT.
LOOP AT SCREEN.
IF screen-name = 'P_DATE'.
screen-input = '0'.
ENDIF.
MODIFY SCREEN.
ENDLOOP.

 

Create the following table structure using SE11 transaction. ZMM_DE_***** data elements need to be created separately before activating the structure.

Structure name: ZMM_ST_AGE_FINAL



MATNR	Types	MATNR	CHAR	40	0	0	Material Number
MAKTX Types MAKTX CHAR 40 0 0 Material Description
MTBEZ Types MTBEZ CHAR 25 0 0 Description of Material Type
WGBEZ Types WGBEZ CHAR 20 0 0 Material Group Description
MEINS Types MEINS UNIT 3 0 0 Base Unit of Measure
BWKEY Types BWKEY CHAR 4 0 0 Valuation area
VBELN Types VBELN CHAR 10 0 0 Sales and Distribution Document Number
LGORT Types ZMM_DE_LOGRT CHAR 10 0 0 Storage Location
LOTNO Types ZMM_DE_LOTNO CHAR 70 0 0 Lot Number
SOBKZ Types SOBKZ CHAR 1 0 0 Special Stock Indicator
BLDAT Types BLDAT DATS 8 0 0 Document Date in Document
CHARG Types CHARG_D CHAR 10 0 0 Batch Number
DAYS Types ZMM_DE_DAYS INT2 5 0 0 Age Days
QTYS Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
VALS Types SALK3 CURR 13 2 0 Value of Total Valuated Stock
SQM Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT Types BRGEW QUAN 13 3 0 Gross weight
QTY1 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
SQM1 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT1 Types BRGEW QUAN 13 3 0 Gross weight
VAL1 Types SALK3 CURR 13 2 0 Value of Total Valuated Stock
QTY2 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
SQM2 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT2 Types BRGEW QUAN 13 3 0 Gross weight
VAL2 Types SALK3 CURR 13 2 0 Value of Total Valuated Stock
QTY3 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
SQM3 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT3 Types BRGEW QUAN 13 3 0 Gross weight
VAL3 Types SALK3 CURR 13 2 0 Value of Total Valuated Stock
QTY4 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
SQM4 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT4 Types BRGEW QUAN 13 3 0 Gross weight
VAL4 Types SALK3 CURR 13 2 0 Value of Total Valuated Stock
QTY5 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
SQM5 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT5 Types BRGEW QUAN 13 3 0 Gross weight
VAL5 Types SALK3 CURR 13 2 0 Value of Total Valuated Stock
QTY6 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
SQM6 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT6 Types BRGEW QUAN 13 3 0 Gross weight
VAL6 Types SALK3 CURR 13 2 0 Value of Total Valuated Stock
QTY7 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
SQM7 Types LABST QUAN 13 3 0 Valuated Unrestricted-Use Stock
GRWT7 Types BRGEW QUAN 13 3 0 Gross weight
VAL7 Types SALK3 CURR 13 2 0 Value of Total Valuated Stock

Currency/quantity fields should be updated as follows.



QTYS	Types	LABST	QUAN	MARA	MEINS	Valuated Unrestricted-Use Stock
VALS Types SALK3 CURR T001 WAERS Value of Total Valuated Stock
SQM Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT Types BRGEW QUAN MARA GEWEI Gross weight
QTY1 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
SQM1 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT1 Types BRGEW QUAN MARA GEWEI Gross weight
VAL1 Types SALK3 CURR T001 WAERS Value of Total Valuated Stock
QTY2 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
SQM2 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT2 Types BRGEW QUAN MARA GEWEI Gross weight
VAL2 Types SALK3 CURR T001 WAERS Value of Total Valuated Stock
QTY3 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
SQM3 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT3 Types BRGEW QUAN MARA GEWEI Gross weight
VAL3 Types SALK3 CURR T001 WAERS Value of Total Valuated Stock
QTY4 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
SQM4 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT4 Types BRGEW QUAN MARA GEWEI Gross weight
VAL4 Types SALK3 CURR T001 WAERS Value of Total Valuated Stock
QTY5 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
SQM5 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT5 Types BRGEW QUAN MARA GEWEI Gross weight
VAL5 Types SALK3 CURR T001 WAERS Value of Total Valuated Stock
QTY6 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
SQM6 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT6 Types BRGEW QUAN MARA GEWEI Gross weight
VAL6 Types SALK3 CURR T001 WAERS Value of Total Valuated Stock
QTY7 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
SQM7 Types LABST QUAN MARA MEINS Valuated Unrestricted-Use Stock
GRWT7 Types BRGEW QUAN MARA GEWEI Gross weight
VAL7 Types SALK3 CURR T001 WAERS Value of Total Valuated Stock

 

Create the following table type using SE11 transaction. This table type needs to store the final result.

Table type name: ZMM_TT_AGE_FINAL



2. Implementation of the Inventory Aging Process in Eclipse


Create CDS view for read batch characteristics.


Open SAP project through Eclipse ide and select a suitable package to create CDS view. Right-click on Data Definition under Core Data Services and select New Data Definition. 


Enter CDS view name ZMM_CDS_BATCH_CHA and description, then click on Next as follows.


Next, Select the same transport request created when starting the development of the selection screen. Then finish with default values as follows.


Replace the generated code with the below code and activate.
@AbapCatalog.sqlViewName: 'ZMM_BATCH_CHA'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Material Characteristics Batch'
define view ZMM_CDS_BATCH_CHA
with parameters
p_atnam :atnam
as select from cabn as cb
inner join ausp as au on cb.atinn = au.atinn
and cb.mandt = au.mandt
{

au.objek,
au.atwrt

}
where
atnam = :p_atnam;

 

Create AMDP Class.


Select a suitable package to create AMDP class.


Goto <Sellected Package> -> Source Code Library -> Classes.

Right-click on the Classes node and create a new ABAP class as follows.


Next, give a class name and click on Next.


It will require selecting an existing transport request or creating a new request to attach the new class. It should select the same transport request created when starting the development of the selection screen. Then click on the Finish button.



An empty class will be created as follows.


Add interface IF_AMDP_MARKER_HDB, next to the public section in the class definition.

Next, add the below method to the class definition next to the interface.
  INTERFACES if_amdp_marker_hdb.

METHODS process_inv_age AMDP OPTIONS READ-ONLY
CDS SESSION CLIENT current
IMPORTING VALUE(im_sp_mara) TYPE string
VALUE(im_sp_mchb) TYPE string
VALUE(im_age1) TYPE int8
VALUE(im_age2) TYPE int8
VALUE(im_age3) TYPE int8
VALUE(im_age4) TYPE int8
VALUE(im_age5) TYPE int8
VALUE(im_age6) TYPE int8
VALUE(im_date) TYPE budat
EXPORTING VALUE(ex_tt_age_final) TYPE zmm_tt_age_final
RAISING cx_amdp_error.

Tables used for the development:





































































Table Proxy Object Database Entity
MARA General Material Data
MCHB NSDM_V_MCHB NSDM_E_MCHB Batch Stocks
MAKT Material Description
T134T Material Type Descriptions
T023T Material Group Descriptions
MBEW MBVMBEW MBV_MBEW Material Valuation
MCH1 Batches (if Batch Management Cross-Plant)
MATDOC Material Documents
MARM Units of Measure for Material
ZMM_CDS_BATCH_CHA Above created CDS view for read Batch characteristic data

The proxy object can be found using SE16N transaction as follows.


Next, add the below method with tables and proxy objects inside the class implementation.
  METHOD process_inv_age BY DATABASE
PROCEDURE FOR HDB LANGUAGE
SQLSCRIPT OPTIONS READ-ONLY
USING mara nsdm_v_mchb makt mch1 mbvmbew matdoc
marm zmm_cds_batch_cha t134t t023t.



ENDMETHOD.

It will give error on nsdm_v_mchb and mbvmbew. The eclipse IDE will suggest to use the associated entity instead of them. Please change them accordingly.



CLASS zcl_amdp_inv_age IMPLEMENTATION.

METHOD process_inv_age BY DATABASE
PROCEDURE FOR HDB LANGUAGE
SQLSCRIPT OPTIONS READ-ONLY
USING mara nsdm_e_mchb makt mch1 mbv_mbew matdoc
marm zmm_cds_batch_cha t134t t023t.

ENDMETHOD.

ENDCLASS.

Next, add the below code inside the method. In my scenario, I have used the posting date of the material document (matdoc-budat) to calculate the batch age for opening stocks (matdoc-bwart = '561'). Otherwise,  I have used batch creation date (mch1-ersda) for age calculation. You need to change the date values for 'yyyymmdd' in the below code. You are free to change this logic according to your scenario.

If you want to display some batch characteristic values, you will be required to use custom CDS view ZMM_CDS_BATCH_CHA('ZZZZZ') and change the suitable value to 'ZZZZZ' filter inside the brackets according to your context or remove the usage from the query.
    declare lv_dt_age1, lv_dt_age2, lv_dt_age3, lv_dt_age4, lv_dt_age5, lv_dt_age6 DATE;

if im_age1 > 0 then
lv_dt_age1 = add_months( CURRENT_DATE, (im_age1 * -1) );
END IF ;

if im_age2 > 0 then
lv_dt_age2 = add_months( CURRENT_DATE, (im_age2 * -1) );
END IF ;

if im_age3 > 0 then
lv_dt_age3 = add_months( CURRENT_DATE, (im_age3 * -1) );
END IF ;

if im_age4 > 0 then
lv_dt_age4 = add_months( CURRENT_DATE, (im_age4 * -1) );
END IF ;

if im_age5 > 0 then
lv_dt_age5 = add_months( CURRENT_DATE, (im_age5 * -1) );
END IF ;

if im_age6 > 0 then
lv_dt_age6 = add_months( CURRENT_DATE, (im_age6 * -1) );
END IF ;

it_mara = APPLY_FILTER (mara, :im_sp_mara);

it_nsdm_e_mchb = APPLY_FILTER (nsdm_e_mchb, :im_sp_mchb);

it_mchb = SELECT distinct m.matnr, mk.maktx, mb.werks, mb.lgort, '' as lifnr, mb.charg,
mb.clabs + mb.cinsm + mb.cspem AS qtys,
m.mtart, m.brgew, mty.mtbez, mgp.wgbez, m.meins,
SESSION_CONTEXT('LOCALE_SAP') as lan, SESSION_CONTEXT('CLIENT') as clnt,
'' as sobkz, '' as vbeln, '' as posnr
FROM :it_mara AS m
inner join :it_nsdm_e_mchb AS mb ON m.matnr = mb.matnr
AND m.mandt = SESSION_CONTEXT('CLIENT')
inner join makt AS mk ON m.matnr = mk.matnr
and mk.spras = SESSION_CONTEXT('LOCALE_SAP')
AND mk.mandt = SESSION_CONTEXT('CLIENT')
inner join t134t mty ON m.mtart = mty.mtart
and mty.spras = SESSION_CONTEXT('LOCALE_SAP')
AND mty.mandt = SESSION_CONTEXT('CLIENT')
inner join t023t AS mgp ON m.matkl = mgp.matkl
and mgp.spras = SESSION_CONTEXT('LOCALE_SAP')
AND mgp.mandt = SESSION_CONTEXT('CLIENT');

it_mchb_mbew = select distinct bs.*, mv.bwkey, mv.salk3, mv.lbkum
from :it_mchb as bs left outer join MBV_MBEW as mv on bs.matnr = mv.matnr
and bs.werks = mv.bwkey
and mv.mandt = SESSION_CONTEXT('CLIENT');

it_all = select * from :it_mchb_mbew;

it_mch1 = select distinct bs.matnr, bs.maktx, bs.werks, bs.lgort, bs.lifnr, bs.charg,
bs.qtys, bs.mtart, bt.ersda, bt.lwedt, bs.salk3, bs.lbkum,
:im_date as bldat, md.budat, md.bwart,
case when bt.lwedt = 'yyyymmdd' then
case when md.budat = 'yyyymmdd' and md.bwart = '561' then
md.bldat
else
bt.ersda
end
else
bt.ersda
end as age_date,
case when bt.lwedt = 'yyyymmdd' then
case when md.budat = 'yyyymmdd' and md.bwart = '561' then
DAYS_BETWEEN(md.budat, CURRENT_DATE)
else
0
end
else
case when bt.ersda is not null then
DAYS_BETWEEN(bt.ersda, CURRENT_DATE)
else
0
end
end as days,
case when bs.lbkum <> 0 and bs.salk3 <> 0 then
bs.qtys * ( bs.salk3 / bs.lbkum )
else
0
end as vals,
case when mr.meinh = 'M2' then
case when mr.umrez = 0 or mr.umrez is null then
0
else
bs.qtys * mr.umren / mr.umrez
end
else 0
end as sqm,
bs.brgew,
bs.qtys * bs.brgew as grwt,
bh.atwrt,
CURRENT_DATE as pdate,
bs.mtbez,
bs.wgbez,
bs.bwkey,
bs.sobkz,
mr.meinh,
bs.meins,
bt.cuobj_bm,
bh.objek,
bs.vbeln
from :it_all as bs
left outer join mch1 as bt on bs.matnr = bt.matnr
and bs.charg = bt.charg
and bt.mandt = SESSION_CONTEXT('CLIENT')
left outer join matdoc as md on bs.matnr = md.matnr
and bs.charg = md.charg
and md.bwart = '561'
and md.mandt = SESSION_CONTEXT('CLIENT')
left outer join marm as mr on bs.matnr = mr.matnr
and mr.meinh = 'M2'
and mr.mandt = SESSION_CONTEXT('CLIENT')
left outer join ZMM_CDS_BATCH_CHA( 'ZZZZZ' ) bh on bt.cuobj_bm = bh.objek
where bs.qtys > 0;

ex_tt_age_final = select distinct matnr, maktx, mtbez,
wgbez, meins, werks as bwkey, vbeln,
case when lgort = '' then
lifnr
else lgort end as lgort,
atwrt as lotno, sobkz, bldat,
charg, days, qtys, vals, sqm, grwt,
case when :im_age1 > 0 then
case when age_date >= :lv_dt_age1 then
qtys
else 0.000 end
else 0.000
end as qty1,
case when :im_age1 > 0 then
case when age_date >= :lv_dt_age1 then
sqm
else 0.000 end
else 0.000
end as sqm1,
case when :im_age1 > 0 then
case when age_date >= :lv_dt_age1 then
grwt
else 0.000 end
else 0.000
end as grwt1,
case when :im_age1 > 0 then
case when age_date >= :lv_dt_age1 then
vals
else 0.00 end
else 0.00
end as val1,

case when :im_age2 > 0 then
case when age_date >= :lv_dt_age2 and age_date < :lv_dt_age1 then
qtys
else 0.000 end
else
case when age_date < :lv_dt_age1 then
qtys
else 0.000 end
end as qty2,
case when :im_age2 > 0 then
case when age_date >= :lv_dt_age2 and age_date < :lv_dt_age1 then
sqm
else 0.000 end
else
case when age_date < :lv_dt_age1 then
sqm
else 0.000 end
end as sqm2,
case when :im_age2 > 0 then
case when age_date >= :lv_dt_age2 and age_date < :lv_dt_age1 then
grwt
else 0.000 end
else
case when age_date < :lv_dt_age1 then
grwt
else 0.000 end
end as grwt2,
case when :im_age2 > 0 then
case when age_date >= :lv_dt_age2 and age_date < :lv_dt_age1 then
vals
else 0.00 end
else
case when age_date < :lv_dt_age1 then
vals
else 0.00 end
end as val2,

case when :im_age3 > 0 then
case when age_date >= :lv_dt_age3 and age_date < :lv_dt_age2 then
qtys
else 0.000 end
else
case when age_date < :lv_dt_age2 then
qtys
else 0.000 end
end as qty3,
case when :im_age3 > 0 then
case when age_date >= :lv_dt_age3 and age_date < :lv_dt_age2 then
sqm
else 0.000 end
else
case when age_date < :lv_dt_age2 then
sqm
else 0.000 end
end as sqm3,
case when :im_age3 > 0 then
case when age_date >= :lv_dt_age3 and age_date < :lv_dt_age2 then
grwt
else 0.000 end
else
case when age_date < :lv_dt_age2 then
grwt
else 0.000 end
end as grwt3,
case when :im_age3 > 0 then
case when age_date >= :lv_dt_age3 and age_date < :lv_dt_age2 then
vals
else 0.00 end
else
case when age_date < :lv_dt_age2 then
vals
else 0.00 end
end as val3,

case when :im_age4 > 0 then
case when age_date >= :lv_dt_age4 and age_date < :lv_dt_age3 then
qtys
else 0 end
else
case when age_date < :lv_dt_age3 then
qtys
else 0.000 end
end as qty4,
case when :im_age4 > 0 then
case when age_date >= :lv_dt_age4 and age_date < :lv_dt_age3 then
sqm
else 0.000 end
else
case when age_date < :lv_dt_age3 then
sqm
else 0.000 end
end as sqm4,
case when :im_age4 > 0 then
case when age_date >= :lv_dt_age4 and age_date < :lv_dt_age3 then
grwt
else 0.000 end
else
case when age_date < :lv_dt_age3 then
grwt
else 0.000 end
end as grwt4,
case when :im_age4 > 0 then
case when age_date >= :lv_dt_age4 and age_date < :lv_dt_age3 then
vals
else 0.00 end
else
case when age_date < :lv_dt_age3 then
vals
else 0.00 end
end as val4,

case when :im_age5 > 0 then
case when age_date >= :lv_dt_age5 and age_date < :lv_dt_age4 then
qtys
else 0.000 end
else
case when age_date < :lv_dt_age4 then
qtys
else 0.000 end
end as qty5,
case when :im_age5 > 0 then
case when age_date >= :lv_dt_age5 and age_date < :lv_dt_age4 then
sqm
else 0.000 end
else
case when age_date < :lv_dt_age4 then
sqm
else 0.000 end
end as sqm5,
case when :im_age5 > 0 then
case when age_date >= :lv_dt_age5 and age_date < :lv_dt_age4 then
grwt
else 0.000 end
else
case when age_date < :lv_dt_age4 then
grwt
else 0.000 end
end as grwt5,
case when :im_age5 > 0 then
case when age_date >= :lv_dt_age5 and age_date < :lv_dt_age4 then
vals
else 0.00 end
else
case when age_date < :lv_dt_age4 then
vals
else 0.00 end
end as val5,

case when :im_age6 > 0 then
case when age_date >= :lv_dt_age6 and age_date < :lv_dt_age5 then
qtys
else 0.000 end
else
case when age_date < :lv_dt_age5 then
qtys
else 0.000 end
end as qty6,
case when :im_age6 > 0 then
case when age_date >= :lv_dt_age6 and age_date < :lv_dt_age5 then
sqm
else 0.000 end
else
case when age_date < :lv_dt_age5 then
sqm
else 0.000 end
end as sqm6,
case when :im_age6 > 0 then
case when age_date >= :lv_dt_age6 and age_date < :lv_dt_age5 then
grwt
else 0.000 end
else
case when age_date < :lv_dt_age5 then
grwt
else 0.000 end
end as grwt6,
case when :im_age6 > 0 then
case when age_date >= :lv_dt_age6 and age_date < :lv_dt_age5 then
vals
else 0.00 end
else
case when age_date < :lv_dt_age5 then
vals
else 0.00 end
end as val6,

case when :im_age6 > 0 then
case when age_date < :lv_dt_age6 then
qtys
else 0.000 end
else 0.000
end as qty7,
case when :im_age6 > 0 then
case when age_date < :lv_dt_age6 then
sqm
else 0.000 end
else 0.000
end as sqm7,
case when :im_age6 > 0 then
case when age_date < :lv_dt_age6 then
grwt
else 0.000 end
else 0.000
end as grwt7,
case when :im_age6 > 0 then
case when age_date < :lv_dt_age6 then
vals
else 0.00 end
else 0.00
end as val7
from :it_mch1
where qtys > 0;

Next, activate the AMDP class as follows.





3. Calling the AMDP Class through the Selection Screen and Generate the Output ALV


Open the selection screen program ZMM_INVENTORY_AGE in SE80 (Implemented in point 1) and uncomment the line INCLUDE ZMM_INVENTORY_AGE_F01 in the module pool program as follows.


Double-click on the above uncommented ZMM_INVENTORY_AGE_F01 and click Yes on the popup dialog boxes until the save dialog box appears as follows.


Click on the save button leaving the default values in the save dialog as follows.


Select a package to save it and select the transport request. Then, save the entire program. It will create an include file for ZMM_INVENTORY_AGE_F01 as follows.


Next, go to the include ZMM_INVENTORY_AGE_SEL, add below code lines below to the end of the file, and save the program.
START-OF-SELECTION.

IF p_comp IS NOT INITIAL.
SELECT SINGLE bukrs INTO @DATA(lv_bukrs)
FROM t001
WHERE bukrs = @p_comp.

IF lv_bukrs IS INITIAL.
MESSAGE 'Incorrect company code' TYPE 'I' DISPLAY LIKE 'E'.
ELSE.
PERFORM get_data.
* PERFORM build_fcat.
* PERFORM call_alv.
* CALL SCREEN 1001.
ENDIF.
ELSE.
MESSAGE 'Enter company code' TYPE 'I' DISPLAY LIKE 'E'.
ENDIF.

Next, double-click on PERFORM get_data to create the subroutine in ZMM_INVENTORY_AGE_F01. click on the Yes button as follows.


Next, select the Include ZMM_INVENTORY_AGE_F01 and continue as follows.


It will generate a subroutine in the Include ZMM_INVENTORY_AGE_F01 as follows. Then, save the entire program.



 

 

 

 

 

 

 

Add below code lines inside the FORM get_data and save the program.
  CLEAR: s_plant.

IF p_comp IS NOT INITIAL.
IF p_plant IS INITIAL.
SELECT k~bwkey w~name1 INTO TABLE it_bwkey
FROM t001k AS k
INNER JOIN t001w AS w
ON k~bwkey = w~werks
WHERE bukrs = p_comp.

LOOP AT it_bwkey INTO DATA(wa_bw).

s_plant-low = wa_bw-bwkey.
s_plant-sign = 'I'.
s_plant-option = 'EQ'.

APPEND s_plant.
ENDLOOP.
ELSE.
s_plant-low = p_plant.
s_plant-sign = 'I'.
s_plant-option = 'EQ'.

APPEND s_plant.
ENDIF.
ENDIF.

CLEAR :it_return, it_bwkey, wa_dynpread, it_dynpread.

DATA(sp_mara) = cl_shdb_seltab=>combine_seltabs(
it_named_seltabs = VALUE #( ( name = 'MTART' dref = REF #( s_mtt[] ) )
( name = 'MATNR' dref = REF #( s_mat[] ) ) )
iv_client_field = 'MANDT').

DATA(sp_mchb) = cl_shdb_seltab=>combine_seltabs(
it_named_seltabs = VALUE #( ( name = 'MATNR' dref = REF #( s_mat[] ) )
( name = 'WERKS' dref = REF #( s_plant[] ) )
( name = 'LGORT' dref = REF #( s_loc[] ) ) )
iv_client_field = 'MANDT') .

TRY.



CATCH cx_root INTO DATA(exp_root).
MESSAGE exp_root->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

Next, open the Include ZMM_INVENTORY_AGE_TOP and add the below line to the end of the file. This line is used to instantiate the object for the above-implemented AMDP class.
DATA(obj_mm_age) = NEW zcl_amdp_inv_age( ).

Then activate the Include ZMM_INVENTORY_AGE_TOP.

Open the include ZMM_INVENTORY_AGE_F01 and set the cursor inside the try-catch block as follows.


Next, click on the Pattern. Select ABAP Objects Patterns option on the popup dialog as follows and click continue.


Next, select the Call Method option, fill in the values as follows, and continue.


Instance = Object name declared in TOP include ZMM_INVENTORY_AGE_TOP.

Class/Interface = AMDP class name implemented in the Eclipse.

Method = Implemented method inside the AMDP Class.

Fill in the import-export parameters, format the generated code as follows, and save the file.
  TRY.

CALL METHOD obj_mm_age->process_inv_age
EXPORTING
im_sp_mara = sp_mara
im_sp_mchb = sp_mchb
im_age1 = CONV int8( p_age1 )
im_age2 = CONV int8( p_age2 )
im_age3 = CONV int8( p_age2 )
im_age4 = CONV int8( p_age4 )
im_age5 = CONV int8( p_age5 )
im_age6 = CONV int8( p_age6 )
im_date = p_date
IMPORTING
ex_tt_age_final = it_age_final.

CATCH cx_root INTO DATA(exp_root).
MESSAGE exp_root->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

Open the include ZMM_INVENTORY_AGE_TOP, add below code line below to the end of the file, and activate the include ZMM_INVENTORY_AGE_TOP.
DATA: it_age_final TYPE zmm_tt_age_final.

Next, open the module pool program ZMM_INVENTORY_AGE and activate the entire program. The program should be activated without any error.

Open the Include ZMM_INVENTORY_AGE_TOP, add the code line below, and activate the include.
DATA : lt_fieldcat TYPE lvc_t_fcat,
wa_fieldcat TYPE lvc_s_fcat.

Open the include ZMM_INVENTORY_AGE_F01 and uncomment the code linePERFORM call_alv_batch as follows.


Double-click on the PERFORM build_fcat and create a subroutine in the ZMM_INVENTORY_AGE_F01 as previously done. The generated subroutine will be displayed as follows. Save the include ZMM_INVENTORY_AGE_F01.


Add below code lines inside the FORM buid_fcat subroutine and save the file.
  TRY.
CLEAR: lt_fieldcat, wa_fieldcat.

wa_fieldcat-fieldname = 'MATNR'.
wa_fieldcat-coltext = 'Material'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'MAKTX'.
wa_fieldcat-coltext = 'Material Description'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'MTBEZ'.
wa_fieldcat-coltext = 'Material Type'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'WGBEZ'.
wa_fieldcat-coltext = 'Material Group'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'MEINS'.
wa_fieldcat-coltext = 'UOM'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'BWKEY'.
wa_fieldcat-coltext = 'Plant'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'LGORT'.
wa_fieldcat-coltext = 'Storage Location'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'BLDAT'.
wa_fieldcat-coltext = 'Stock on Key Date'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-outputlen = 10.

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'CHARG'.
wa_fieldcat-coltext = 'Batch'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'LOTNO'.
wa_fieldcat-coltext = 'Lot No'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'SOBKZ'.
wa_fieldcat-coltext = 'Spl. Stock Indicator'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'VBELN'.
wa_fieldcat-coltext = 'Sales Doc'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'QTYS'.
wa_fieldcat-coltext = 'Quantity Total'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'GRWT'.
wa_fieldcat-coltext = 'KG Total'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'SQM'.
wa_fieldcat-coltext = 'SQM Total'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

wa_fieldcat-fieldname = 'VALS'.
wa_fieldcat-coltext = 'Value Total'.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

PERFORM age_fields_generation.

CATCH cx_root INTO DATA(exp_root).
MESSAGE exp_root->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

Double-click on the code line PERFORM age_fields_generation in the above code and create a subroutine for age_fields_generation in the include ZMM_INVENTORY_AGE_F01 as previously done. The generated code will be displayed as follows.


Add below code lines inside the subroutine for FORM age_fields_generation.
  DATA : lv_age_column  TYPE char25,
lv_prev_age TYPE char2,
lv_f_name_qty TYPE char4,
lv_f_name_grwt TYPE char5,
lv_f_name_sqm TYPE char4,
lv_f_name_val TYPE char4.

IF p_age1 IS NOT INITIAL.
CONCATENATE 'QTY 0 ' '-' p_age1 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'QTY1'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'QTY KG 0 ' '-' p_age1 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'GRWT1'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE '0 ' '-' p_age1 'Months SQM' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'SQM1'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Value' '0 ' '-' p_age1 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'VAL1'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

lv_f_name_qty = 'QTY2'.
lv_f_name_grwt = 'GRWT2'.
lv_f_name_sqm = 'SQM2'.
lv_f_name_val = 'VAL2'.

lv_prev_age = p_age1.
ENDIF.

IF p_age2 IS NOT INITIAL.
CONCATENATE 'QTY' p_age1 '-' p_age2 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'QTY2'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'QTY KG' p_age1 '-' p_age2 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'GRWT2'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE p_age1 '-' p_age2 'Months SQM' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'SQM2'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Value' p_age1 '-' p_age2 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'VAL2'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

lv_f_name_qty = 'QTY3'.
lv_f_name_grwt = 'GRWT3'.
lv_f_name_sqm = 'SQM3'.
lv_f_name_val = 'VAL3'.

lv_prev_age = p_age2.
ENDIF.

IF p_age3 IS NOT INITIAL.
CONCATENATE 'QTY' p_age2 '-' p_age3 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'QTY3'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'QTY KG' p_age2 '-' p_age3 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'GRWT3'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE p_age2 '-' p_age3 'Months SQM' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'SQM3'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Value' p_age2 '-' p_age3 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'VAL3'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

lv_f_name_qty = 'QTY4'.
lv_f_name_grwt = 'GRWT4'.
lv_f_name_sqm = 'SQM4'.
lv_f_name_val = 'VAL4'.

lv_prev_age = p_age3.
ENDIF.

IF p_age4 IS NOT INITIAL.
CONCATENATE 'QTY' p_age3 '-' p_age4 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'QTY4'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'QTY KG' p_age3 '-' p_age4 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'GRWT4'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE p_age3 '-' p_age4 'Months SQM' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'SQM4'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Value' p_age3 '-' p_age4 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'VAL4'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

lv_f_name_qty = 'QTY5'.
lv_f_name_grwt = 'GRWT5'.
lv_f_name_sqm = 'SQM5'.
lv_f_name_val = 'VAL5'.

lv_prev_age = p_age4.
ENDIF.

IF p_age5 IS NOT INITIAL.
CONCATENATE 'QTY' p_age4 '-' p_age5 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'QTY5'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'QTY KG' p_age4 '-' p_age5 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'GRWT5'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE p_age4 '-' p_age5 'Months SQM' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'SQM5'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Value' p_age4 '-' p_age5 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'VAL5'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

lv_f_name_qty = 'QTY6'.
lv_f_name_grwt = 'GRWT6'.
lv_f_name_sqm = 'SQM6'.
lv_f_name_val = 'VAL6'.

lv_prev_age = p_age5.
ENDIF.

IF p_age6 IS NOT INITIAL.
CONCATENATE 'QTY' p_age5 '-' p_age6 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'QTY6'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'QTY KG' p_age5 '-' p_age6 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'GRWT6'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE p_age5 '-' p_age6 'Months SQM' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'SQM6'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Value' p_age5 '-' p_age6 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = 'VAL6'.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

lv_f_name_qty = 'QTY7'.
lv_f_name_grwt = 'GRWT7'.
lv_f_name_sqm = 'SQM7'.
lv_f_name_val = 'VAL7'.

lv_prev_age = p_age6.
ENDIF.
* ENDLOOP.

CONCATENATE 'QTY Above' lv_prev_age 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = lv_f_name_qty.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'QTY KG Above' lv_prev_age 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = lv_f_name_grwt.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Above' lv_prev_age 'Months SQM' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = lv_f_name_sqm.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

CLEAR : lv_age_column.
CONCATENATE 'Value above' lv_prev_age 'Months' INTO lv_age_column SEPARATED BY space.
wa_fieldcat-fieldname = lv_f_name_val.
wa_fieldcat-coltext = lv_age_column.
wa_fieldcat-tabname = 'IT_FINAL_DETAILS' .
wa_fieldcat-decimals_o = '2'.

APPEND wa_fieldcat TO lt_fieldcat.

Save the include ZMM_INVENTORY_AGE_F01, open the module pool program ZMM_INVENTORY_AGE, and activate the entire program. The program should be activated without any error.

Right-click on the module pool program ZMM_INVENTORY_AGE. Then select the option Create -> Screen as follows.


Enter the screen number as 1001 and click on continue as follows.


Enter the short description and save the screen. The screen will be created as follows in the object navigator.



Click on the layout button to open the Screen Painter as follows.



Next, click on the Custom Control icon from the toolbar on the right. Then, put it into a screen area, and resize it to full-screen size as follows. Enter the control name as CC_ALV.


Next, save the screen. Then, activate it, and close the Screen Painter window.

Enter OK_CODE to the 2nd row name in the Element List tab as follows.


Open the Module Pool program ZMM_INVENTORY_AGE. Then, uncomment the following lines and create an include for both of them as done previously and save the changes.
INCLUDE ZMM_INVENTORY_AGE_O01                   .    " PBO-Modules
INCLUDE ZMM_INVENTORY_AGE_I01 . " PAI-Modules

Open the screen 101. Then, uncomment the 2nd line in the Flow Logic tab as follows and double-click on it.


Click on Yes the popup dialog. Then select the include ZMM_INVENTORY_AGE_O01 and continue as follows.


The generated code will be shown as follows.


Uncomment the code. Then, change the code as follows.
MODULE status_1001 OUTPUT.
SET PF-STATUS 'STATUS'.
SET TITLEBAR 'TITLE'.
ENDMODULE.

Double-click on the 'STATUS' and click on Yes until the following screen appears. Enter a Short description and continue.


Next, enter BACK, EXIT, and CANCEL values under the Functions Keys section as follows and save the changes.


Go back to the include ZMM_INVENTORY_AGE_O01. Then double-click on 'TITLE' and enter the title on the popup window as follows and continue. Save the include ZMM_INVENTORY_AGE_O01.


Go back to the screen Flow Logic tab and uncomment the line 5 as follows.
PROCESS AFTER INPUT.
MODULE user_command_1001.

Double-click on MODULE user_command_1001. Click on Yes in the popup dialog. Then select the include ZMM_INVENTORY_AGE_I01 and continue as follows.


The generated code will be shown as follows.


Replace the code as follows and save the Include ZMM_INVENTORY_AGE_I01.
MODULE user_command_1001 INPUT.
CASE ok_code.
WHEN 'BACK'.
LEAVE TO SCREEN 0.
WHEN 'CANCEL'.
LEAVE TO SCREEN 0.
WHEN 'EXIT'.
LEAVE TO SCREEN 0.
ENDCASE.
ENDMODULE.

Open the include ZMM_INVENTORY_AGE_SEL. Then, uncomment the remaining lines of PERFORM call_alv  and CALL SCREEN 1001 as follows.
START-OF-SELECTION.

IF p_comp IS NOT INITIAL.
SELECT SINGLE bukrs INTO @DATA(lv_bukrs)
FROM t001
WHERE bukrs = @p_comp.

IF lv_bukrs IS INITIAL.
MESSAGE 'Incorrect company code' TYPE 'I' DISPLAY LIKE 'E'.
ELSE.
PERFORM get_data.
PERFORM build_fcat.
PERFORM call_alv.
CALL SCREEN 1001.
ENDIF.
ELSE.
MESSAGE 'Enter company code' TYPE 'I' DISPLAY LIKE 'E'.
ENDIF.

Save the file and double-click on call_alv to create the subroutine. Select the include ZMM_INVENTORY_AGE_F01 as follows and continue as follows.


Add below code lines to generate subroutines as follows. Save the changes.
FORM call_alv .

TRY.
lwa_variant-report = sy-repid.

CREATE OBJECT cc_alv
EXPORTING
container_name = 'CC_ALV'.

CREATE OBJECT o_grid
EXPORTING
i_parent = cc_alv.

lwa_layout = 'X'.

CALL METHOD o_grid->set_table_for_first_display
EXPORTING
is_variant = lwa_variant
is_layout = lwa_layout
i_default = 'X'
i_save = 'A'
CHANGING
it_outtab = it_age_final
it_fieldcatalog = lt_fieldcat
EXCEPTIONS
invalid_parameter_combination = 1
program_error = 2
too_many_lines = 3
OTHERS = 4.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
CATCH cx_root INTO DATA(exp_root).
MESSAGE exp_root->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.

ENDFORM.

Open the include and add the following code lines.
DATA : ok_code TYPE sy-ucomm.
DATA : cc_alv TYPE REF TO cl_gui_custom_container.

DATA : o_grid TYPE REF TO cl_gui_alv_grid.

DATA : lwa_layout TYPE lvc_s_layo.

DATA : lwa_variant TYPE disvariant.

Save the all changes and activate the entire program. The program should be activated without any error.

Now you are ready to execute the program. The following output will be shown as ALV with your data.


The output ALV format is as per the given age blocks in the selection screens.

















































Material Material Description Material Type Material Group UOM Plant Storage Location Stock on Key Date Batch Lot No Spl. Stock Indicator Sales Doc Quantity Total KG Total SQM Total Value Total QTY 0 - 1 Months QTY KG 0 - 1 Months 0 - 1 Months SQM Value 0 - 1 Months QTY 1 - 2 Months QTY KG 1 - 2 Months 1 - 2 Months SQM Value 1 - 2 Months QTY 2 - 3 Months QTY KG 2 - 3 Months 2 - 3 Months SQM Value 2 - 3 Months QTY 3 - 4 Months QTY KG 3 - 4 Months 3 - 4 Months SQM Value 3 - 4 Months QTY 4 - 5 Months QTY KG 4 - 5 Months 4 - 5 Months SQM Value 4 - 5 Months QTY 5 - 6 Months QTY KG 5 - 6 Months 5 - 6 Months SQM Value 5 - 6 Months QTY Above 6 Months QTY KG Above 6 Months Above 6 Months SQM Value above 6 Months

 
2 Comments
Labels in this area