場景:
第三方調用SAP接口,建立單據,如果對方因為某種原因在極短的時間内,使用重複資料連續調用了sap接口,怎樣防止重複建立單據。
之前群裡聊過這個問題,我把問題抛出來,大家随便聊聊而已。
場景其實挺簡單,也很常見,至于怎麼實作,無非是什麼加鎖,加日志之類的。
我也是做了一個簡單測試。
場景是推送資料到sap,建立PO。
先建立了個log表:
然後建了個鎖
然後寫了倆函數,分别是用鎖和用log表。
第一個函數
FUNCTION*"----------------------------------------------------------------------*"*"本地接口:*" IMPORTING*" VALUE(IS_DATA) TYPE ZLMT_PO_LOG OPTIONAL*" EXPORTING*" VALUE(ES_DATA) TYPE ZLMT_PO_LOG*"----------------------------------------------------------------------
DATA:LT_LOG TYPE TABLE OF ZLMT_PO_LOG.DATA:LS_LOG TYPE ZLMT_PO_LOG.
DATA: LT_RETURN LIKE TABLE OF BAPIRET2, LT_POITEM LIKE TABLE OF BAPIMEPOITEM, LT_POITEMX LIKE TABLE OF BAPIMEPOITEMX, LT_POCOND LIKE TABLE OF BAPIMEPOCOND, LT_POCONDX LIKE TABLE OF BAPIMEPOCONDX, LS_POCOND LIKE BAPIMEPOCOND, LS_POCONDX LIKE BAPIMEPOCONDX.DATA: LS_POHEADER LIKE BAPIMEPOHEADER, LS_POHEADERX LIKE BAPIMEPOHEADERX, LS_RETURN LIKE BAPIRET2, LS_POITEM LIKE BAPIMEPOITEM, LS_POITEMX LIKE BAPIMEPOITEMX.DATA:LV_PO_NUMBER LIKE BAPIMEPOHEADER-PO_NUMBER.
*--------------------------------------------------------------------** 參數指派*--------------------------------------------------------------------*
IF MOVE-CORRESPONDING IS_DATA TO LS_LOG. ELSE.
FUNCTION '/SAPSLL/GUID_CREATE' IMPORTING EV_GUID_32 = LS_LOG-GUID.
'LM00001' ."外部單據号 LS_LOG-BUKRS = '1710' ."公司代碼'NB' ."訂單類型(采購) LS_LOG-LIFNR = 'USSU-VSF04' ."供應商或債權人的帳号'1710' ."采購組織 LS_LOG-EKGRP = '002' ."采購組'MZ-RM-R300-01' ."物料編号 LS_LOG-WERKS = '1710' ."工廠'171C' ."庫存地點 LS_LOG-KSCHA = 'PMP0' ."條件類型'1' ."條件金額 LS_LOG-WAERS = 'USD' ."貨币碼
LS_LOG-UNAME = SY-UNAME. LS_LOG-DATUM = SY-DATUM. LS_LOG-UZEIT = SY-UZEIT.
ENDIF.
*--------------------------------------------------------------------** 枷鎖*--------------------------------------------------------------------*
FUNCTION 'ENQUEUE_EZLMT_PO_LOG' EXPORTING'X' MANDT = SY-MANDT WEB_ORDER = LS_LOG-WEB_ORDER'3' EXCEPTIONS123.IF SY-SUBRC <> 0.'E'.'被鎖'.
INSERT ZLMT_PO_LOG FROM LS_LOG. COMMIT WORK AND WAIT.
ES_DATA = LS_LOG. RETURN. ENDIF.
*--------------------------------------------------------------------** 檢查庫表内該 web order是否已經成功建立 po*--------------------------------------------------------------------*DATA(LS_TMP) WHERE WEB_ORDER = @LS_LOG-WEB_ORDER.
IF SY-SUBRC = 0.'E'.'重複建立'. INSERT ZLMT_PO_LOG FROM LS_LOG. COMMIT WORK AND WAIT.
ES_DATA = LS_LOG. RETURN. ENDIF.*--------------------------------------------------------------------** 指派 call bapi*--------------------------------------------------------------------* CLEAR LS_POHEADER. CLEAR LS_POHEADERX. LS_POHEADER-COMP_CODE = LS_LOG-BUKRS. LS_POHEADER-CURRENCY = LS_LOG-WAERS. LS_POHEADER-DOC_DATE = SY-DATUM. LS_POHEADER-DOC_TYPE = LS_LOG-BSART. LS_POHEADER-VENDOR = LS_LOG-LIFNR. LS_POHEADER-PURCH_ORG = LS_LOG-EKORG. LS_POHEADER-PUR_GROUP = LS_LOG-EKGRP.'X'.'X'.'X'.'X'.'X'.'X'.'X'. CLEAR: LS_POITEM,LS_POITEMX. CLEAR: LT_POITEM[],LT_POITEMX[].
'10'. "采購憑證的項目編号 LS_POITEM-MATERIAL = LS_LOG-MATNR. "商品代碼1." "采購訂單數量'EA' . "采購訂單的計量機關 LS_POITEM-PLANT = LS_LOG-WERKS. "工廠"庫存地點
APPEND LS_POITEM TO LT_POITEM.
LS_POITEMX-PO_ITEM = '10'. "采購憑證的項目編号'X'. "商品代碼 LS_POITEMX-QUANTITY = 'X'. "采購訂單數量'X' . "采購訂單的計量機關 LS_POITEMX-PLANT = 'X'. "工廠'X'. "庫存地點
APPEND LS_POITEMX TO LT_POITEMX.
CLEAR LT_POCOND[]. CLEAR LT_POCONDX[]. CLEAR LS_POCOND.
LS_POCOND-ITM_NUMBER = '10'. LS_POCOND-COND_TYPE = LS_LOG-KSCHA. "定價條件 LS_POCOND-COND_VALUE = LS_LOG-AMOUNT."币别 LS_POCOND-CHANGE_ID = 'I'. "修改類型 I U D
APPEND LS_POCOND TO LT_POCOND.
CLEAR LS_POCONDX.
'10'."定價條件 LS_POCONDX-COND_VALUE = 'X'. "價格'X'. "修改類型
IF LS_POCOND-CURRENCY IS NOT INITIAL. LS_POCONDX-CURRENCY = 'X'. "币别 ENDIF.
APPEND LS_POCONDX TO LT_POCONDX.
*& call bapi
FUNCTION 'BAPI_PO_CREATE1' EXPORTING POHEADER = LS_POHEADER POHEADERX = LS_POHEADERX IMPORTING EXPPURCHASEORDER = LV_PO_NUMBER TABLESRETURN POITEM = LT_POITEM POITEMX = LT_POITEMX POCOND = LT_POCOND POCONDX = LT_POCONDX.
*--------------------------------------------------------------------** save log*--------------------------------------------------------------------* LS_LOG-EBELN = LV_PO_NUMBER.'S'.'建立成功'.
LS_LOG-UNAME = SY-UNAME. LS_LOG-DATUM = SY-DATUM. LS_LOG-UZEIT = SY-UZEIT.
ES_DATA = LS_LOG.
INSERT ZLMT_PO_LOG FROM LS_LOG.
FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING'X'.
*--------------------------------------------------------------------** 解鎖*--------------------------------------------------------------------*FUNCTION 'DEQUEUE_EZLMT_PO_LOG' EXPORTING MANDT = SY-MANDT WEB_ORDER = LS_LOG-WEB_ORDER .ENDFUNCTION.
僅僅是測試代碼而已。
第二個函數,隻是沒用鎖,自己把 加鎖 解鎖 注釋掉就行了,
(LS_LOG-WEB_ORDER = 'LM00002')。
第一個函數沒有重複資料。
第二個函數出現了問題:
大概就是這個意思了。
僅僅是簡單測試了下,如果有什麼不對的地方歡迎批評指正。謝謝!~
這個其實還有一個極端情況的問題,就是第一條鎖釋放後,到第一條資料落表的這個時間差裡,進來的資料。
這個場景我沒模拟出來。