프로젝트시 MM모듈을 담당할때 제일 많이 접하게는 BAPI_PO_CREATE1에 대하여 남겨볼까 합니다.
기본 구조는 아래와 같습니다. 그런데 이런걸 인터넷검색하면 너무~~많습니다.
이건걸 원하지는 않겠죠~..ㅎㅎ
DATA: ls_header TYPE bapimepoheader,
lt_item TYPE TABLE OF bapimepoitem,
lt_itemx TYPE TABLE OF bapimepoitemx,
lt_return TYPE TABLE OF bapiret2.
ls_header-doc_type = 'NB'.
ls_header-vendor = '10000001'.
ls_header-purch_org = '1000'.
ls_header-pur_group = '001'.
ls_header-comp_code = '1000'.
APPEND VALUE #( po_item = '00010'
material = 'MAT001'
quantity = '10'
plant = '1000'
net_price = '100' ) TO lt_item.
APPEND VALUE #( po_item = '00010'
po_itemx = 'X'
material = 'X'
quantity = 'X'
plant = 'X'
net_price = 'X' ) TO lt_itemx.
CALL FUNCTION 'BAPI_PO_CREATE1'
EXPORTING
poheader = ls_header
poheaderx = VALUE bapimepoheaderx( doc_type = 'X' vendor = 'X'
purch_org = 'X' pur_group = 'X' comp_code = 'X' )
TABLES
return = lt_return
poitem = lt_item
poitemx = lt_itemx.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING wait = 'X'.
제가 템플릿으로 만들려고 했던 프로그램의 핵심로직이 PO생성입니다.
100번 스크린입니다. 이것을 바탕으로 아래 코드들로 STO(PO)를 생성합니다.
FORM create_sto USING ps_pohead.
" 그룹핑을 위한 키 선언: 계약번호 + 플랜트 + 자재
DATA: lt_head TYPE SORTED TABLE OF ty_head
WITH UNIQUE KEY vbeln_c werks hmatnr,
ls_head TYPE ty_head.
FIELD-SYMBOLS: <fs_head> TYPE ty_head.
DATA: lv_exppurchaseorder TYPE ekko-ebeln.
" BAPI 관련 테이블 구조 선언
DATA: lt_poitem TYPE STANDARD TABLE OF bapimepoitem WITH DEFAULT KEY,
lt_poitemx TYPE STANDARD TABLE OF bapimepoitemx WITH DEFAULT KEY,
lt_cond TYPE STANDARD TABLE OF bapimepocond WITH DEFAULT KEY,
lt_condx TYPE STANDARD TABLE OF bapimepocondx WITH DEFAULT KEY,
lt_poschedule TYPE STANDARD TABLE OF bapimeposchedule WITH DEFAULT KEY,
lt_poschedulex TYPE STANDARD TABLE OF bapimeposchedulx WITH DEFAULT KEY,
lt_poshipping TYPE STANDARD TABLE OF bapiitemship WITH DEFAULT KEY,
lt_poshippingx TYPE STANDARD TABLE OF bapiitemshipx WITH DEFAULT KEY,
lt_bapiparex TYPE STANDARD TABLE OF bapiparex WITH DEFAULT KEY,
lt_potextheader TYPE STANDARD TABLE OF bapimepotextheader WITH DEFAULT KEY,
lt_potextitem TYPE STANDARD TABLE OF bapimepotext WITH DEFAULT KEY,
lt_return TYPE STANDARD TABLE OF bapiret2 WITH DEFAULT KEY.
DATA: ls_poheader TYPE bapimepoheader,
ls_poheaderx TYPE bapimepoheaderx.
" 선택된 항목 기준으로 그룹핑 키 수집
LOOP AT gt_out INTO DATA(gs_out) WHERE chk = c_x.
ls_head-vbeln_c = gs_out-vbeln_c.
ls_head-werks = gs_out-werks.
INSERT ls_head INTO TABLE lt_head.
ENDLOOP.
" 그룹별 반복 처리
LOOP AT lt_head ASSIGNING <fs_head>.
" BAPI 관련 변수 초기화
PERFORM clear_po_bapi_data.
" PO Header 및 HeaderX 설정
PERFORM set_bapi_po_header
USING <fs_head>
CHANGING ls_poheader ls_poheaderx.
" Extension (Z필드 등) 설정
PERFORM set_bapi_po_extension
USING <fs_head>
CHANGING lt_bapiparex.
" PO Item, ItemX, 조건, 납기 등 구성
PERFORM append_po_item_lines
USING <fs_head>
CHANGING lt_poitem lt_poitemx
lt_cond lt_condx
lt_poschedule lt_poschedulex
lt_poshipping lt_poshippingx.
" Text 편집기 입력값 추가 (Header/Item 텍스트)
PERFORM read_text_editor
TABLES lt_potextheader lt_potextitem.
" BAPI 호출
PERFORM call_bapi_po_create1
USING ls_poheader ls_poheaderx
lt_poitem lt_poitemx
lt_cond lt_condx
lt_poschedule lt_poschedulex
lt_poshipping lt_poshippingx
lt_bapiparex
lt_potextheader lt_potextitem
CHANGING lv_exppurchaseorder lt_return.
" 결과에 따라 성공/오류 처리
IF lv_exppurchaseorder IS NOT INITIAL.
PERFORM save_history_zict1050 USING <fs_head> lv_exppurchaseorder.
PERFORM update_success_status USING <fs_head> lv_exppurchaseorder.
ELSE.
PERFORM update_error_status USING <fs_head> lt_return.
ENDIF.
ENDLOOP.
" ALV 데이터 갱신
PERFORM refresh_alv_after_sto .
ENDFORM.
사용되는 FORM문입니다.
*&---------------------------------------------------------------------*
*& Form clear_po_bapi_data
*&---------------------------------------------------------------------*
FORM clear_po_bapi_data.
CLEAR : gv_ebeln,
gv_return,
gs_poheader,
gv_supplier,
gv_reference,
gv_sales_group,
gv_sales_office,
gv_po_number,
gv_ret_message,
gt_poitem, gt_poitem[].
ENDFORM .
FORM set_bapi_po_header
USING ps_head TYPE ty_head
CHANGING ps_poheader TYPE bapimepoheader
ps_poheaderx TYPE bapimepoheaderx.
"poheader
ps_poheader-comp_code = gs_0030-dbukrs.
ps_poheader-doc_type = gs_0030-bsart.
ps_poheader-vendor = |{ gs_0030-lifnr ALPHA = IN }|.
ps_poheader-purch_org = gs_0030-pkorg.
ps_poheader-pur_group = gs_head-ekgrp.
ps_poheader-doc_date = sy-datlo.
ps_poheader-our_ref = ps_head-vbeln_c.
ps_poheader-pmnttrms = gs_head-zterm.
IF NOT gs_head-inco1 IS INITIAL.
ps_poheader-incoterms1 = gs_head-inco1.
ps_poheaderx-incoterms1 = c_x.
ENDIF.
IF NOT gs_head-inco2_l IS INITIAL.
ps_poheader-incoterms2 = gs_head-inco2_l.
ps_poheaderx-incoterms2 = c_x.
ENDIF.
"poheaderx
ps_poheaderx-item_intvl = c_x.
ps_poheaderx-comp_code = c_x.
ps_poheaderx-doc_type = c_x.
ps_poheaderx-vendor = c_x.
ps_poheaderx-purch_org = c_x.
ps_poheaderx-pur_group = c_x.
ps_poheaderx-doc_date = c_x.
ps_poheaderx-our_ref = c_x.
ps_poheaderx-pmnttrms = c_x.
ENDFORM.
FORM set_bapi_po_extension
USING ps_head TYPE ty_head
CHANGING pt_ext TYPE STANDARD TABLE.
DATA: ls_ext TYPE bapiparex,
ls_ext_data TYPE bapi_te_mepoheader,
ls_extx_data TYPE bapi_te_mepoheaderx.
CLEAR: pt_ext[].
ls_ext_data-zbstnk = gs_head-zbstnk.
ls_ext_data-zvkgrp = gs_head-zvkgrp.
ls_ext_data-zvkbur = gs_head-zvkbur.
ls_ext-structure = 'BAPI_TE_MEPOHEADER'.
ls_ext-valuepart1 = ls_ext_data.
APPEND ls_ext TO pt_ext.
CLEAR ls_ext.
ls_extx_data-zbstnk = 'X'.
ls_extx_data-zvkgrp = 'X'.
ls_extx_data-zvkbur = 'X'.
ls_ext-structure = 'BAPI_TE_MEPOHEADERX'.
ls_ext-valuepart1 = ls_extx_data.
APPEND ls_ext TO pt_ext.
ENDFORM.
FORM append_po_item_lines
USING ps_head TYPE ty_head
CHANGING pt_item TYPE ty_t_bapimepoitem
pt_itemx TYPE ty_t_bapimepoitemx
pt_cond TYPE ty_t_bapimepocond
pt_condx TYPE ty_t_bapimepocondx
pt_sched TYPE ty_t_bapimeposchedule
pt_schedx TYPE ty_t_bapimeposchedulx
pt_ship TYPE ty_t_bapiitemship
pt_shipx TYPE ty_t_bapiitemshipx.
DATA: lv_posnr_num TYPE i VALUE 0,
lv_posnr_str TYPE char10,
lv_posnr TYPE ekpo-ebelp,
lv_chage_id TYPE zcheck,
ls_item TYPE bapimepoitem,
ls_itemx TYPE bapimepoitemx.
FIELD-SYMBOLS: <fs_out> TYPE ty_out.
DATA lv_vbeln_c TYPE vbeln.
CLEAR: lv_vbeln_c.
lv_vbeln_c = ps_head-vbeln_c.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_vbeln_c
IMPORTING
output = lv_vbeln_c.
READ TABLE gt_out TRANSPORTING NO FIELDS
WITH KEY chk = c_x
vbeln_c = ps_head-vbeln_c
werks = ps_head-werks.
IF sy-subrc <> 0.
MESSAGE 'NO MATCHING DATA IN GT_OUT' TYPE 'I'.
RETURN.
ENDIF.
DATA lv_has_match TYPE abap_bool VALUE abap_false.
LOOP AT gt_out INTO DATA(fs_out) WHERE chk = c_x
AND vbeln_c = lv_vbeln_c
AND werks = ps_head-werks.
lv_has_match = c_x.
" 아이템 번호 생성
lv_posnr_num += 10.
lv_posnr_str = lv_posnr_num.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_posnr_str
IMPORTING
output = lv_posnr.
READ TABLE gt_out ASSIGNING <fs_out>
WITH KEY chk = c_x
vbeln_c = fs_out-vbeln_c
posnr_c = fs_out-posnr_c
werks = fs_out-werks
ematnr = fs_out-ematnr.
IF sy-subrc = 0.
<fs_out>-ebelp = lv_posnr.
ENDIF.
"BAPI에 넘길 아이템 번호
fs_out-ebelp = lv_posnr.
IF fs_out-retpo = 'X'.
" PO ITEM
* DATA(ls_item) = VALUE bapimepoitem(
ls_item = VALUE bapimepoitem(
po_item = lv_posnr
material = fs_out-ematnr "
plant = fs_out-werks "
stge_loc = fs_out-lgort "
quantity = fs_out-menge "
po_unit = fs_out-meins "
tax_code = fs_out-mwskz "
ret_item = fs_out-retpo "반품
over_dlv_tol = fs_out-uebto "over_dlv
unlimited_dlv = fs_out-uebtk "unlimited_dlv
customer = fs_out-kunnr "KUNNR
calctype = 'B' "조건 재결정
gr_basediv = space
po_price = '2'
net_price = fs_out-netpr
price_unit = fs_out-peinh
).
APPEND ls_item TO pt_item.
* DATA(ls_itemx) = VALUE bapimepoitemx(
ls_itemx = VALUE bapimepoitemx(
po_item = lv_posnr
material = c_x
plant = c_x
stge_loc = c_x
quantity = c_x
po_unit = c_x
tax_code = c_x
ret_item = c_x
over_dlv_tol = c_x
unlimited_dlv = c_x
customer = c_x
calctype = c_x
gr_basediv = c_x
po_price = c_x
net_price = c_x
price_unit = c_x
).
APPEND ls_itemx TO pt_itemx.
ELSE.
" PO ITEM
ls_item = VALUE bapimepoitem(
po_item = lv_posnr
material = fs_out-ematnr "
plant = fs_out-werks "
stge_loc = fs_out-lgort "
quantity = fs_out-menge "
po_unit = fs_out-meins "
tax_code = fs_out-mwskz "
ret_item = fs_out-retpo "반품
over_dlv_tol = fs_out-uebto "over_dlv
unlimited_dlv = fs_out-uebtk "unlimited_dlv
customer = fs_out-kunnr "KUNNR
calctype = 'B' "조건 재결정
gr_basediv = space
* po_price = '2'
* net_price = fs_out-netpr
).
APPEND ls_item TO pt_item.
ls_itemx = VALUE bapimepoitemx(
po_item = lv_posnr
material = c_x
plant = c_x
stge_loc = c_x
quantity = c_x
po_unit = c_x
tax_code = c_x
ret_item = c_x
over_dlv_tol = c_x
unlimited_dlv = c_x
customer = c_x
gr_basediv = c_x
* po_price = c_x
* net_price = c_x
calctype = c_x
).
APPEND ls_itemx TO pt_itemx.
ENDIF.
" 납기일자
IF fs_out-eindt IS NOT INITIAL.
DATA(ls_sched) = VALUE bapimeposchedule(
po_item = lv_posnr
delivery_date = fs_out-eindt
).
APPEND ls_sched TO pt_sched.
DATA(ls_schedx) = VALUE bapimeposchedulx(
po_item = lv_posnr
delivery_date = c_x
).
APPEND ls_schedx TO pt_schedx.
ENDIF.
" 배송
DATA(ls_ship) = VALUE bapiitemship( po_item = lv_posnr ).
APPEND ls_ship TO pt_ship.
DATA(ls_shipx) = VALUE bapiitemshipx(
po_item = lv_posnr
po_itemx = c_x
).
APPEND ls_shipx TO pt_shipx.
" Conditon - PB00 - 자동결정으로 하도록 변경
IF fs_out-retpo IS INITIAL.
IF fs_out-netpr IS NOT INITIAL.
DATA(ls_cond_pb00) = VALUE bapimepocond(
itm_number = lv_posnr
cond_type = 'PB00'
cond_value = fs_out-netpr
currency = fs_out-waers
cond_unit = fs_out-bprme
cond_p_unt = fs_out-peinh
change_id = 'U'
).
APPEND ls_cond_pb00 TO pt_cond.
DATA(ls_condx_pb00) = VALUE bapimepocondx(
itm_number = lv_posnr
cond_type = c_x
cond_value = c_x
currency = c_x
cond_unit = c_x
cond_p_unt = c_x
).
APPEND ls_condx_pb00 TO pt_condx.
ENDIF.
ENDIF. "ret_po is initial.
"Conditon - ZTA1(Customs Duty)----------------
IF fs_out-werks <> '3204'.
CLEAR lv_chage_id.
IF fs_out-zta1_c = c_x.
IF fs_out-zta1 IS NOT INITIAL.
lv_chage_id = 'U'.
ELSE.
lv_chage_id = 'D'.
ENDIF.
ELSE.
lv_chage_id = 'I'.
ENDIF.
IF lv_chage_id = 'D' OR
( lv_chage_id <> 'D' AND fs_out-zta1 IS NOT INITIAL ).
DATA(ls_cond_zta1) = VALUE bapimepocond(
itm_number = lv_posnr
cond_type = 'ZTA1'
cond_value = fs_out-zta1
change_id = lv_chage_id
).
APPEND ls_cond_zta1 TO pt_cond.
DATA(ls_condx_zta1) = VALUE bapimepocondx(
itm_number = lv_posnr
cond_type = c_x
cond_value = c_x
change_id = c_x
).
APPEND ls_condx_zta1 TO pt_condx.
ENDIF.
ENDIF.
"Conditon - ZTA1(Customs Duty)----------------
"Conditon - ZFR1(Import Freight)--------------
CLEAR lv_chage_id.
IF fs_out-zfr1_c = c_x.
IF fs_out-zfr1 IS NOT INITIAL.
lv_chage_id = 'U'.
ELSE.
lv_chage_id = 'D'.
ENDIF.
ELSE.
lv_chage_id = 'I'.
ENDIF.
IF lv_chage_id = 'D' OR
( lv_chage_id <> 'D' AND fs_out-zfr1 IS NOT INITIAL ).
DATA(ls_cond_zfr1) = VALUE bapimepocond(
itm_number = lv_posnr
cond_type = 'ZFR1'
cond_value = fs_out-zfr1
change_id = lv_chage_id
).
APPEND ls_cond_zfr1 TO pt_cond.
DATA(ls_condx_zfr1) = VALUE bapimepocondx(
itm_number = lv_posnr
cond_type = c_x
cond_value = c_x
change_id = c_x
).
APPEND ls_condx_zfr1 TO pt_condx.
ENDIF.
"Conditon - ZFR1(Import Freight)--------------
"Conditon - ZFR2(Other Cost)------------------
CLEAR lv_chage_id.
IF fs_out-zfr2_c = c_x.
IF fs_out-zfr2 IS NOT INITIAL.
lv_chage_id = 'U'.
ELSE.
lv_chage_id = 'D'.
ENDIF.
ELSE.
lv_chage_id = 'I'.
ENDIF.
IF lv_chage_id = 'D' OR
( lv_chage_id <> 'D' AND fs_out-zfr2 IS NOT INITIAL ).
DATA(ls_cond_zfr2) = VALUE bapimepocond(
itm_number = lv_posnr
cond_type = 'ZFR2'
cond_value = fs_out-zfr2
change_id = lv_chage_id
).
APPEND ls_cond_zfr2 TO pt_cond.
DATA(ls_condx_zfr2) = VALUE bapimepocondx(
itm_number = lv_posnr
cond_type = c_x
cond_value = c_x
change_id = c_x
).
APPEND ls_condx_zfr2 TO pt_condx.
ENDIF.
"Conditon - ZFR2(Other Cost)------------------
ENDLOOP.
ENDFORM.
FORM read_text_editor
TABLES pt_potextheader STRUCTURE bapimepotextheader
pt_potextitem STRUCTURE bapimepotext.
DATA: lt_text_lines TYPE TABLE OF char255,
lv_line TYPE char255,
ls_item TYPE bapimepotext,
ls_header TYPE bapimepotextheader.
CLEAR: gv_text, pt_potextheader[], pt_potextitem[].
" 1. 에디터 객체 준비됐는지 확인
IF go_editor IS BOUND AND gv_editor_ready = c_x.
" 2. 텍스트 줄 단위로 읽기
CALL METHOD go_editor->get_text_as_stream
IMPORTING
text = lt_text_lines.
CALL METHOD cl_gui_cfw=>flush.
" 3. 하나의 긴 문자열로 병합 → gv_text
gv_text = REDUCE string( INIT acc TYPE string
FOR line IN lt_text_lines
NEXT acc = acc && line && cl_abap_char_utilities=>newline ).
" 4. Header Text - 텍스트 헤더 구성
ls_header-text_id = 'F01'.
ls_header-text_form = '*'.
ls_header-po_item = ''.
APPEND ls_header TO pt_potextheader.
" 5. Header Text - 텍스트 라인 구성
LOOP AT lt_text_lines INTO lv_line.
CLEAR ls_item.
ls_item-po_item = ''.
ls_item-text_id = 'F01'.
ls_item-text_line = lv_line.
APPEND ls_item TO pt_potextitem.
ENDLOOP.
ELSE.
MESSAGE '텍스트 에디터가 초기화되지 않았습니다.' TYPE 'S' DISPLAY LIKE 'E'.
ENDIF.
ENDFORM.
FORM call_bapi_po_create1
USING ps_header TYPE bapimepoheader
ps_headerx TYPE bapimepoheaderx
pt_item TYPE STANDARD TABLE
pt_itemx TYPE STANDARD TABLE
pt_cond TYPE STANDARD TABLE
pt_condx TYPE STANDARD TABLE
pt_sched TYPE STANDARD TABLE
pt_schedx TYPE STANDARD TABLE
pt_ship TYPE STANDARD TABLE
pt_shipx TYPE STANDARD TABLE
pt_ext TYPE STANDARD TABLE
pt_texthead TYPE STANDARD TABLE
pt_textitem TYPE STANDARD TABLE
CHANGING pv_po_number TYPE ekko-ebeln
pt_return TYPE STANDARD TABLE.
CALL FUNCTION 'BAPI_PO_CREATE1'
EXPORTING
poheader = ps_header
poheaderx = ps_headerx
IMPORTING
exppurchaseorder = pv_po_number
TABLES
poitem = pt_item
poitemx = pt_itemx
pocond = pt_cond
pocondx = pt_condx
poschedule = pt_sched
poschedulex = pt_schedx
poshipping = pt_ship
poshippingx = pt_shipx
extensionin = pt_ext
potextheader = pt_texthead
potextitem = pt_textitem
return = pt_return.
IF pv_po_number IS NOT INITIAL.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = 'X'.
LOOP AT gt_out ASSIGNING FIELD-SYMBOL(<fs_out>)
WHERE vbeln_c = ps_header-our_ref AND status = gc_red.
CLEAR: <fs_out>-chk.
ENDLOOP.
ELSE.
IF pt_return IS NOT INITIAL.
APPEND VALUE #( vbeln_c = ps_header-our_ref return = pt_return ) TO gt_vbeln_return.
ENDIF.
ENDIF.
ENDFORM.
FORM save_history_zict1050 USING ps_head TYPE ty_head
pv_po TYPE ekko-ebeln.
DATA: ls_hist TYPE zict1050.
LOOP AT gt_out INTO DATA(ls_out)
WHERE vbeln_c = ps_head-vbeln_c
AND chk = c_x.
CLEAR ls_hist.
ls_hist-ebeln = pv_po.
ls_hist-ebelp = ls_out-ebelp.
ls_hist-vbeln_c = ls_out-vbeln_c.
ls_hist-posnr_c = ls_out-posnr_c.
ls_hist-matnr_c = ls_out-hmatnr.
ls_hist-matnr_p = ls_out-ematnr.
ls_hist-retpo = ls_out-retpo.
ls_hist-zadditm = ls_out-zadd.
ls_hist-aedat = sy-datum.
ls_hist-aezet = sy-uzeit.
ls_hist-aenam = sy-uname.
INSERT zict1050 FROM ls_hist.
ENDLOOP.
ENDFORM.
FORM update_success_status USING ps_head TYPE ty_head
pv_po TYPE ekko-ebeln.
LOOP AT gt_out INTO DATA(ls_out)
WHERE chk = c_x
AND vbeln_c = ps_head-vbeln_c
AND werks = ps_head-werks.
ls_out-ebeln = pv_po.
ls_out-status = gc_green.
ls_out-msg = 'PO created'.
ls_out-chk = ''.
MODIFY gt_out FROM ls_out TRANSPORTING ebeln status msg chk .
ENDLOOP.
ENDFORM.
FORM update_error_status
USING ps_head TYPE ty_head
pt_return TYPE ty_t_bapiret2.
READ TABLE pt_return INTO DATA(ls_return) WITH KEY type = 'E'.
LOOP AT gt_out INTO DATA(ls_out)
WHERE chk = c_x
AND vbeln_c = ps_head-vbeln_c
AND werks = ps_head-werks.
ls_out-status = gc_red.
ls_out-msg = COND string(
WHEN sy-subrc = 0 THEN ls_return-message
ELSE 'PO creation failed'
).
CLEAR: ls_out-chk, ls_out-ebelp.
MODIFY gt_out FROM ls_out TRANSPORTING status msg chk ebelp.
ENDLOOP.
ENDFORM.
'ABAP' 카테고리의 다른 글
[ABAP] 구시스템 참조하여 데이터 가져오기 (0) | 2025.06.28 |
---|---|
[ABAP] BAPI_PO_CREATE1(엑셀 업로드) (0) | 2025.06.28 |
[step-3] executable program templete - PBO,PAI,CLS,F01 (0) | 2025.06.24 |
[step-2] executable program templete - TOP,SEL (0) | 2025.06.23 |
[step-1] executable program templete - 프로그램 구조 (0) | 2025.06.22 |