Friday, November 30, 2007

Writing a Multi-Level BOM Cost Roll-up with ABAP

REPORT ZBOMCOST NO STANDARD PAGE HEADING LINE-SIZE 195
LINE-COUNT 60(2) MESSAGE-ID Z1.

TABLES: MBEW,
MAPL,
PLPO,
PLAS,
CRHD,
CRCO,
CSSL,
COST,
EINE,
EINA,
MARA, "Material Master
MAKT,
MARC,
MAST, "BOM Header
STKO, "BOM Detail
STPO, "Bom Components
STAS. "BOM Alternative

SELECT-OPTIONS: S_WERKS FOR MAST-WERKS,
S_MATNR FOR MAST-MATNR,
S_MTART FOR MARA-MTART.

PARAMETERS: XBASE TYPE I DEFAULT '2000'.

DATA: W_MATNR LIKE MAPL-MATNR.

DATA: S_BASE TYPE I,
PARENT-MATNR LIKE MAST-MATNR,
CHILD-MATNR LIKE STPO-IDNRK,
CHILD-WERKS LIKE MAST-WERKS,
CHILD-STLAL LIKE MAST-STLAL,
W_MAKTX LIKE MAKT-MAKTX,
W_STD TYPE P DECIMALS 5,
W_MAV TYPE P DECIMALS 5,
W_MENGE TYPE P DECIMALS 3,
W_LEVEL TYPE I,
W_DOT(1),
W_LVL(12),
W_LVL1(12),
W_LVL2(2),
W_COL TYPE I,
W_LFLAG,
W_TTL LIKE MARD-LABST,
WCNT TYPE I.

DATA: WCONV TYPE P DECIMALS 5,
WCOST TYPE P DECIMALS 5,
WUCOST TYPE P DECIMALS 5,
WOHCOST TYPE P DECIMALS 5,
WEXCOST TYPE P DECIMALS 5,
WMCOST TYPE P DECIMALS 5,
WTCOST TYPE P DECIMALS 5.

DATA: WLAR LIKE PLPO-LAR01,
WVGW LIKE PLPO-VGW01,
WVGE LIKE PLPO-VGE01.

DATA: BEGIN OF ITAB OCCURS 100,
CNT TYPE I,
LEVEL TYPE I,
LVL1 LIKE W_LVL1,
WERKS LIKE MAST-WERKS,
POSNR LIKE STPO-POSNR,
IDNRK LIKE STPO-IDNRK,
MENGE TYPE P DECIMALS 5, " req qty
MEINS LIKE STPO-MEINS,
END OF ITAB.

DATA: BEGIN OF ITAB1 OCCURS 100,
WERKS LIKE MAST-WERKS,
IDNRK LIKE STPO-IDNRK,
UCOST TYPE P DECIMALS 5,
* mcost type p decimals 5,
* ohcost type p decimals 5,
* excost type p decimals 5,
END OF ITAB1.

DATA: BEGIN OF ITAB2 OCCURS 100,
CNT TYPE I,
SUBCNT TYPE I,
LEVEL TYPE I,
LVL1 LIKE W_LVL1,
WERKS LIKE MAST-WERKS,
POSNR LIKE STPO-POSNR,
IDNRK LIKE STPO-IDNRK,
SBASE TYPE P,
AUSSS LIKE MARC-AUSSS,
MENGE TYPE P DECIMALS 5,
MEINS LIKE STPO-MEINS,
STD TYPE P DECIMALS 5,
MAV TYPE P DECIMALS 5,
VPRSV LIKE MBEW-VPRSV,
VORNR LIKE PLPO-VORNR,
ARBPL LIKE CRHD-ARBPL,
BMSCH LIKE PLPO-BMSCH,
UCOST TYPE P DECIMALS 5,
WLAR LIKE PLPO-LAR01,
WDL TYPE P DECIMALS 5,
WDLR TYPE P DECIMALS 2,
WDLH TYPE P DECIMALS 3,
WMSU TYPE P DECIMALS 5,
WMSUR TYPE P DECIMALS 2,
WMSUH TYPE P DECIMALS 3,
WTS TYPE P DECIMALS 5,
WTSR TYPE P DECIMALS 2,
WTSH TYPE P DECIMALS 3,
WAST TYPE P DECIMALS 5,
WASTR TYPE P DECIMALS 2,
WASTH TYPE P DECIMALS 3,
WOTHA LIKE PLPO-LAR01,
WOTH TYPE P DECIMALS 5,
WOTHR TYPE P DECIMALS 2,
WOTHH TYPE P DECIMALS 3,
OHCOST TYPE P DECIMALS 5,
MCOST TYPE P DECIMALS 5,
LIFNR LIKE EINA-LIFNR,
EXCOST TYPE P DECIMALS 5,
NETPR LIKE EINE-NETPR,
PEINH LIKE EINE-PEINH,
WCONV LIKE WCONV,
END OF ITAB2.

DATA: WPERIOD LIKE T009B-POPER,
WGJAHR LIKE CSSL-GJAHR.

CALL FUNCTION 'DATE_TO_PERIOD_CONVERT'
EXPORTING
I_DATE = SY-DATUM
* I_MONMIT = 00
I_PERIV = 'K4'
IMPORTING
E_BUPER = WPERIOD
E_GJAHR = WGJAHR
EXCEPTIONS
INPUT_FALSE = 1
T009_NOTFOUND = 2
T009B_NOTFOUND = 3
OTHERS = 4.

IF S_BASE EQ 0.
S_BASE = 1.
ENDIF.

FORMAT INTENSIFIED OFF.
** append multi level bom
SELECT * FROM MAST WHERE WERKS IN S_WERKS AND
MATNR IN S_MATNR.
SELECT SINGLE * FROM MARA WHERE MATNR = MAST-MATNR AND
MTART IN S_MTART.
IF SY-SUBRC NE 0.
CONTINUE.
ENDIF.
IF MARA-LVORM <> 'X'.
PARENT-MATNR = MAST-MATNR.
CHILD-MATNR = MAST-MATNR.
CHILD-WERKS = MAST-WERKS.
CHILD-STLAL = MAST-STLAL.
CLEAR ITAB.
CLEAR ITAB-LEVEL.
MOVE MAST-WERKS TO ITAB-WERKS.
MOVE MAST-MATNR TO ITAB-IDNRK.
MOVE MARA-MEINS TO ITAB-MEINS.
WCNT = WCNT + 1.
MOVE WCNT TO ITAB-CNT.
APPEND ITAB.
W_LEVEL = 1.
PERFORM GETCHILD.
ENDIF.
ENDSELECT.

SORT ITAB BY LEVEL DESCENDING.
LOOP AT ITAB.
CLEAR: ITAB1, ITAB2.
CLEAR: MARC-SOBSL, MARC-BESKZ, MARC-AUSSS.
SELECT SINGLE * FROM MARC WHERE MATNR = ITAB-IDNRK AND
WERKS = ITAB-WERKS.
IF SY-SUBRC EQ 0 AND
MARC-AUSSS NE 0.
S_BASE = XBASE + ( ( XBASE * MARC-AUSSS ) / 100 ).
ELSE.
S_BASE = XBASE.
ENDIF.
CLEAR: WOHCOST, WMCOST, WEXCOST, WUCOST.
PERFORM GET_ROUTE.
PERFORM GET_SUBC.
WTCOST = WOHCOST + WEXCOST.
PERFORM GET_BOM.
MOVE ITAB-WERKS TO ITAB1-WERKS.
MOVE ITAB-IDNRK TO ITAB1-IDNRK.
MOVE WUCOST TO ITAB1-UCOST.
APPEND ITAB1.
CLEAR ITAB2.
MOVE-CORRESPONDING ITAB TO ITAB2.
ITAB2-AUSSS = MARC-AUSSS.
ITAB2-SBASE = S_BASE.
MOVE WMCOST TO ITAB2-MCOST.
MOVE WOHCOST TO ITAB2-OHCOST.
MOVE WEXCOST TO ITAB2-EXCOST.
MOVE ITAB1-UCOST TO ITAB2-UCOST.
APPEND ITAB2.
ENDLOOP.

*loop at itab1.
* write:/ itab1-idnrk, itab1-ucost.
*endloop.
SORT ITAB2 BY CNT VORNR.
LOOP AT ITAB2.
WTCOST = ITAB2-MCOST + ITAB2-OHCOST + ITAB2-EXCOST.
IF ITAB2-LEVEL = 0 AND
ITAB2-SUBCNT = 0.
NEW-PAGE.
FORMAT COLOR COL_GROUP INVERSE ON.
CLEAR: MAKT-MAKTX, W_STD, W_MAV.
SELECT SINGLE * FROM MAKT WHERE MATNR = ITAB2-IDNRK AND
SPRAS = 'E'.
SELECT SINGLE * FROM MBEW WHERE MATNR = ITAB2-IDNRK AND
BWKEY = ITAB2-WERKS.
W_MAKTX = MAKT-MAKTX.
IF SY-SUBRC EQ 0.
W_STD = MBEW-STPRS / MBEW-PEINH.
W_MAV = MBEW-VERPR / MBEW-PEINH.
ENDIF.
WRITE:/ '***',
008 ITAB2-IDNRK,
034 MAKT-MAKTX,
076(6) ITAB2-AUSSS NO-ZERO,
096 ITAB2-MEINS,
101(12) ITAB2-UCOST,
114(12) W_STD,
127(12) W_MAV,
140(12) ITAB2-MCOST DECIMALS 3 NO-ZERO,
153(12) ITAB2-OHCOST DECIMALS 3 NO-ZERO,
166(12) ITAB2-EXCOST DECIMALS 3 NO-ZERO,
179(12) WTCOST DECIMALS 3 NO-ZERO.
FORMAT COLOR OFF INVERSE OFF.
ELSEIF ITAB2-LIFNR NE ''.
WRITE: /008 '**', 'Subcontact Cost'.
WRITE: /014 '*', ITAB2-LIFNR,
034 ITAB2-NETPR, '/' , ITAB2-PEINH.

ELSEIF ITAB2-VORNR NE ''.
WOHCOST = ITAB2-WDL + ITAB2-WMSU + ITAB2-WAST
+ ITAB2-WTS + ITAB2-WOTH.
IF WOHCOST NE 0.
CLEAR WVGW.
IF ITAB2-SUBCNT = '1'.
WRITE:/008 '**', 'Process Cost'.
ENDIF.
WVGW = ( ITAB2-WDLH / ITAB2-BMSCH ) * ITAB2-SBASE.
WRITE:/014 ITAB2-VORNR, ITAB2-ARBPL,
034 'DL',
040(10) ITAB2-WDLH,
052(10) ITAB2-WDLR,
064(12) WVGW,
078(16) ITAB2-WDL,
096 ITAB2-BMSCH LEFT-JUSTIFIED.
IF ITAB2-WMSUH NE 0.
WVGW = ( ITAB2-WMSUH / ITAB2-BMSCH ) * ITAB2-SBASE.
WRITE:/034 'MSU',
040(10) ITAB2-WMSUH,
052(10) ITAB2-WMSUR,
064(12) WVGW,
078(16) ITAB2-WMSU.
ENDIF.
IF ITAB2-WTSH NE 0.
WRITE:/034 'TOOLST',
040(10) ITAB2-WTSH,
052(10) ITAB2-WTSR,
064(12) ITAB2-WTSH,
078(16) ITAB2-WTS.
ENDIF.
IF ITAB2-WASTH NE 0.
WRITE:/034 'AST',
040(10) ITAB2-WASTH,
052(10) ITAB2-WASTR,
064(12) ITAB2-WASTH,
078(16) ITAB2-WAST.
ENDIF.
ENDIF.
IF ITAB2-WOTHH NE 0.
WVGW = ( ITAB2-WOTHH / ITAB2-BMSCH ) * S_BASE.
WRITE:/034 ITAB2-WOTHA,
040(8) ITAB2-WOTHH,
050(10) ITAB2-WOTHR,
062(8) WVGW,
072(10) ITAB2-WOTH.
ENDIF.
ELSE.
SKIP.
CLEAR: MAKT-MAKTX, W_STD, W_MAV.
SELECT SINGLE * FROM MAKT WHERE MATNR = ITAB2-IDNRK AND
SPRAS = 'E'.
SELECT SINGLE * FROM MBEW WHERE MATNR = ITAB2-IDNRK AND
BWKEY = ITAB2-WERKS.
IF SY-SUBRC EQ 0.
W_STD = MBEW-STPRS / MBEW-PEINH.
W_MAV = MBEW-VERPR / MBEW-PEINH.
ENDIF.
FORMAT INTENSIFIED ON.
WRITE:/001 ITAB2-LVL1,
008 ITAB2-POSNR,
014 ITAB2-IDNRK,
034 MAKT-MAKTX,
076(6) ITAB2-AUSSS NO-ZERO,
084(10) ITAB2-MENGE,
096 ITAB2-MEINS,
101(12) ITAB2-UCOST,
114(12) W_STD,
127(12) W_MAV,
140(12) ITAB2-MCOST DECIMALS 3 NO-ZERO,
153(12) ITAB2-OHCOST DECIMALS 3 NO-ZERO,
166(12) ITAB2-EXCOST DECIMALS 3 NO-ZERO,
179(12) WTCOST DECIMALS 3 NO-ZERO.
FORMAT INTENSIFIED OFF.
ENDIF.
ENDLOOP.

** get child parts
FORM GETCHILD.
SELECT * FROM STPO WHERE STLNR = MAST-STLNR
ORDER BY POSNR.
SELECT SINGLE * FROM STKO WHERE STLNR = STPO-STLNR
AND STLAL = MAST-STLAL.
SELECT SINGLE * FROM STAS WHERE STLNR = STPO-STLNR AND
STLKN = STPO-STLKN AND
STLAL = MAST-STLAL.
IF SY-SUBRC EQ 0.
CLEAR: W_DOT, W_LVL, W_LVL1.
PERFORM MOV_DATA.
CHILD-MATNR = STPO-IDNRK.
W_LEVEL = W_LEVEL + 1.
PERFORM SUBCHILD.
W_LEVEL = W_LEVEL - 1.
ENDIF.
ENDSELECT.
ENDFORM.

** get grand children parts
FORM SUBCHILD.
SELECT SINGLE * FROM MAST WHERE MATNR = CHILD-MATNR
AND WERKS = CHILD-WERKS.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
SELECT * FROM STPO WHERE STLNR = MAST-STLNR
ORDER BY POSNR.
SELECT SINGLE * FROM STKO WHERE STLNR = STPO-STLNR AND
STLAL = MAST-STLAL.
SELECT SINGLE * FROM STAS WHERE STLNR = STPO-STLNR AND
STLKN = STPO-STLKN AND
STLAL = STKO-STLAL.
IF SY-SUBRC EQ 0.
W_DOT = '.'.
PERFORM MOV_DATA.
CHILD-MATNR = STPO-IDNRK.
W_LEVEL = W_LEVEL + 1.
PERFORM SUBCHILD.
W_LEVEL = W_LEVEL - 1.
SHIFT W_LVL.
ENDIF.
ENDSELECT.
ENDFORM.

TOP-OF-PAGE.
WRITE:/ SY-DATUM,SY-UZEIT,
90 'ABC PRIVATE LIMITED',
180 'Page', SY-PAGNO.
WRITE: / SY-REPID,
88 'Roll-Up Cost (Multi-Level)',
180 SY-UNAME.
SKIP.
CLEAR W_LFLAG.
WRITE:/ 'Material No.:', ITAB2-IDNRK, W_MAKTX,
75 'Plant :', ITAB2-WERKS,
97 'Base Qty :', XBASE LEFT-JUSTIFIED.
SKIP.
ULINE.
FORMAT COLOR COL_HEADING.
WRITE: /001 'Level',
008 'Item',
014 'Component',
034 'Description',
075 'Scrap %',
084 ' Per',
096 'UOM',
101 'Roll-Up Cst',
114 'MM Std Cost',
127 'MM Mvg Cost',
140 ' Matl Cost',
153 'Process Cst',
166 'Sub-Con Cst',
179 ' Total Cost',
190 ' '.
WRITE: /034 'Act',
040 ' Std Val',
052 ' Act Rate',
064 ' Hours',
078 ' Cost',
096 'Base Qty',
190 ' '.
FORMAT COLOR OFF.
ULINE.

FORM MOV_DATA.
W_LVL2 = W_LEVEL.
CONCATENATE W_DOT W_LVL INTO W_LVL.
CONCATENATE W_LVL W_LVL2 INTO W_LVL1.
MOVE W_LVL1 TO ITAB-LVL1.
MOVE W_LEVEL TO ITAB-LEVEL.
MOVE MAST-WERKS TO ITAB-WERKS.
MOVE STPO-POSNR TO ITAB-POSNR.
MOVE STPO-IDNRK TO ITAB-IDNRK.
MOVE STPO-MEINS TO ITAB-MEINS.
ITAB-MENGE = ( STPO-MENGE / STKO-BMENG ).
WCNT = WCNT + 1.
ITAB-CNT = WCNT.
APPEND ITAB.
ENDFORM.

FORM GET_BOM.
CLEAR: WMCOST.
SELECT SINGLE * FROM MAST WHERE MATNR EQ ITAB-IDNRK AND
WERKS = ITAB-WERKS.
IF SY-SUBRC EQ 0.
SELECT * FROM STPO WHERE STLTY = 'M' AND
STLNR = MAST-STLNR AND
DATUV LE SY-DATUM.
SELECT SINGLE * FROM STKO WHERE STLTY = 'M' AND
STLNR = STPO-STLNR AND
STLAL = MAST-STLAL.
SELECT SINGLE * FROM STAS WHERE STLNR = STPO-STLNR AND
STLKN = STPO-STLKN AND
STLAL = STKO-STLAL.
IF SY-SUBRC EQ 0.
READ TABLE ITAB1 WITH KEY IDNRK = STPO-IDNRK
WERKS = ITAB-WERKS.
IF SY-SUBRC EQ 0.
WMCOST = WMCOST + ( ( STPO-MENGE / STKO-BMENG ) * S_BASE
* ITAB1-UCOST ).
ENDIF.
ENDIF.
ENDSELECT.
WUCOST = ( WTCOST + WMCOST ) / XBASE.
ELSE.
IF WTCOST EQ 0.
SELECT SINGLE * FROM MBEW WHERE BWKEY = ITAB-WERKS AND
MATNR = ITAB-IDNRK.
IF SY-SUBRC EQ 0.
IF MBEW-VPRSV = 'S'.
WUCOST = ( MBEW-STPRS / MBEW-PEINH ).
ELSE.
WUCOST = ( MBEW-VERPR / MBEW-PEINH ).
ENDIF.
ENDIF.
ELSE.
WUCOST = WTCOST / XBASE.
ENDIF.
ENDIF.
ENDFORM.

FORM GET_ROUTE.
CLEAR: WOHCOST, WCNT.
SELECT SINGLE * FROM MAPL WHERE WERKS = ITAB-WERKS AND
MATNR = ITAB-IDNRK AND
LOEKZ NE 'X'.
IF SY-SUBRC EQ 0.
SELECT * FROM PLAS WHERE PLNNR = MAPL-PLNNR AND
PLNAL = MAPL-PLNAL AND
DATUV LE SY-DATUM AND
LOEKZ NE 'X'.
SELECT * FROM PLPO WHERE PLNNR = PLAS-PLNNR AND
PLNKN = PLAS-PLNKN.
SELECT SINGLE * FROM CRHD WHERE OBJID = PLPO-ARBID.
SELECT SINGLE * FROM CRCO WHERE OBJTY = 'A' AND
OBJID = PLPO-ARBID AND
BEGDA LE SY-DATUM AND
ENDDA GE SY-DATUM.
CLEAR ITAB2.
MOVE ITAB-CNT TO ITAB2-CNT.
MOVE ITAB-LEVEL TO ITAB2-LEVEL.
MOVE PLPO-VORNR TO ITAB2-VORNR.
MOVE CRHD-ARBPL TO ITAB2-ARBPL.
MOVE PLPO-BMSCH TO ITAB2-BMSCH.
ITAB2-AUSSS = MARC-AUSSS.
ITAB2-SBASE = S_BASE.
IF PLPO-LAR01 CO SPACE.
WLAR = 'DL'.
ELSE.
WLAR = PLPO-LAR01.
ENDIF.
WVGW = PLPO-VGW01.
WVGE = PLPO-VGE01.
PERFORM MLCOST.
IF PLPO-LAR02 CO SPACE.
WLAR = 'TOOLST'.
ELSE.
WLAR = PLPO-LAR02.
ENDIF.
WVGW = PLPO-VGW02.
WVGE = PLPO-VGE02.
PERFORM MLCOST.
IF PLPO-LAR03 CO SPACE.
WLAR = 'MSU'.
ELSE.
WLAR = PLPO-LAR03.
ENDIF.
WVGW = PLPO-VGW03.
WVGE = PLPO-VGE03.
PERFORM MLCOST.
IF PLPO-LAR04 CO SPACE.
WLAR = 'AST'.
ELSE.
WLAR = PLPO-LAR04.
ENDIF.
WVGW = PLPO-VGW04.
WVGE = PLPO-VGE04.
PERFORM MLCOST.
ITAB2-OHCOST = ITAB2-WDL + ITAB2-WMSU + ITAB2-WTS +
ITAB2-WAST + ITAB2-WOTH.
WOHCOST = WOHCOST + ITAB2-OHCOST.
WCNT = WCNT + 1.
ITAB2-SUBCNT = WCNT.
APPEND ITAB2.
ENDSELECT.
ENDSELECT.
ENDIF.
ENDFORM.

FORM MLCOST.
SELECT SINGLE * FROM CSSL WHERE KOKRS = CRCO-KOKRS AND
KOSTL = CRCO-KOSTL AND
GJAHR = WGJAHR AND
LSTAR = WLAR.
IF SY-SUBRC EQ 0.
SELECT * FROM COST WHERE OBJNR = CSSL-OBJNR AND
GJAHR = WGJAHR.
IF WVGE = 'MIN'.
WVGW = WVGW / 60.
ENDIF.
IF WLAR = 'AST'.
ITAB2-WASTH = WVGW.
ITAB2-WASTR = COST-TKG012.
ITAB2-WAST = WVGW * COST-TKG012.
ELSEIF WLAR = 'TOOLST'.
ITAB2-WTSH = WVGW.
ITAB2-WTSR = COST-TKG012.
ITAB2-WTS = WVGW * COST-TKG012.
ELSEIF WLAR = 'DL'.
ITAB2-WDLH = WVGW.
ITAB2-WDLR = COST-TKG012.
ITAB2-WDL = ( WVGW * COST-TKG012 * S_BASE ) / PLPO-BMSCH.
ELSEIF WLAR = 'MSU'.
ITAB2-WMSUH = WVGW.
ITAB2-WMSUR = COST-TKG012.
ITAB2-WMSU = ( WVGW * S_BASE * COST-TKG012 ) / PLPO-BMSCH.
ELSE.
ITAB2-WOTHA = WLAR.
ITAB2-WOTHH = WVGW.
ITAB2-WOTHR = COST-TKG012.
ITAB2-WOTH = ( WVGW * S_BASE * COST-TKG012 ) / PLPO-BMSCH.
ENDIF.
ENDSELECT.
ENDIF.
ENDFORM.

FORM GET_SUBC.
CLEAR ITAB2.
IF MARC-SOBSL = 30 AND
MARC-BESKZ = 'F'.
SELECT SINGLE * FROM EINA WHERE MATNR = ITAB-IDNRK AND
LOEKZ NE 'X'.
IF SY-SUBRC EQ 0.
SELECT SINGLE * FROM EINE WHERE INFNR = EINA-INFNR AND
WERKS = ITAB-WERKS AND
ESOKZ = '3'.
IF SY-SUBRC EQ 0.
WCONV = ( EINE-BPUMN / EINE-BPUMZ ) * EINE-PEINH.
IF EINA-UMREN NE EINA-UMREZ.
WCONV = WCONV / EINA-UMREN * EINA-UMREZ.
ENDIF.
ITAB2-EXCOST = ( EINE-NETPR / WCONV ) * S_BASE.
ITAB2-LIFNR = EINA-LIFNR.
ITAB2-NETPR = EINE-NETPR.
ITAB2-PEINH = EINE-PEINH.
MOVE ITAB-CNT TO ITAB2-CNT.
MOVE ITAB-LEVEL TO ITAB2-LEVEL.
MOVE '9999' TO ITAB2-VORNR.
ITAB2-SUBCNT = 1.
APPEND ITAB2.
WEXCOST = ITAB2-EXCOST.
ENDIF.
ENDIF.
ENDIF.
ENDFORM.

Blog Archive