SAP 판매 오더 세액 조정을 위한 ABAP 개발 전략
SAP 시스템에서 판매 오더 품목에 대한 세액(예: MWSI 또는 MWST)을 프로그래밍 방식으로 조정해야 하는 경우가 있습니다. 특히, 프론트엔드 트랜잭션 코드 VA02에서 직접 수정 가능한 세액 필드를 인터페이스를 통해 변경해야 할 때 이러한 요구사항이 발생합니다.
일반적으로 세액은 KOMV-KWERT(조건 값) 필드에 해당하며, 관련 필드로는 KOMV-KBETR(조건 금액 또는 백분율) 및 KOMV-KAWRT(조건 기준 값)가 있습니다. 이 문서에서는 BAPI_SALESORDER_CHANGE 사용 시 겪을 수 있는 한계점과 이를 극복하기 위한 효과적인 ABAP 개발 방안을 제시합니다.
BAPI_SALESORDER_CHANGE를 통한 초기 시도 및 한계
판매 오더를 변경할 때 BAPI_SALESORDER_CHANGE BAPI를 사용하는 것이 일반적인 접근 방식입니다. 이 BAPI는 조건 데이터를 처리하기 위한 CONDITIONS_IN 및 CONDITIONS_INX 테이블 파라미터를 제공합니다. 다음은 초기 시도 코드 예시입니다.
* 판매 오더 상세 정보 조회 등 초기 로직 수행 (예: BAPISDORDER_GETDETAILEDLIST 호출)
* 이 예시에서는 MWST 세금 유형의 값을 업데이트하려는 상황을 가정합니다.
DATA: gt_conditions TYPE STANDARD TABLE OF BAPICOND,
gs_condition_data TYPE BAPICOND,
gt_condition_flags TYPE STANDARD TABLE OF BAPICONDX,
gs_condition_flag TYPE BAPICONDX,
gv_table_index TYPE sy-tabix,
gv_sales_order_num TYPE vbeln_va,
gs_order_item TYPE BAPIITEM. " 임시 구조, 실제 품목 데이터는 조회 필요
* ... (gv_sales_order_num, gs_order_item, gt_conditions 데이터는 이전에 조회되었다고 가정) ...
* 특정 품목의 MWST 세금 조건 조회 및 업데이트
READ TABLE gt_conditions INTO gs_condition_data WITH KEY item_number = gs_order_item-item_pos
condition_type = 'MWST'. " 예시: MWST 세금 유형
IF sy-subrc = 0.
gv_table_index = sy-tabix.
gs_condition_data-condition_value = gs_order_item-new_tax_amount. " 변경할 세금 금액
MODIFY gt_conditions FROM gs_condition_data INDEX gv_table_index.
ENDIF.
* CONDITIONS_INX 테이블 설정: 변경된 조건에 대한 플래그
CLEAR gs_condition_flag.
gs_condition_flag-update_flag = 'U'.
gs_condition_flag-item_number = gs_order_item-item_pos.
gs_condition_flag-cond_step = gs_condition_data-cond_step.
gs_condition_flag-cond_count = gs_condition_data-cond_count.
gs_condition_flag-cond_unit = 'X'.
gs_condition_flag-cond_type = gs_condition_data-condition_type.
gs_condition_flag-cond_value = 'X'. " 조건 값 변경 플래그 (KBETR에 해당)
gs_condition_flag-currency = 'X'.
* ... 기타 필요한 플래그 설정 ...
APPEND gs_condition_flag TO gt_condition_flags.
* BAPI 호출 부분
DATA: gs_header_change_flags TYPE BAPISDH1X,
gs_logic_switch TYPE BAPISDLS,
gt_return_messages TYPE STANDARD TABLE OF BAPIRET2.
gs_logic_switch-cond_handl = 'X'. " 조건 처리 활성화
CALL FUNCTION 'BAPI_SALESORDER_CHANGE'
EXPORTING
salesdocument = gv_sales_order_num
order_header_inx = gs_header_change_flags
logic_switch = gs_logic_switch
TABLES
return = gt_return_messages
conditions_in = gt_conditions " 업데이트된 조건 데이터
conditions_inx = gt_condition_flags " 조건 변경 플래그
* ... 기타 테이블 파라미터 ...
.
하지만 이 방식으로는 KOMV-KBETR(조건 금액 또는 백분율) 필드는 변경할 수 있지만, 우리가 목표로 하는 KOMV-KWERT(조건 값) 필드를 직접 수정할 수는 없습니다. BAPICONDX 구조(CONDITIONS_INX에 사용)에는 KWERT 필드를 표시하는 플래그가 없기 때문입니다.
최종 ABAP 처리 방안: 사용자 Exit 및 암시적 개선(Implicit Enhancement) 활용
BAPI_SALESORDER_CHANGE의 한계를 극복하기 위해, 판매 오더 조건 평가 로직 내에서 KOMV-KWERT 값을 직접 조작하는 사용자 Exit을 활용하는 것이 가장 효과적인 방법입니다. 특히 프로그램 RV61AFZB에 있는 FORM USEREXIT_XKOMV_BEWERTEN_END는 조건 평가가 완료된 후 실행되므로, 이 시점에서 최종 세액을 조정하기에 적합합니다.
1. 프로그램 RV61AFZB의 FORM USEREXIT_XKOMV_BEWERTEN_END 암시적 개선
해당 사용자 Exit 내에서 글로벌 변수를 참조하여 원하는 세액으로 xkomv(조건 작업 영역)의 kwert 필드를 업데이트합니다. ksteu 필드도 'E'로 설정하여 수동으로 설정되었음을 나타내는 것이 좋습니다.
FORM USEREXIT_XKOMV_BEWERTEN_END.
" 암시적 개선 시작
ENHANCEMENT 1 Z_SALES_ORDER_TAX_ADJ. " 활성 버전 이름
TYPES: BEGIN OF ty_modified_tax_info,
doc_cond_no TYPE knumv, " 문서 조건 번호 (KNUMV)
item_no TYPE kposn, " 품목 번호 (KPOSN)
step_no TYPE stunr, " 스텝 번호 (STUNR)
cond_type TYPE kscha, " 조건 유형 (KSCHA)
fixed_value TYPE komv-kwert, " 고정된 조건 값 (KWERT)
base_value TYPE komv-kawrt, " 조건 기준 값 (KAWRT, 선택 사항)
END OF ty_modified_tax_info.
DATA: lt_custom_taxes TYPE TABLE OF ty_modified_tax_info.
" 호출 프로그램의 함수 그룹에 선언된 글로벌 변수 참조
" 예: '(ZFG_SD_SALES_UTIL)G_MODIFIED_TAX_DATA'
ASSIGN ('(ZFG_SD_SALES_UTIL)G_MODIFIED_TAX_DATA') TO FIELD-SYMBOL().
IF IS NOT ASSIGNED OR IS INITIAL.
RETURN. " 글로벌 데이터가 없으면 처리하지 않음
ENDIF.
" 글로벌 변수의 내용을 로컬 테이블로 복사
MOVE-CORRESPONDING TO lt_custom_taxes.
FIELD-SYMBOLS: LIKE LINE OF xkomv.
LOOP AT lt_custom_taxes INTO DATA(ls_custom_tax).
READ TABLE xkomv ASSIGNING
WITH KEY knumv = ls_custom_tax-doc_cond_no
kposn = ls_custom_tax-item_no
stunr = ls_custom_tax-step_no
kschl = ls_custom_tax-cond_type.
IF sy-subrc = 0.
" XKOMV 테이블의 KWERT 값을 우리가 원하는 값으로 직접 변경
-kwert = ls_custom_tax-fixed_value.
" 조건을 수동으로 처리했음을 나타내는 플래그 설정
-ksteu = 'E'.
ENDIF.
ENDLOOP.
ENDENHANCEMENT.
" 암시적 개선 종료
ENDFORM.
2. 함수 그룹 TOP Include에 글로벌 변수 선언
위 사용자 Exit에서 참조할 글로벌 변수를 BAPI 호출이 이루어지는 프로그램의 함수 그룹(예: ZFG_SD_SALES_UTIL)의 TOP Include (예: LZFG_SD_SALES_UTILTOP)에 선언합니다.
* TYPES 정의 (USEREXIT과 동일해야 함)
TYPES: BEGIN OF ty_modified_tax_info,
doc_cond_no TYPE knumv,
item_no TYPE kposn,
step_no TYPE stunr,
cond_type TYPE kscha,
fixed_value TYPE komv-kwert,
base_value TYPE komv-kawrt,
END OF ty_modified_tax_info.
* 글로벌 데이터 테이블 선언
DATA: g_modified_tax_data TYPE TABLE OF ty_modified_tax_info.
3. BAPI 호출 전에 글로벌 변수 g_modified_tax_data에 값 할당
BAPI_SALESORDER_CHANGE를 호출하기 전에, 변경하고자 하는 세금 정보를 g_modified_tax_data 글로벌 테이블에 채웁니다. 이때, 판매 오더의 문서 조건 번호(KNUMV), 품목 번호(POSNR), 스텝 번호(STUNR), 조건 유형(KSCHA) 등의 식별 정보와 함께 최종 KWERT 값을 설정합니다.
DATA: lv_sales_order_num TYPE vbeln_va,
lv_document_condition_num TYPE knumv,
gs_item_input TYPE BAPIITEM, " 사용자 입력 품목 데이터
gt_original_conditions TYPE STANDARD TABLE OF BAPICOND. " BAPISDORDER_GETDETAILEDLIST 등으로 조회된 조건
* ... (lv_sales_order_num, gs_item_input, gt_original_conditions 데이터는 이전에 설정되었다고 가정) ...
* 판매 오더의 문서 조건 번호 조회
SELECT SINGLE knumv
INTO @lv_document_condition_num
FROM vbak
WHERE vbeln = @lv_sales_order_num.
IF lv_document_condition_num IS NOT INITIAL.
" 예시: 특정 품목의 MWST 세액을 변경하는 경우
IF gs_item_input-new_mwst_amount IS NOT INITIAL. " 새로운 MWST 세액이 제공된 경우
READ TABLE gt_original_conditions INTO DATA(ls_orig_cond)
WITH KEY item_number = gs_item_input-item_pos
condition_type = 'MWST'. " MWST 조건 유형
IF sy-subrc = 0.
" 글로벌 세금 테이블에 추가
APPEND VALUE ty_modified_tax_info(
doc_cond_no = lv_document_condition_num
item_no = ls_orig_cond-item_number
step_no = ls_orig_cond-cond_step
cond_type = ls_orig_cond-condition_type
fixed_value = gs_item_input-new_mwst_amount " 변경하고자 하는 최종 KWERT 값
) TO g_modified_tax_data.
ENDIF.
ENDIF.
" MWSI 등 다른 세금 유형에 대한 로직도 유사하게 추가 가능 ...
ENDIF.
4. BAPI_SALESORDER_CHANGE 호출 (세금 조건 매개변수 없이)
글로벌 변수에 모든 필요한 세금 정보가 채워진 후에는 BAPI_SALESORDER_CHANGE를 호출합니다. 이때, CONDITIONS_IN 및 CONDITIONS_INX 테이블 파라미터에는 변경할 세금 조건에 대한 정보를 명시적으로 전달할 필요가 없습니다. 시스템은 BAPI 처리 과정 중 사용자 Exit이 실행될 때 글로벌 변수에 접근하여 세액을 자동으로 조정할 것입니다.
DATA: gs_header_change_flags TYPE BAPISDH1X,
gs_logic_switch TYPE BAPISDLS,
gt_return_messages TYPE STANDARD TABLE OF BAPIRET2.
* ... (lv_sales_order_num, gs_header_change_flags, gs_logic_switch 데이터는 이전에 설정되었다고 가정) ...
CALL FUNCTION 'BAPI_SALESORDER_CHANGE'
EXPORTING
salesdocument = lv_sales_order_num
order_header_inx = gs_header_change_flags
logic_switch = gs_logic_switch
TABLES
return = gt_return_messages
* conditions_in = gt_conditions " 세금 KWERT는 글로벌 변수로 처리되므로 여기서는 전달 불필요
* conditions_inx = gt_condition_flags " 세금 KWERT는 글로벌 변수로 처리되므로 여기서는 전달 불필요
* ... 기타 테이블 파라미터 ...
.
COMMIT WORK AND WAIT.
IF line_exists( gt_return_messages[ type = 'E' ] ) OR line_exists( gt_return_messages[ type = 'A' ] ).
ROLLBACK WORK.
ELSE.
" 성공적으로 변경 처리 완료
ENDIF.