SAP 판매 오더 세액 조정을 위한 ABAP 개발 전략

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_INCONDITIONS_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_INCONDITIONS_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.

태그: SAP ABAP BAPI Sales Order Tax

7월 19일 18:09에 게시됨