SAP PO Multi 시 Ack 값 받아오기
FUNCTION z_qm_if_lims_insp_type.
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" VALUE(I_DATE) TYPE TAB_ISUR_DATUM OPTIONAL
*" VALUE(I_SYSID) TYPE STRING
*" EXPORTING
*" VALUE(E_RET) TYPE ZIF_STATUS
*" VALUE(E_MSG) TYPE CHAR100
*" VALUE(E_SCNT) TYPE SATC_D_JOB_LIMIT_UPPER
*" VALUE(E_ECNT) TYPE SATC_D_JOB_LIMIT_UPPER
*" TABLES
*" LT_Z045 STRUCTURE ZQMT_045
*" LT_WERKS STRUCTURE WERKS_RANG OPTIONAL
*"----------------------------------------------------------------------
DATA : lt_callstack TYPE sys_callst,
ls_callstack LIKE LINE OF lt_callstack,
lv_func_name TYPE dbglevent.
* 현재 function name 가져오기 시작
*** Get Stack
CALL FUNCTION 'SYSTEM_CALLSTACK'
EXPORTING
max_level = 0
IMPORTING
et_callstack = lt_callstack.
LOOP AT lt_callstack INTO ls_callstack
WHERE eventtype = 'FUNC'. " Get Last FUNC Call
EXIT.
ENDLOOP.
*** Set Function Name
lv_func_name = ls_callstack-eventname.
* 현재 function name 가져오기 종료
DATA: ls_z045 LIKE LINE OF lt_z045,
lv_werks_set TYPE zqmt_045-werks,
lv_werks TYPE t001w-werks,
ls_date LIKE LINE OF i_date.
DATA: BEGIN OF ls_cdhdr.
DATA:
tabkey TYPE cdpos-tabkey,
objectid TYPE cdpos-objectid,
udate TYPE cdhdr-udate,
mpdau TYPE qmat-mpdau.
DATA: END OF ls_cdhdr,
lt_cdhdr LIKE TABLE OF ls_cdhdr.
DATA: BEGIN OF ls_coll.
DATA: art TYPE qals-art,
matnr TYPE qals-matnr,
werks TYPE qals-werk,
aktiv TYPE qmat-aktiv,
mpdau TYPE qmat-mpdau,
aedat TYPE cdhdr-udate.
DATA: END OF ls_coll,
lt_coll LIKE TABLE OF ls_coll.
DATA: gt_qmat TYPE TABLE OF zcl_dt_qm00820_serp_gt_qmat,
gs_qmat LIKE LINE OF gt_qmat.
DATA: werks_sql TYPE string.
IF lt_werks[] IS NOT INITIAL.
READ TABLE lt_werks INDEX 1.
CONCATENATE 'pos~tabkey like ''' lt_werks-low '%''' INTO werks_sql.
lv_werks_set = lt_werks-low.
ENDIF.
* Get Code Group
SELECT pos~tabkey,
pos~objectid,
hdr~udate
INTO CORRESPONDING FIELDS OF TABLE @lt_cdhdr
FROM cdhdr AS hdr
INNER JOIN cdpos AS pos
ON pos~objectclas = hdr~objectclas
AND pos~objectid = hdr~objectid
AND pos~changenr = hdr~changenr
WHERE (werks_sql)
AND hdr~objectclas = 'MATERIAL'
AND hdr~udate IN @i_date
AND pos~tabname = 'DQMAT'
GROUP BY pos~tabkey, pos~objectid, hdr~udate.
LOOP AT lt_cdhdr INTO ls_cdhdr.
ls_coll-art = ls_cdhdr-tabkey+4(4).
ls_coll-matnr = ls_cdhdr-objectid.
ls_coll-werks = ls_cdhdr-tabkey+0(4).
ls_coll-aedat = ls_cdhdr-udate.
SELECT SINGLE aktiv, mpdau
INTO (@ls_coll-aktiv, @ls_coll-mpdau)
FROM qmat
WHERE art = @ls_coll-art
AND matnr = @ls_coll-matnr
AND werks = @ls_coll-werks.
COLLECT ls_coll INTO lt_coll.
CLEAR ls_coll.
ENDLOOP.
loop at lt_coll into ls_coll.
MOVE-CORRESPONDING ls_coll to gs_qmat.
append gs_qmat to gt_qmat.
clear gs_qmat.
ENDLOOP.
READ TABLE i_date INTO ls_date INDEX 1.
IF gt_qmat[] IS INITIAL.
ls_z045-i_object = lv_func_name.
ls_z045-werks = lv_werks_set.
ls_z045-idate_fr = ls_date-low.
ls_z045-idate_to = ls_date-high.
ls_z045-i_sysid = i_sysid.
ls_z045-e_ret = 'E'.
ls_z045-e_scnt = 0.
ls_z045-e_ecnt = 0.
ls_z045-e_msg = 'No Data'.
ls_z045-ernam = sy-uname.
ls_z045-erdat = sy-datlo.
ls_z045-erzet = sy-timlo.
APPEND ls_z045 TO lt_z045.
e_msg = ls_z045-e_msg.
e_ret = 'E'.
EXIT.
ENDIF.
DATA: ev_ret TYPE char1,
ev_msg TYPE zmesse,
lv_date TYPE sy-datlo,
lv_time TYPE sy-timlo.
DATA : lt_sysid TYPE TABLE OF string,
ls_sysid TYPE string,
lv_sys_cnt TYPE i,
lv_sel_cnt TYPE i.
SPLIT i_sysid AT ',' INTO TABLE lt_sysid.
LOOP AT lt_sysid INTO ls_sysid.
IF ls_sysid IS INITIAL.
DELETE lt_sysid.
ENDIF.
ENDLOOP.
"전송하게 될 system 수량 계산
lv_sys_cnt = lines( lt_sysid ).
DATA: lv_cnt1 TYPE i,
lv_cnt2 TYPE i,
lv_fr_num TYPE i,
lv_to_num TYPE i,
lv_total TYPE i,
lv_ava_cnt TYPE i,
lv_xnum TYPE i,
lv_do_time TYPE i.
* DATA: lo_proxy_lims TYPE REF TO zcl_co_qm00820_serp_ao.
* DATA: lo_fault TYPE REF TO cx_ai_system_fault,
* lv_emsg TYPE string.
* DATA: ls_proxy_out TYPE zcl_mt_qm00820_serp,
* lv_cnt1 TYPE i,
* lv_cnt2 TYPE i,
* lv_fr_num TYPE i,
* lv_to_num TYPE i,
* lv_total TYPE i,
* lv_ava_cnt TYPE i,
* lv_xnum TYPE i,
* lv_do_time TYPE i.
CONSTANTS:
gc_max_size TYPE i VALUE '3072000',
gc_size1 TYPE i VALUE '64'.
lv_cnt1 = lines( gt_qmat ).
"전송되는 Table size 계산
lv_total = lv_cnt1 * gc_size1.
"1번에 send 가능한 size 계산
lv_ava_cnt = gc_max_size / gc_size1.
"나누어 전송해야 하는 Count 계산
lv_do_time = lv_total / gc_max_size + 1.
* IF gc_max_size < lv_total.
*
* ENDIF.
"Code group 과 code를 LIMS에 전송
CLEAR: e_scnt, e_ecnt.
"처음에 Success로 setting 한 뒤
"한번이라도 Error가 발생하면 Error로 setting
e_ret = 'S'.
DATA: lo_client_proxy TYPE REF TO zcl_co_qm00820_serp_ao,
ls_proxy_out TYPE zcl_mt_qm00820_serp.
DATA: lv_cs_root TYPE REF TO cx_root,
lo_fault TYPE REF TO cx_ai_system_fault,
lo_ai_application_fault TYPE REF TO cx_ai_application_fault,
lv_send_emsg TYPE string,
lv_emsg TYPE string.
DATA: lo_msg_protocol TYPE REF TO if_wsprotocol_message_id,
l_msg_id TYPE sxmsmguid,
lo_ack TYPE REF TO if_ws_acknowledgment,
l_ack_status_simple TYPE prx_ack_status,
l_ack_status_detail TYPE prx_ack_status_detail_table.
DATA: lo_async_messaging TYPE REF TO if_wsprotocol_async_messaging,
lv_ack_request TYPE prx_ack_request_details.
CREATE OBJECT lo_client_proxy.
lv_date = sy-datlo.
lv_time = sy-timlo.
lv_fr_num = 1.
DO lv_do_time TIMES.
CLEAR ls_proxy_out.
ls_proxy_out-mt_qm00820_serp-xnums = lv_xnum.
ls_proxy_out-mt_qm00820_serp-xdate = lv_date.
ls_proxy_out-mt_qm00820_serp-xtime = lv_time.
ls_proxy_out-mt_qm00820_serp-xsysid = i_sysid.
lv_to_num = lv_to_num + lv_ava_cnt.
CLEAR: ls_proxy_out-mt_qm00820_serp-gt_qmat[], gs_qmat.
LOOP AT gt_qmat INTO gs_qmat FROM lv_fr_num TO lv_to_num.
CONDENSE gs_qmat-mpdau.
APPEND gs_qmat TO ls_proxy_out-mt_qm00820_serp-gt_qmat.
CLEAR gs_qmat.
ENDLOOP.
lv_cnt1 = lines( ls_proxy_out-mt_qm00820_serp-gt_qmat ).
ls_proxy_out-mt_qm00820_serp-xrows = lv_cnt1.
CONDENSE ls_proxy_out-mt_qm00820_serp-xnums.
CONDENSE ls_proxy_out-mt_qm00820_serp-xrows.
TRY.
CLEAR: lv_emsg, lv_send_emsg.
* get protocol for asynchronous messaging
lo_async_messaging ?=
lo_client_proxy->get_protocol( if_wsprotocol=>async_messaging ).
* Ask for transport acknowledgment
CLEAR lv_ack_request.
lv_ack_request =
if_wsprotocol_async_messaging=>co_transport_acknowledgment.
lo_async_messaging->set_acknowledgment_requested( lv_ack_request ).
CATCH cx_ai_system_fault cx_ai_application_fault INTO lv_cs_root.
CALL METHOD lv_cs_root->if_message~get_text
RECEIVING
result = lv_send_emsg.
ENDTRY.
TRY.
CALL METHOD lo_client_proxy->qm00820_serp_ao
EXPORTING
output = ls_proxy_out.
COMMIT WORK AND WAIT.
CATCH cx_ai_system_fault cx_ai_application_fault INTO lv_cs_root.
CALL METHOD lv_cs_root->if_message~get_text
RECEIVING
result = lv_send_emsg.
ENDTRY.
TRY.
* Ack Message 읽어오기
lo_msg_protocol ?=
lo_client_proxy->get_protocol( if_wsprotocol=>message_id ).
l_msg_id = lo_msg_protocol->get_message_id( ).
DO 10 TIMES.
CLEAR: ls_z045.
SELECT SINGLE st~msgguid,
st~ack_state,
CASE st~ack_state
WHEN '072' THEN 'S'
WHEN '077' THEN 'S'
WHEN '080' THEN 'A'
WHEN '000' THEN 'W'
ELSE 'E'
END,
err~errtxt
INTO (@ls_z045-ifkey, @ls_z045-ack_state,
@ls_z045-e_ret, @ls_z045-e_msg)
FROM sxmspmast AS st
LEFT OUTER JOIN sxmsperror AS err
ON err~msgguid = st~msgguid
WHERE st~msgguid = @l_msg_id.
IF ls_z045-ack_state <> '000' AND
ls_z045-ack_state <> '071'.
EXIT.
ENDIF.
"ack_state 값이 늦게 들어오는 경우가 있어서 Wait 함
IF ls_z045-ack_state = '000' OR
ls_z045-ack_state = '071'.
WAIT UP TO 1 SECONDS.
ENDIF.
ENDDO.
* lo_ack = cl_proxy_access=>get_acknowledgment( l_msg_id ).
* l_ack_status_simple = lo_ack->get_status( ).
"Ack Message가 여러개의 sub msg를 가지고 있는 경우
"sxmspmast에서 sub msg의 ack status를 읽어서 처리함
IF ls_z045-ack_state = '080'.
DO 10 TIMES.
CLEAR: ls_z045, lt_z045.
SELECT st~msgguid AS ifkey,
st~ack_state,
CASE st~ack_state
WHEN '072' THEN 'S'
WHEN '077' THEN 'S'
WHEN '080' THEN 'A'
WHEN '000' THEN 'W'
ELSE 'E'
END AS e_ret,
CASE mas~ob_system "PO xsysid 값이 있는 필드
WHEN 'ILIM_COM_D' THEN 'LM0'
WHEN 'ALIM_TJN_D' THEN 'LMC'
WHEN 'ALIM_DGN_D' THEN 'LMD'
WHEN 'ALIM_HUN_D' THEN 'LMH'
WHEN 'ALIM_MEX_D' THEN 'LMM'
WHEN 'ALIM_VNM_D' THEN 'LMV'
END AS i_sysid,
err~errtxt AS e_msg
INTO CORRESPONDING FIELDS OF TABLE @lt_z045
* INTO (@ls_z045-ifkey, @ls_z045-ack_state,
* @ls_z045-e_ret, @ls_z045-i_sysid,
* @ls_z045-e_msg)
FROM sxmspmast AS st
INNER JOIN sxmspemas AS mas
ON mas~msgguid = st~msgguid
LEFT OUTER JOIN sxmsperror AS err
ON err~msgguid = mas~msgguid
WHERE st~parentmsg = @l_msg_id.
LOOP AT lt_z045 INTO ls_z045.
ls_z045-i_object = lv_func_name.
ls_z045-werks = lv_werks_set.
ls_z045-idate_fr = ls_date-low.
ls_z045-idate_to = ls_date-high.
IF ls_z045-e_ret = 'S'.
ls_z045-e_scnt = lv_cnt1.
ELSE.
ls_z045-e_ecnt = lv_cnt1.
ENDIF.
ls_z045-ernam = sy-uname.
ls_z045-erdat = lv_date.
ls_z045-erzet = lv_time.
MODIFY lt_z045 FROM ls_z045 INDEX sy-tabix.
ENDLOOP.
lv_sel_cnt = lines( lt_z045 ).
"ack_state 값이 늦게 들어오는 경우가 있어서 Wait 함
IF sy-subrc <> 0 OR
ls_z045-ack_state = '000' OR
ls_z045-ack_state = '071' OR
"insert 가 늦게 되어서 전송한 system 전체 값이 나오지
"않는 경우가 발생하여 전송한 count 와 비교함
lv_sel_cnt < lv_sys_cnt.
WAIT UP TO 1 SECONDS.
CONTINUE.
ENDIF.
IF sy-subrc = 0 AND
* ls_z045-ack_state <> '000' AND
ls_z045-ack_state <> '071'.
EXIT.
ENDIF.
ENDDO.
"1개의 system에 전송한 경우
ELSE.
ls_z045-i_object = lv_func_name.
ls_z045-werks = lv_werks_set.
ls_z045-idate_fr = ls_date-low.
ls_z045-idate_to = ls_date-high.
ls_z045-i_sysid = i_sysid.
IF ls_z045-e_ret = 'S'.
ls_z045-e_scnt = lv_cnt1.
ELSE.
ls_z045-e_ecnt = lv_cnt1.
ENDIF.
* ls_z045-e_msg = e_msg.
ls_z045-ernam = sy-uname.
ls_z045-erdat = lv_date.
ls_z045-erzet = lv_time.
APPEND ls_z045 TO lt_z045.
* lo_ack->get_status_detail( IMPORTING ack_status_detail_table = l_ack_status_detail ).
ENDIF.
CATCH cx_ai_system_fault cx_ai_application_fault INTO lv_cs_root.
CALL METHOD lv_cs_root->if_message~get_text
RECEIVING
result = lv_send_emsg.
ENDTRY.
ADD 1 TO lv_xnum.
lv_fr_num = lv_to_num + 1.
IF lv_send_emsg IS INITIAL.
e_ret = ls_z045-e_ret.
IF ls_z045-e_ret = 'S'.
e_scnt = e_scnt + lv_cnt1.
ELSE.
e_ecnt = e_ecnt + lv_cnt1.
ENDIF.
ELSE.
ls_z045-i_object = lv_func_name.
ls_z045-werks = lv_werks_set.
ls_z045-i_sysid = i_sysid.
ls_z045-idate_fr = ls_date-low.
ls_z045-idate_to = ls_date-high.
ls_z045-e_ret = 'E'.
ls_z045-e_ecnt = lv_cnt1.
ls_z045-e_msg = lv_send_emsg.
ls_z045-ernam = sy-uname.
ls_z045-erdat = lv_date.
ls_z045-erzet = lv_time.
APPEND ls_z045 TO lt_z045.
e_msg = lv_emsg.
"처음에 Success로 setting 한 뒤
"한번이라도 Error가 발생하면 Error로 setting
e_ret = 'F'.
e_ecnt = e_ecnt + lv_cnt1.
ENDIF.
ENDDO.
ENDFUNCTION.