demo:同步接口处理接收数据

标签:
abapliumengsap接口luw |
分类: 接口相关 |
场景:
第三方调用SAP接口,创建单据,如果对方因为某种原因在极短的时间内,使用重复数据连续调用了sap接口,怎样防止重复创建单据。
之前群里聊过这个问题,我把问题抛出来,大家随便聊聊而已。
场景其实挺简单,也很常见,至于怎么实现,无非是什么加锁,加日志之类的。
我也是做了一个简单测试。
场景是推送数据到sap,创建PO。
先创建了个log表:
然后写了俩函数,分别是用锁和用log表。
第一个函数
FUNCTION ZLM_CREATE_PO.
*"----------------------------------------------------------------------
*"*"本地接口:
*" 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 IS_DATA IS NOT INITIAL.
MOVE-CORRESPONDING IS_DATA TO LS_LOG.
ELSE.
CALL FUNCTION '/SAPSLL/GUID_CREATE'
IMPORTING
EV_GUID_32 = LS_LOG-GUID.
LS_LOG-WEB_ORDER = 'LM00001' ."外部单据号 LS_LOG-BUKRS = '1710' ."公司代码
LS_LOG-BSART = 'NB' ."订单类型(采购)
LS_LOG-LIFNR = 'USSU-VSF04' ."供应商或债权人的帐号
LS_LOG-EKORG = '1710' ."采购组织
LS_LOG-EKGRP = '002' ."采购组
LS_LOG-MATNR = 'MZ-RM-R300-01' ."物料编号
LS_LOG-WERKS = '1710' ."工厂
LS_LOG-LGORT = '171C' ."库存地点
LS_LOG-KSCHA = 'PMP0' ."条件类型
LS_LOG-AMOUNT = '1' ."条件金额
LS_LOG-WAERS = 'USD' ."货币码
LS_LOG-UNAME = SY-UNAME.
LS_LOG-DATUM = SY-DATUM.
LS_LOG-UZEIT = SY-UZEIT.
ENDIF.
*--------------------------------------------------------------------*
* 枷锁
*--------------------------------------------------------------------*
CALL FUNCTION 'ENQUEUE_EZLMT_PO_LOG'
EXPORTING
MODE_ZLMT_PO_LOG = 'X'
MANDT = SY-MANDT
WEB_ORDER = LS_LOG-WEB_ORDER
_SCOPE = '3'
EXCEPTIONS
FOREIGN_LOCK = 1
SYSTEM_FAILURE = 2
OTHERS = 3.
IF SY-SUBRC <> 0.
LS_LOG-TYPE = 'E'.
LS_LOG-MESSAGE = '被锁'.
INSERT ZLMT_PO_LOG FROM LS_LOG.
COMMIT WORK AND WAIT.
ES_DATA = LS_LOG.
RETURN.
ENDIF.
*--------------------------------------------------------------------*
* 检查库表内该 web order是否已经成功创建 po
*--------------------------------------------------------------------*
SELECT SINGLE * FROM ZLMT_PO_LOG INTO @DATA(LS_TMP)
WHERE WEB_ORDER = @LS_LOG-WEB_ORDER.
IF SY-SUBRC = 0.
LS_LOG-TYPE = 'E'.
LS_LOG-MESSAGE = '重复创建'.
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.
LS_POHEADERX-COMP_CODE = 'X'.
LS_POHEADERX-DOC_TYPE = 'X'.
LS_POHEADERX-VENDOR = 'X'.
LS_POHEADERX-PURCH_ORG = 'X'.
LS_POHEADERX-PUR_GROUP = 'X'.
LS_POHEADERX-CURRENCY = 'X'.
LS_POHEADERX-DOC_DATE = 'X'.
CLEAR: LS_POITEM,LS_POITEMX.
CLEAR: LT_POITEM[],LT_POITEMX[].
LS_POITEM-PO_ITEM = '10'. "采购凭证的项目编号
LS_POITEM-MATERIAL = LS_LOG-MATNR. "商品代码
LS_POITEM-QUANTITY = 1." "采购订单数量
LS_POITEM-PO_UNIT = 'EA' . "采购订单的计量单位
LS_POITEM-PLANT = LS_LOG-WERKS. "工厂
LS_POITEM-STGE_LOC = LS_LOG-LGORT. "库存地点
APPEND LS_POITEM TO LT_POITEM.
LS_POITEMX-PO_ITEM = '10'. "采购凭证的项目编号
LS_POITEMX-MATERIAL = 'X'. "商品代码
LS_POITEMX-QUANTITY = 'X'. "采购订单数量
LS_POITEMX-PO_UNIT = 'X' . "采购订单的计量单位
LS_POITEMX-PLANT = 'X'. "工厂
LS_POITEMX-STGE_LOC = '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-CURRENCY = LS_LOG-WAERS. "币别
LS_POCOND-CHANGE_ID = 'I'. "修改类型 I U D
APPEND LS_POCOND TO LT_POCOND.
CLEAR LS_POCONDX.
LS_POCONDX-ITM_NUMBER = '10'.
LS_POCONDX-COND_TYPE = LS_LOG-AMOUNT. "定价条件
LS_POCONDX-COND_VALUE = 'X'. "价格
LS_POCONDX-CHANGE_ID = 'X'. "修改类型
IF LS_POCOND-CURRENCY IS NOT INITIAL.
LS_POCONDX-CURRENCY = 'X'. "币别
ENDIF.
APPEND LS_POCONDX TO LT_POCONDX.
*& call bapi
CALL FUNCTION 'BAPI_PO_CREATE1'
EXPORTING
POHEADER = LS_POHEADER
POHEADERX = LS_POHEADERX
IMPORTING
EXPPURCHASEORDER = LV_PO_NUMBER
TABLES
RETURN = LT_RETURN
POITEM = LT_POITEM
POITEMX = LT_POITEMX
POCOND = LT_POCOND
POCONDX = LT_POCONDX.
*--------------------------------------------------------------------*
* save log
*--------------------------------------------------------------------*
LS_LOG-EBELN = LV_PO_NUMBER.
LS_LOG-TYPE = 'S'.
LS_LOG-MESSAGE = '创建成功'.
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.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
WAIT = 'X'.
*--------------------------------------------------------------------*
* 解锁
*--------------------------------------------------------------------*
CALL FUNCTION 'DEQUEUE_EZLMT_PO_LOG'
EXPORTING
MANDT = SY-MANDT
WEB_ORDER = LS_LOG-WEB_ORDER
. ENDFUNCTION.
仅仅是测试代码而已。
第二个函数,只是没用锁,自己把 加锁 解锁 注释掉就行了,
(LS_LOG-WEB_ORDER
第一个函数没有重复数据。
第二个函数出现了问题:
大概就是这个意思了。
仅仅是简单测试了下,如果有什么不对的地方欢迎批评指正。谢谢!~
这个其实还有一个极端情况的问题,就是第一条锁释放后,到第一条数据落表的这个时间差里,进来的数据。
这个场景我没模拟出来。