Throughput Accounting (TA) with SAP Part I – Investment- First steps

Throughput Accounting (TA) with SAP

Part I – Investment – First steps

As I mentioned at the end of my latest post, I am going to build a tool for TA in an SAP environment. For this tool I will start with the component of TA called investment (I). (For more information see “The Haystack Syndrome” by Dr E.M. Goldratt 1990 or “Throughput Accounting” by Thomas Corbett 1998.) The investment consists of work in process (WIP), finished goods ( including finished assemblies), raw materials, machines, buildings, etc. Starting with the first three items (WIP, finished goods, and raw materials), let´s build the first cornerstone.

Each item of these three is evaluated for the purpose of TA only by Totally Variable Cost (TVC): that is, the amount of cost that varies for every increase in the product´s sale (in the majority of the cases it is just raw material). (“Throughput Accounting” by Thomas Corbett 1998, p.30.) So we need to programme a class in ABAP that serves us TVC for those items mentioned above per given financial period. Let´s call it ZCL_TA_PRODUCT. The class provides various methods and primarily serves TVC of the product (GET_PRODUCT_TVC method). The logic of this method is very simple. It starts with a check to see if the product is a directly purchased part. If this is the case, then by using the next method (GET_STD_PRICE) the class returns the value of TVC. It is in this particular case that is the standard price from database tables MBEW or MBEWH (depending on actual or nearest financial year and period ). If the product is finished goods or assembly then the class reads the actual bill of materials (BOM) for the product using the GET_BOM method. Once the BOM is built, the class checks the whole BOM for purchased materials in the GET_PRODUCT_TVC method. For all these materials their own standard prices are read from database tables MBEW and MBEWH using an actual financial period or the nearest to it. At the end, all single prices are added in the result TVC for the product.

CLASS zcl_ta_product DEFINITION PUBLIC CREATE PUBLIC . 
PUBLIC SECTION. 
TYPES: BEGIN OF t_material_tvc . 
TYPES: matnr TYPE matnr,
menge TYPE menge13, 
tvc TYPE stprs. 
TYPES END OF t_material_tvc . 
TYPES: tab_mat_tvc TYPE TABLE OF t_material_tvc . 
DATA matnr TYPE matnr . 
DATA tvc TYPE stprs . 
DATA stprs TYPE stprs . 
DATA peinh TYPE peinh . 
METHODS constructor 
IMPORTING VALUE(i_matnr) TYPE matnr 
VALUE(i_werk) TYPE werks-werks OPTIONAL 
VALUE(i_fyear) TYPE cosp-gjahr 
VALUE(i_perieod) TYPE cosp-perbl . 
METHODS get_bom . 
METHODS get_tab_mat_tvc_from_order 
IMPORTING 
VALUE(i_aufnr) TYPE aufnr 
VALUE(i_end) TYPE sy-datum . 
METHODS get_product_tvc IMPORTING VALUE(i_amount) TYPE menge13 
CHANGING !ch_t_buffer_tvc TYPE STANDARD TABLE OPTIONAL 
RETURNING VALUE(r_tvc) TYPE stprs . 
METHODS get_std_price . 
PROTECTED SECTION. 
DATA werk TYPE werks-werks VALUE '013' ##NO_TEXT. 
DATA gt_stueckliste TYPE roij_stpox_t . 
DATA gs_stueckliste TYPE stpox . 
CONSTANTS c_capid TYPE capid VALUE 'PP01' ##NO_TEXT. 
CONSTANTS c_mehr TYPE ccxfeld VALUE 'X' ##NO_TEXT. 
CONSTANTS c_rndkz TYPE ccxfeld VALUE '1' ##NO_TEXT. 
CONSTANTS c_stlal TYPE stlal VALUE '01' ##NO_TEXT. 
CONSTANTS c_stlan TYPE stlan VALUE 1 ##NO_TEXT. 
PRIVATE SECTION. 
DATA gs_material_tvc TYPE t_material_tvc . 
DATA: gt_material_tvc TYPE TABLE OF t_material_tvc . "t_material_tvc . 
DATA fyear TYPE cosp-gjahr . 
DATA period TYPE cosp-perbl . 
DATA gt_tvc_buffer TYPE TABLE OF zcl_ta_i_products=>t_tvc . 
DATA gs_tvc_buffer TYPE zcl_ta_i_products=>t_tvc . 
ENDCLASS. 
CLASS zcl_ta_product IMPLEMENTATION. 
METHOD constructor. me->matnr = i_matnr. 
IF i_werk IS NOT INITIAL. 
me->werk = i_werk. 
ENDIF. 
fyear = i_fyear. 
period = i_perieod. 
ENDMETHOD. 
METHOD get_bom. 
CALL FUNCTION 'CS_BOM_EXPL_MAT_V2' 
EXPORTING 
* FTREL = ' ' 
* ALEKZ = ' ' 
* ALTVO = ' ' 
* AUFSW = ' ' 
* AUMGB = ' ' 
* AUMNG = 0 
* AUSKZ = ' ' 
* AMIND = ' ' 
* BAGRP = ' ' 
* BEIKZ = ' ' 
* BESSL = ' ' 
* BGIXO = ' ' 
* BREMS = ' ' 
capid = me->c_capid 
* CHLST = ' ' 
* COSPR = ' ' 
cuobj = 000000000000022231 
cuovs = 0 
* CUOLS = ' ' 
datuv = sy-datum 
* DELNL = ' ' 
* DRLDT = ' ' 
* EHNDL = ' ' 
* EMENG = 0 
* ERSKZ = ' ' 
* ERSSL = ' ' 
* FBSTP = ' ' 
* KNFBA = ' ' 
* KSBVO = ' ' 
* MBWLS = ' ' 
* MKTLS = 'X' 
* MDMPS = ' ' 
mehrs = me->c_mehr 
* MKMAT = ' ' 
* MMAPS = ' ' 
* SALWW = ' ' 
* SPLWW = ' ' 
* MMORY = ' ' 
mtnrv = me->matnr 
* NLINK = ' ' 
* POSTP = ' ' 
rndkz = me->c_rndkz 
* RVREL = ' ' 
* SANFR = ' ' 
* SANIN = ' ' 
* SANKA = ' ' 
* SANKO = ' ' 
* SANVS = ' ' 
* SCHGT = ' ' 
* STKKZ = ' ' 
stlal = me->c_stlal 
stlan = me->c_stlan 
* STPST = 0 
* SVWVO = 'X' 
werks = me->werk 
* NORVL = ' ' 
* MDNOT = ' ' 
* PANOT = ' ' 
* QVERW = ' ' 
* VERID = ' ' 
* VRSVO = 'X' 
* IMPORTING 
* TOPMAT = 
* DSTST = 
TABLES 
stb = me->gt_stueckliste 
* MATCAT = 
EXCEPTIONS 
alt_not_found = 1 
call_invalid = 2 
material_not_found = 3 
missing_authorization = 4 
no_bom_found = 5 
no_plant_data = 6 
no_suitable_bom_found = 7 
conversion_error = 8 
OTHERS = 9 . 
CASE sy-subrc. 
WHEN 0. 
* Do Nothing. 
WHEN 5. MESSAGE s344(ck) WITH me->matnr me->werk. 
* Material & Werk & : Stückliste wurde nicht gefunden 
WHEN OTHERS. 
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 
ENDCASE. 
ENDMETHOD. 
METHOD get_product_tvc. 
DATA: lo_position TYPE REF TO zcl_ta_product, 
lv_beskz TYPE marc-beskz, 
lv_sobsl TYPE marc-sobsl, 
wa TYPE zcl_ta_i_products=>t_tvc, 
wt LIKE TABLE OF wa. 
wt = ch_t_buffer_tvc. ***me myself purchase material? 
SELECT SINGLE beskz sobsl FROM marc INTO (lv_beskz,lv_sobsl) 
WHERE matnr EQ me->matnr 
AND werks EQ me->werk. 
IF lv_beskz = 'F' . 
me->get_std_price( ). 
tvc = stprs / peinh .
 r_tvc = tvc * i_amount. * "*** control if under positions *
"** if not subcontracting
* IF lv_sobsl <> '30'. 
* EXIT. 
* ENDIF. 
gs_tvc_buffer-matnr = me->matnr. 
gs_tvc_buffer-fyear = me->fyear. 
gs_tvc_buffer-period = me->period. 
gs_tvc_buffer-tvc = me->tvc. 
READ TABLE wt INTO wa WITH KEY matnr = matnr fyear = fyear period = period. 
IF sy-subrc NE 0. 
APPEND gs_tvc_buffer TO wt. 
ENDIF. 
CLEAR: wa,gs_tvc_buffer.
 ELSE. get_bom( ). 
LOOP AT gt_stueckliste INTO gs_stueckliste WHERE dismm = 'PD'. 
"check if purchase material !!!! ???? 
SELECT SINGLE beskz FROM marc INTO lv_beskz 
WHERE matnr EQ gs_stueckliste-idnrk AND werks EQ gs_stueckliste-werks.
 IF lv_beskz = 'F'. 
CREATE OBJECT lo_position 
EXPORTING i_matnr = gs_stueckliste-idnrk 
i_werk = gs_stueckliste-werks 
i_fyear = me->fyear 
i_perieod = me->period . 
lo_position->get_std_price( ).
 lo_position->tvc = lo_position->stprs / lo_position->peinh . 
r_tvc = r_tvc + ( ( lo_position->tvc ) * i_amount * gs_stueckliste-menge ). 
gs_tvc_buffer-matnr = me->matnr. 
gs_tvc_buffer-fyear = me->fyear. 
gs_tvc_buffer-period = me->period. 
gs_tvc_buffer-tvc = me->tvc. 
READ TABLE wt INTO wa WITH KEY matnr = matnr fyear = fyear period = period.
 IF sy-subrc NE 0. 
APPEND gs_tvc_buffer TO wt. 
ENDIF. 
CLEAR: wa,gs_tvc_buffer. 
*** control if under positions 
IF gs_stueckliste-xtlnr IS NOT INITIAL.
 lo_position->get_bom( ). 
LOOP AT lo_position->gt_stueckliste INTO gs_stueckliste. 
DELETE TABLE gt_stueckliste FROM gs_stueckliste. 
CLEAR: gs_stueckliste. 
ENDLOOP. 
ENDIF. 
CLEAR: gs_stueckliste, lo_position,lv_beskz.
 ENDIF. 
ENDLOOP. 
CLEAR: lv_beskz, lv_sobsl. 
ENDIF. 
ch_t_buffer_tvc = wt.
 ENDMETHOD. 
METHOD get_std_price. 
DATA: lt_mbewh TYPE TABLE OF mbewh, 
ls_mbewh TYPE mbewh,
 lv_year TYPE mbewh-lfgja. 
SELECT * FROM mbewh INTO TABLE lt_mbewh
 WHERE matnr = matnr AND bwkey = werk. 
SELECT SINGLE * FROM mbew INTO CORRESPONDING FIELDS OF ls_mbewh
 WHERE matnr = matnr 
AND bwkey = werk. 
APPEND ls_mbewh TO lt_mbewh.
 CLEAR ls_mbewh. 
SORT lt_mbewh DESCENDING BY lfgja lfmon. 
lv_year = fyear. 
WHILE stprs IS INITIAL . 
LOOP AT lt_mbewh INTO ls_mbewh 
WHERE lfgja = lv_year AND lfmon <= period AND verpr IS NOT INITIAL. 
stprs = ls_mbewh-verpr. 
peinh = ls_mbewh-peinh. 
EXIT.
 ENDLOOP. 
IF stprs IS NOT INITIAL. 
EXIT. 
ENDIF.
 lv_year = lv_year - 1. 
IF sy-index > 5. " max 5 year back, if not than price = 0. 
EXIT. 
ENDIF. 
ENDWHILE. 
ENDMETHOD. 
METHOD get_tab_mat_tvc_from_order. 
DATA: lt_mseg TYPE TABLE OF mseg,
 ls_mseg TYPE mseg, 
lo_position TYPE REF TO zcl_ta_product.
 SELECT * FROM mseg INTO TABLE lt_mseg 
WHERE aufnr EQ i_aufnr AND budat_mkpf <= i_end. 
SORT lt_mseg BY matnr.
 LOOP AT lt_mseg INTO ls_mseg. 
gs_material_tvc-matnr = ls_mseg-matnr. 
IF ls_mseg-bwart = '262'. 
ls_mseg-menge = ls_mseg-menge * -1. 
ENDIF. 
gs_material_tvc-menge = ls_mseg-menge. 
COLLECT gs_material_tvc INTO gt_material_tvc. 
CLEAR: ls_mseg, gs_material_tvc. 
ENDLOOP.
 LOOP AT gt_material_tvc INTO gs_material_tvc. 
CREATE OBJECT lo_position
 EXPORTING i_matnr = gs_material_tvc-matnr 
i_werk = me->werk 
i_fyear = me->fyear
 i_perieod = me->period . 
gs_material_tvc-tvc = 
lo_position->get_product_tvc( i_amount = gs_material_tvc-menge ). 
MODIFY gt_material_tvc FROM gs_material_tvc.
 tvc = tvc + gs_material_tvc-tvc. 
CLEAR: gs_material_tvc.
ENDLOOP. 
ENDMETHOD. 
ENDCLASS

The next part is the superclass ZCL_TA_I_PRODUCTS. This gives a collective framework (attributes, methods) for its underclasses (WIP, finished goods, and raw materials). Its common attributes are, for example, financial year and period (month), plant, the sum of TVC, etc. Its common methods are then constructed and GET_DATES_FOR_PERIOD.

 Here is the ABAP coding:

 CLASS zcl_ta_i_products DEFINITION PUBLIC CREATE PUBLIC . 
PUBLIC SECTION. 
TYPES: BEGIN OF t_tvc . 
TYPES: matnr TYPE matnr, 
fyear TYPE cosp-gjahr, 
period TYPE cosp-perbl, 
tvc TYPE stapr . 
TYPES END OF t_tvc . 
DATA tvc_sum TYPE stapr . 
CLASS-DATA gt_tvc_buffer TYPE TABLE OF t_tvc . 
CLASS-DATA gs_tvc_buffer TYPE t_tvc . 
METHODS constructor
IMPORTING !i_fyear TYPE cosp-gjahr 
!i_period TYPE cosp-perbl . 
PROTECTED SECTION. 
TYPES: BEGIN OF t_itab . 
TYPES: product TYPE REF TO zcl_ta_product, matnr 
TYPE matnr, 
menge TYPE menge13,
 tvc TYPE stapr . 
TYPES END OF t_itab . 
DATA fyear TYPE cosp-gjahr . 
DATA period TYPE cosp-perbl . 
DATA gs_itab TYPE t_itab . 
DATA: gt_itab TYPE TABLE OF t_itab . 
DATA start TYPE sy-datum . 
DATA end TYPE sy-datum . 
CLASS-DATA c_periv TYPE t009b-periv VALUE 'Q1' ##NO_TEXT. 
DATA werks TYPE werks-werks VALUE '013' ##NO_TEXT. 
DATA go_product TYPE REF TO zcl_ta_product . 
METHODS get_dates_for_period . 
METHODS get_tvc_for_itab . 
PRIVATE SECTION. 
ENDCLASS. 
CLASS zcl_ta_i_products IMPLEMENTATION. 
METHOD constructor. 
fyear = i_fyear. 
period = i_period. 
get_dates_for_period( ). 
ENDMETHOD. 
METHOD get_dates_for_period. 
CALL FUNCTION 'FIRST_DAY_IN_PERIOD_GET' 
EXPORTING i_gjahr = fyear 
* I_MONMIT = 00 
i_periv = c_periv 
i_poper = period 
IMPORTING e_date = start 
* EXCEPTIONS 
* INPUT_FALSE = 1 
* T009_NOTFOUND = 2 
* T009B_NOTFOUND = 3 
* OTHERS = 4 . 
IF sy-subrc <> 0. 
* Implement suitable error handling here 
ENDIF. 
CALL FUNCTION 'LAST_DAY_IN_PERIOD_GET' 
EXPORTING i_gjahr = fyear 
* I_MONMIT = 00 
i_periv = c_periv 
i_poper = period I
MPORTING e_date = end 
* EXCEPTIONS 
* INPUT_FALSE = 1 
* T009_NOTFOUND = 2 
* T009B_NOTFOUND = 3 
* OTHERS = 4 . 
IF sy-subrc <> 0. 
* Implement suitable error handling here 
ENDIF. 
ENDMETHOD. 
METHOD get_tvc_for_itab. 
LOOP AT gt_itab INTO gs_itab. 
CREATE OBJECT go_product 
EXPORTING i_matnr = gs_itab-matnr 
i_werk = werks
 i_fyear = fyear 
i_perieod = period . 
gs_itab-tvc = go_product->get_product_tvc( i_amount = gs_itab-menge ). 
gs_itab-product = go_product. 
MODIFY gt_itab FROM gs_itab.
 tvc_sum = tvc_sum + gs_itab-tvc. 
CLEAR: go_product, gs_itab. 
ENDLOOP. 
gs_itab-matnr = 'SUM'. 
gs_itab-tvc = tvc_sum. 
APPEND gs_itab TO gt_itab. 
CLEAR gs_itab. 
ENDMETHOD. 
ENDCLASS. 

Using classes ZCL_TA_I_PRODUCTS and ZCL_TA_PRODUCT, let´s build a class for WIP called ZCL_TA_WIP. The main method in this class is GET_TVC_SUM, which turns the sum off TVC in a given financial period. The process in that method goes like this: the first three steps prepare a selection table that is used as an input table in the third method GET_TAB_AFKO. Here a function module borrowed from a well-known SAP transaction COOIS is used (information system for orders and plan orders in production, etc.) The result of that method is a table with all production orders that are in some state of progress at the end of the given financial period. The next step is only a check. All orders in the table are checked for whether or not goods movements have been done. If there are no movements the particular order is deleted from the table. The next step is called the GET_MAT_TVC_FORM_ORDER method. It calls all items in the table with orders and finds out how many pieces of materials have been confirmed for that particular production order until the last day of the given financial period. For those, all pieces of the class ZCL_TA_PRODUCT and its GET_PRODUCT_TVC method deliver the total variable costs (TVC). All items and their TVCs are added in the final sum.  

Here is the ABAP coding:

CLASS zcl_ta_wip DEFINITION PUBLIC 
INHERITING FROM zcl_ta_i_products FINAL CREATE PUBLIC . 
PUBLIC SECTION. 
METHODS get_tvc_sum . 
PROTECTED SECTION. 
DATA: gt_afko TYPE TABLE OF afko . 
PRIVATE SECTION. 
DATA gs_afko TYPE afko . 
DATA c_auart TYPE aufk-auart VALUE 'FEAU' ##NO_TEXT. 
DATA: rng_order_start TYPE RANGE OF sy-datum . 
DATA: rng_order_end TYPE RANGE OF sy-datum . 
DATA: gt_seltab TYPE TABLE OF rsparams . 
DATA gs_seltab TYPE rsparams . 
DATA gv_auvnr TYPE afko-aufnr . 
METHODS get_range_tables . 
METHODS get_seltab . 
METHODS set_seltab . 
METHODS get_tab_afko . 
METHODS controll_withdrawn .
 METHODS controll_withdrawn_routine 
RETURNING VALUE(r_positive) TYPE char1 . 
METHODS get_tvc_sum_methode . 
ENDCLASS. 
CLASS zcl_ta_wip IMPLEMENTATION. 
METHOD controll_withdrawn. 
DATA: lt_delete LIKE gt_afko, lv_flag TYPE char1.
 LOOP AT gt_afko INTO gs_afko. 
gv_auvnr = gs_afko-aufnr. 
lv_flag = controll_withdrawn_routine( ).
 IF lv_flag IS INITIAL. 
APPEND gs_afko TO lt_delete. 
ENDIF. 
CLEAR: lv_flag, gs_afko. 
ENDLOOP. 
LOOP AT lt_delete INTO gs_afko. 
DELETE TABLE gt_afko FROM gs_afko. 
CLEAR gs_afko. 
ENDLOOP. 
ENDMETHOD.
 METHOD controll_withdrawn_routine. 
DATA: lt_resbd TYPE TABLE OF resbd, 
ls_resbd TYPE resbd, 
ls_caufvd TYPE caufvd. 
CALL FUNCTION 'CO_SF_CAUFVD_GET' 
EXPORTING aufnr_imp = gv_auvnr 
IMPORTING caufvd_exp = ls_caufvd 
* EXCEPTIONS 
* NOT_FOUND = 1 
* OTHERS = 2 .
 IF sy-subrc <> 0. 
* Implement suitable error handling here
 ENDIF. 
CALL FUNCTION 'CMOC_COMP_READ' 
EXPORTING i_caufvd = ls_caufvd 
* I_AFVGD = 
* I_CHECK_LOG_DEL = 'X' 
* I_CHECK_UPD_DEL = 'X' 
TABLES e_resbd_tab = lt_resbd . 
LOOP AT lt_resbd INTO ls_resbd WHERE enmng > 0 AND xwaok = 'X'.
 IF sy-subrc = 0. 
r_positive = 'X'. 
EXIT.
 ENDIF. 
CLEAR ls_resbd. 
ENDLOOP. 
ENDMETHOD. 
METHOD get_range_tables. 
DATA: ls_s LIKE LINE OF rng_order_start, 
ls_e LIKE LINE OF rng_order_end. 
ls_s-sign = 'I'. 
ls_s-option = 'BT'. 
ls_s-low = start - 365. 
ls_s-high = end . 
APPEND ls_s TO rng_order_start.
CLEAR ls_s.
ls_e-sign = 'I'.
 ls_e-option = 'BT'.
 ls_e-low = end + 1. 
ls_e-high = end + 365. 
APPEND ls_e TO rng_order_end. 
CLEAR: ls_e. 
ls_e-sign = 'I'. 
ls_e-option = 'EQ'.
 ls_e-low = '00000000'. 
APPEND ls_e TO rng_order_end.
 CLEAR: ls_e. 
ENDMETHOD. 
METHOD get_seltab. 
DATA: ls_tcoa TYPE tcoa, 
lv_overview TYPE flag, 
l_repid TYPE sy-repid, 
l_valid(1) TYPE c. 
l_repid = 'PPIO_ENTRY'. 
CALL FUNCTION 'RS_REFRESH_FROM_SELECTOPTIONS'
EXPORTING curr_report = l_repid 
TABLES selection_table = gt_seltab 
EXCEPTIONS 
not_found = 1 
no_report = 2 
OTHERS = 3. 
IF sy-subrc <> 0. 
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 
EXIT. 
ENDIF. 
ENDMETHOD. 
METHOD get_tab_afko. 
DATA:lt_tcoa TYPE TABLE OF tcoa ,
 ls_tcoa TYPE tcoa. 
DATA: ioheader_tab TYPE ioheader_tab .
 ls_tcoa-layoutid_aa = '/AMOAT_ST'.
 ls_tcoa-header_sel = 'X'. 
ls_tcoa-item_sel = 'Y'.
 ls_tcoa-aedat = '00000000'. 
APPEND ls_tcoa TO lt_tcoa. 
CALL FUNCTION 'COIS_SELECT_PARAMETERS_SET' 
EXPORTING it_parameter = gt_seltab 
is_tcoa = ls_tcoa.
"lt_tcoa[]. 
CALL FUNCTION 'COIS_SELECT_ORDERS_READ'
 CHANGING ct_ioheader = ioheader_tab[]. 
MOVE-CORRESPONDING ioheader_tab TO gt_afko. 
ENDMETHOD. 
METHOD get_tvc_sum. get_range_tables( ). 
get_seltab( ). set_seltab( ). 
get_tab_afko( ). 
controll_withdrawn( ). 
get_tvc_sum_methode( ). 
ENDMETHOD. 
METHOD get_tvc_sum_methode.
DATA: ls_caufvd TYPE caufvd, 
lo_product TYPE REF TO zcl_ta_product. 
LOOP AT gt_afko INTO gs_afko. 
CALL FUNCTION 'CO_SF_CAUFVD_GET' 
EXPORTING aufnr_imp = gs_afko-aufnr 
IMPORTING caufvd_exp = ls_caufvd 
* EXCEPTIONS
 * NOT_FOUND = 1 
* OTHERS = 2 . 
IF sy-subrc <> 0. 
* Implement suitable error handling here 
ENDIF. 
CREATE OBJECT lo_product 
EXPORTING i_matnr = ls_caufvd-plnbez
 i_werk = ls_caufvd-werks
 i_fyear = me->fyear 
i_perieod = me->period . 
lo_product->get_tab_mat_tvc_from_order( i_aufnr = ls_caufvd-aufnr i_end = end ). tvc_sum = tvc_sum + lo_product->tvc. 
gs_itab-product = lo_product. 
gs_itab-matnr = ls_caufvd-plnbez. 
gs_itab-menge = ls_caufvd-gamng. 
gs_itab-tvc = lo_product->tvc.
 APPEND gs_itab TO gt_itab. 
CLEAR: gs_afko, lo_product, gs_itab, ls_caufvd. 
ENDLOOP.
 ENDMETHOD. 
METHOD set_seltab. 
DATA: ls LIKE LINE OF rng_order_start.
 LOOP AT gt_seltab INTO gs_seltab. 
CASE gs_seltab-selname. 
WHEN 'P_ALV'. 
gs_seltab-low = 'X'. 
WHEN 'P_AUTYP'. 
gs_seltab-low = '10'. 
WHEN 'P_SC1100'. 
gs_seltab-low = 'PPIOH000 00000000001X'. 
WHEN 'P_TCOA'. 
gs_seltab-low = '000IOHEADER 000001 00000'. 
WHEN 'P_TCODE'. 
gs_seltab-low = 'COOIS'. 
WHEN 'S_ISTST '. 
READ TABLE rng_order_start INTO ls INDEX 1. 
gs_seltab-sign = ls-sign. 
gs_seltab-option = ls-option. 
gs_seltab-low = ls-low. 
gs_seltab-high = ls-high. 
CLEAR ls. 
WHEN 'S_ISTEN '.
 READ TABLE rng_order_end INTO ls INDEX 1. 
gs_seltab-sign = ls-sign. 
gs_seltab-option = ls-option. 
gs_seltab-low = ls-low. 
gs_seltab-high = ls-high. 
CLEAR ls. 
WHEN 'P_MAXNUM'. 
gs_seltab-low = ' 0'. 
WHEN 'S_AUART'. 
gs_seltab-sign = 'I'.
 gs_seltab-option = 'EQ'. 
gs_seltab-low = 'FEAU'. 
WHEN 'S_WERKS'. 
gs_seltab-sign = 'I'.
 gs_seltab-option = 'EQ'. 
gs_seltab-low = werks. 
WHEN 'P_SYSH2'. 
gs_seltab-low = 'I0045'. 
WHEN 'P_SYST2'. 
gs_seltab-low = 'TABG'. 
WHEN 'P_KZ_E2'. 
gs_seltab-low = 'X'. 
WHEN 'S_FCTALW '. 
gs_seltab-sign = 'E'. 
gs_seltab-option = 'CP'. 
gs_seltab-low = '*'. 
ENDCASE. 
MODIFY gt_seltab FROM gs_seltab.
 ENDLOOP. 
READ TABLE rng_order_end INTO ls INDEX 2.
 gs_seltab-selname = 'S_ISTEN'. 
gs_seltab-kind = 'S'. 
gs_seltab-sign = ls-sign. 
gs_seltab-option = ls-option. 
gs_seltab-low = ls-low. 
gs_seltab-high = ls-high. 
APPEND gs_seltab TO gt_seltab.
 CLEAR ls. 
ENDMETHOD.
 ENDCLASS. 

The next items for investment evaluation in TA, as mentioned above, are raw materials, unfinished goods (assemblies), and finished goods. You can use various approaches to evaluate them. The principle in SAP remains the same. I have chosen to evaluate all items at once. You can, of course, evaluate them separately. Let´s look at the class for stock materials. I named it ZCL_TA_STOCK and it is inherited from ZCL_TA_I_PRODUCTS. Its function is very simple. Firstly, we must build an internal table with a stock of all materials on the last day of the evaluated period. For this purpose, we can use the database table MARDH. There are not entries for all periods. You can read the explanation in the SAP-Note 193554 – Stock/valuation data of previous periods. Once the table with all the materials and their stock is built, we evaluate them in the same way as in WIP using class ZCL_PRODUCT_TVC and its GET_PRODUCT_TVC method.  

Here is the ABAP coding:

CLASS zcl_ta_stock DEFINITION PUBLIC 
INHERITING FROM zcl_ta_i_products FINAL CREATE PUBLIC . 
PUBLIC SECTION. 
DATA: gt_print TYPE TABLE OF t_itab . 
METHODS get_tvc_sum_for_stock . 
PROTECTED SECTION. 
PRIVATE SECTION. 
DATA: gt_mardh_wa TYPE TABLE OF mardh . 
DATA: gt_mardh TYPE TABLE OF mardh . 
DATA gs_mardh TYPE mardh . 
DATA gs_mardh_wa TYPE mardh . 
METHODS get_items . 
METHODS get_stock .
ENDCLASS. 
CLASS ZCL_TA_STOCK IMPLEMENTATION. 
METHOD get_items. 
SELECT mardh~matnr mardh~werks mardh~lgort mardh~lfgja mardh~lfmon mardh~labst mardh~umlme mardh~insme mardh~einme mardh~speme mardh~retme mardh~vklab mardh~vkuml FROM mardh INNER JOIN marc ON mardh~matnr = marc~matnr AND mardh~werks = marc~werks INTO CORRESPONDING FIELDS OF TABLE gt_mardh WHERE mardh~werks = werks AND marc~dismm <> 'ND'. 
gt_mardh_wa = gt_mardh. 
SORT gt_mardh_wa STABLE BY matnr. 
DELETE ADJACENT DUPLICATES FROM gt_mardh_wa COMPARING matnr. ENDMETHOD. 
METHOD get_stock. 
*** To get stock on the last day of the period i´m using MARDH and MARD 
*** table, which could be not always usefull 
*** there are plenty of other methods to gain it. 
*** e.i. a night jon on the last day of the period serving needed date
*** and storing them in a database table. 
DATA: lv_year TYPE ckmlpp-bdatj, 
lv_period TYPE ckmlpp-poper,
 lv_year_w TYPE ckmlpp-bdatj,
 lv_period_w TYPE ckmlpp-poper,
 lv_citac type i, 
lt_mardh_lgort TYPE TABLE OF mardh,
 ls_mardh_wa LIKE LINE OF lt_mardh_lgort.
 LOOP AT gt_mardh_wa INTO gs_mardh_wa. 
lv_year = fyear. 
lv_period = period. 
clear lv_citac. 
WHILE lt_mardh_lgort IS INITIAL . 
LOOP AT gt_mardh INTO gs_mardh 
WHERE matnr = gs_mardh_wa-matnr 
AND lfmon = lv_period 
AND lfgja = lv_year. 
IF sy-subrc = 0 . 
APPEND gs_mardh TO lt_mardh_lgort. 
CLEAR gs_mardh. 
ELSE.
 EXIT. 
ENDIF. 
ENDLOOP. ""read table gt_mardh INTO gs_mardh 
CALL FUNCTION 'CKML_F_GET_PREVIOUS_PERIOD' 
EXPORTING 
input_period = lv_period
 input_year = lv_year
 input_periv = c_periv 
IMPORTING 
previous_period = lv_period_w 
previous_year = lv_year_w .
 lv_citac = lv_citac + 1. 
CLEAR: lv_period, lv_year. 
lv_period = lv_period_w.
 lv_year = lv_year_w. 
CLEAR: lv_period_w, lv_year_w. 
***** go back only for 5 times.
 IF lv_citac > 5. 
clear lv_citac. 
EXIT.
 ENDIF. 
ENDWHILE. 
LOOP AT lt_mardh_lgort INTO ls_mardh_wa. 
gs_itab-menge = gs_itab-menge + ls_mardh_wa-labst + ls_mardh_wa-umlme + ls_mardh_wa-insme + ls_mardh_wa-einme + ls_mardh_wa-speme + ls_mardh_wa-retme + ls_mardh_wa-vklab + ls_mardh_wa-vkuml. 
CLEAR: ls_mardh_wa. 
ENDLOOP. 
IF gs_itab-menge > 0. 
gs_itab-matnr = gs_mardh_wa-matnr. 
APPEND gs_itab TO gt_itab. 
ENDIF. 
CLEAR: gs_mardh_wa, gs_itab, lt_mardh_lgort,lv_year,lv_period. 
ENDLOOP. 
ENDMETHOD. 
METHOD get_tvc_sum_for_stock. 
get_items( ). 
get_stock( ). 
get_tvc_for_itab( ). 
gt_print = gt_itab. 
ENDMETHOD. 
ENDCLASS. 

We now have all of the needed classes to evaluate WIP, raw materials, unfinished goods, and finished goods in a financial period.