Fw:BAPI_ACC_DOCUMENT_POST相关增强的实现

文章转自 http://blog.163.com/way_lich/blog/static/26631112012010104213569/

调用BAPI_ACC_DOCUMENT_POST的时候有的参数(如记账码、我们自己增强的现金流量码等)在ACCOUNTGL,ACCOUNTRECEIVABLE,ACCOUNTPAYABLE等参数中都没有对应的字段传入,该怎么办呢?

这个BAPI的TABLES参数里面不是有一个EXTENSION2么~

Step1:创建Badi

tcode:SE19

此处有2种方式来创建增强,“Classic BADI”或“New BADI”

创建Classic Badi名称:ACC_DOCUMENT

或创建New Badi名称:BADI_ACC_DOCUMENT

此处注意:如果首先创建Classic Badi,随后保存的时候,系统会提示必须将Classic Badi迁移到New Badi,具体方式参见http://blog.csdn.net/longgerr/archive/2009/09/01/4505877.aspx后面的部分

这篇文章里以创建Classic Badi为例。

命名为Z_MY_ACC_DOCUMENT

Step2:增加一个Filter

新增一条BKPFF的Filter

Step3:保存

如果保存时出现了下面这个消息,说明你必须将你做的Classic Badi迁移到New Badi。

此时可以选择已有的或创建新的Badi Enhancement Implementation。我们选择创建新的。

创建好之后,系统会提示消息。

Step4:删除原始Classic Badi

回到SE19。

如上面红字链接的文章里面所说,如果进行了迁移,则在双击我们新建的New Badi的时候会报出消息:

所以我们删除我们之前创建的Z_MY_ACC_DOCUMENT,才能保证这个增强能够被正常调用。

删除Classic Badi时,系统首先提示:

这个选择Yes

随后系统又提示:

这个提示的意思是询问,是否删除从这个Classic Badi迁移过去的New Badi。显然要保留,这个选择No

Step5:编辑代码

在New Badi里面显示Z_MY_ACC_DOCUMENT,此时将不会报出需要删除Classic Badi的警告了。

双击CHANGE方法即可进入编辑。

代码例子:

[c-sharp] view plain copy print ?
  1. METHOD IF_EX_ACC_DOCUMENT~CHANGE. 
  2.   DATA: WA_EXTENSION TYPE BAPIPAREX, 
  3.         ZEXT_DATA    TYPE ZKS_OA_ACC_EXT. 
  4.  
  5.   FIELD-SYMBOLS: TYPE ACCIT. 
  6.   IF C_EXTENSION2[] IS NOT INITIAL. 
  7.     LOOP AT C_EXTENSION2 INTO WA_EXTENSION 
  8.                          WHERE STRUCTURE = 'ZKS_OA_ACC_EXT'
  9.       ZEXT_DATA = WA_EXTENSION-VALUEPART1. 
  10.       READ TABLE C_ACCIT ASSIGNING WITH KEY POSNR = ZEXT_DATA-POSNR. 
  11.       IF SY-SUBRC = 0. 
  12.         -ABPER = ZEXT_DATA-ABPER. 
  13.         -ZZCASHFLOW = ZEXT_DATA-ZZCASHFLOW. 
  14.         -BSCHL = ZEXT_DATA-BSCHL. 
  15.         -XREF1_HD = ZEXT_DATA-XREF1_HD. 
  16.       ENDIF. 
  17.     ENDLOOP. 
  18.   ENDIF. 
  19. ENDMETHOD. 

METHOD IF_EX_ACC_DOCUMENT~CHANGE. DATA: WA_EXTENSION TYPE BAPIPAREX, ZEXT_DATA TYPE ZKS_OA_ACC_EXT. FIELD-SYMBOLS: TYPE ACCIT. IF C_EXTENSION2[] IS NOT INITIAL. LOOP AT C_EXTENSION2 INTO WA_EXTENSION WHERE STRUCTURE = 'ZKS_OA_ACC_EXT'. ZEXT_DATA = WA_EXTENSION-VALUEPART1. READ TABLE C_ACCIT ASSIGNING WITH KEY POSNR = ZEXT_DATA-POSNR. IF SY-SUBRC = 0. -ABPER = ZEXT_DATA-ABPER. -ZZCASHFLOW = ZEXT_DATA-ZZCASHFLOW. -BSCHL = ZEXT_DATA-BSCHL. -XREF1_HD = ZEXT_DATA-XREF1_HD. ENDIF. ENDLOOP. ENDIF. ENDMETHOD.

代码释义

CHANGE方法中参数FLT_VAL,C_ACCHD,C_ACCIT,C_ACCCR,C_ACCWT,C_ACCTX均与凭证数据相关。

C_EXTENSION2中传入的数据即为BAPI_ACC_DOCUMENT_POST中EXTENSION2参数。

BAPIPAREX-TE_STRUC为数据字典中结构的名称,其余为扩展数据。

上面例子中,生成BAPI的EXTENTION2参数时,就是按照ZKS_OA_ACC_EXT的数据结构顺序写入的,读取时也按照相同的方式读取即可。

根据参数里面的类型和说明来判断某个参数对应凭证中的什么数据,将BAPI中无法传入的数据从EXTENTION2里面取出,传入CHANGE的参数里面即可。

---------------------------------------------

转关于BAPI BAPI_ACC_DOCUMENT_POST  的几篇网文, 备查

原文地址:http://community.kingdee.com/pages/carllu/blog/archive/2010/04/28/420713.aspx

1.    举个我们这次系统中的一个业务场景

前面讲到我们需要把一个Oracle应付发票的凭证导入到SAP中,但是导入的字段比较多,就会出现如下的问题:
SAP系统中把凭证中的[分支号]作为不同系统的来源,例如凭证来源于Oracle,金蝶,用友,那么分支号分别是'001','002','003'。
我们这里使用BAPI_ACC_DOCUMENT_POST来导入凭证,
大家可以看一下在BKPF(操作
代码SE11)表中存在[分支号]字段      

但是在BAPIACHE09(操作代码SE37)结构中却没有[分支号]这个字段,BAPIACHE09是BAPI_ACC_DOCUMENT_POST导入凭证头的入口结构       
       
那么标准API没有[分支号],SAP采用何种方法才能将[分支号]导入系统哪?

很高兴看到SAP提供了增强BAdi(客户化创建BAdi)来导入标准API没有的字段
一般情况下,不需要对BAdi作增强,但是当需要将某个不常用的字段导入到SAP,但是标准的BAPI又不能够支持这个字段,则需要对BAdi作增强,那么如何对BAdi作增强那?
下面简单做个讲解:
1)首先需要我们对标准的BAdi(操作代码SE19)做个实例化,本场景中,我们对ACC_DOCUMENT这个标准的BAdi实例化     

       

       
关键是上图中的CHANGE部分,双击就可以进入BAdi的ABAP程序
源代码,是不是感觉很爽,不过别高兴太早,因为进入源代码的编辑器之后,是空的,当然,源代码是需要自己添加的,请看下图:
       
上面的代码看不懂没关系,我来解释一下:
DATA部分是定义变量,liw_accit TYPE accit就是定义一个accit的结构类型的变量liw_accit;
LOOP部分就是对BAPI中的extension2的数据作循环
Liw_accit-bschl就是对bschl这个字段根据实际传入的数据作赋值,当然,bschl就是类似[分支号]的字段;
MODIFY就是将bashl等字段写入到c_accit结构中,相当于更新accit表中的数据


大家看到这里,可能已经明白了BAdi是怎么回事。但是大家可能会问,BAPI怎么会去调用BAdi来做这个事情哪?这个问题可能比较复杂,但是我把他简化了说:
在下图中,BAPI一般会有
[Import]传入参数
[Export]传出参数
[Tabellen]这个是table类型的,用来传入和传出数组类型或table类型的数据,在table类型的数据中有个参数是extension2,作为扩展导入的字段,只要在extension2中作了定义,那么就会执行所有实例化的BAdi,所以这也算是SAP的一个缺点,因为假设你定义了2个相同类型的BAdi,它们都会被执行,假设这两个BAdi逻辑相悖,则会导致所无的数据,所以要在SAP的开发中避免
       

1.    SAP导入多个凭证

不过讲到这里,我们也只是一个凭证,但是在我们实际的业务场景中,我们大部分都需要导入多个凭证,那么如果想要导入多个凭证,使用SAP的API如何来实现那?

既然可以使用BAPI_ACC_DOCUMENT_POST可以导入单个凭证,只要对它循环操作就可以实现多个凭证的导入了,大家看了下面的代码就会理解,红色的部分就是循环调用BAPI_ACC_DOCUMENT_POST就可以批量导入凭证

凭证导入程序开发,ZBAPI_ACC_DOCUMENT_POST。                   
代码:                   
Import:              
Export:              
Changing:              
Tables:              
T_DOCUMENT    LIKE    ZDOCUMENT   凭证内容
Exceptions:              
Source Code:  
FUNCTION ZBAPI_ACC_DOCUMENT_POST.
*"----------------------------------------------------------------------
*"*"Local interface:
*"  TABLES
*"      T_DOCUMENT STRUCTURE  ZDOCUMENT
*"----------------------------------------------------------------------
  DATA: WA_DOCUMENTHEADER    TYPE BAPIACHE09,                    "待传凭证抬头 工作区

    WA_ACCOUNTGL         TYPE BAPIACGL09,                    "总帐科目项 工作区
    IT_ACCOUNTGL         TYPE STANDARD TABLE OF BAPIACGL09,  "总帐科目项 内表
    WA_ACCOUNTRECEIVABLE TYPE BAPIACAR09,                    "客户项目 工作区
    IT_ACCOUNTRECEIVABLE TYPE STANDARD TABLE OF BAPIACAR09,  "客户项目 内表
    WA_ACCOUNTPAYABLE    TYPE BAPIACAP09,                    "供应商项目 工作区
    IT_ACCOUNTPAYABLE    TYPE STANDARD TABLE OF BAPIACAP09,  "供应商项目 内表
    WA_CURRENCYAMOUNT    TYPE BAPIACCR09,                    "货币项目 工作区
    IT_CURRENCYAMOUNT    TYPE STANDARD TABLE OF BAPIACCR09,  "货币项目 内表
    WA_EXTENSION2        TYPE BAPIPAREX,                     "参考结构 工作区
    IT_EXTENSION2        TYPE STANDARD TABLE OF BAPIPAREX,   "参考结构 内表
    WA_RETURN            TYPE BAPIRET2,                      "返回参数 工作区
    IT_RETURN            TYPE STANDARD TABLE OF BAPIRET2,    "返回参数 内表
    WA_ZBKPF_SEND        TYPE ZBKPF_SEND,                    "已导凭证 工作区
    IT_ZBKPF_SEND        TYPE STANDARD TABLE OF ZBKPF_SEND.  "已导凭证 内表

  DATA: W_DOCUMENT  TYPE ZDOCUMENT,        "凭证头 工作区
    LW_DOCUMENT TYPE ZDOCUMENT.        "临时 凭证头 工作区

  DATA: CNS_DR_R TYPE CHAR2 VALUE 'DR',    "凭证借方标识
    CNS_CR_R TYPE CHAR2 VALUE 'CR',    "凭证贷方标识
    CNS_X    TYPE CHAR1 VALUE 'X',     "确认标识
    CNS_RFBU TYPE CHAR4 VALUE 'RFBU',  "业务事务
    CNS_SA   TYPE CHAR2 VALUE 'SA',    "总分类账凭证
    CNS_KR   TYPE CHAR2 VALUE 'KR',    "供应商发票
    CNS_40   TYPE CHAR2 VALUE '40',    "总账-借
    CNS_50   TYPE CHAR2 VALUE '50',    "总账-贷
    CNS_01   TYPE CHAR2 VALUE '01',    "应收-借
    CNS_11   TYPE CHAR2 VALUE '11',    "应收-贷
    CNS_21   TYPE CHAR2 VALUE '21',    "应付-借
    CNS_31   TYPE CHAR2 VALUE '31',    "应付-贷
  DATA: L_RETURN_TABCOUNT TYPE I,
    L_BELNR           TYPE BKPF-BELNR.
  CHECK T_DOCUMENT IS NOT INITIAL.

  SORT T_DOCUMENT BY BELNR ASCENDING.

  LOOP AT T_DOCUMENT INTO W_DOCUMENT.

    LW_DOCUMENT = W_DOCUMENT.
*------------------------转换表头------------------------------------
    AT NEW BELNR.
      WA_DOCUMENTHEADER-BUS_ACT    = CNS_RFBU.           "业务事务
      WA_DOCUMENTHEADER-USERNAME   = SY-UNAME.           "系统当前用户
      WA_DOCUMENTHEADER-COMP_CODE  = LW_DOCUMENT-BUKRS.  "公司代码
      WA_DOCUMENTHEADER-DOC_DATE   = LW_DOCUMENT-BLDAT.  "凭证中的凭证日期
      WA_DOCUMENTHEADER-PSTNG_DATE = LW_DOCUMENT-BUDAT.  "凭证中的记帐日期
      WA_DOCUMENTHEADER-FISC_YEAR  = LW_DOCUMENT-GJAHR.  "会计年度
      WA_DOCUMENTHEADER-FIS_PERIOD = LW_DOCUMENT-MONAT.  "会计期间
      WA_DOCUMENTHEADER-DOC_TYPE   = LW_DOCUMENT-BLART.  "凭证类型
      WA_DOCUMENTHEADER-REF_DOC_NO = LW_DOCUMENT-XBLNR.  "参考凭证号
      WA_DOCUMENTHEADER-HEADER_TXT = LW_DOCUMENT-BKTXT.  "凭证抬头文本
    ENDAT.

    CASE LW_DOCUMENT-BLART.
*------------------------总账科目------------------------------------
      WHEN CNS_SA.
*------------------------总帐科目项----------------------------------
    WA_ACCOUNTGL-ITEMNO_ACC = LW_DOCUMENT-BUZEI.            "会计凭证中的行项目数
    WA_ACCOUNTGL-GL_ACCOUNT = LW_DOCUMENT-HKONT.            "总分类帐帐目
    WA_ACCOUNTGL-COMP_CODE  = LW_DOCUMENT-BUKRS.            "公司代码
    WA_ACCOUNTGL-COSTCENTER = LW_DOCUMENT-KOSTL.            "成本中心
    WA_ACCOUNTGL-PROFIT_CTR = LW_DOCUMENT-PRCTR.            "利润中心
    APPEND WA_ACCOUNTGL TO IT_ACCOUNTGL.
    CLEAR WA_ACCOUNTGL.
*------------------------供应商发票OR供应商贷项凭证----------------
      WHEN CNS_KR OR CNS_KG.
*      统驭科目
    IF LW_DOCUMENT-MITKZ = CNS_X.
*------------------------供应商项目----------------------------------
      WA_ACCOUNTPAYABLE-ITEMNO_ACC = LW_DOCUMENT-BUZEI.       "会计凭证中的行项目数
      WA_ACCOUNTPAYABLE-VENDOR_NO  = LW_DOCUMENT-LIFNR.       "供应商
      APPEND WA_ACCOUNTPAYABLE TO IT_ACCOUNTPAYABLE.
      CLEAR WA_ACCOUNTPAYABLE.
*      非统驭科目
    ELSE.
*------------------------总帐科目项----------------------------------
      WA_ACCOUNTGL-ITEMNO_ACC = LW_DOCUMENT-BUZEI.            "会计凭证中的行项目数
      WA_ACCOUNTGL-GL_ACCOUNT = LW_DOCUMENT-HKONT.            "总分类帐帐目
      WA_ACCOUNTGL-COMP_CODE  = LW_DOCUMENT-BUKRS.            "公司代码
      WA_ACCOUNTGL-COSTCENTER = LW_DOCUMENT-KOSTL.            "成本中心
      WA_ACCOUNTGL-PROFIT_CTR = LW_DOCUMENT-PRCTR.            "利润中心
      APPEND WA_ACCOUNTGL TO IT_ACCOUNTGL.
      CLEAR WA_ACCOUNTGL.
    ENDIF.
    ENDCASE.

*------------------------增强字段-----------------------------------
    IF LW_DOCUMENT-BRNCH IS NOT INITIAL.
      WA_EXTENSION2-STRUCTURE  = 'BRNCH'.              "分支号
      WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.    "行项目数
      WA_EXTENSION2-VALUEPART2 = LW_DOCUMENT-BRNCH.    "分支号值

      APPEND WA_EXTENSION2 TO IT_EXTENSION2.
      CLEAR WA_EXTENSION2.
    ENDIF.

    IF LW_DOCUMENT-UMSKZ IS INITIAL.
      CASE LW_DOCUMENT-BLART.
    WHEN CNS_SA.
      IF LW_DOCUMENT-SHKZG = CNS_DR_R.
        WA_EXTENSION2-STRUCTURE  = 'BSCHL'.
        WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.
        WA_EXTENSION2-VALUEPART2 = CNS_40.
      ELSEIF LW_DOCUMENT-SHKZG = CNS_CR_R.
        WA_EXTENSION2-STRUCTURE  = 'BSCHL'.
        WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.
        WA_EXTENSION2-VALUEPART2 = CNS_50.
      ENDIF.
       ENDCASE.

      APPEND WA_EXTENSION2 TO IT_EXTENSION2.
      CLEAR WA_EXTENSION2.
    ELSE.
      WA_EXTENSION2-STRUCTURE  = 'UMSKZ'.              "特别总/分类帐指示符
      WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.    "行项目数
      WA_EXTENSION2-VALUEPART2 = LW_DOCUMENT-UMSKZ.    "特别总/分类帐值

      APPEND WA_EXTENSION2 TO IT_EXTENSION2.
      CLEAR WA_EXTENSION2.

      CASE LW_DOCUMENT-BLART.
    WHEN CNS_KR OR CNS_KG.
      IF LW_DOCUMENT-SHKZG = CNS_DR_R.
        WA_EXTENSION2-STRUCTURE  = 'BSCHL'.
        WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.
        WA_EXTENSION2-VALUEPART2 = CNS_29.
      ELSEIF LW_DOCUMENT-SHKZG = CNS_CR_R.
        WA_EXTENSION2-STRUCTURE  = 'BSCHL'.
        WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.
        WA_EXTENSION2-VALUEPART2 = CNS_39.
      ENDIF.
    WHEN CNS_DR OR CNS_DG.
      IF LW_DOCUMENT-SHKZG = CNS_DR_R.
        WA_EXTENSION2-STRUCTURE  = 'BSCHL'.
        WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.
        WA_EXTENSION2-VALUEPART2 = CNS_09.
      ELSEIF LW_DOCUMENT-SHKZG = CNS_CR_R.
        WA_EXTENSION2-STRUCTURE  = 'BSCHL'.
        WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.
        WA_EXTENSION2-VALUEPART2 = CNS_19.
      ENDIF.
      ENDCASE.

      APPEND WA_EXTENSION2 TO IT_EXTENSION2.
      CLEAR WA_EXTENSION2.
    ENDIF.


    IF LW_DOCUMENT-SGTXT IS NOT INITIAL.
      WA_EXTENSION2-STRUCTURE  = 'SGTXT'.              "项目文本
      WA_EXTENSION2-VALUEPART1 = LW_DOCUMENT-BUZEI.    "行项目数
      WA_EXTENSION2-VALUEPART2 = LW_DOCUMENT-SGTXT.    "项目文本值
      APPEND WA_EXTENSION2 TO IT_EXTENSION2.
      CLEAR WA_EXTENSION2.
    ENDIF.

    AT END OF BELNR.

                        CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
    EXPORTING
      DOCUMENTHEADER          = WA_DOCUMENTHEADER     "录入凭证头
    TABLES
      ACCOUNTGL               = IT_ACCOUNTGL          "总帐科目项
      ACCOUNTRECEIVABLE       = IT_ACCOUNTRECEIVABLE  "客户项目
      ACCOUNTPAYABLE          = IT_ACCOUNTPAYABLE     "供应商项目
      CURRENCYAMOUNT          = IT_CURRENCYAMOUNT     "货币项目
      EXTENSION2              = IT_EXTENSION2         "扩展字段
      RETURN                  = IT_RETURN.            "返回值

      DESCRIBE TABLE IT_RETURN LINES L_RETURN_TABCOUNT.

      IF L_RETURN_TABCOUNT = 1.                           "凭证导入成功
    CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
                        *      记录已导入的凭证号
    READ TABLE IT_RETURN INTO WA_RETURN INDEX 1.
    IF SY-SUBRC IS INITIAL.
      L_BELNR = WA_RETURN-MESSAGE_V2+0(10).

      WA_ZBKPF_SEND-BELNR = L_BELNR.
      WA_ZBKPF_SEND-CPUDT = SY-DATUM.
      WA_ZBKPF_SEND-CPUTM = SY-UZEIT.
      WA_ZBKPF_SEND-USNAM = SY-UNAME.

      APPEND WA_ZBKPF_SEND TO IT_ZBKPF_SEND.
    ENDIF.
      ELSE.                                               "凭证导入失败

      ENDIF.
      CLEAR: L_RETURN_TABCOUNT,
         WA_ZBKPF_SEND,
         WA_DOCUMENTHEADER,
         IT_ACCOUNTGL,
         IT_ACCOUNTPAYABLE,
         IT_CURRENCYAMOUNT,
         IT_EXTENSION2,
         IT_RETURN.
    ENDAT.
    CLEAR: W_DOCUMENT,LW_DOCUMENT.
  ENDLOOP.
*------------------------往表ZBKPF_SEND插入已导凭证数据-------------------
  IF IT_ZBKPF_SEND IS NOT INITIAL.
    INSERT ZBKPF_SEND FROM TABLE IT_ZBKPF_SEND ACCEPTING DUPLICATE KEYS.
    CLEAR IT_ZBKPF_SEND.           
  ENDIF.           
ENDFUNCTION.          

===========================

原文地址:http://hi.baidu.com/gaoyl2007/blog/item/8fc078fb0cfd0362034f5682.html/cmtid/93c148ec437f23dd2e2e2117

前天测试程序的发现了一个问题,主要关于BAPI_ACC_DOCUMENT_POST的用法,懂ABAP的人都知道这是用于过账的,而BAPI_ACC_DOCUMENT_CHECK是用于做过账前的Check处理的。

我程序里明明设置好了参数,但是Debug测试时只看到Post Successfully的消息,却看不到我要的会计凭证号,当时很奇怪。百翻思考,网上查资料,后来问题终于得到解决。原来是因为我在 documentheader里多传进去了三个参数:OBJ_TYPE, OBJ_KEY,OBJ_SYS。如果删除这三个参数的话就能在返回的内部table里抓去我想要的凭证号码了。呵呵!问题搞定,当时真的很兴奋!

如果谁对BAPI_ACC_DOCUMENT_POST和BAPI_ACC_DOCUMENT_CHECK这两个BAPI不太熟悉的话,那麽在 SAP ECC6.0以上的版本上有一本系统程序ACC_BAPI_TEST_DOCUMENT,可供参考。里面有关于他们的用法以及参数设置。。。

 

你可能感兴趣的:(sap,abap,创建会计凭证,sap,abap)