18.3. 業務對象和BAPI
18.3.1. SAP業務對象(SWO1)
業務對象類型是業務對象的定義和描述,對象類型(Object Type) 相當於(但不等於)對象設計語言中類(Class) 的概念,它封裝了業務功能和數據
業務對象與BAPI早於ABAP OO,通過非面向對象語言,以面向對象的形式設計了業務對象與BAPI
18.3.1.1. 業務對象類型的組成
l 接口:需實現的業務接口,可以是多個
l 關鍵字段:用於唯一確定一個業務對象類型的實例,通常是業務對象底層數據庫表的對應主鍵
l 屬性:業務對象的數據部分, 可以是數據表中的字段、運行值(又稱虛擬屬性, virtual attribute) 或指向其它業務對象的指針(對象引用, object reference)等
l 方法:用於操作業務對象屬性,可以通過調用事務、function module、 report 或ABAP程序來實現方法,即業務方法的實現方法有多種
l 事件:狀態的改變,可通過事件觸發工作流或任務
業務對象類型也是可以繼承的,如業務對象類型BUS1001006(標准物料)和BUS1001001(零售物料)的父類型都是BUS1001(物料):
18.3.1.2. 業務對象(BO)設計
18.3.1.2.1. 創建業務表
業務對象代表具體的業務數據,因此業務對象類型都有相對應的數據字典結構對應:
18.3.1.2.2. 創建業務對象類型
系統已自動引用SAP標准接口IFSAP,並從中繼承了一些默認的屬性和方法
18.3.1.2.3. 添加(繼承)接口
創建業務對象類型時,除自動默認繼承的接口IFSAP外:
還可以為業務對象添加(或叫實現吧)其他的SAP接口,業務對象將從接口中自動繼承接口里的屬性或方法,其中大多方法需要在業務對象中重新實現。將光標放在Interfaces位置,點擊按鈕,添加IFCREATE接口
注:這些接口類型也是通過SWO1創建的,只是在初始界面選擇的是“Interface type(相當於接口)”,而不是“Object type(相當於類)”
同理添加IFEDIT接口,最后結構如下:
通過查看繼承過來的方法屬性,發現只有Create方法是靜態的,與實例無關
18.3.1.2.4. 添加關鍵字段Key
關鍵字段代表着一個業務對象類型的實例,由它來區分各個業務對象,實例業務對象需要此Key
將鼠標放在“Key fields”所在位置上,點擊新建按鈕,系統將提示是否參照ABAP字典中的表結構創建關鍵字段,本例中的業務對象基於數據庫表ZTAB_EMPLOYEE:
生成的程序代碼:
18.3.1.2.5. 添加屬性
將光標置於Attributes所在行,點擊新建按鈕功能,系統將提示是否參照ABAP字典中的表結構創建關鍵字段:
並為每一個屬性輸入名稱之后,各字段將出現在Attributes列表中:
18.3.1.2.6. 通過報表程序來實現業務對象的方法
18.3.1.2.6.1. 報表程序
現以報表程序的方式,來重新實現業務對象類型繼承過來原有方法(Create、Edit、Display等),業務對象的這些方法將通過提交到該報表的方式來實現這些方法的功能:
REPORT zbo_employee_rep.
TABLES: ztab_employee.
PARAMETERS: id LIKE ztab_employee-id OBLIGATORY,
name LIKE ztab_employee-name,
phone LIKE ztab_employee-phone,
email LIKE ztab_employee-email,
op.
START-OF-SELECTION.
ztab_employee-id = id.
ztab_employee-name = name.
ztab_employee-phone = phone.
ztab_employee-email = email.
CASE op.
WHEN 'I'."插入數據
INSERT ztab_employee.
IF sy-subrc = 0.
MESSAGE s016(rp) WITH 'One record inserted.'.
ELSE.
MESSAGE e016(rp) WITH 'No record inserted,ID existed.'.
ENDIF.
WHEN 'U'."更新數據
UPDATE ztab_employee.
IF sy-subrc = 0.
MESSAGE s016(rp) WITH 'One record updated.'.
ELSE.
MESSAGE e016(rp) WITH 'No record update,ID not existed.'.
ENDIF.
WHEN 'V'."顯示數據
SELECT SINGLE * FROM ztab_employee WHERE id = ztab_employee-id.
IF sy-subrc = 0.
WRITE:/ 'Employee No:',ztab_employee-id,
/ 'Employee Name:',ztab_employee-name,
/ 'Employee Phone:',ztab_employee-phone,
/ 'Employee Email:',ztab_employee-email.
ENDIF.
ENDCASE.
18.3.1.2.6.2. 重定義接口與方法實現
在沒有進行重定義之前,這些繼承而來的方法名稱顯示為深紅色。將光標置於方法名上,點擊(即方法的重定義)按鈕,每個方法都經過該操作后,底色會變為白色:
將光標置於Display方法名上,點擊“Program”按鈕,提示方法還未進行代碼實現:
YES后,進行程序代碼實現界面,在業務對象的實現程序中添加以下代碼:
ExistenceCheck方法用於檢查對象實現是否存在,如在對象測試界面中,需要選擇“Instance”按鈕來測試實例相關的一些方法時,如果未實現該方法,則如果輸入一個不存在的ID,系統將仍進入實例測試界面,但實例相關的測試功能不可用。正確實現ExistenceCheck方法后,如果指定關鍵字段的對象不存在,系統將給出消息提示:Object does not exist。
其中object變量為前面自動生成的變量,相關代碼如下:
注:在每次修改程序后,都需要保存並重新生成業務對象類型,才能進行測試
18.3.1.2.6.3. 測試
注:測試界面上的屏幕參數就是 Report 程序選擇屏幕
18.3.1.2.7. 通過BAPI函數來實現業務對象方法
本小節將在前面章節的基礎上,為業務對象類型添加兩個BAPI方法:ZEMPLOYEE_obj.GetList(讀取職員列表)和ZEMPLOYEE_obj.GetDetail(讀取職員詳細信息)。
BAPI方法與上節中所添加的普通方法是不同的,那些借助於報表程序來實現的Create、Edit等方法,僅可在SAP系統內部使用,但BAPI不同的是可以供非SAP系統對業務對象進行訪問。
18.3.1.2.7.1. 創建BAPI參數結構
BAPI方法ZEMPLOYEE_obj.GetList需要用到的結構類型(BAPI自定義結構類型需要以ZBAPI開頭——其實BAPI函數、BAPI函數的Group、以及BAPI函數參數參照的結構名稱中都需要包含BAPI名稱串,另外,BAPI函數參數所參照的表結構類型只能被一個BAPI使用,因為釋放BAPI后相應結構會被凍結):
BAPI方法ZEMPLOYEE_obj.GetDetail需要用到的結構類型:
18.3.1.2.7.2. 創建BAPI函數、BAPI調用返回RETURN結果處理
先創建函數組 ZEMP,並激活:
現創建BAPI方法需要調用的兩個RFM遠程函數:ZBAPI_GET_EMPLOYEE_LIST和ZBAPI_GET_EMPLOYEE_DETAIL,ZEMPLOYEE_obj.GetList、ZEMPLOYEE_obj.GetDetail兩個BAPI業務方法將借助於這兩個BAPI函數來實現。
注:BAPI函數中Export必須有return返回參數(約定俗成), BAPI調用成功與否一般通過RETURN參數返回,該參數的數據結構可以參照數據字典結構BAPIRETURN,其重要的字段有:
l TYPE, 消息類型,如S、E、W、I
l ID, 消息類型
l NUMBER, 消息編號
l MESSAGE, 消息文本
l MESSAGE_V1、MESSAGE_V2、MESSAGE_V3、MESSAGE_V4,消息變量
在函數組ZEMP 的LZEMPTOP頂層包含文件中定義全局的數據變量:
並為ZBAPI_GET_EMPLOYEE_LIST函數添加以下源碼:
FUNCTION zbapi_get_employee_list.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" EXPORTING
*" VALUE(RETURN) TYPE BAPIRETURN
*" TABLES
*" ZEMP_LIST STRUCTURE ZBAPIEMPLIST
*"----------------------------------------------------------------------
CLEAR zemp_list.
REFRESH zemp_list.
CLEAR return.
CLEAR ztab_employee.
SELECT * FROM ztab_employee INTO CORRESPONDING FIELDS OF TABLE zemp_list.
IF sy-subrc <> 0."如果BAPI函數中數據驗證不通過,則對返回具有E類型消息的RETURN消息返回內表,則外部主調程序對RETURN內表進行判斷,根據RETURN中的結果來決定是否Commit Work
CLEAR message.
message-msgty = 'E'.
message-msgid = 'RP'.
message-msgno = 16.
message-msgv1 = 'No Employee is available.'.
PERFORM set_return_message USING message CHANGING return.
ENDIF.
ENDFUNCTION.
BAPIRETURN構造:
FORM set_return_message USING p_message LIKE message
CHANGING p_return LIKE bapireturn.
CHECK NOT message IS INITIAL.
CALL FUNCTION 'BALW_BAPIRETURN_GET'
EXPORTING
type = p_message-msgty
cl = p_message-msgid
number = p_message-msgno
par1 = p_message-msgv1
par2 = p_message-msgv2
par3 = p_message-msgv3
par4 = p_message-msgv4
IMPORTING
bapireturn = p_return
EXCEPTIONS
OTHERS = 1.
ENDFORM.
注:此BAPI函數為實例對象業務方法,所以需要在Import設置與業務對象Key一樣的參數,如這里的ID(名稱與類型最好都一致)
FUNCTION zbapi_get_employee_detail.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(ID) TYPE ZTAB_EMPLOYEE-ID
*" EXPORTING
*" VALUE(ZEMP_DETAIL) TYPE ZBAPIEMPDETAIL
*" TABLES
*" RETURN STRUCTURE BAPIRETURN
*"----------------------------------------------------------------------
CLEAR zemp_detail.
CLEAR return.
CLEAR ztab_employee.
SELECT SINGLE * FROM ztab_employee INTO CORRESPONDING FIELDS OF zemp_detail WHERE id = id.
IF sy-subrc <> 0.
CLEAR message.
message-msgty = 'E'.
message-msgid = 'RP'.
message-msgno = 16.
message-msgv1 = 'Employee does not exist.'.
PERFORM set_return_message USING message CHANGING return.
ENDIF.
ENDFUNCTION.
18.3.1.2.7.3. 將BAPI函數綁定到相應的業務方法
為什么在RFC函數創建好后,還需要將該函數綁定到業務對象類型中:
創建BAPI的最后一步就是為業務對象類型添加BAPI方法,並將上面創建BAPI函數分配給這些BAPI方法:
由於BAPI函數中定義了關鍵字段作為輸入參數,當在添加該方法時就默認此方法為實例方法,所以不能選中Instance-independent選項
點擊按鈕進行下一步操作,設置待加BAPI方法的參數,一般使用建議,與BAPI函數參數相對應:
通過相同的方法,創建List BAPI方法,並將ZBAPI_GET_EMPLOYEE_LIST BAPI函數分配給它,由於List為靜態方法,所以鈎上Instance-independent:
業務對象方法如果是通過BAPI方法來實現的,則實現方式要選擇API function,另外還需要指定對應到的BAPI功能模塊:
18.3.2. BAPI
BAPI:Business Application Process Interface(業務應用編輯接口),它實質上就是一種特殊的RFC函數
BAPI函數及函數參數參考的結構類型名,都要以ZBAPI開
BAPI函數參數只能是傳值,不能有Change與Exception參數
BAPI函數需要有Return返回參數
18.3.2.1. BAPI瀏覽器
18.3.2.2. SE37查找:BAPI函數的命名規則
BAPI對應的功能模塊命名規則BAPI_<業務對象名>_<method>,因此可以直接在SE37中通過前綴BAPI加對象名稱或方法名稱作為關鍵字,快速查找一個BAPI功能模塊函數。如檢索 BAPI*Material*Get*
18.3.2.3. 查找某事務碼所對應的BAPI
如果只知道事物代碼,可以通過下面的方式查詢相應的BAPI。例如找創建銷售(物料模板根據此方法好像找不出)訂單的BAPI,我們知道事物代碼是VA01:
1. 我們進入VA01 界面,找到system status
2. 在事物代碼位置上雙擊(注:不是程序上雙擊),找到PACKAGE VA
3. 用SE80打開包 VA ,或點擊 Display Object List按鈕直接進入到SE80對象列表:
18.3.2.4. 常用BAPI函數
BAPI_TRANSACTION_COMMIT COMMIT WORK AND WAIT.
BAPI_TRANSACTION_ROLLBACK ROLLBACK WORK.
BAPI_MATERIAL_SAVEDATA 創建及更改物料主數據
BAPI_GOODSMVT_CREATE 物料移動(創建物料憑證 )
BAPI_MATERIAL_AVAILABILITY 可用庫存
BAPI_PR_CREATE 創建PR (采購申請)
BAPI_PO_CREATE1 創建PO(采購單)
BAPI_SALESORDER_CREATEFROMDAT2 創建銷售訂單
BAPI_OUTB_DELIVERY_CREATE_SLS 根據銷售訂單創建交貨單
BAPI_BILLINGDOC_CREATEMULTIPLE 創建發票
BAPI_ACC_DOCUMENT_POST 創建會計憑證