ABAP BAPI_ACC_DOCUMENT_POST 资产过账问题

本文讲述使用BAPI:BAPI_ACC_DOCUMENT_POST进行资产过账时遇到的三个问题,包括不能自动带出统驭科目、无资产号或负资产号报错、过账凭证号不能冲销。还给出了解决方式,如对记账码等进行增强,实现资产过账的演示代码等。

在使用BAPI:BAPI_ACC_DOCUMENT_POST进行资产过账的时候遇到了一些问题,过账的需求如下:
过账需求

遇到的问题主要有三个:
第一个问题:如上图中的行项目,第一行是固定的科目编码,第二行是根据内表中的不同资产号进行填充科目编码,在手工过账的时候,输入第一个行项目之后回车会自动带出一个统驭科目编号,然后输入第二个行项目就可以过账了,但是在BAPI中不能自动带出统驭科目;
第二个问题:对于资产过账,一定要有资产号和负资产号,否则过账的时候会报告“资产不属于公司xxxx的错误”。
第三个问题:当前两个问题解决了之后,成功过账,发现过账的凭证号不能冲销,对比手工和自己程序产生的凭证号,看起来的不同点,如下图所示:

对比不同点

但是这个只是表面上的不同,因为我到BSEG表中修改了对应的金额字段之后还是不能成功冲销,根本原因是因为货币。
只对以上载开发中遇到的问题,自己找到了一个解决方式,可能不是最好的,如果有大神有更好的方法,还望提醒。
说明: F-02对应的bapi是BAPI_ACC_DOCUMENT_POST,这个是最常用的产生凭证的bapi,但是在SAP系统中还有资产报废过账的标准事务代码和对应的bapi(BAPI_ASSET_RETIREMENT_POST),本文实现的是用F-02对应的BAPI进行资产过账。
注:在过账的时候一定要保证所有行项目的金额之和为0,手工过账的时候金额都是写的负数,但是BAPI中要写清楚是正还是负。
下面是实现步骤:
第一步:对于过账中的记账码,付款原因代码和事务类型等需要进行增强,增强的方式网上有不少,这里还是说明一下。
1.SE11创建一个结构,示例如图:
增强结构

其中项目编号必须有,下面的字段根据自己的需要添加。
2.SE19实现BADI增强
ACC_DOCUMENT 这个增强是用来将BAPI_ACC_DOCUMENT_POST参数表EXTENSION2传入系统表,如果没有增强点,则新建一个增强点:

创建增强点

需要注意的是要参考业务类型,这个一定要选对,不然执行BAPI的时候不会调用这个BADI,常用的是BKPFF,BKPF,如图:

业务类型参考

创建完成之后,找到change方法,这个方法用来完成字段的扩展,双击进入(可以查看ACC_DOCUMENT 的实现例子CL_EXM_IM_ACC_DOCUMENT 参考学习change方法的实现)我这里添加如下代码:

METHOD IF_EX_ACC_DOCUMENT~CHANGE.
  DATA: WA_EXTENSION   TYPE BAPIPAREX,
       EXT_VALUE(960) TYPE C,
       WA_ACCIT       TYPE ACCIT,
       L_REF          TYPE REF TO DATA.
  DATA: WA_ZEXTEN TYPE ZEXTEN.
  FIELD-SYMBOLS: <ACCIT> TYPE ACCIT.
  FIELD-SYMBOLS: <L_STRUC> TYPE ANY,
                 <L_FIELD> TYPE ANY.
  SORT C_EXTENSION2 BY STRUCTURE.
  LOOP AT C_EXTENSION2 INTO WA_EXTENSION
    WHERE STRUCTURE = 'ZEXTEN'. "对应于SE11创建的结构
    WA_ZEXTEN = WA_EXTENSION-VALUEPART1.
    READ TABLE C_ACCIT ASSIGNING <ACCIT> 
                WITH KEY POSNR = WA_ZEXTEN-ITEMNO_ACC.
    IF SY-SUBRC = 0.
      <ACCIT>-RSTGR = WA_ZEXTEN-RSTGR.
      <ACCIT>-BSCHL = WA_ZEXTEN-BSCHL.
      <ACCIT>-UMSKZ = WA_ZEXTEN-UMSKZ.
      <ACCIT>-ANBWA = WA_ZEXTEN-ANBWA.
      <ACCIT>-XNEGP = WA_ZEXTEN-XNEGP.
    ENDIF.
  ENDLOOP.
ENDMETHOD.

第二步:实现资产过账,这里直接给出演示代码:

FORM FRM_BAPI_DO_ACCDOCMENT CHANGING P_WS_COS LIKE WA_SHOW_COS.
  DATA: GD_DOCUMENTHEADER   LIKE BAPIACHE09,
        LT_ACCOUNTGL        LIKE TABLE OF BAPIACGL09 
                                    WITH HEADER LINE,
        LT_CURRENCYAMOUNT   LIKE TABLE OF BAPIACCR09 
                                    WITH HEADER LINE,
        LT_RETURN           LIKE TABLE OF BAPIRET2   
                                    WITH HEADER LINE.
  DATA: LW_EXTENSION TYPE BAPIEXTC,
        LT_EXTENSION TYPE STANDARD TABLE OF BAPIPAREX 
                                    WITH HEADER LINE.
  DATA: E_MONAT  LIKE BKPF-MONAT,
        E_GJAHR  LIKE BKPF-GJAHR.
  DATA: LD_GL_ACOUNT TYPE STRING.
  DATA: L_HEADTEXT TYPE STRING.   "抬头文本
  DATA: LD_ITEM TYPE I,
        LD_ITEM_TEMP TYPE I.
  DATA: E_SAKNR LIKE BSEG-SAKNR.
  DATA: LW_ZFIDOCEXT TYPE ZEXTEN."ZFIDOCEXT.
  DATA: GL_MESSAGE TYPE STRING.

  REFRESH : LT_ACCOUNTGL[],LT_CURRENCYAMOUNT[],LT_EXTENSION[].
  REFRESH : LT_RETURN[].
  CLEAR : GD_DOCUMENTHEADER,LW_ZFIDOCEXT.

  LD_ITEM = 1.
  E_GJAHR = SY-DATUM+0(4).
  E_MONAT = SY-DATUM+4(2).
  L_HEADTEXT = '模具财务报废凭证'.

  GD_DOCUMENTHEADER-USERNAME   = SY-UNAME.   "录入用户(必输)
  GD_DOCUMENTHEADER-COMP_CODE  = P_BUKRS.    "公司代码(必输)
  GD_DOCUMENTHEADER-DOC_DATE   = SY-DATUM.   "凭证日期(必输)
  GD_DOCUMENTHEADER-PSTNG_DATE = P_WS_COS-ZCWBFD. "过账日期(必输)
  GD_DOCUMENTHEADER-FIS_PERIOD = E_MONAT.    "过账期间(必输)
  GD_DOCUMENTHEADER-DOC_TYPE   = 'SA'.       "凭证类型(必输)
  GD_DOCUMENTHEADER-FISC_YEAR  = E_GJAHR.    "会计年度
*  GD_DOCUMENTHEADER-BUS_ACT    = 'RMWE'.    "业务事务
*  GD_DOCUMENTHEADER-OBJ_TYPE   = 'BKPFF'.   "参考交易

  CONCATENATE '模具报废' SY-DATUM INTO LD_GL_ACOUNT.
  LT_ACCOUNTGL-ITEMNO_ACC = LD_ITEM.        "会计凭证行项目编号
  LT_ACCOUNTGL-GL_ACCOUNT = '6602010100'.   "总分类帐帐目
  LT_ACCOUNTGL-COSTCENTER = P_WS_COS-KOSTL. "成本中心
*  LT_ACCOUNTGL-BUS_AREA   = P_WS_COS-GSBER. "业务范围
  LT_ACCOUNTGL-ITEM_TEXT  = LD_GL_ACOUNT.   "项目文本
  LT_ACCOUNTGL-ALLOC_NMBR = LD_GL_ACOUNT.   "分配
  APPEND LT_ACCOUNTGL.
  CLEAR  LT_ACCOUNTGL.

  "添加金额
  LT_CURRENCYAMOUNT-ITEMNO_ACC = LD_ITEM.
  LT_CURRENCYAMOUNT-AMT_DOCCUR = P_WS_COS-ZMOJZ.  "凭证货币金额
  LT_CURRENCYAMOUNT-CURR_TYPE  = '10'.
  LT_CURRENCYAMOUNT-CURRENCY   = 'CNY'.
  APPEND LT_CURRENCYAMOUNT.
  CLEAR  LT_CURRENCYAMOUNT.

  "添加金额(**重复添加金额就是解决不能冲销的问题**)
  LT_CURRENCYAMOUNT-ITEMNO_ACC = LD_ITEM.
  LT_CURRENCYAMOUNT-AMT_DOCCUR = P_WS_COS-ZMOJZ.  "凭证货币金额
  LT_CURRENCYAMOUNT-CURR_TYPE  = '00'.
  LT_CURRENCYAMOUNT-CURRENCY   = 'CNY'.
  APPEND LT_CURRENCYAMOUNT.
  CLEAR  LT_CURRENCYAMOUNT.

  "添加记账码
  LW_ZFIDOCEXT-ITEMNO_ACC = LD_ITEM.  "Item No
  LW_ZFIDOCEXT-BSCHL      = '40'. "记帐码

*是否创建预制凭证,否则凭证直接过账
  LT_EXTENSION-STRUCTURE =  'ZEXTEN'.
  LT_EXTENSION-VALUEPART1 = LW_ZFIDOCEXT.
  APPEND LT_EXTENSION.
  CLEAR : LT_EXTENSION,LW_ZFIDOCEXT.

  "记账码75
  LD_ITEM = LD_ITEM + 1.
  LT_ACCOUNTGL-ITEMNO_ACC = LD_ITEM.
  LT_ACCOUNTGL-ASSET_NO   = P_WS_COS-ANLN1. "主资产号
  LT_ACCOUNTGL-ACCT_TYPE  = 'A'.            "科目类型
  LT_ACCOUNTGL-SUB_NUMBER = P_WS_COS-ANLN2. "次资产号
  LT_ACCOUNTGL-COSTCENTER = P_WS_COS-KOSTL. "成本中心
  LT_ACCOUNTGL-ALLOC_NMBR = LD_GL_ACOUNT.   "分配
  LT_ACCOUNTGL-ITEM_TEXT  = LD_GL_ACOUNT.     "文本
*  LT_ACCOUNTGL-COMP_CODE  = P_BUKRS.

  APPEND LT_ACCOUNTGL.
  CLEAR  LT_ACCOUNTGL.

  "添加金额
  LT_CURRENCYAMOUNT-ITEMNO_ACC = LD_ITEM.
  LT_CURRENCYAMOUNT-AMT_DOCCUR = P_WS_COS-ZMOJZ * ( -1 ).  "凭证货币金额
  LT_CURRENCYAMOUNT-CURR_TYPE  = '10'.
  LT_CURRENCYAMOUNT-CURRENCY   = 'CNY'.
  APPEND LT_CURRENCYAMOUNT.
  CLEAR  LT_CURRENCYAMOUNT.

  "添加金额
  LT_CURRENCYAMOUNT-ITEMNO_ACC = LD_ITEM.
  LT_CURRENCYAMOUNT-AMT_DOCCUR = P_WS_COS-ZMOJZ * ( -1 ).  "凭证货币金额
  LT_CURRENCYAMOUNT-CURR_TYPE  = '00'.
  LT_CURRENCYAMOUNT-CURRENCY   = 'CNY'.
  APPEND LT_CURRENCYAMOUNT.
  CLEAR  LT_CURRENCYAMOUNT.

  "记账码
  LW_ZFIDOCEXT-ITEMNO_ACC = LD_ITEM.  "Item No
  LW_ZFIDOCEXT-BSCHL      = '75'. "记帐码
  LW_ZFIDOCEXT-ANBWA      = '100'.

*是否创建预制凭证,否则凭证直接过账
  LT_EXTENSION-STRUCTURE =  'ZEXTEN'.
  LT_EXTENSION-VALUEPART1 = LW_ZFIDOCEXT.
  APPEND LT_EXTENSION.
  CLEAR : LT_EXTENSION,LW_ZFIDOCEXT.

  CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
  EXPORTING
    DOCUMENTHEADER = GD_DOCUMENTHEADER
  TABLES
    ACCOUNTGL      = LT_ACCOUNTGL
    CURRENCYAMOUNT = LT_CURRENCYAMOUNT
    RETURN         = LT_RETURN
    EXTENSION2     = LT_EXTENSION.

  READ TABLE LT_RETURN WITH KEY TYPE = 'E'.
*  BREAK-POINT.
  IF SY-SUBRC <> 0.
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
    EXPORTING
      WAIT   = 'X'
    IMPORTING
      RETURN = LT_RETURN.
    READ TABLE LT_RETURN INDEX 1.
    IF SY-SUBRC = 0.
      "报废凭证
      P_WS_COS-ZCWBFI = LT_RETURN-MESSAGE_V2+0(10).
      "清空冲销凭证
      CLEAR : P_WS_COS-ZCXBFI,P_WS_COS-ZCXBFD.
    ENDIF.
  ELSE.
    CLEAR GL_MESSAGE.
    LOOP AT LT_RETURN WHERE TYPE = 'E'.
      IF SY-TABIX = 1.
        CONTINUE.
      ENDIF.
      CONCATENATE GL_MESSAGE '|' LT_RETURN-MESSAGE 
                                      INTO GL_MESSAGE.
    ENDLOOP.
    CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'
    IMPORTING
      RETURN = LT_RETURN.
    MESSAGE E001(Z001) WITH GL_MESSAGE.
  ENDIF.
ENDFORM.                    " FRM_BAPI_DO_ACCDOCMENT

可以发现代码中重复添加了金额,对应的“CURR_TYPE”分别是“00”和“10”,这样产生的凭证号就可以和手工产生的一样正常冲销成功了。
至于冲销就使用BDC,很简单就可以冲销了,这里就不多介绍了。

<think>我们正在讨论如何使用 `BAPI_ACC_DOCUMENT_POST` 进行清账动作。 根据之前的引用和知识,我们知道: - 引用[1]提到:客户收款并清账没有专用BAPI,通常结合多个BAPI实现。 - 引用[2]中列出了`BAPI_ACC_DOCUMENT_POST`,并提到它用于采购付款过帐等。 - 引用[3]详细说明了`BAPI_ACC_DOCUMENT_POST`,包括它在总账、应收应付等场景的应用,并提到常见错误。 特别地,引用[3]中虽然没有直接说清账,但提到了该BAPI可以处理应收账款、应付账款等业务场景。而清账动作(如客户清账F-40、供应商清账F-44)正是这些模块的常见操作。 因此,我们可以使用`BAPI_ACC_DOCUMENT_POST`来模拟清账过程。在会计凭证中,清账操作需要指定特殊的过账码(Posting Key)和清账标识(Clearing Indicator)。 步骤: 1. 理解清账凭证的结构:清账凭证通常包含两个部分: a. 原未清项(如发票)的冲销行(使用原发票的过账码,例如客户发票是01,清账时用01但金额为负或正以冲销) b. 收款或付款行(例如收款用15,付款用25等) 但实际上,在清账凭证中,我们并不需要真正冲销原凭证,而是通过清账标识将原未清项标记为已清。 2. 在SAP中,清账凭证过账码规则: - 客户清账:原发票行项目(借方)的过账码是01,清账时对应的清账行项目过账码也是01(但金额为负),收款行项目过账码为15(贷方)。 - 但是,使用`BAPI_ACC_DOCUMENT_POST`时,我们可以通过设置清账字段(CLEARING)来实现自动清账。 3. 关键参数设置: - 在凭证行项目(ITEM参数内表)中,对于需要被清账的未清项,设置: `CLEAR_KEY` = 'KSR' (对于客户清账)或 'PSR' (对于供应商清账) - 同时,必须指定该未清项的凭证编号(REF_DOC_NO)和凭证会计年度(REF_DOC_YEAR)或者凭证行项目号(REF_DOC_ITEM)等,以便系统识别要清的是哪个未清项。 4. 另外,对于收款行(即清账凭证中的现金或银行行项目),则不需要设置清账标识,而是正常的过账码和科目。 5. 注意:清账凭证必须是平衡的(借贷相等)。 具体步骤: 步骤1:准备凭证抬头数据(在参数`DOCUMENTHEADER`中) - 设置公司代码(COMP_CODE) - 凭证日期(DOC_DATE) - 过账日期(PSTNG_DATE) - 凭证类型(DOC_TYPE),例如收款凭证使用“DZ”(客户收款)或“KZ”(供应商付款) 步骤2:准备行项目数据(在参数`ACCOUNTGL`, `ACCOUNTRECEIVABLE`等表中,但统一用`ITEM`内表) - 实际上,`BAPI_ACC_DOCUMENT_POST`的行项目是通过一个统一的内表`ITEM`来传递的,其中每个行项目需要指定: - 行项目号(ITEMNO_ACC) - 科目(GL_ACCOUNT, CUSTOMER, VENDOR等,取决于行项目类型) - 金额(AMT_DOCCUR,凭证货币金额) - 过账码(PSTNG_KEY) - 清账标识(CLEAR_KEY)-> 对于需要被清账的行项目设置 - 参考凭证(REF_DOC_NO, REF_DOC_YEAR, REF_DOC_ITEM)-> 指向要清账的未清项凭证 注意:通常,清账凭证有两行(或更多行): 行1:收款行(贷方)-> 过账码15(客户收款)或25(供应商付款),科目为银行或现金科目,不需要清账标识。 行2:清账行(借方)-> 过账码01(客户发票)或11(供应商发票),但是这里我们要清掉之前的未清项,所以设置: CUSTOMER = 客户编号 PSTNG_KEY = '01' (注意:原发票的过账码就是01,这里清账时也是用01,但金额为负?实际上,清账凭证的借贷方向由金额正负和过账码共同决定,但通常我们按正数填,系统自动处理方向) 同时,设置CLEAR_KEY = 'KSR',并指定REF_DOC_NO(原发票凭证号)和REF_DOC_YEAR(原发票年度)。 但是,注意:在清账凭证中,我们并不需要自己填写金额为负。系统会根据清账标识自动调整方向。实际上,我们只需要指定要清账的金额(通常等于原发票金额)即可。 然而,还有一种做法是:收款行(贷方)金额为正,清账行(借方)金额为负(这样凭证平衡)。但根据SAP规则,过账码已经决定了借贷方向。例如: - 过账码01(客户借方)通常用于借方,所以金额为正表示借方,负表示贷方。 - 过账码15(客户贷方)用于贷方,金额为正表示贷方。 因此,在清账凭证中: 收款行:过账码15,金额为正(贷方) 清账行:过账码01,金额为负(相当于贷方,冲销原发票的借方)?但这样凭证就平衡了。 但是,使用清账标识后,我们不必这样做。因为设置清账标识后,系统会自动调整金额的符号。所以,我们只需按照以下方式: 行1(收款行): ITEMNO_ACC = '1' PSTNG_KEY = '15' (客户收款贷方) ACCOUNT = 银行科目 (或通过GL_ACCOUNT指定总账科目) AMT_DOCCUR = 100 (贷方,所以系统自动处理为正数表示贷方) 行2(清账行): ITEMNO_ACC = '2' PSTNG_KEY = '01' (客户发票的过账码,但这里用于清账) CUSTOMER = '12345678' (客户编号) CLEAR_KEY = 'KSR' (客户清账标识) REF_DOC_NO = '1900000010' (原发票凭证号) REF_DOC_YEAR = '2023' (原发票年度) // 注意:这里不需要填写金额,因为系统会根据原未清项的金额自动清账。但也可以指定金额(如果部分清账)?然而,根据SAP,清账行通常不直接填金额,而是由系统根据清账规则匹配。 然而,实际上,我们必须在清账行填写金额,而且这个金额应该是负的(因为原发票是借方,现在要冲销贷方)。但这样就需要自己计算。 但是,更常见的做法是:我们只需要在收款行指定金额,清账行只需要指定清账标识和参考凭证,系统会自动将收款行的金额分配到清账行(即自动匹配未清项)。但使用BAPI时,我们必须明确指定每一行的金额。 这里有一个关键点:在清账凭证中,清账行的金额应该是多少?通常,清账金额等于原未清项金额(全额清账)或部分金额(部分清账)。所以,我们需要在调用BAPI前就知道要清多少。 因此,有两种方式: 方式一:在清账行明确指定金额。 收款行:贷方100,清账行:借方-100(但过账码01表示借方,所以填负数相当于贷方,这样不行,因为过账码和金额符号共同决定借贷方向) 实际上,过账码01要求金额为正(表示借方),但我们想要冲销(贷方)则应该用负数?但这样会导致过账码01和负数金额组合成为贷方。 方式二:利用清账标识,我们只指定收款行的金额,清账行的金额由系统根据参考凭证自动带出?但BAPI要求我们指定金额。 查阅SAP标准做法:在清账凭证中,清账行(即未清项行)的金额应该为0!然后通过一个特殊字段(例如,在`ACCOUNTWT`表中指定税?)或者通过分配字段?其实不是。 实际上,我们通过设置清账标识后,清账行的金额应该填多少呢?答案是:填0。然后系统会根据参考凭证自动清掉整个未清项。但是,如果部分清账,需要填写部分金额(正数,方向由过账码决定)。 然而,根据SAP标准文档: 在清账行(即对未清项进行清账的行),需要设置: AMT_DOCCUR = 0 (表示全额清账) 如果需要部分清账,则填写部分金额(正数,因为过账码01表示借方,所以如果你要部分清账,比如原发票100,现在只清80,那么这里填80?但这样就是借方80,而收款行是贷方80?) 所以,实际上: 全额清账:清账行的金额填0,系统自动用未清项的余额清账。 部分清账:清账行的金额填部分金额(正数,表示要清的金额,方向由过账码决定)。 但是,注意:在清账凭证中,清账行的过账码决定了该行的账户类型(客户/供应商/总账)和借贷方向。对于客户清账,原发票是借方(01),清账时我们实际上是贷方,但为什么用01?因为清账行也是同一个客户,所以用01(借方)但金额为正表示增加借方?不对。 这里有一个重要的概念:清账凭证中的清账行并不是实际产生新的借贷,而是将原未清项标记为已清。所以,在清账行,我们并不需要真正记录借贷,而是通过清账标识告诉系统:这个行项目是用来清哪个未清项的。因此,该行的金额就是我们要清的金额,方向由过账码和金额符号决定,但必须与未清项的方向相反(这样才能冲销)。 具体到客户清账: 原发票(借方)100,用01(借方)过账码,金额100(正)。 现在清账,我们要冲销(贷方)100,那么清账行应该用01(借方)过账码,但金额填-100吗?这样系统会认为你又在做一笔贷方。但实际上,清账凭证中,清账行我们通常用01(借方)过账码,金额填100(正)?这岂不是又增加一笔借方? 所以,正确做法是:清账行使用贷方过账码15?不行,因为15是用于银行贷方的。 实际上,在清账凭证中,清账行(即客户行)的过账码还是01(客户借方),但金额填写负数(-100)表示贷方。这样,凭证行项目如下: 行1:银行贷方100(过账码15,金额100) 行2:客户贷方100(过账码01,金额-100)-> 这样凭证平衡。 但是,系统如何知道行2是用来清某个未清项的呢?通过REF_DOC_NO和CLEAR_KEY='KSR'。这样系统就会将这笔贷方金额与原发票的未清项(借方100)进行清账。 所以,在调用BAPI时,清账行需要: 过账码01(客户借方),金额-100(表示贷方) 设置CLEAR_KEY='KSR' 设置REF_DOC_NO、REF_DOC_YEAR等。 但是,这样操作在凭证上会显示客户借方-100,即贷方100,与收款行的贷方100平衡。 然而,这种方式需要开发人员自己计算金额和方向,容易出错。 另一种推荐方式:使用清账行的特殊字段`CLEAR_KEY`,并设置金额为0(表示全额清账)或部分金额(正数,表示要清账的金额,方向由过账码决定)?但是,如果设置金额为0,系统会自动用未清项的余额清账,那么就不需要填写负数了。 根据SAP标准,在清账凭证中,清账行(即针对未清项的行)的金额应该填写正数(表示要清账的金额),方向由过账码决定: 原发票是借方(01),那么清账时,我们想要冲销(贷方)就需要用贷方过账码吗?不对,客户账户的贷方过账码是15?但是15是用于银行贷方的,不是用于客户贷方的。 实际上,对于同一个客户,在清账凭证中,我们使用相同的过账码(01)来代表客户行,但是: 收款时,客户账户应该减少(贷方),所以金额应该为负(在过账码01下,负金额代表贷方)。 或者,我们也可以使用贷方过账码(15)来代表客户账户的贷方,但是注意:过账码15通常用于总账科目的贷方(比如银行科目),而不是客户科目。客户科目的贷方过账码是11?不对。 在SAP中,客户行项目的过账码: 01:客户借方(发票) 11:客户贷方(收款) 15:总账科目贷方(通常用于银行) 25:总账科目借方(通常用于银行付款) 所以,在清账凭证中,我们不应该用01(客户借方)来清账,而应该用11(客户贷方)来表示收款(客户账户减少)。同时,我们也不需要设置负金额,而是正金额(因为11表示贷方,正数就是贷方)。 因此,正确的清账凭证应该是: 行1:银行科目(贷方)-> 过账码15,金额100(贷方) 行2:客户科目(贷方)-> 过账码11,金额100(贷方)?不行,这样凭证就不平衡了(贷方200,没有借方)。 更正:应该是: 行1:银行科目(贷方) -> 过账码15,金额100(贷方) 行2:客户科目(借方) -> 过账码01,金额-100(贷方)?或者 行1:银行科目(贷方) -> 过账码15,金额100(贷方) 行2:客户科目(贷方) -> 过账码11,金额100(贷方)-> 这样凭证不平衡(贷方200,借方0)-> 错误。 实际上,客户账户在收款时应该是减少(贷方),所以应该是贷方100,与银行贷方100平衡?不对,这样两个贷方,没有借方。 所以,正确的做法是: 行1:银行科目(贷方100) -> 过账码15(总账贷方),科目=银行科目,金额=100(贷方) 行2:客户科目(借方-100)-> 但借方负数是贷方100,所以相当于贷方100?那么凭证平衡(贷方200)?不对。 我们必须明确:凭证必须借贷平衡。所以,应该是: 行1:银行科目(贷方100) -> 过账码15(总账贷方),金额100(贷方) 行2:客户科目(借方-100)-> 过账码01(客户借方),金额-100(即贷方100)-> 这样,行2就是贷方100,那么整个凭证贷方200?没有借方? 这里,行2(客户行)的过账码01(借方)加上负金额,实际效果就是贷方。所以,整个凭证: 银行贷方100 + 客户贷方100 = 贷方200,没有借方。不平衡。 正确的凭证分录应该是: 借:银行存款 100 (银行科目借方) 贷:应收账款 100 (客户科目贷方) 但是在SAP中,银行收款时,银行存款增加(借方),应收账款减少(贷方)。 因此,在凭证中: 行1:银行存款科目(借方100) -> 使用过账码40(总账科目借方)?但通常银行科目是总账科目,过账码40(总账借方)或50(总账贷方)? 行2:应收账款科目(贷方100) -> 使用过账码11(客户贷方) 所以,正确的凭证行项目: 行1:银行存款增加(借方) ITEMNO_ACC = '1' ACCOUNT = 银行存款科目(总账科目) PSTNG_KEY = '40' (总账借方) AMT_DOCCUR = 100 (借方) 行2:应收账款减少(贷方) ITEMNO_ACC = '2' CUSTOMER = '12345678' (客户编号) PSTNG_KEY = '11' (客户贷方) AMT_DOCCUR = 100 (贷方) 同时,对于行2,我们要清掉该客户的某个未清项,所以设置: CLEAR_KEY = 'KSR' REF_DOC_NO = '原发票凭证号' REF_DOC_YEAR = '原发票年度' 这样,凭证平衡,而且系统会根据清账标识和参考凭证,将原发票的未清项(借方)与这笔贷方100进行清账。 结论: 使用`BAPI_ACC_DOCUMENT_POST`进行客户清账时,需要准备两行: 行1:银行存款(总账科目)借方,过账码40,金额100(正数) 行2:客户贷方,过账码11,金额100(正数),并设置清账标识(CLEAR_KEY='KSR')和参考凭证信息。 部分清账:如果部分清账,则行2的金额小于原发票金额(比如80),那么系统会将该未清项部分清账(剩余20仍为未清)。 因此,在ABAP代码中,我们需要构建如下内表: DATA: lt_item TYPE TABLE OF bapiaccit, ls_item TYPE bapiaccit. * 行1:银行存款 ls_item-itemno_acc = '1'. ls_item-gl_account = '银行存款科目编号'. " 例如10010100 ls_item-pstng_key = '40'. " 总账借方 ls_item-amt_doccurn = 100. " 借方金额(正数) ls_item-currency = 'USD'. " 币种 APPEND ls_item TO lt_item. CLEAR ls_item. * 行2:客户贷方,并清账 ls_item-itemno_acc = '2'. ls_item-customer = '12345678'. " 客户编号 ls_item-pstng_key = '11'. " 客户贷方 ls_item-amt_doccurn = 100. " 贷方金额(正数) ls_item-currency = 'USD'. ls_item-clear_key = 'KSR'. " 客户清账标识 ls_item-ref_doc_no = '原发票凭证号'. " 例如'1900000010' ls_item-ref_doc_year = '原发票年度'. " 例如2024 " 如果知道行项目号,可以指定:ls_item-ref_doc_item = '原发票行项目号' APPEND ls_item TO lt_item. * 凭证抬头 DATA: ls_header TYPE bapiache09. ls_header-obj_type = 'BKPFF'. " 凭证类型(可选) ls_header-username = sy-uname. ls_header-comp_code = '公司代码'. ls_header-doc_date = sy-datum. ls_header-pstng_date = sy-datum. ls_header-doc_type = 'DZ'. " 收款凭证 * 调用BAPI DATA: lt_return TYPE TABLE OF bapiret2. CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST' EXPORTING documentheader = ls_header TABLES accountgl = ... " 注意:这个参数用于总账行,但我们上面的行1是总账行(银行存款),行2是客户行(应收账款) accountreceivable = ... " 客户行项目 return = lt_return. 但是,注意:`BAPI_ACC_DOCUMENT_POST`的行项目参数有多个,包括: ACCOUNTGL :总账科目行项目(如银行存款) ACCOUNTRECEIVABLE:客户行项目 ACCOUNTPAYABLE:供应商行项目 ... 所以,我们需要将行1(总账科目)放在ACCOUNTGL表中,行2(客户)放在ACCOUNTRECEIVABLE表中。 或者,我们可以使用统一的内表`ACCPRINCIPLE`(但该BAPI中没有这个参数),所以我们必须分开传递。 因此,修改: DATA: lt_accountgl TYPE TABLE OF bapiacgl09, ls_accountgl TYPE bapiacgl09. DATA: lt_receivable TYPE TABLE OF bapiacar09, ls_receivable TYPE bapiacar09. * 行1:总账科目行 ls_accountgl-itemno_acc = '1'. ls_accountgl-gl_account = '银行存款科目'. ls_accountgl-pstng_key = '40'. ls_accountgl-amt_doccurn = 100. ls_accountgl-currency = 'USD'. APPEND ls_accountgl TO lt_accountgl. * 行2:客户行 ls_receivable-itemno_acc = '2'. ls_receivable-customer = '12345678'. ls_receivable-pstng_key = '11'. ls_receivable-amt_doccurn = 100. ls_receivable-currency = 'USD'. ls_receivable-clear_key = 'KSR'. ls_receivable-ref_doc_no = '原发票凭证号'. ls_receivable-ref_doc_year = '2024'. APPEND ls_receivable TO lt_receivable. * 调用BAPI CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST' EXPORTING documentheader = ls_header TABLES accountgl = lt_accountgl accountreceivable = lt_receivable return = lt_return. 然后,检查lt_return中的消息。如果有错误,调用`BAPI_TRANSACTION_ROLLBACK`。如果没有错误,调用`BAPI_TRANSACTION_COMMIT`。 注意事项: - 必须指定正确的过账码(40和11)和科目。 - 清账行(客户行)必须提供参考凭证(原发票凭证号及年度)以及清账标识。 - 金额币种必须一致。 另外,引用[3]中提到的常见错误需要避免,例如科目主数据不存在、公司代码未分配会计年度等。 因此,总结步骤: 1. 准备凭证抬头(公司代码、日期、凭证类型等) 2. 准备行项目: 收款行:总账科目(银行存款)借方,过账码40,金额为正。 清账行:客户贷方,过账码11,金额为正,设置清账标识和参考凭证。 3. 分别放入ACCOUNTGL和ACCOUNTRECEIVABLE表中。 4. 调用BAPI,并检查返回消息。 注意:以上是基于全额清账。部分清账时,清账行的金额填写实际要清账的金额(小于原未清项金额)即可。 供应商清账(付款)类似,但过账码不同: 银行行:贷方(过账码50) 供应商行:借方(过账码31),清账标识为'PSR' 供应商付款分录: 借:应付账款(供应商行,过账码31,金额正数表示借方) 贷:银行存款(总账行,过账码50,金额正数表示贷方) 同时,供应商行设置CLEAR_KEY='PSR'以及参考凭证信息。 以上。 </think>### 使用 `BAPI_ACC_DOCUMENT_POST` 实现清账操作的方法 在 SAP 中,`BAPI_ACC_DOCUMENT_POST` 是通用的会计凭证过账 BAPI,可通过配置行项目的 **清账标识** 和 **参考凭证** 实现客户/供应商清账(如 F-40、F-44 事务码功能)。以下是详细步骤和关键参数配置: --- ### 一、清账凭证的核心逻辑 1. **清账凭证结构** 清账凭证需包含两类行项目: - **结算行**:收付款行(如银行科目),正常过账。 - **清账行**:针对未清项的行,需设置清账标识 `CLEAR_KEY` 和参考凭证号,系统自动匹配原未清项[^1][^3]。 2. **借贷方向规则** | 业务场景 | 结算行过账码 | 清账行过账码 | 清账标识 | |----------------|--------------|--------------|----------| | **客户收款清账** | 40(银行借方) | 11(客户贷方) | `KSR` | | **供应商付款清账** | 50(银行贷方) | 31(供应商借方) | `PSR` | --- ### 二、关键参数配置步骤 #### 1. 凭证抬头(`DOCUMENTHEADER`) ```abap DATA: ls_header TYPE bapiache09. ls_header-obj_type = 'BKPFF'. " 业务对象类型 ls_header-username = sy-uname. " 用户名 ls_header-comp_code = '1000'. " 公司代码 ls_header-doc_date = sy-datum. " 凭证日期 ls_header-pstng_date = sy-datum. " 过账日期 ls_header-doc_type = 'DZ'. " 凭证类型:客户收款 ls_header-ref_doc_no = 'REF_001'. " 参考凭证号(可选) ``` #### 2. 行项目配置(分结算行和清账行) ```abap " 1. 结算行(银行收款) DATA: ls_item_gl TYPE bapiacgl09. ls_item_gl-itemno_acc = '1'. " 行号 ls_item_gl-gl_account = '10010100'. " 银行科目 ls_item_gl-pstng_key = '40'. " 40: 总账借方 ls_item_gl-amt_doccurn = 100. " 金额 $100$(借方) ls_item_gl-currency = 'USD'. " 货币 " 2. 清账行(客户贷方) DATA: ls_item_ar TYPE bapiacar09. ls_item_ar-itemno_acc = '2'. " 行号 ls_item_ar-customer = '000012345'. " 客户编号 ls_item_ar-pstng_key = '11'. " 11: 客户贷方 ls_item_ar-amt_doccurn = 100. " 金额 $100$(贷方) ls_item_ar-currency = 'USD'. ls_item_ar-clear_key = 'KSR'. " 客户清账标识 ls_item_ar-ref_doc_no = '1900000010'. " 原发票凭证号 ls_item_ar-ref_doc_year = '2024'. " 原发票年度 ``` #### 3. 调用 BAPI ```abap DATA: lt_acc_gl TYPE TABLE OF bapiacgl09, lt_acc_ar TYPE TABLE OF bapiacar09, lt_return TYPE TABLE OF bapiret2. APPEND ls_item_gl TO lt_acc_gl. APPEND ls_item_ar TO lt_acc_ar. CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST' EXPORTING documentheader = ls_header TABLES accountgl = lt_acc_gl " 总账行项目 accountreceivable = lt_acc_ar " 客户行项目 return = lt_return. " 错误处理 READ TABLE lt_return WITH KEY type = 'E'. IF sy-subrc = 0. CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'. ELSE. CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = abap_true. ENDIF. ``` --- ### 三、注意事项 1. **必填字段** - 清账行必须包含 `CLEAR_KEY`(`KSR`/`PSR`)、`REF_DOC_NO`(原凭证号)、`REF_DOC_YEAR`(原凭证年度)[^3]。 - 结算行与清账行金额必须相等(借贷平衡)。 2. **常见错误排查** | 错误代码 | 原因 | 解决方案 | |----------|---------------------|------------------------------| | F5 700 | 科目不存在 | FS00 检查科目主数据 | | F5 505 | 公司代码未配置会计年度 | OBH2 配置会计年度变式 | | F5 230 | 无效货币 | 维护货币代码表 TCURV | 3. **部分清账** 如需部分清账,调整清账行金额(例如 `$80$`),系统自动将剩余金额 $20$ 保留为未清项。 --- ### 四、完整示例场景 **场景**:客户 `K-1001` 的发票 `1900000010`(金额 $100$)通过银行收款清账。 ```abap " 凭证抬头 ls_header-comp_code = '1000'. ls_header-doc_type = 'DZ'. " 客户收款凭证类型 " 银行行(结算行) ls_item_gl-itemno_acc = '1'. ls_item_gl-gl_account = '10010100'. " 银行存款科目 ls_item_gl-pstng_key = '40'. " 总账借方 ls_item_gl-amt_doccurn = 100. " $100$ ls_item_gl-currency = 'USD'. " 客户行(清账行) ls_item_ar-itemno_acc = '2'. ls_item_ar-customer = 'K-1001'. " 客户编号 ls_item_ar-pstng_key = '11'. " 客户贷方 ls_item_ar-amt_doccurn = 100. " $100$ ls_item_ar-clear_key = 'KSR'. ls_item_ar-ref_doc_no = '1900000010'. ls_item_ar-ref_doc_year = '2024'. ``` > 执行后生成凭证:银行借方 $100$ + 客户贷方 $100$,并清除原发票未清项[^1][^3]。 --- ### 五、扩展建议 - **预校验**:调用 `BAPI_ACC_DOCUMENT_CHECK` 预先校验凭证数据。 - **批量处理**:通过内表循环实现多凭证批量清账。 - **增强点**:在清账行扩展字段(如分配字段 `ALLOC_NMBR`)传递业务自定义参数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值