📄 zfir0008.txt
字号:
********************************************************************
* Program Name : ZFIR0008 *
* T Code : *
* Program Title: 应收帐款-催款函 *
* Model : FI *
* Created by : LIJIA *
* Created on : 2007/05/31 *
* Version : 1.0 *
*------------------------------------------------------------------*
* Modification Log: *
* Date Programmer Correction Number Correction Type *
********************************************************************
INCLUDE zfir0008top . " global Data
INCLUDE zfir0008o01 . " PBO-Modules
INCLUDE zfir0008i01 . " PAI-Modules
INCLUDE zfir0008f01 . " FORM-Routines
********************************************************************************************************
*程序逻辑说明:该程序只统计完全交货的合同数据,相关关系是一个合同可能包含多个销售订单,
* 每个销售订单的交货状态都必须为C(完全交货)时,才考虑该合同的数据,此程序
* 不关心是否已开票。根据交货数量*销售订单上的单价,就可以得到应收的交货金额,
* 但是此合同有可能是已经收了部分款或者已经收到了一些预收款,所以应该用交货
* 金额 - 已收金额(包括已收+预收)。要得到已收金额需要从表BSID和BSAD中取相关数据
* BSID是未清数据,部分清帐的数据也在BSID表中,只有完全清帐的数据才在BSAD中,所以
* BSID的取数逻辑是:1、取凭证类型为DZ、DA且特别总帐标识不等于A、S、W,(正常已收未清或部分清帐)
* 2、取凭证类型为DZ,且特别总帐标识等于A、S、W的数据。(预收未清或部分清帐)
* BSAD的取数逻辑是:1、取凭证类型为DZ、DA且特别总帐标识不等于A、S、W,(正常已收已清)
* 2、取凭证类型为DZ,且特别总帐标识等于A、S、W的数据。(预收已清)
* 开票金额是取BSID和BSAD中作证类型为RV的数据
*由于输出的信息需要定位在EXCEL中,涉及文本输出的内容全部在程序中固定,如果需要调整此部分内容需要修改程序完成。
********************************************************************************************************
*---> start of selection screen
SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE text-001.
PARAMETERS: bukrs LIKE bsid-bukrs OBLIGATORY. "公司代码
SELECT-OPTIONS: kunnr FOR vbak-kunnr, "客户代码
zuonr FOR vbak-bstnk. "合同号
PARAMETERS: budat LIKE vbak-erdat OBLIGATORY . "截止日期
SELECTION-SCREEN END OF BLOCK block1 .
SELECTION-SCREEN: BEGIN OF BLOCK blk2 WITH FRAME TITLE text-002.
PARAMETERS: p_hbkid(5), "开户银行
p_hktid(5). "帐户
SELECTION-SCREEN: END OF BLOCK blk2.
*---> end of selection screen
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_hbkid.
PERFORM f4_help_hbkid. "开户银行的search help
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_hktid.
PERFORM f4_help_hktid. "开户银行的search help
START-OF-SELECTION.
g_bukrs = bukrs.
g_hbkid = p_hbkid.
g_hktid = p_hktid.
dueday = budat.
"因为要统计五天内将要到期的数据
zbudat = budat + 5.
*--->得到公司代码下所有的销售组织
SELECT bukrs
vkorg FROM tvko INTO TABLE it_tvko
WHERE bukrs EQ bukrs.
*--->要统计销售订单状态为C,且相关的所有交货单已全部发货(也就是说所有的交货单状态都要为C)
*--->得到销售订单状态为C,且满足选择屏幕条件的数据
PERFORM get_sales_order_state.
CHECK flag1 NE 'N'. "如果没有交货数据存在,就不用运行后面的程序了
*--->得到满足条件的销售订单后,要判断这些销售订单所涉及的所有交货单是否已经发货完成(交货单的货物移动状态
*--->必须是C),
PERFORM get_deliver_state.
DESCRIBE TABLE it_aging_deliver LINES zline.
IF zline EQ 0.
EXIT.
ENDIF.
"填充明细数据-有关交货的
PERFORM fill_it_detail_data_01.
"得到有关交货所涉及到的合同号
LOOP AT it_detail.
it_contract-bstkd = it_detail-bstkd.
APPEND it_contract.
ENDLOOP.
DELETE ADJACENT DUPLICATES FROM it_contract .
"得到收款金额
PERFORM get_bsid_data.
"填充明细数据-有关已收和已开票的
PERFORM fill_it_detail_data_02.
"得到最终帐龄数据,就是包含BSID和Delivery的数据
PERFORM get_itab_data.
PERFORM output_alv.
END-OF-SELECTION.
*&---------------------------------------------------------------------*
*& Form GET_BSID_DATA
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM get_bsid_data .
PERFORM get_yishou_data. "得到已收金额
PERFORM get_yushou_data. "得到预收金额.
PERFORM get_kaipiao_data. "得到开票金额
ENDFORM. "get_bsid_data
*&---------------------------------------------------------------------*
*& Form get_sales_order_state
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM get_sales_order_state .
"销售订单交货状态为C,
SELECT a~bstkd
a~bstdk
a~vbeln
a~kunnr
a~auart
b~posnr
b~kwmeng
b~kzwi1 FROM m_vmvaa AS a INNER JOIN vbap AS b
ON b~vbeln EQ a~vbeln
AND b~posnr EQ a~posnr
AND b~abgru EQ space
INNER JOIN vbuk AS c
ON c~vbeln EQ a~vbeln
AND c~lfstk EQ 'C'
INTO TABLE it_so
FOR ALL ENTRIES IN it_tvko
WHERE a~kunnr IN kunnr
AND a~bstkd IN zuonr
AND a~vkorg EQ it_tvko-vkorg.
IF sy-subrc NE 0.
flag1 = 'N'. "没有相关的交货数据
ENDIF.
ENDFORM. " get_sales_order_state
*&---------------------------------------------------------------------*
*& Form get_deliver_state
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM get_deliver_state .
DATA: BEGIN OF temp_deliver OCCURS 0,
vbeln LIKE vbak-vbeln,
date TYPE d, "应回款日期(最大交货日期+付款条件)
date1 TYPE d, "发货日期(最大交货日期)
flag,
END OF temp_deliver.
DATA zfael LIKE t052-zfael ."收付基准日期的日历天
DATA ztabix2 LIKE sy-tabix.
SELECT a~vbelv
a~posnv
a~vbeln
a~posnn
a~vbtyp_n
a~rfmng
b~wbsta
d~wadat_ist "交货单的实际货特移动日期
c~kzwi1 "销售订单行项目含税总价
c~kwmeng FROM vbfa AS a INNER JOIN vbup AS b
ON b~vbeln EQ a~vbeln AND
b~posnr EQ a~posnn
INNER JOIN vbap AS c
ON c~vbeln EQ a~vbelv AND
c~posnr EQ a~posnv
INNER JOIN likp AS d
ON d~vbeln EQ a~vbeln
INTO TABLE it_deliver
FOR ALL ENTRIES IN it_so
WHERE a~vbelv EQ it_so-vbeln
AND a~posnv EQ it_so-posnr
AND a~vbtyp_n IN ('J','T').
LOOP AT it_deliver.
temp_deliver-vbeln = it_deliver-vbelv.
APPEND temp_deliver.
ENDLOOP.
DELETE ADJACENT DUPLICATES FROM temp_deliver.
"判断一个销售订单相关的所有交货单是否已经全部发货完成。只处理全部发货完成的数据
LOOP AT temp_deliver.
ztabix = sy-tabix.
"读取销售订单的付款条件。
SELECT SINGLE b~zfael FROM vbkd AS a INNER JOIN t052 AS b
ON b~zterm EQ a~zterm
INTO zfael
WHERE a~vbeln EQ temp_deliver-vbeln.
LOOP AT it_deliver WHERE vbelv EQ temp_deliver-vbeln.
ztabix2 = sy-tabix.
IF it_deliver-wbsta NE 'C'.
DELETE it_deliver[] WHERE vbelv = temp_deliver-vbeln.
temp_deliver-flag = 'D'.
MODIFY temp_deliver INDEX ztabix.
ELSE.
"如果有一个交货单的日期大于截止日期,就视为部分交货,所以就不考虑此数据
it_deliver-date1 = it_deliver-wadat_ist.
it_deliver-wadat_ist = it_deliver-wadat_ist + zfael.
IF it_deliver-wadat_ist > budat.
DELETE it_deliver[] WHERE vbelv = temp_deliver-vbeln.
temp_deliver-flag = 'D'.
MODIFY temp_deliver INDEX ztabix.
ELSE.
MODIFY it_deliver INDEX ztabix2 TRANSPORTING wadat_ist date1.
ENDIF.
ENDIF.
ENDLOOP.
ENDLOOP.
"把发货未完成的销售订单排除,不进行后续计算
DELETE temp_deliver[] WHERE flag EQ 'D'.
"将交货信息的内表按销售订单号和基准日期降序编号,排序之后每个销售订单号所对应的第一条记录的日期一定是最大日期
SORT it_deliver DESCENDING BY vbelv wadat_ist.
SORT temp_deliver DESCENDING BY vbeln.
"得到每一个销售订单的最大交货日期
LOOP AT temp_deliver.
ztabix = sy-tabix.
READ TABLE it_deliver WITH KEY vbelv = temp_deliver-vbeln.
temp_deliver-date = it_deliver-wadat_ist.
temp_deliver-date1 = it_deliver-date1.
MODIFY temp_deliver INDEX ztabix.
ENDLOOP.
LOOP AT it_deliver.
ON CHANGE OF it_deliver-vbelv.
READ TABLE temp_deliver WITH KEY vbeln = it_deliver-vbelv.
ENDON.
CASE it_deliver-vbtyp_n.
WHEN 'J'. "正常发货
it_aging_deliver-vbeln = it_deliver-vbelv.
it_aging_deliver-zday = zbudat - temp_deliver-date.
it_aging_deliver-kzwi1 = it_deliver-kzwi1.
it_aging_deliver-date = temp_deliver-date.
it_aging_deliver-date1 = temp_deliver-date1.
WHEN 'T'. "退货
it_aging_deliver-vbeln = it_deliver-vbelv.
it_aging_deliver-zday = zbudat - temp_deliver-date.
it_aging_deliver-kzwi1 = - it_deliver-kzwi1.
it_aging_deliver-date = temp_deliver-date.
it_aging_deliver-date1 = temp_deliver-date1.
ENDCASE.
COLLECT it_aging_deliver.
CLEAR it_aging_deliver.
ENDLOOP.
ENDFORM. " get_deliver_state
*&---------------------------------------------------------------------*
*& Form get_itab_data
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM get_itab_data .
LOOP AT it_detail.
itab-kunnr = it_detail-kunnr.
"根据时间判断应该放入哪个帐龄字段里面
PERFORM get_aging_position USING it_detail-aging
it_detail-ysje.
COLLECT itab.
CLEAR itab.
ENDLOOP.
LOOP AT itab.
ztabix = sy-tabix.
SELECT SINGLE name1 FROM kna1 INTO itab-name1
WHERE kunnr EQ itab-kunnr.
itab-zhj = itab-dmbtr_d_1_5 + itab-dmbtr_d_6_10 + itab-dmbtr_d_11_35
+ itab-dmbtr_d_36_65.
IF itab-zhj <= 0.
DELETE itab INDEX ztabix.
ENDIF.
MODIFY itab INDEX ztabix.
ENDLOOP.
ENDFORM. " get_itab_data
*&---------------------------------------------------------------------*
*& Form get_aging_position
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_IT_AGING_DELIVER_ZDAY text
* -->P_IT_AGING_DELIVER_KZWI1 text
*----------------------------------------------------------------------*
FORM get_aging_position USING p_day p_dmbtr.
IF p_day BETWEEN 1 AND 5.
itab-dmbtr_d_1_5 = p_dmbtr.
ENDIF.
IF p_day BETWEEN 6 AND 10.
itab-dmbtr_d_6_10 = p_dmbtr.
ENDIF.
IF p_day BETWEEN 11 AND 35.
itab-dmbtr_d_11_35 = p_dmbtr.
ENDIF.
IF p_day BETWEEN 36 AND 65.
itab-dmbtr_d_36_65 = p_dmbtr.
ENDIF.
IF p_day > 66.
itab-dmbtr_d_66 = p_dmbtr.
ENDIF.
ENDFORM. " get_aging_position
*&---------------------------------------------------------------------*
*& Form output_alv
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM output_alv .
CALL SCREEN 2000.
ENDFORM. " output_alv
*&---------------------------------------------------------------------*
*& Form get_yishou_data
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM get_yishou_data .
* BSID的取数逻辑是:1、取凭证类型为DZ、DA且特别总帐标识不等于A、S、W,(正常已收未清或部分清帐)
* 借贷标识是H的是部分清帐,S是冲销,这部分要扣除
*
* BSAD的取数逻辑是:1、取凭证类型为DZ、DA且特别总帐标识不等于A、S、W,(正常已收已清)
* 借贷标识S是已清帐的,H是冲销,扣除这部分
SELECT kunnr
belnr
zfbdt
zuonr
dmbtr
xblnr
umskz
shkzg
blart FROM bsid INTO TABLE it_bsid
FOR ALL ENTRIES IN it_contract
WHERE bukrs EQ bukrs
AND kunnr IN kunnr
AND zuonr EQ it_contract-bstkd
AND umskz EQ space
AND blart IN ('DZ','DA')
AND budat <= budat.
LOOP AT it_bsid.
IF it_bsid-shkzg = 'H'.
it_contract-skje = it_bsid-dmbtr.
ELSE.
it_contract-skje = - it_bsid-dmbtr.
ENDIF.
it_contract-bstkd = it_bsid-zuonr.
COLLECT it_contract.
CLEAR it_contract.
ENDLOOP.
FREE it_bsid.
CLEAR it_bsid.
SELECT kunnr
belnr
zfbdt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -