Automatic Clearing For Multiple Customers/ F-32 Clearing
Hello Folks,
earlier i went through some blogs for the clearing process and seems it to be a difficult task for multiple customers ( F-32 transaction for multiple customers ). I finally found out a way of doing it through a program using BDC but with transaction f-05 . Here is the code what i am using for my scenario but a part of it can really be useful thats why i thought of sharing.
REPORT zrf011_clearing_dp_bp.
**********************************************************************
* Table Declaration
**********************************************************************
TABLES : kna1,
vbak.
**********************************************************************
* Type Pool Declarations
**********************************************************************
TYPE-POOLS : slis.
************************************************************************
* Types Declarations
************************************************************************
TYPES : BEGIN OF ty_mtab, “#EC *
vbeln TYPE vbak-vbeln,
invno TYPE vbrk-vbeln,
belnr TYPE bkpf-belnr,
msgtyp LIKE bdcmsgcoll-msgtyp,
text(200) TYPE c,
END OF ty_mtab.
TYPES : BEGIN OF ty_vbak,
vbeln TYPE vbak-vbeln,
knumv TYPE vbak-knumv,
END OF ty_vbak.
TYPES : BEGIN OF ty_vbkd,
vbeln TYPE vbak-vbeln,
zlsch TYPE vbkd-zlsch,
END OF ty_vbkd.
************************************************************************
* Constants Declarations
************************************************************************
CONSTANTS : c_zdpr LIKE konv-kschl VALUE ‘ZDPR’,
c_zbpr LIKE konv-kschl VALUE ‘ZBPR’.
**********************************************************************
* Global variables
**********************************************************************
DATA : gv_dp TYPE bseg-wrbtr,
gv_bp TYPE bseg-wrbtr,
gv_inv TYPE bseg-wrbtr,
gv_mode(1) TYPE c VALUE ‘A’,
gv_flag(1) TYPE c,
gv_stat(1) TYPE c,
gv_dcpfm TYPE usr01-dcpfm,
gv_bschl TYPE bsid-bschl.
************************************************************************
* Internal Table Declarations
************************************************************************
DATA : gt_bsid LIKE bsid OCCURS 0 WITH HEADER LINE,
gt_sel LIKE bsid OCCURS 0 WITH HEADER LINE,
gt_error LIKE bsid OCCURS 0 WITH HEADER LINE.
DATA : gt_vbak TYPE STANDARD TABLE OF ty_vbak INITIAL SIZE 0
WITH HEADER LINE.
DATA : gt_konv TYPE STANDARD TABLE OF konv INITIAL SIZE 0
WITH HEADER LINE.
DATA : gt_vbkd TYPE STANDARD TABLE OF ty_vbkd.
DATA: gt_bdcdata LIKE bdcdata OCCURS 0 WITH HEADER LINE.
DATA : gt_msgtab LIKE bdcmsgcoll OCCURS 0 WITH HEADER LINE.
DATA: t_mtab TYPE STANDARD TABLE OF ty_mtab.
*——————— ALV VARIABLES Declartion ———————-*
DATA: fieldcatalog TYPE slis_t_fieldcat_alv WITH HEADER LINE,
it_listheader TYPE slis_t_listheader,
it_events TYPE slis_t_event,
it_fieldcat TYPE slis_t_fieldcat_alv,
gw_tab_group TYPE slis_t_sp_group_alv,
is_layout TYPE slis_layout_alv,
gv_repid LIKE sy-repid.
************************************************************************
* Work Area Declarations
************************************************************************
DATA : gs_bsid TYPE bsid,
wa_mtab TYPE ty_mtab,
gw_vbkd TYPE ty_vbkd.
***********************************************************************
* Selection Screen
***********************************************************************
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text–001.
PARAMETERS : p_bukrs LIKE t001-bukrs OBLIGATORY DEFAULT ‘INDO’, ” Company Code
p_gjahr LIKE bkpf-gjahr OBLIGATORY, ” Fiscal Year
p_budat LIKE bkpf-budat OBLIGATORY. ” Clearing date
SELECT-OPTIONS : s_kunnr FOR kna1-kunnr OBLIGATORY, ” Customer
s_vbeln FOR vbak-vbeln.
SELECTION-SCREEN END OF BLOCK b1.
************************************************************************
* At Selection Screen
************************************************************************
AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_vbeln-low.
PERFORM get_orders USING s_vbeln-low.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_vbeln-high.
PERFORM get_orders USING s_vbeln-high.
************************************************************************
* Initiallization
************************************************************************
INITIALIZATION.
SELECT SINGLE dcpfm FROM usr01 INTO gv_dcpfm
WHERE bname = sy-uname.
************************************************************************
* Start-of-selection
************************************************************************
START-OF-SELECTION.
CLEAR : gv_flag.
WHILE gv_flag = space.
PERFORM get_customer_open_items.
PERFORM get_customer_orders.
PERFORM get_customer_payments.
PERFORM post_clearing.
REFRESH : gt_vbak, gt_vbkd, gt_konv, gt_bsid, gt_bdcdata.
IF gv_stat = ‘X’.
gv_flag = ‘X’.
ENDIF.
ENDWHILE.
************************************************************************
* End-of-selection
************************************************************************
END–OF-SELECTION.
PERFORM display_data.
************************************************************************
* Forms and subroutines
************************************************************************
*&———————————————————————*
*& Form GET_CUSTOMER_OPEN_ITEMS
*&———————————————————————*
FORM get_customer_open_items .
SELECT * FROM bsid INTO TABLE gt_bsid
WHERE bukrs = p_bukrs
AND kunnr IN s_kunnr
AND gjahr = p_gjahr
AND vbel2 IN s_vbeln.
* Delete records which have been processed earlier
LOOP AT gt_error.
DELETE gt_bsid WHERE gjahr = gt_error-gjahr
AND belnr = gt_error-belnr
AND buzei = gt_error-buzei.
ENDLOOP.
IF gt_bsid[] IS INITIAL.
gv_flag = ‘X’.
ENDIF.
ENDFORM. ” GET_CUSTOMER_OPEN_ITEMS
*&———————————————————————*
*& Form GET_CUSTOMER_ORDERS
*&———————————————————————*
FORM get_customer_orders .
IF gt_bsid[] IS NOT INITIAL.
SELECT vbeln knumv FROM vbak INTO TABLE gt_vbak
FOR ALL ENTRIES IN gt_bsid
WHERE vbeln = gt_bsid-vbel2
AND vbtyp = ‘C’.
ENDIF.
ENDFORM. ” GET_CUSTOMER_ORDERS
*&———————————————————————*
*& Form GET_CUSTOMER_PAYMENTS
*&———————————————————————*
FORM get_customer_payments .
IF gt_vbak[] IS NOT INITIAL.
SORT gt_vbak by vbeln.
* Get payment type for the orders
SELECT vbeln zlsch FROM vbkd INTO table gt_vbkd
FOR ALL ENTRIES IN gt_vbak
WHERE vbeln = gt_vbak-vbeln
AND zlsch IN (‘L’, ‘T’). ” 100% Credit payment type is not handled here
SORT gt_vbkd by zlsch vbeln.
LOOP AT gt_vbak.
READ TABLE gt_vbkd INTO gw_vbkd WITH KEY vbeln = gt_vbak-vbeln.
IF sy-subrc <> 0.
DELETE gt_vbak.
ENDIF.
ENDLOOP.
ENDIF.
*Get Down Payment and Balance Payment percentage.
IF gt_vbak[] IS NOT INITIAL.
SELECT * FROM konv INTO TABLE gt_konv
FOR ALL ENTRIES IN gt_vbak
WHERE knumv = gt_vbak-knumv
AND kschl IN (‘ZDPR’, ‘ZBPR’).
ELSE.
gv_flag = ‘X’.
ENDIF.
ENDFORM. ” GET_CUSTOMER_PAYMENTS
*&———————————————————————*
*& Form POST_CLEARING
*&———————————————————————*
FORM post_clearing .
gv_stat = ‘X’.
LOOP AT gt_vbak.
PERFORM f_select_docs_for_clearing.
IF gt_sel[] IS INITIAL.
CLEAR wa_mtab.
wa_mtab-vbeln = gt_vbak-vbeln.
wa_mtab-text = text–002.
REPLACE ‘&’ IN wa_mtab-text WITH gt_vbak-vbeln.
APPEND wa_mtab TO t_mtab .
ELSE.
CLEAR gv_stat.
PERFORM bdc_for_fb05.
CLEAR wa_mtab.
wa_mtab-vbeln = gt_vbak-vbeln.
READ TABLE gt_sel WITH KEY bschl = gv_bschl. “’01’.
IF sy-subrc = 0.
wa_mtab-invno = gt_sel-zuonr.
wa_mtab-belnr = gt_sel-belnr.
ENDIF.
PERFORM get_error_message.
PERFORM delete_processed_records.
WAIT UP TO 2 SECONDS.
ENDIF.
ENDLOOP.
ENDFORM. ” POST_CLEARING
*&———————————————————————*
*& Form F_SELECT_DOCS_FOR_CLEARING
*&———————————————————————*
FORM f_select_docs_for_clearing .
DATA : lv_belnr TYPE bsid-belnr,
lv_count TYPE i.
DATA : lv_dpr TYPE percent,
lv_bpr TYPE percent,
lv_amt TYPE bsid-dmbtr,
lv_dp_amt TYPE bsid-dmbtr,
lv_bp_amt TYPE bsid-dmbtr,
lv_dp_act TYPE bsid-dmbtr,
lv_bp_act TYPE bsid-dmbtr,
lv_inv_act TYPE bsid-dmbtr.
gt_sel[] = gt_bsid[].
DELETE gt_sel WHERE vbel2 <> gt_vbak-vbeln.
* Consider only BSCHL = 19 along with special GL indicator
DELETE gt_sel WHERE umskz = ‘A’
AND bschl <> ’19’.
DELETE gt_sel WHERE umskz = ‘B’
AND bschl <> ’19’.
* Retain only one invoice
SORT gt_sel BY budat.
CLEAR : gv_bschl.
gv_bschl = ’01’.
READ TABLE gt_sel WITH KEY bschl = gv_bschl.
IF sy-subrc = 0.
lv_belnr = gt_sel-belnr.
LOOP AT gt_sel.
IF lv_belnr <> gt_sel-belnr.
IF ( gt_sel-umskz <> ‘A’ AND gt_sel-umskz <> ‘B’ ).
DELETE gt_sel.
ENDIF.
ENDIF.
ENDLOOP.
ELSE.
gv_bschl = ’04’.
READ TABLE gt_sel WITH KEY bschl = gv_bschl.
IF sy-subrc = 0.
lv_belnr = gt_sel-belnr.
LOOP AT gt_sel.
IF lv_belnr <> gt_sel-belnr.
IF ( gt_sel-umskz <> ‘A’ AND gt_sel-umskz <> ‘B’ ).
DELETE gt_sel.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
* Ensure internal table has only one line for DP
READ TABLE gt_sel WITH KEY umskz = ‘A’.
IF sy-subrc = 0.
lv_belnr = gt_sel-belnr.
LOOP AT gt_sel.
IF lv_belnr <> gt_sel-belnr.
IF gt_sel-umskz = ‘A’.
DELETE gt_sel.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
* Ensure internal table has only one line for BP
READ TABLE gt_sel WITH KEY umskz = ‘B’.
IF sy-subrc = 0.
lv_belnr = gt_sel-belnr.
LOOP AT gt_sel.
IF lv_belnr <> gt_sel-belnr.
IF gt_sel-umskz = ‘B’.
DELETE gt_sel.
ENDIF.
ENDIF.
ENDLOOP.
ENDIF.
CLEAR gw_vbkd.
READ TABLE gt_vbkd INTO gw_vbkd WITH KEY vbeln = gt_vbak-vbeln.
IF gw_vbkd-zlsch = ‘T’.
* Ensure table contains only one invoice and at least one DP or BP line
READ TABLE gt_sel WITH KEY bschl = gv_bschl. “’01’.
IF sy-subrc = 0.
READ TABLE gt_sel WITH KEY umskz = ‘A’.
IF sy-subrc <> 0.
READ TABLE gt_sel WITH KEY umskz = ‘B’.
IF sy-subrc <> 0.
REFRESH gt_sel.
ENDIF.
ENDIF.
ELSE.
REFRESH gt_sel.
ENDIF.
ELSEIF gw_vbkd-zlsch = ‘L’.
READ TABLE gt_sel WITH KEY bschl = gv_bschl. “’01’.
IF sy-subrc = 0.
READ TABLE gt_sel WITH KEY umskz = ‘A’.
IF sy-subrc <> 0.
REFRESH gt_sel.
ENDIF.
REFRESH gt_sel.
ENDIF.
ENDIF.
IF gt_sel[] IS INITIAL.
EXIT.
ENDIF.
DESCRIBE TABLE gt_sel LINES lv_count.
IF lv_count = 1.
REFRESH gt_sel.
EXIT.
ENDIF.
* Calculating the amounts
CLEAR : gv_dp, gv_bp, gv_inv, lv_amt, lv_dp_amt, lv_bp_amt, lv_dp_act, lv_bp_act.
READ TABLE gt_sel WITH KEY bschl = gv_bschl. “’01’.
READ TABLE gt_konv WITH KEY knumv = gt_vbak-knumv
kschl = c_zdpr.
IF sy-subrc = 0.
lv_dpr = gt_konv-kbetr / 10.
gv_dp = ( gt_sel-dmbtr + gt_sel-mwsts ) * lv_dpr / 100.
ENDIF.
READ TABLE gt_konv WITH KEY knumv = gt_vbak-knumv
kschl = c_zbpr.
IF sy-subrc = 0.
lv_bpr = gt_konv-kbetr / 10.
gv_bp = ( gt_sel-dmbtr + gt_sel-mwsts ) * lv_bpr / 100.
ENDIF.
READ TABLE gt_sel WITH KEY umskz = ‘A’.
IF sy-subrc = 0.
lv_amt = ( gt_sel-dmbtr + gt_sel-mwsts ) – gv_dp. ” Residual DP amount
lv_dp_act = ( gt_sel-dmbtr + gt_sel-mwsts ). ” Actual DP amount available
IF lv_amt <= 0.
lv_dp_amt = gt_sel-dmbtr + gt_sel-mwsts.
gv_dp = 0.
ELSE.
lv_dp_amt = gv_dp.
gv_dp = lv_amt.
ENDIF.
ELSE.
gv_dp = 0.
ENDIF.
READ TABLE gt_sel WITH KEY umskz = ‘B’.
IF sy-subrc = 0.
lv_amt = ( gt_sel-dmbtr + gt_sel-mwsts ) – gv_bp. ” Residual BP amount
lv_bp_act = ( gt_sel-dmbtr + gt_sel-mwsts ). ” Actual BP amount available
IF lv_amt <= 0.
lv_bp_amt = ( gt_sel-dmbtr + gt_sel-mwsts ).
gv_bp = 0.
ELSE.
lv_bp_amt = gv_bp.
gv_bp = lv_amt.
ENDIF.
ELSE.
gv_bp = 0.
ENDIF.
READ TABLE gt_sel WITH KEY bschl = gv_bschl. “’01’.
lv_inv_act = ( gt_sel-dmbtr + gt_sel-mwsts ). ” Actual Invoice amount available
IF ( lv_dp_act > 0 ) AND ( lv_bp_act > 0 ).
lv_amt = ( gt_sel-dmbtr + gt_sel-mwsts ) – lv_dp_amt – lv_bp_amt. ” Residual invoice amount
IF lv_amt <= 0.
gv_inv = 0.
ELSE.
gv_inv = lv_amt.
ENDIF.
ELSEIF lv_dp_act > 0.
IF lv_dp_act > lv_inv_act.
gv_dp = lv_dp_act – lv_inv_act. ” Residual DP amount
gv_inv = 0. ” Residual invoice amount
ELSEIF lv_dp_act = lv_inv_act.
gv_dp = 0. ” Residual DP amount
gv_inv = 0. ” Residual invoice amount
ELSE.
gv_dp = 0. ” Residual DP amount
gv_inv = lv_inv_act – lv_dp_act. ” Residual invoice amount
ENDIF.
ELSEIF lv_bp_act > 0.
IF lv_bp_act > lv_inv_act.
gv_bp = lv_bp_act – lv_inv_act. ” Residual BP amount
gv_inv = 0. ” Residual invoice amount
ELSEIF lv_bp_act = lv_inv_act.
gv_bp = 0. ” Residual BP amount
gv_inv = 0. ” Residual invoice amount
ELSE.
gv_bp = 0. ” Residual BP amount
gv_inv = lv_inv_act – lv_bp_act. ” Residual invoice amount
ENDIF.
ENDIF.
* To make sure thatbalances are zero
CLEAR : lv_amt, lv_inv_act, lv_bp_act.
READ TABLE gt_sel WITH KEY bschl = gv_bschl. “’01’.
IF sy-subrc = 0.
lv_inv_act = ( gt_sel-dmbtr + gt_sel-mwsts ).
ENDIF.
READ TABLE gt_sel WITH KEY umskz = ‘A’.
IF sy-subrc = 0.
lv_inv_act = lv_inv_act – ( gt_sel-dmbtr + gt_sel-mwsts ).
ENDIF.
READ TABLE gt_sel WITH KEY umskz = ‘B’.
IF sy-subrc = 0.
lv_inv_act = lv_inv_act – ( gt_sel-dmbtr + gt_sel-mwsts ).
ENDIF.
lv_amt = gv_inv – gv_dp – gv_bp.
IF lv_amt <> lv_inv_act.
IF lv_amt > 0.
gv_bp = gv_bp + lv_amt.
ENDIF.
IF lv_amt < 0.
gv_inv = gv_inv – lv_amt.
ENDIF.
ENDIF.
ENDFORM. ” F_SELECT_DOCS_FOR_CLEARING
*&———————————————————————*
*& Form BDC_FOR_FB05
*&———————————————————————*
FORM bdc_for_fb05 .
CONSTANTS: lc_blart TYPE bkpf-blart VALUE ‘AB’,
lc_agkoa TYPE koart VALUE ‘D’, “Customers
gc_x TYPE ftclear-xnops VALUE ‘X’,
lc_selfd TYPE fld30_f05a VALUE ‘BELNR’,
lc_feldn(20) TYPE c VALUE ‘RF05A-FELDN(‘,
lc_sel01(20) TYPE c VALUE ‘RF05A-SEL01(‘,
lc_sel02(20) TYPE c VALUE ‘RF05A-SEL02(‘,
lc_psdif(20) TYPE c VALUE ‘DF05B-PSDIF(‘,
lc_close(2) TYPE c VALUE ‘)’.
DATA : lv_budat TYPE char10,
lv_ser(2) TYPE n,
lv_fnam TYPE bdcdata-fnam,
lv_selvon TYPE ftclear-selvon,
lv_amt(20) TYPE c.
REFRESH gt_bdcdata.
* Convert the date format from YYYYMMDD -> DD.MM.YYYY
PERFORM: f_convert_date USING p_budat
CHANGING lv_budat.
READ TABLE gt_sel INDEX 1.
* Screen : Post with Clearing : Header Data
PERFORM bdc_dynpro USING ‘SAPMF05A’ ‘0122’.
PERFORM bdc_field USING ‘BDC_CURSOR’
‘BKPF-XBLNR’.
PERFORM bdc_field USING ‘BDC_OKCODE’
‘=SL’.
PERFORM bdc_field USING ‘RF05A-XPOS1(4)’
‘X’.
PERFORM bdc_field USING ‘BKPF-BLDAT’
lv_budat. “‘13.02.2012’.
PERFORM bdc_field USING ‘BKPF-BLART’
lc_blart. “‘ab’.
PERFORM bdc_field USING ‘BKPF-BUKRS’
gt_sel-bukrs. “‘INDO’.
PERFORM bdc_field USING ‘BKPF-BUDAT’
lv_budat. “‘13.02.2012’.
* perform bdc_field using ‘BKPF-MONAT’
* ‘2’.
PERFORM bdc_field USING ‘BKPF-WAERS’
gt_sel-waers. “‘IDR’.
PERFORM bdc_field USING ‘BKPF-XBLNR’
gt_sel-vbel2. “‘0030000102’.
PERFORM bdc_field USING ‘FS006-DOCID’
‘*’.
* Screen : Post with Clearing Select open items
PERFORM bdc_dynpro USING ‘SAPMF05A’ ‘0710’.
PERFORM bdc_field USING ‘BDC_CURSOR’
‘RF05A-AGUMS’.
PERFORM bdc_field USING ‘BDC_OKCODE’
‘=SLB’.
PERFORM bdc_field USING ‘RF05A-AGBUK’
gt_sel-bukrs. “‘INDO’.
PERFORM bdc_field USING ‘RF05A-AGKON’
gt_sel-kunnr. “‘1000000063’.
PERFORM bdc_field USING ‘RF05A-AGKOA’
lc_agkoa. “‘D’.
PERFORM bdc_field USING ‘RF05A-AGUMS’
lc_blart. “‘ab’.
PERFORM bdc_field USING ‘RF05A-XNOPS’
gc_x. “‘X’.
* Screen : Post with Clearing Enter selection criteria
PERFORM bdc_dynpro USING ‘SAPMF05A’ ‘0733’.
PERFORM bdc_field USING ‘BDC_CURSOR’
‘RF05A-SEL02(03)’.
PERFORM bdc_field USING ‘BDC_OKCODE’
‘=BU’.
CLEAR : lv_ser, lv_fnam.
LOOP AT gt_sel.
* perform bdc_field using ‘RF05A-FELDN(01)’
* ‘BELNR’.
* perform bdc_field using ‘RF05A-FELDN(02)’
* ‘BELNR’.
* perform bdc_field using ‘RF05A-FELDN(03)’
* ‘BELNR’.
* perform bdc_field using ‘RF05A-SEL01(01)’
* ‘07000001652011001’.
* perform bdc_field using ‘RF05A-SEL01(02)’
* ‘14000001632011002’.
* perform bdc_field using ‘RF05A-SEL01(03)’
* ‘14000001642011002’.
* perform bdc_field using ‘RF05A-SEL02(01)’
* ‘07000001652011001’.
* perform bdc_field using ‘RF05A-SEL02(02)’
* ‘14000001632011002’.
* perform bdc_field using ‘RF05A-SEL02(03)’
* ‘14000001642011002’.
lv_ser = lv_ser + 1.
CLEAR lv_fnam.
CONCATENATE lc_feldn lv_ser lc_close INTO lv_fnam.
CONDENSE lv_fnam.
PERFORM bdc_field USING lv_fnam “‘RF05A-FELDN(01)’
lc_selfd. “‘BELNR’.
CLEAR lv_fnam.
CONCATENATE lc_sel01 lv_ser lc_close INTO lv_fnam.
CONDENSE lv_fnam.
CONCATENATE gt_sel-belnr
gt_sel-gjahr
gt_sel-buzei INTO lv_selvon.
PERFORM bdc_field USING lv_fnam “‘RF05A-SEL01(01)’
lv_selvon. “‘07000001652011001’.
CLEAR lv_fnam.
CONCATENATE lc_sel02 lv_ser lc_close INTO lv_fnam.
CONDENSE lv_fnam.
CONCATENATE gt_sel-belnr
gt_sel-gjahr
gt_sel-buzei INTO lv_selvon.
PERFORM bdc_field USING lv_fnam “‘RF05A-SEL02(01)’
lv_selvon. “‘07000001652011001’.
ENDLOOP.
* Screen : Post with Clearing Process open items
PERFORM bdc_dynpro USING ‘SAPDF05X’ ‘3100’.
PERFORM bdc_field USING ‘BDC_OKCODE’
‘=REST’.
PERFORM bdc_field USING ‘BDC_CURSOR’
‘DF05B-PSSKT(01)’.
PERFORM bdc_field USING ‘RF05A-ABPOS’
‘1’.
PERFORM bdc_dynpro USING ‘SAPDF05X’ ‘3100’.
PERFORM bdc_field USING ‘BDC_OKCODE’
‘/00’.
PERFORM bdc_field USING ‘BDC_CURSOR’
‘DF05B-PSDIF(03)’.
PERFORM bdc_field USING ‘RF05A-ABPOS’
‘1’.
CLEAR lv_ser.
LOOP AT gt_sel.
* perform bdc_field using ‘DF05B-PSDIF(01)’
* ‘ 0’.
* perform bdc_field using ‘DF05B-PSDIF(02)’
* ‘ 679448000-‘.
* perform bdc_field using ‘DF05B-PSDIF(03)’
* ‘ 84931000-‘.
lv_ser = lv_ser + 1.
CLEAR : lv_fnam, lv_amt.
CONCATENATE lc_psdif lv_ser lc_close INTO lv_fnam.
CONDENSE lv_fnam.
IF gt_sel-bschl = gv_bschl. “’01’.
WRITE gv_inv TO lv_amt CURRENCY gt_sel-waers.
REPLACE ALL OCCURRENCES OF ‘,’ IN lv_amt WITH space.
* PERFORM convert_to_user_format USING lv_amt.
CONDENSE lv_amt.
ELSEIF gt_sel-umskz = ‘A’.
WRITE gv_dp TO lv_amt CURRENCY gt_sel-waers.
REPLACE ALL OCCURRENCES OF ‘,’ IN lv_amt WITH space.
* PERFORM convert_to_user_format USING lv_amt.
CONDENSE lv_amt.
IF lv_amt > 0.
CONCATENATE lv_amt ‘-‘ INTO lv_amt.
CONDENSE lv_amt.
ENDIF.
ELSEIF gt_sel-umskz = ‘B’.
WRITE gv_bp TO lv_amt CURRENCY gt_sel-waers.
REPLACE ALL OCCURRENCES OF ‘,’ IN lv_amt WITH space.
* PERFORM convert_to_user_format USING lv_amt.
CONDENSE lv_amt.
IF lv_amt > 0.
CONCATENATE lv_amt ‘-‘ INTO lv_amt.
CONDENSE lv_amt.
ENDIF.
ENDIF.
PERFORM bdc_field USING lv_fnam “‘DF05B-PSDIF(01)’
lv_amt. “‘ 0’.
ENDLOOP.
* Screen : Post with Clearing Create residual items
PERFORM bdc_dynpro USING ‘SAPDF05X’ ‘3100’.
PERFORM bdc_field USING ‘BDC_OKCODE’
‘=BU’.
PERFORM bdc_field USING ‘BDC_CURSOR’
‘DF05B-PSDIF(03)’.
PERFORM bdc_field USING ‘RF05A-ABPOS’
‘1’.
CALL TRANSACTION ‘FB05’ USING gt_bdcdata
MODE gv_mode
UPDATE ‘A’
MESSAGES INTO gt_msgtab.
ENDFORM. ” BDC_FOR_FB05
*&———————————————————————*
*& Form F_CONVERT_DATE
*&———————————————————————*
FORM f_convert_date USING p_datum
CHANGING p_budat.
CALL FUNCTION ‘CONVERSION_EXIT_PDATE_OUTPUT’
EXPORTING
input = p_datum
IMPORTING
output = p_budat.
ENDFORM. ” F_CONVERT_DATE
*———————————————————————-*
* Start new screen *
*———————————————————————-*
FORM bdc_dynpro USING program dynpro. “#EC *
CLEAR gt_bdcdata.
gt_bdcdata-program = program.
gt_bdcdata-dynpro = dynpro.
gt_bdcdata-dynbegin = ‘X’.
APPEND gt_bdcdata.
ENDFORM. “BDC_DYNPRO
*———————————————————————-*
* Insert field *
*———————————————————————-*
FORM bdc_field USING fnam fval. “#EC *
CLEAR gt_bdcdata.
gt_bdcdata-fnam = fnam.
gt_bdcdata-fval = fval.
APPEND gt_bdcdata.
ENDFORM. “BDC_FIELD
*&———————————————————————*
*& Form GET_ERROR_MESSAGE
*&———————————————————————*
FORM get_error_message .
LOOP AT gt_msgtab. “tmess_mtab .
CALL FUNCTION ‘MASS_MESSAGE_GET’ “To get the Message Text
EXPORTING
arbgb = gt_msgtab-msgid
msgnr = gt_msgtab-msgnr
msgv1 = gt_msgtab-msgv1
msgv2 = gt_msgtab-msgv2
msgv3 = gt_msgtab-msgv3
msgv4 = gt_msgtab-msgv4
IMPORTING
msgtext = wa_mtab-text
EXCEPTIONS
message_not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
wa_mtab-msgtyp = gt_msgtab-msgtyp.
wa_mtab-invno = gt_sel-zuonr.
wa_mtab-belnr = gt_sel-belnr.
APPEND wa_mtab TO t_mtab .
CLEAR wa_mtab.
ENDLOOP.
DELETE t_mtab WHERE msgtyp = ‘W’.
ENDFORM. ” GET_ERROR_MESSAGE
*&———————————————————————*
*& Form DISPLAY_DATA
*&———————————————————————*
FORM display_data .
SORT t_mtab by vbeln.
DELETE ADJACENT DUPLICATES FROM t_mtab COMPARING ALL FIELDS.
PERFORM fill_layout_structure.
PERFORM alv_header USING it_listheader.
PERFORM fill_fieldcat USING :
‘VBELN’ ‘Order Number’ 10 ‘T_MTAB’ space space space,
‘INVNO’ ‘Invoice Number’ 10 ‘T_MTAB’ space space space,
‘BELNR’ ‘Acc Doc Number’ 10 ‘T_MTAB’ space space space,
‘MSHTYP’ ‘Msg Type’ 10 ‘T_MTAB’ space space space,
‘TEXT’ ‘Message Text’ 10 ‘T_MTAB’ space space space.
PERFORM alv_events USING it_events.
PERFORM alv_display.
ENDFORM. ” DISPLAY_DATA
*&———————————————————————*
*& Form FILL_LAYOUT_STRUCTURE
*&———————————————————————*
FORM fill_layout_structure .
DATA: lw_event TYPE slis_alv_event,
lw_listheader TYPE slis_t_listheader.
CLEAR is_layout.
is_layout-zebra = ‘X’.
is_layout-colwidth_optimize = ‘X’.
* is_layout-F2CODE = ‘&ETA’.
* is_layout-detail_popup = ‘X’.
ENDFORM. ” FILL_LAYOUT_STRUCTURE
*&———————————————————————*
*& Form ALV_HEADER
*&———————————————————————*
FORM alv_header USING p_listheader.
DATA : wa_listheader TYPE slis_listheader.
DATA : v_date1(10).
DATA : v_date2(10).
DATA : v_lifnr1 LIKE rbkp-lifnr.
DATA : v_lifnr2 LIKE rbkp-lifnr.
DATA : v_bukrs LIKE rbkp-bukrs.
DATA : v_exnum1 LIKE rbkp-belnr.
DATA : v_exnum2 LIKE rbkp-belnr.
CLEAR wa_listheader.
wa_listheader-typ = ‘H’.
wa_listheader-info = ‘Indo Ispat’.
* MOVE NAME1
* TO WA_LISTHEADER-INFO.
APPEND wa_listheader TO it_listheader.
wa_listheader-typ = ‘H’.
MOVE ‘Customer Clearing’
TO wa_listheader-info.
APPEND wa_listheader TO it_listheader.
CLEAR wa_listheader.
wa_listheader-typ = ‘S’.
wa_listheader-key = ‘Company Code : ‘.
wa_listheader-info = p_bukrs.
APPEND wa_listheader TO it_listheader.
**To print date range from the select options in the top of report
**——————————————————————*
* WRITE s_gltrp-low TO v_date1 DD/MM/YYYY NO-GAP.
* WRITE s_gltrp-high TO v_date2 DD/MM/YYYY NO-GAP.
*
* IF NOT s_gltrp-low IS INITIAL AND s_gltrp-high IS NOT INITIAL.
*
* CLEAR wa_listheader.
* wa_listheader-typ = ‘S’.
* wa_listheader-key = ‘Date : ‘.
* CONCATENATE v_date1 ‘To’ v_date2 INTO
* wa_listheader-info SEPARATED BY space.
* APPEND wa_listheader TO it_listheader.
*
* ELSEIF s_gltrp-low IS INITIAL AND s_gltrp-high IS INITIAL.
*
* CLEAR wa_listheader.
* wa_listheader-typ = ‘S’.
* wa_listheader-key = ‘Date :’.
* WRITE ‘*’ TO wa_listheader-info.
* APPEND wa_listheader TO it_listheader.
*
* ELSEIF s_gltrp-high IS INITIAL.
*
* CLEAR wa_listheader.
* wa_listheader-typ = ‘S’.
* wa_listheader-key = ‘Date :’.
* wa_listheader-info = v_date1.
* APPEND wa_listheader TO it_listheader.
*
* ENDIF.
*To print delivery plant in the top of list
*——————————————————————-*
* v_bukrs = bukrs.
* DATA : name1 LIKE t001w-name1.
*
* IF NOT werks IS INITIAL.
*
* SELECT SINGLE name1
* FROM t001w
* INTO name1
* WHERE werks = werks.
*
* CLEAR wa_listheader.
* wa_listheader-typ = ‘S’.
* wa_listheader-key = ‘Plant : ‘.
* CONCATENATE werks ‘,’ name1 INTO wa_listheader-info.
* APPEND wa_listheader TO it_listheader.
* ENDIF.
*
ENDFORM. ” ALV_HEADER
*&———————————————————————*
*& Form FILL_FIELDCAT
*&———————————————————————*
* text
*———————————————————————-*
* –>P_0832 text
* –>P_0833 text
* –>P_10 text
* –>P_0835 text
* –>P_SPACE text
* –>P_SPACE text
* –>P_SPACE text
*———————————————————————-*
FORM fill_fieldcat USING f d o t to p e.
DATA wa_fieldcat TYPE slis_fieldcat_alv.
STATICS pos LIKE sy-index VALUE 1.
pos = pos + 1.
CLEAR wa_fieldcat.
MOVE : 1 TO wa_fieldcat-row_pos,
pos TO wa_fieldcat-col_pos,
f TO wa_fieldcat-fieldname,
d TO wa_fieldcat-seltext_l,
o TO wa_fieldcat-outputlen,
t TO wa_fieldcat-tabname,
to TO wa_fieldcat-do_sum,
p TO wa_fieldcat-fix_column,
e TO wa_fieldcat-edit.
APPEND wa_fieldcat TO it_fieldcat.
ENDFORM. ” FILL_FIELDCAT
*&———————————————————————*
*& Form ALV_EVENTS
*&———————————————————————*
* text
*———————————————————————-*
* –>P_IT_EVENTS text
*———————————————————————-*
FORM alv_events USING p_events TYPE slis_t_event.
DATA : wa_events TYPE slis_alv_event.
CLEAR wa_events.
wa_events-name = ‘TOP_OF_PAGE’.
wa_events-form = ‘TOP_OF_PAGE’.
APPEND wa_events TO it_events.
ENDFORM. ” ALV_EVENTS
***********************************************************************
*
*FORM FOR TOP OF PAGE
***********************************************************************
*
FORM top_of_page.
CALL FUNCTION ‘REUSE_ALV_COMMENTARY_WRITE’
EXPORTING
it_list_commentary = it_listheader
i_logo = ‘ISPATLOGO’.
ENDFORM. “top_of_page
*&———————————————————————*
*& Form ALV_DISPLAY
*&———————————————————————*
* text
*———————————————————————-*
* –> p1 text
* <– p2 text
*———————————————————————-*
FORM alv_display .
gv_repid = sy-repid.
CALL FUNCTION ‘REUSE_ALV_GRID_DISPLAY’
EXPORTING
i_callback_program = gv_repid
i_callback_top_of_page = ‘TOP-OF-PAGE’ “see FORM
i_callback_user_command = ‘CALL_TCODE’
is_layout = is_layout
it_fieldcat = it_fieldcat
i_default = ‘X’
i_save = ‘A’
it_events = it_events
TABLES
t_outtab = t_mtab
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM. ” ALV_DISPLAY
*&——————————————————————–*
*& Form EVENT_CALL
*&——————————————————————–*
* we get all events – TOP OF PAGE or USER COMMAND in table v_events
*———————————————————————*
FORM event_call.
CALL FUNCTION ‘REUSE_ALV_EVENTS_GET’
EXPORTING
i_list_type = 0
IMPORTING
et_events = it_events
* EXCEPTIONS
* LIST_TYPE_WRONG = 1
* OTHERS = 2
.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
ENDFORM. “EVENT_CALL
*&——————————————————————–*
*& Form POPULATE_EVENT
*&——————————————————————–*
* Events populated for TOP OF PAGE & USER COMAND
*———————————————————————*
FORM populate_event.
DATA : wa_event TYPE slis_alv_event.
READ TABLE it_events INTO wa_event WITH KEY name = ‘TOP_OF_PAGE’.
IF sy-subrc EQ 0.
wa_event-form = ‘TOP_OF_PAGE’.
MODIFY it_events FROM wa_event TRANSPORTING form WHERE name =
wa_event-form.
ENDIF.
READ TABLE it_events INTO wa_event WITH KEY name = ‘USER_COMMAND’.
IF sy-subrc EQ 0.
wa_event-form = ‘USER_COMMAND’.
MODIFY it_events FROM wa_event TRANSPORTING form WHERE name =
wa_event-name.
ENDIF.
ENDFORM. “POPULATE_EVENT
*&——————————————————————–*
*& Form USER_COMMAND
*&——————————————————————–*
* text
*———————————————————————*
* –>R_UCOMM text
* –>, text
* –>RS_SLEFIELDtext
*———————————————————————*
FORM user_command USING r_ucomm LIKE sy-ucomm
rs_selfield TYPE slis_selfield.
CASE r_ucomm.
WHEN ‘&IC1’.
READ TABLE t_mtab INTO wa_mtab INDEX rs_selfield-tabindex.
ENDCASE.
ENDFORM. “user_command
*&———————————————————————*
*& Form CONVERT_TO_USER_FORMAT
*&———————————————————————*
form CONVERT_TO_USER_FORMAT using p_amt.
CASE gv_dcpfm.
WHEN ”. “dot + comma e.g. 1.000.000,10
REPLACE ALL OCCURRENCES OF ‘.’ IN p_amt WITH space. “‘,’.
WHEN ‘X’. “comma + dot e.g. 1,000,000.10
REPLACE ALL OCCURRENCES OF ‘,’ IN p_amt WITH space. “‘.’.
WHEN ‘Y’. “space + comma e.g. 1 000 000,10
REPLACE ALL OCCURRENCES OF ‘.’ IN p_amt WITH space. “‘,’.
ENDCASE.
endform. ” CONVERT_TO_USER_FORMAT
*&———————————————————————*
*& Form DELETE_PROCESSED_RECORDS
*&———————————————————————*
form DELETE_PROCESSED_RECORDS .
LOOP AT gt_sel.
DELETE gt_bsid WHERE gjahr = gt_sel-gjahr
AND belnr = gt_sel-belnr
AND buzei = gt_sel-buzei.
* Store processed records to skip during the next run
APPEND gt_sel to gt_error.
ENDLOOP.
endform. ” DELETE_PROCESSED_RECORDS
*&———————————————————————*
*& Form GET_ORDERS
*&———————————————————————*
form GET_ORDERS using p_vbeln.
DATA : BEGIN OF it_order OCCURS 0,
vbeln TYPE vbak-vbeln,
kunnr TYPE vbak-kunnr,
END OF it_order.
SELECT VBELN kunnr
FROM VBAK
INTO TABLE it_order
WHERE VBELN <> ‘ ‘
AND vbtyp = ‘C’.
IF p_vbeln = ‘S_VBELN-LOW’.
CALL FUNCTION ‘F4IF_INT_TABLE_VALUE_REQUEST’
EXPORTING
* DDIC_STRUCTURE = ‘ ‘
retfield = ‘VBELN’
* PVALKEY = ‘ ‘
DYNPPROG = sy-repid
DYNPNR = sy-dynnr
DYNPROFIELD = ‘S_VBELN-LOW’
* STEPL = 0
* WINDOW_TITLE =
* VALUE = ‘ ‘
VALUE_ORG = ‘S’
* MULTIPLE_CHOICE = ‘ ‘
* DISPLAY = ‘ ‘
* CALLBACK_PROGRAM = ‘ ‘
* CALLBACK_FORM = ‘ ‘
* MARK_TAB =
* IMPORTING
* USER_RESET =
tables
value_tab = it_order
* FIELD_TAB =
* RETURN_TAB =
* DYNPFLD_MAPPING =
EXCEPTIONS
PARAMETER_ERROR = 1
NO_VALUES_FOUND = 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.
ENDIF.
ELSE.
CALL FUNCTION ‘F4IF_INT_TABLE_VALUE_REQUEST’
EXPORTING
* DDIC_STRUCTURE = ‘ ‘
retfield = ‘VBELN’
* PVALKEY = ‘ ‘
DYNPPROG = sy-repid
DYNPNR = sy-dynnr
DYNPROFIELD = ‘S_VBELN-HIGH’
* STEPL = 0
* WINDOW_TITLE =
* VALUE = ‘ ‘
VALUE_ORG = ‘S’
* MULTIPLE_CHOICE = ‘ ‘
* DISPLAY = ‘ ‘
* CALLBACK_PROGRAM = ‘ ‘
* CALLBACK_FORM = ‘ ‘
* MARK_TAB =
* IMPORTING
* USER_RESET =
tables
value_tab = it_order
* FIELD_TAB =
* RETURN_TAB =
* DYNPFLD_MAPPING =
EXCEPTIONS
PARAMETER_ERROR = 1
NO_VALUES_FOUND = 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.
ENDIF.
ENDIF.
endform. ” GET_ORDERS
Hey Animesh,
Great piece of code, and thanks for sharing. Just that i am reading your posts after implementing the BDC myself from scratch after facing swaths of problems in the BDC. But finally was able to do it.
There are some trivial things that i would like to share for people implementing this requirement and reading your blog.
1 - User settings: Each user might have different settings for the screen in transaction FB05 / F-32, which might impact the program behaviour, so it is important that while creating the BDC such options are kept in mind / or else the impact is negated by chaging such setting in the BDC itself.
Sample code for such thing is metioned as under:
if lv_userval1+7(1) ne 'X' or lv_userval1+0(1) eq 'X' or lv_userval2 ne 'K2'.
* Populate the bdc data for settings for open items.
perform bdc_dynpro using 'SAPMF05A' '0122'.
perform bdc_field using 'BDC_OKCODE'
'/EB00'.
perform bdc_field using 'BDC_CURSOR'
'BKPF-BLDAT'.
perform bdc_dynpro using 'SAPMF05O' '2000'.
perform bdc_field using 'BDC_OKCODE'
'=SICH' .
* Populate the Local currency "Document only in Local currency".
perform bdc_field using 'RFOPT-XNOWA'
' '.
perform bdc_field using 'RF05O-XBWBU'
'X'.
perform bdc_field using 'RF05O-VARSB'
'SAP01'.
perform bdc_field using 'RF05O-VARRG'
'SAP01'.
perform bdc_field using 'RF05O-VARVO'
'SAP01'.
perform bdc_field using 'RF05O-VARKM'
'SAP01'.
perform bdc_field using 'RFCU4-VBLUE'
'ZCP'.
perform bdc_field using 'BDC_CURSOR'
'RFOPT-XOPIN'.
perform bdc_field using 'RFOPT-XOPIN'
'X'.
perform bdc_field using 'XLINE'
'X'.
perform bdc_field using 'RFOPT2-XDOLD'
'X'.
perform bdc_field using 'RFOPT2-XCROC'
'X'.
perform bdc_field using 'FCJOPT-XPERLAST'
'X'.
perform bdc_dynpro using 'SAPMF05O' '2000'.
perform bdc_field using 'BDC_OKCODE'
'=RW'.
perform bdc_field using 'RF05O-XBWBU'
'X'.
perform bdc_field using 'RF05O-VARSB'
'SAP01'.
perform bdc_field using 'RF05O-VARRG'
'SAP01'.
perform bdc_field using 'RF05O-VARVO'
'SAP01'.
perform bdc_field using 'RF05O-VARKM'
'SAP01'.
perform bdc_field using 'RFCU4-VBLUE'
'ZCP'.
perform bdc_field using 'BDC_CURSOR'
'RFCU4-VAUSD'.
perform bdc_field using 'RFOPT-XOPIN'
'X'.
perform bdc_field using 'RFCU4-VAUSD'
'K2'.
perform bdc_field using 'GD_BH_SHOW'
'X'.
perform bdc_field using 'GD_SHOW_LEGEND'
'X'.
perform bdc_field using 'GD_SAVE_LAYOUT'
'X'.
perform bdc_field using 'GD_LYSEL_AR'
'1SAP'.
perform bdc_field using 'GD_LYSEL_GL'
'/GL4GST'.
perform bdc_field using 'GD_ALV_CLASSIC'
'X'.
perform bdc_field using 'XLINE'
'X'.
perform bdc_field using 'RFOPT2-XDOLD'
'X'.
perform bdc_field using 'RFOPT2-XCROC'
'X'.
perform bdc_field using 'FCJOPT-XPERLAST'
'X'.
*Call the BDC to set the Editing options in FB05
call transaction 'FB05' using bdcdata[]
options from ls_ctu_params
messages into lt_msg[].
refresh:bdcdata[], lt_msg[] .
endif.
This will make sure that no matter who is running the BDC, the BDC runs seemlessly with a certain setting. Generally the BDC programs are meant to be run with the batch user id, but just to be covered from all aspects it is better to code.
2- How to track the index of the open item and then determine the residual value:
For a customer there can be many open items at the same time. So the BDC has to be dynamic enough to pick the exact open item for which the payment is to be booked. This can be done in two steps:
- Get all the open items: Use the BAPI " BAPI_AR_ACC_GETOPENITEMS" to determine what are the total number of open items present for the customer. This can also be used to validate that the open item for which the payment is to be booked is valid or not. Else the BDC will book the payment against any open item, if not found in the list.
- Get the idex in the "Residual Items" tab page: In order to book the payment against the correct invoice, we need to sort the open items per any given criterion, get the index and then book the residual amount.Here is the sample code to sort the items in the BDC.
* sort logic for in screen level
perform bdc_dynpro using 'SAPDF05X' '3100'.
perform bdc_field using 'BDC_OKCODE' '=OSO'.
perform bdc_field using 'BDC_CURSOR' 'RFOPS_DK-XBLNR(01)'.
perform bdc_field using 'RF05A-ABPOS' '1'.
perform bdc_dynpro using 'SAPDF05X' '3100'.
perform bdc_field using 'BDC_OKCODE' '/00'.
perform bdc_field using 'BDC_CURSOR' 'RF05A-ABPOS'.
perform bdc_field using 'RF05A-ABPOS' lv_tabix.
*end of sorting logic.
In the above code, the sorting was done based on the "XBLNR" field.
Hope this will be helpful to the users in future.
Ashish