在项目中,遇到对于客户信用控制启用SAP标准信贷控制之外,对于无信贷限额的客户,使用款到发货控制,即在收到客户货款时,针对客户来款情况进行发货管理。
客户来款后,财务将银行流水(行号、客户编号、来款金额等信息)导入CRM系统,销售进行来款认领,生成凭证,财务审核后将凭证同步至SAP系统,此时款到发货客户应收账龄表中将会有客户的预付款,通过该预付款控制发货价值即可。
款到发货逾期控制逻辑:
用IDCNAR表中未清项目总计的负数-LIKP表中BS(开票)状态=A且货物移动状态=C的数据,在创建新的交货单时,用(IDCNAR表中未清项目总计的负数-LIKP表中BS(开票)状态=A且货物移动状态=C的金额)-(需要创建交货单的VBAP-VBELN销售订单号+VBAP-POSNR行项目的KBETR金额*LIPS-LFIMG交货数量),若差值>=0,则允许创建交货单,若差值<0,则报错显示逾期金额*元,不允许创建交货单;其中需要将过账之后的退货订单类型(ZRE1、ZRE2、ZRE3、ZRE4、ZRE5、ZRE6、ZRE7、ZRE8、ZRE9、ZCR1)的KZWI1小计1金额计入IDCNAR表中的未清项目总计中参与计算,过账之后的退货订单类型ZCR2的KZWI1小计1金额无需计入IDCNAR表中的未清项目总计中参与计算;其中无需对ZOR5、ZCG1、ZOR2三种订单类型及总金额=0订单的款到发货客户进行逾期控制。
***INCLUDE MV50AFZ1 .
************************************************************************
* *
* This include is reserved for user modifications *
* *
* Forms for delivery processing *
* *
* The name of modification modules should begin with 'ZZ'. *
* *
************************************************************************
*---------------------------------------------------------------------*
* FORM ZZEXAMPLE *
*---------------------------------------------------------------------*
* text...................................... *
*---------------------------------------------------------------------*
*FORM ZZEXAMPLE.
* ...
*ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_DELETE_DOCUMENT *
*---------------------------------------------------------------------*
* This userexit can be used to delete data in additional tables *
* when a delivery is deleted. *
* *
* This form is called in dialog at the end of form BELEG_LOESCHEN*
* just before form BELEG_SICHERN is performed to delete the *
* datas on the database. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_DELETE_DOCUMENT.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_MOVE_FIELD_TO_LIKP *
*---------------------------------------------------------------------*
* This userexit can be used to move some fields into the *
* delivery header workaerea LIKP. *
* This form is called, when a header is created *
* This form is called at the end of form LIKP_FUELLEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_MOVE_FIELD_TO_LIKP.
* LIKP-zzfield = xxxx-zzfield2.
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Form USEREXIT_MOVE_FIELD_TO_LIKP, Ende A
*$*$-Start: (1)---------------------------------------------------------------------------------$*$*
ENHANCEMENT 1 ZIM_SD_DLV_BAPI_CUS_FIELD1. "active version
DATA: LS_DLV_APD TYPE ZSDS_DLV_BAPI_CUS_FILED .
INCLUDE ZBCX_PUBLIC_FORMS .
*-----------------------------------------------------------------------*
*--交货单创建BAPI 导入附加字段
*-----------------------------------------------------------------------*
IF GS_VORGABE_DATEN IS NOT INITIAL .
MOVE-CORRESPONDING GS_VORGABE_DATEN TO LS_DLV_APD .
MOVE-CORRESPONDING LS_DLV_APD TO LIKP .
ENDIF.
*-----------------------------------------------------------------------*
*--"过账的交货单 POD日期等于过账日期
*-----------------------------------------------------------------------*
"修改增强字段時不过此处增强 替代到 SE19 -> ZIM_SH_DELIVERY_PROC 实现
* IF LIKP-ZZPODAT IS INITIAL AND LIKP-WBSTK = ZIF_BC_CONSTANTS=>GC_C .
* LIKP-ZZPODAT = LIKP-WADAT_IST .
* ENDIF.
ENDENHANCEMENT.
*$*$-End: (1)---------------------------------------------------------------------------------$*$*
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_MOVE_FIELD_TO_LIPS *
*---------------------------------------------------------------------*
* This userexit can be used to move some fields into the *
* delivery item workaerea LIPS *
* This form is called, when an item is created *
* *
* *
* This form is called at the end of form LIPS_FUELLEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_MOVE_FIELD_TO_LIPS.
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(2) Form USEREXIT_MOVE_FIELD_TO_LIPS, Anfang A
*$*$-Start: (2)---------------------------------------------------------------------------------$*$*
ENHANCEMENT 2 ZIM_SD_DLV_BAPI_CUS_FIELD1. "active version
IF GS_VORGABE_DATEN IS NOT INITIAL .
LIPS-LGORT = GS_VORGABE_DATEN-LGORT .
LIPS-ZZQUA = GS_VORGABE_DATEN-ZZQUA .
ENDIF.
ENDENHANCEMENT.
*$*$-End: (2)---------------------------------------------------------------------------------$*$*
* LIPS-zzfield = xxxx-zzfield2.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_NUMBER_RANGE *
*---------------------------------------------------------------------*
* This userexit can be used to determine the numberranges for *
* the internal document number. *
* *
* US_RANGE_INTERN - internal number range *
* *
* This form is called from form BELEG_SICHERN *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_NUMBER_RANGE USING US_RANGE_INTERN.
* Example: Numer range from TVLK like in standard
* US_RANGE_INTERN = TVLK-NUMKI.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_READ_DOCUMENT *
*---------------------------------------------------------------------*
* This userexit can be used to read data in additional tables *
* when the program reads a delivery. *
* *
* This form is called at the end of form BELEG_LESEN. *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_READ_DOCUMENT.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_SAVE_DOCUMENT *
*---------------------------------------------------------------------*
* This userexit can be used to save data in additional tables *
* when a document is saved. *
* *
* If field T180-TRTYP contents 'H', the document will be *
* created, else it will be changed. *
* *
* This form is called at from form BELEG_SICHERN, before COMMIT *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_SAVE_DOCUMENT.
* Example:
* CALL FUNCTION 'ZZ_EXAMPLE'
* IN UPDATE TASK
* EXPORTING
* ZZTAB = ZZTAB.
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_SAVE_DOCUMENT_PREPARE *
*---------------------------------------------------------------------*
* This userexit can be used for changes or checks, before a *
* document is saved. *
* *
* If field T180-TRTYP contents 'H', the document will be *
* created, else it will be changed. *
* *
* This form is called at the beginning of form BELEG_SICHERN *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_SAVE_DOCUMENT_PREPARE.
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(3) Form USEREXIT_SAVE_DOCUMENT_PREPARE, Anfang A
*$*$-Start: (3)---------------------------------------------------------------------------------$*$*
ENHANCEMENT 1 ZIM_SD_DLV_ZQUAAM_CAL. "active version
*-->计算抬头件数总计,行项目件数汇总:
DATA:LV_ZQUAAM TYPE LIPS-ZZQUA.
INCLUDE ZBCX_PUBLIC_FORMS .
CLEAR: LV_ZQUAAM .
LOOP AT XLIPS INTO DATA(LS_LIPS).
LV_ZQUAAM = LV_ZQUAAM + LS_LIPS-ZZQUA.
ENDLOOP.
XLIKP-ZZQUAAM = LIKP-ZZQUAAM = LV_ZQUAAM.
MODIFY XLIKP INDEX 1.
ENDENHANCEMENT.
*$*$-End: (3)---------------------------------------------------------------------------------$*$*
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(4) Form USEREXIT_SAVE_DOCUMENT_PREPARE, Ende A
*$*$-Start: (4)---------------------------------------------------------------------------------$*$*
ENHANCEMENT 2 ZIM_SD_DLV_ZQUAAM_CAL. "active version
*----------------------------------------------------------------------*
*--控制信贷检查不过不能创建交货单
*----------------------------------------------------------------------*
IF XLIKP-UPDKZ = ZIF_BC_CONSTANTS=>GC_I AND XVBUK-CMGST = ZIF_BC_CONSTANTS=>GC_B.
MESSAGE e005(ZSD_MSG001) .
ENDIF.
*-----------------------------------------------------------------------*
*--对客户是否存在逾期交货的控制
*-----------------------------------------------------------------------*
CONSTANTS: CNS_AUART_ZOR1 TYPE VBAK-AUART VALUE 'ZOR1',
CNS_AUART_ZOR2 TYPE VBAK-AUART VALUE 'ZOR2',
CNS_AUART_ZOR3 TYPE VBAK-AUART VALUE 'ZOR3',
CNS_AUART_ZOR4 TYPE VBAK-AUART VALUE 'ZOR4',
CNS_AUART_ZOR5 TYPE VBAK-AUART VALUE 'ZOR5',
CNS_AUART_ZCG1 TYPE VBAK-AUART VALUE 'ZCG1'.
IF SY-TCODE <> 'VL31N' AND SY-TCODE <> 'VL32N'.
IF XLIKP-UPDKZ = ZIF_BC_CONSTANTS=>GC_I AND XLIKP-LFART NE 'LR'. "新建交货单的时候控制逾期 " 排除掉退货订单
LOOP AT XLIPS INTO DATA(LS_XLIPS).
SELECT SINGLE AUART
FROM VBAK
WHERE VBELN = @LS_XLIPS-VGBEL
INTO @DATA(LV_AUART) .
IF LV_AUART NE CNS_AUART_ZOR2 AND
LV_AUART NE CNS_AUART_ZOR5 AND
LV_AUART NE CNS_AUART_ZCG1.
CALL FUNCTION 'Z_SD_DN_AR_CHECK'
EXPORTING
IS_LIKP = LIKP
TABLES
IT_LIPS = XLIPS[].
EXIT .
ENDIF.
CLEAR LV_AUART .
ENDLOOP.
ENDIF.
ENDIF.
ENDENHANCEMENT.
*$*$-End: (4)---------------------------------------------------------------------------------$*$*
ENDFORM.
*eject
*---------------------------------------------------------------------*
* FORM USEREXIT_REFRESH_DOCUMENT *
*---------------------------------------------------------------------*
* It is always necessary to refresh user-specific data before *
* the next document will be processed. *
* This can be done in this userexit. *
* This userexit can be used to refresh user-specific data *
* when the processing of a delivery is finished *
* - after the document is saved *
* - when you leave the document processing with F3 or F15 *
* It may be necessary to refresh user-specific data before *
* the next document will be processed. *
* *
* This form is called in dialog at the end of form *
* BELEG_INITIALISIEREN *
* *
*---------------------------------------------------------------------*
FORM USEREXIT_REFRESH_DOCUMENT.
* clear: ZZ50A.
* refresh: zzitemtab.
ENDFORM.
*eject
FUNCTION Z_SD_DN_AR_CHECK.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(IS_LIKP) TYPE LIKP
*" TABLES
*" IT_LIPS STRUCTURE LIPSVB OPTIONAL
*"----------------------------------------------------------------------
TYPES: BEGIN OF TYP_LIKP ,
BUKRS TYPE T001-BUKRS,
KUNAG TYPE LIKP-KUNAG,
WADAT TYPE LIKP-WADAT_IST,
VBELN TYPE LIKP-VBELN,
VBTYP TYPE LIKP-VBTYP,
WAERS TYPE LIKP-WAERK,
GBSTK TYPE LIKP-GBSTK,
WBSTK TYPE LIKP-WBSTK,
POSNR TYPE LIPS-POSNR,
VGBEL TYPE LIPS-VGBEL,
VGPOS TYPE LIPS-VGPOS,
LFIMG TYPE LIPS-LFIMG,
SHKZG TYPE LIPS-SHKZG,
VBELN_VF TYPE VBRK-VBELN,
FKDAT TYPE VBRK-FKDAT,
KZWI1 TYPE VBAP-KZWI1,
KWMENG TYPE VBAP-KWMENG,
KURSK TYPE VBKD-KURSK,
END OF TYP_LIKP .
DATA: LV_DATA TYPE REF TO DATA .
DATA: R_HKONT TYPE RANGE OF BSID_VIEW-HKONT WITH HEADER LINE,
R_KUNNR TYPE RANGE OF LIKP-KUNAG WITH HEADER LINE,
R_BUKRS TYPE RANGE OF TVKO-BUKRS WITH HEADER LINE,
R_AUART TYPE RANGE OF VBAK-AUART WITH HEADER LINE.
CONSTANTS: CNS_HKONT TYPE BSID_VIEW-HKONT VALUE '1122020000',
CNS_CHAR_% TYPE C VALUE '%',
CNS_D001 TYPE C LENGTH 4 VALUE 'D001'.
FIELD-SYMBOLS:
DATA: LT_LIKP TYPE STANDARD TABLE OF TYP_LIKP.
DATA: LT_LIPS LIKE STANDARD TABLE OF LIPSVB .
DATA: LS_AR_HEAD TYPE IDCN_S_AR_AGING_HEADER .
DATA: LV_PRCNT TYPE STRING,
LV_AMOUNT TYPE BF_AAFAG. "IDCN_S_AR_AGING_HEADER-AMOUNT.
*----------------------------------------------------------------------*
SELECT PARTNER,
CREDIT_SGMNT ,
CREDIT_LIMIT
FROM UKMBP_CMS_SGM
WHERE PARTNER = @IS_LIKP-KUNAG
AND CREDIT_LIMIT > 0
INTO TABLE @DATA(LT_UKM)
UP TO 1 ROWS.
IF SY-SUBRC EQ 0 . "启用信用管理的客户 不考虑付款逾期的问题
RETURN .
ENDIF.
*-----------------------------------------------------------------------*
*--客户
*-----------------------------------------------------------------------*
R_KUNNR-SIGN = ZIF_BC_CONSTANTS=>GC_I .
R_KUNNR-OPTION = ZIF_BC_CONSTANTS=>GC_EQ .
R_KUNNR-LOW = IS_LIKP-KUNAG.
APPEND R_KUNNR .
*-----------------------------------------------------------------------*
*--公司代码
*-----------------------------------------------------------------------*
SELECT SINGLE BUKRS
FROM TVKO
WHERE VKORG = @IS_LIKP-VKORG
INTO @DATA(LV_BUKRS) .
R_BUKRS-SIGN = ZIF_BC_CONSTANTS=>GC_I .
R_BUKRS-OPTION = ZIF_BC_CONSTANTS=>GC_EQ .
R_BUKRS-LOW = LV_BUKRS .
APPEND R_BUKRS .
*-----------------------------------------------------------------------*
*--科目
*-----------------------------------------------------------------------*
R_HKONT-SIGN = ZIF_BC_CONSTANTS=>GC_I .
R_HKONT-OPTION = ZIF_BC_CONSTANTS=>GC_EQ .
R_HKONT-LOW = CNS_HKONT.
APPEND R_HKONT .
*----------------------------------------------------------------------*
*--调用报表获取客户逾期或者付款数据
*----------------------------------------------------------------------*
CL_SALV_BS_RUNTIME_INFO=>SET(
DISPLAY = ''
METADATA = ''
DATA = ABAP_TRUE ) .
SUBMIT RFIDCN_AR_AGING WITH DD_KUNNR IN R_KUNNR
WITH DD_BUKRS IN R_BUKRS
WITH S_RCLACC IN R_HKONT AND RETURN .
TRY .
CL_SALV_BS_RUNTIME_INFO=>GET_DATA_REF(
IMPORTING R_DATA = LV_DATA ) .
ASSIGN LV_DATA->* TO
CATCH CX_SALV_BS_SC_RUNTIME_INFO .
MESSAGE E001(ZSD_MSG001) .
ENDTRY .
CL_SALV_BS_RUNTIME_INFO=>CLEAR_ALL( ) .
*----------------------------------------------------------------------*
SELECT SINGLE NBLOCK_IND "获取客户是否解冻
FROM ZSDT0035
WHERE KUNNR = @IS_LIKP-KUNNR
* AND NBLOCK_IND = @ABAP_TRUE
INTO @DATA(LV_NBLOCK_IND).
SELECT SINGLE ZTERM "获取客户付款条件
FROM KNVV
WHERE KUNNR = @IS_LIKP-KUNAG
AND VKORG = @IS_LIKP-VKORG
INTO @DATA(LV_ZTERM).
*----------------------------------------------------------------------*
READ TABLE
IF SY-SUBRC EQ 0 .
LS_AR_HEAD =
LV_AMOUNT = - LS_AR_HEAD-AMOUNT . "负数的时候是预收款
"并且 未到期金额 < 应收款金额 “表示存在逾期
IF LS_AR_HEAD-AMOUNT > 0 AND LS_AR_HEAD-AMOUNT > LS_AR_HEAD-SEGMENT .
IF LV_NBLOCK_IND IS INITIAL . "未解冻
LV_PRCNT = 100 - LS_AR_HEAD-PERCENT .
LV_PRCNT = LV_PRCNT && CNS_CHAR_% .
MESSAGE E002(ZSD_MSG001) WITH LV_PRCNT .
* ELSE. "客户有逾期
* UPDATE ZSDT0035 SET NBLOCK_IND = '' WHERE KUNNR = IS_LIKP-KUNNR .
ENDIF.
ENDIF.
ENDIF.
*-----------------------------------------------------------------------*
*--款到发货客户
*-----------------------------------------------------------------------*
IF LV_ZTERM = CNS_D001 .
CLEAR: R_AUART,R_AUART[] .
"免费订单
R_AUART(3) = 'IEQ' .
R_AUART-LOW = 'ZOR5' .
APPEND R_AUART .
R_AUART-LOW = 'ZRE5' .
APPEND R_AUART .
"寄售订单
R_AUART-LOW = 'ZOR2' .
APPEND R_AUART .
R_AUART-LOW = 'ZCG1' .
APPEND R_AUART .
R_AUART-LOW = 'ZCR2' .
APPEND R_AUART .
SELECT A~KUNAG,
A~VBELN,
A~VBTYP,
A~WAERK AS WAERS,
A~GBSTK ,
A~WBSTK ,
B~POSNR,
B~VGBEL,
B~VGPOS,
B~LFIMG,
B~SHKZG
FROM LIKP AS A INNER JOIN LIPS AS B ON A~VBELN = B~VBELN
WHERE A~KUNAG = @IS_LIKP-KUNAG
* AND A~WBSTK = @ZIF_BC_CONSTANTS=>GC_C "已发货过账
AND A~FKSTK <> @ZIF_BC_CONSTANTS=>GC_C "未开票
* OR A~GBSTK = @ZIF_BC_CONSTANTS=>GC_C )"当交货单未发货 GBSTK = A 当交货单发货过账或者POD GBSTK = B 当交货单开票后 GBSTK = C
INTO CORRESPONDING FIELDS OF TABLE @LT_LIKP .
IF SY-SUBRC EQ 0 .
SELECT A~* ,
B~KWMENG ,
B~KZWI1 ,
C~KURSK
FROM @LT_LIKP AS A INNER JOIN VBAP AS B ON A~VGBEL = B~VBELN AND A~VGPOS = B~POSNR
INNER JOIN VBAK AS D ON B~VBELN = D~VBELN
INNER JOIN VBKD AS C ON B~VBELN = C~VBELN
WHERE C~POSNR IS INITIAL
AND D~AUART NOT IN @R_AUART "排除订单
INTO CORRESPONDING FIELDS OF TABLE @LT_LIKP .
ENDIF.
LOOP AT LT_LIKP INTO DATA(LS_LIKP) WHERE KWMENG NE 0 .
IF LS_LIKP-SHKZG IS INITIAL .
LV_AMOUNT -= LS_LIKP-KZWI1 * LS_LIKP-LFIMG / LS_LIKP-KWMENG * LS_LIKP-KURSK .
ELSE .
LV_AMOUNT += LS_LIKP-KZWI1 * LS_LIKP-LFIMG / LS_LIKP-KWMENG * LS_LIKP-KURSK .
ENDIF.
ENDLOOP.
CLEAR: LT_LIPS .
APPEND LINES OF IT_LIPS TO LT_LIPS .
SELECT A~VGBEL ,
A~VGPOS ,
B~KWMENG,
B~KZWI1 ,
C~KURSK
FROM @LT_LIPS AS A INNER JOIN VBAP AS B ON A~VGBEL = B~VBELN AND A~VGPOS = B~POSNR
INNER JOIN VBKD AS C ON B~VBELN = C~VBELN
WHERE C~POSNR IS INITIAL
ORDER BY A~VGBEL,A~VGPOS
INTO TABLE @DATA(LT_VBAP_TMP) .
LOOP AT LT_LIPS INTO DATA(LS_LIPS).
READ TABLE LT_VBAP_TMP INTO DATA(LS_VBAP_TMP) WITH KEY VGBEL = LS_LIPS-VGBEL VGPOS = LS_LIPS-VGPOS BINARY SEARCH .
IF SY-SUBRC EQ 0 .
LV_AMOUNT -= LS_VBAP_TMP-KZWI1 * LS_LIPS-LFIMG / LS_VBAP_TMP-KWMENG * LS_VBAP_TMP-KURSK .
ENDIF.
ENDLOOP.
IF LV_AMOUNT < 0 AND LV_NBLOCK_IND IS INITIAL . "付款金额不足 并且未解冻
LV_PRCNT = ABS( LV_AMOUNT ) .
MESSAGE E004(ZSD_MSG001) WITH LV_PRCNT .
ENDIF.
ENDIF.
*----------------------------------------------------------------------*
*--"交货单保存成功 恢复客户冻结
*----------------------------------------------------------------------*
IF LV_NBLOCK_IND IS INITIAL .
UPDATE ZSDT0035 SET NBLOCK_IND = '' WHERE KUNNR = IS_LIKP-KUNNR .
ENDIF.
ENDFUNCTION.
取应收账龄报表IDCNAR中的未到期金额,与未到期金额加逾期金额(应收款)比较,若未到期金额小于应收款,则表示逾期