2032 lines
62 KiB
ABAP
2032 lines
62 KiB
ABAP
class ZCL_COPA_TOPDOWN definition
|
|
public
|
|
create public .
|
|
|
|
public section.
|
|
|
|
types:
|
|
tt_dfies TYPE STANDARD TABLE OF dfies WITH DEFAULT KEY .
|
|
types:
|
|
result_tb TYPE STANDARD TABLE OF zstop_result WITH EMPTY KEY .
|
|
types:
|
|
target_tb TYPE STANDARD TABLE OF zstop_target WITH EMPTY KEY .
|
|
|
|
methods CONSTRUCTOR .
|
|
methods GET_CUSTOM_TABLE_INFO
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
exporting
|
|
!SENDER type STRING
|
|
!RECEIVER type STRING .
|
|
methods GET_VARIANT_LIST
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
returning
|
|
value(RESULT) type FIST_FIELD_EXT
|
|
exceptions
|
|
SELECT_ERR .
|
|
methods SET_VARIANT_DESC
|
|
importing
|
|
value(ERKRS) type ERKRS optional
|
|
value(VARIANT) type COVARIANT optional
|
|
value(PERIO) type JAHRPER optional .
|
|
methods GET_SENDER_RECEIVER_DATA
|
|
importing
|
|
value(ERKRS) type ERKRS optional
|
|
value(VARIANT) type COVARIANT optional
|
|
value(PERIO) type JAHRPER optional
|
|
returning
|
|
value(RESULT) type BAPIRET2 .
|
|
methods GET_FIELD_CATALOG
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
value(PERIO) type JAHRPER
|
|
value(VARIANT) type COVARIANT
|
|
exporting
|
|
value(FIELDCATALOG) type TT_DFIES
|
|
returning
|
|
value(RESULT) type BAPIRET2 .
|
|
methods DELETE_TOPDOWN_TB_DATA
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
value(VARIANT) type COVARIANT
|
|
value(PERIO) type JAHRPER
|
|
value(TYPE) type ZTBLS
|
|
returning
|
|
value(RESULT) type BAPIRET2 .
|
|
methods EXECUTE_TOPDOWN_DISTRIBUTE
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
value(VARIANT) type COVARIANT
|
|
value(PERIO) type JAHRPER
|
|
value(SAVE_YN) type BOE_BOOL default 'X'
|
|
exporting
|
|
value(RT_RESULT) type RESULT_TB
|
|
returning
|
|
value(RESULT) type BAPIRET2 .
|
|
methods POST_ACTUAL_TOPDOWN_DOCUMENTS
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
value(VARIANT) type COVARIANT
|
|
value(PERIO) type JAHRPER
|
|
value(VRGAR) type RKE_VRGAR
|
|
!TESTRUN type TESTRUN default 'X'
|
|
returning
|
|
value(RESULT) type BAPIRET2_T .
|
|
methods GET_COPA_DOC_LIST
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
value(PERIO) type JAHRPER
|
|
value(VARIANT) type COVARIANT
|
|
value(REVERSE) type BLG_STORNO default 'X'
|
|
exporting
|
|
value(COPA_DOC_LIST) type TARGET_TB
|
|
returning
|
|
value(RESULT) type BAPIRET2 .
|
|
PROTECTED SECTION.
|
|
|
|
private section.
|
|
|
|
types:
|
|
BEGIN OF ty_bpsel,
|
|
sort TYPE rke_lfd4,
|
|
fnam TYPE fieldname,
|
|
sign TYPE raldb_sign,
|
|
option TYPE raldb_opti,
|
|
low TYPE rke_low_l,
|
|
high TYPE rke_high_l,
|
|
END OF ty_bpsel .
|
|
types:
|
|
tt_bpsel TYPE STANDARD TABLE OF ty_bpsel WITH EMPTY KEY .
|
|
types:
|
|
BEGIN OF ty_mng_table,
|
|
type TYPE db2type,
|
|
tbname TYPE tabname,
|
|
text TYPE mssviewortable,
|
|
END OF ty_mng_table .
|
|
types:
|
|
tt_bdcdata TYPE STANDARD TABLE OF bdcdata WITH DEFAULT KEY .
|
|
types:
|
|
" 클래스내에서 필요한 기본 정보
|
|
BEGIN OF ty_working_info,
|
|
perio TYPE jahrper,
|
|
variant TYPE covariant,
|
|
END OF ty_working_info .
|
|
types:
|
|
BEGIN OF ty_key_map,
|
|
key_string TYPE string,
|
|
dist_id TYPE pbr_seqre,
|
|
END OF ty_key_map .
|
|
types:
|
|
tt_key_map TYPE HASHED TABLE OF ty_key_map
|
|
WITH UNIQUE KEY key_string .
|
|
types:
|
|
tt_dd03p TYPE STANDARD TABLE OF dd03p WITH DEFAULT KEY .
|
|
types TY_SENDER type ZSTOP_SENDER .
|
|
types TY_RECEIVER type ZSTOP_RECEIVER .
|
|
types TY_VARIANT type ZSTOP_VARIANT .
|
|
types TY_RESULT type ZSTOP_RESULT .
|
|
types TY_TARGET type ZSTOP_TARGET .
|
|
types TY_DISTINFO type ZSTOP_DISTINFO .
|
|
types TY_DISTRULE type ZSTOP_DISTRULE .
|
|
types:
|
|
tt_sender TYPE STANDARD TABLE OF ty_sender WITH EMPTY KEY .
|
|
types:
|
|
tt_receiver TYPE STANDARD TABLE OF ty_receiver WITH EMPTY KEY .
|
|
types:
|
|
tt_variant TYPE STANDARD TABLE OF ty_variant WITH EMPTY KEY .
|
|
types:
|
|
TT_result TYPE STANDARD TABLE OF ty_result WITH EMPTY KEY .
|
|
types:
|
|
tt_target TYPE STANDARD TABLE OF ty_target WITH EMPTY KEY .
|
|
types:
|
|
tt_fieldlist TYPE STANDARD TABLE OF bapi_copa_field WITH DEFAULT KEY .
|
|
types:
|
|
tt_copa_data TYPE STANDARD TABLE OF bapi_copa_data WITH DEFAULT KEY .
|
|
|
|
data SOURCE_STRUCT_DESC type ref to CL_ABAP_STRUCTDESCR .
|
|
data SOURCE_TABLE type ref to DATA .
|
|
data MANAGER_STRUCT_DESC type ref to CL_ABAP_STRUCTDESCR .
|
|
data MANAGER_TABLE type ref to DATA .
|
|
data VARIANT_STRUCT_DESC type ref to CL_ABAP_STRUCTDESCR .
|
|
data VARIANT_TABLE type ref to DATA .
|
|
data SENDER_STRUCT_DESC type ref to CL_ABAP_STRUCTDESCR .
|
|
data SENDER_TABLE type ref to DATA .
|
|
data RECEIVER_STRUCT_DESC type ref to CL_ABAP_STRUCTDESCR .
|
|
data RECEIVER_TABLE type ref to DATA .
|
|
data RESULT_STRUCT_DESC type ref to CL_ABAP_STRUCTDESCR .
|
|
data RESULT_TABLE type ref to DATA .
|
|
data TARGET_STRUCT_DESC type ref to CL_ABAP_STRUCTDESCR .
|
|
data TARGET_TABLE type ref to DATA .
|
|
data:
|
|
gt_mng_table TYPE TABLE OF ty_mng_table .
|
|
data MT_SENDER_KEYS type TT_KEY_MAP .
|
|
data:
|
|
gv_dist_counter TYPE n LENGTH 9 value '000000000' ##NO_TEXT.
|
|
data GV_TABNAME type COVAD-TABNAME .
|
|
data GV_MESSAGE type STRING .
|
|
data GV_SOURCE type TABNAME .
|
|
data GV_MANAGER type TABNAME .
|
|
data GV_VARIANT type TABNAME .
|
|
data GV_SENDER type TABNAME .
|
|
data GV_RECEIVER type TABNAME .
|
|
data GV_RESULT type TABNAME .
|
|
data GV_TARGET type TABNAME .
|
|
data GV_DISTINFO type TABNAME .
|
|
data GV_DISTRULE type TABNAME .
|
|
data WORKING_INFO type TY_WORKING_INFO .
|
|
|
|
methods SET_INFO
|
|
importing
|
|
value(PERIO) type JAHRPER
|
|
value(VARIANT) type COVARIANT .
|
|
methods GET_VARIANT_INFO
|
|
importing
|
|
value(ERKRS) type ERKRS optional
|
|
value(VARIANT) type COVARIANT optional
|
|
exporting
|
|
!COVAD type COVAD .
|
|
methods GET_TABNAME
|
|
importing
|
|
value(ERKRS) type ERKRS optional
|
|
exporting
|
|
!TABNAME type TABNAME .
|
|
methods BUILD_DYNAMIC_QUERY
|
|
importing
|
|
!IV_TYPE type C
|
|
!IT_BPSEL type TT_BPSEL
|
|
returning
|
|
value(RT_DATA) type TT_RECEIVER .
|
|
methods GENERATE_DIST_ID
|
|
importing
|
|
!IS_DATA type ANY
|
|
!IT_BPSEL type TT_BPSEL
|
|
returning
|
|
value(RV_DIST) type PBR_SEQRE .
|
|
methods BUILD_KEY_STRING
|
|
importing
|
|
!IS_DATA type ANY
|
|
!IT_BPSEL type TT_BPSEL
|
|
!IV_TYPE type C
|
|
returning
|
|
value(RV_KEY) type STRING .
|
|
methods SET_SOURCE_INFO
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
returning
|
|
value(RESULT) type BAPIRET2 .
|
|
methods GET_TB_DATA_EXIST_YN
|
|
importing
|
|
value(ERKRS) type ERKRS
|
|
value(VARIANT) type COVARIANT
|
|
value(PERIO) type JAHRPER
|
|
value(TYPE) type ZTBLS
|
|
returning
|
|
value(RESULT) type BAPIRET2 .
|
|
methods BUILD_FIELDLIST
|
|
importing
|
|
!IT_CATALOG type TT_DFIES
|
|
changing
|
|
!CT_FIELDLIST type TT_FIELDLIST .
|
|
methods MAP_DOCUMENT_DATA
|
|
importing
|
|
value(IT_SOURCE) type ANY TABLE
|
|
value(IT_CATALOG) type TT_DFIES
|
|
value(IV_VRGAR) type ANY
|
|
value(IV_REVERSE) type ABAP_BOOL
|
|
value(IV_BUDAT) type DAERF
|
|
changing
|
|
!CT_INPUTDATA type TT_COPA_DATA
|
|
!CV_INDEX type RKE_RECORD_ID .
|
|
methods CREATE_DYNAMIC_TABLE
|
|
importing
|
|
!IV_TABNAME type TABNAME
|
|
returning
|
|
value(RO_TABLE) type ref to DATA .
|
|
methods SET_AUDIT_FIELDS
|
|
changing
|
|
!CS_DATA type TY_DISTINFO .
|
|
methods GENERATE_DYNAMIC_NEW_SQL
|
|
importing
|
|
!IV_SELECT type STRING
|
|
!IV_FROM type STRING
|
|
!IT_WHERE type TABLE
|
|
!IV_GROUP type STRING
|
|
exporting
|
|
!ET_DATA type TT_RECEIVER .
|
|
ENDCLASS.
|
|
|
|
|
|
|
|
CLASS ZCL_COPA_TOPDOWN IMPLEMENTATION.
|
|
|
|
|
|
METHOD build_dynamic_query.
|
|
DATA : l_seq TYPE n VALUE 1,
|
|
lb_first TYPE abap_boolean VALUE 'X'.
|
|
|
|
TYPES : BEGIN OF ty_where,
|
|
seq TYPE n LENGTH 2,
|
|
condition TYPE string,
|
|
END OF ty_where.
|
|
DATA : lt_where TYPE TABLE OF ty_where,
|
|
ls_where TYPE ty_where.
|
|
|
|
DATA: lv_select TYPE string,
|
|
lv_from TYPE string,
|
|
lv_group TYPE string,
|
|
lv_sql TYPE string.
|
|
|
|
DATA: lv_condition TYPE string,
|
|
lv_seq TYPE pu12_seqnr VALUE '0'. "데이타 키(seq)
|
|
|
|
FIELD-SYMBOLS: <fs_sel> TYPE ty_bpsel.
|
|
lv_from = gv_source.
|
|
|
|
" 필수 필드 추가 (rec_waers) 통화키
|
|
lv_select = |{ lv_select } t1~REC_WAERS AS rec_waers, |.
|
|
lv_group = |{ lv_group } REC_WAERS, |.
|
|
|
|
* WHERE 조건
|
|
"통화유형 필드 필수
|
|
ls_where = VALUE #( seq = 0
|
|
condition = |t1~PALEDGER = '01'| "경영단위 통화 데이타 사용
|
|
).
|
|
APPEND ls_where TO lt_where.
|
|
|
|
"기간/연도 필드 필수
|
|
ls_where = VALUE #( seq = 1
|
|
condition = |AND t1~perio = '{ working_info-perio }'|
|
|
).
|
|
APPEND ls_where TO lt_where.
|
|
|
|
CASE iv_type.
|
|
WHEN 'S'. " 센더 쿼리 구성
|
|
"동일 필드(FNAM)가 2개 이상인 필드명 추출(OR 연산자 생성 목적)
|
|
TYPES: BEGIN OF ty_cnt,
|
|
fnam TYPE fieldname,
|
|
cnt TYPE i,
|
|
END OF ty_cnt.
|
|
|
|
DATA: lt_grp TYPE TABLE OF ty_cnt,
|
|
lt_OR TYPE TABLE OF fieldname.
|
|
|
|
lt_grp = VALUE #(
|
|
FOR GROUPS group OF row IN it_bpsel WHERE ( sort = '0200' )
|
|
GROUP BY ( fnam = row-fnam )
|
|
( fnam = group-fnam
|
|
cnt = REDUCE i( INIT x = 0 FOR r IN GROUP group NEXT x = x + 1 ) )
|
|
).
|
|
|
|
lt_OR = VALUE #( FOR or IN lt_grp WHERE ( cnt > 1 ) ( or-fnam ) ).
|
|
|
|
" SELECT 절 구성 (SORT=0270, LOW=X)
|
|
LOOP AT it_bpsel ASSIGNING <fs_sel> WHERE sort = '0270' AND low = 'X'.
|
|
lv_select = |{ lv_select } t1~{ <fs_sel>-fnam },|.
|
|
lv_group = |{ lv_group }{ <fs_sel>-fnam },|.
|
|
ENDLOOP.
|
|
|
|
" SUM 필드 추가 (SORT=0300, LOW=X)
|
|
LOOP AT it_bpsel ASSIGNING <fs_sel> WHERE sort = '0300' AND low = 'X'.
|
|
lv_select = |{ lv_select } SUM( t1~{ <fs_sel>-fnam } ) AS { <fs_sel>-fnam },|.
|
|
ENDLOOP.
|
|
|
|
" WHERE 조건 (SORT=200) - 단일조건 AND ...AND 연결
|
|
LOOP AT it_bpsel ASSIGNING <fs_sel> WHERE sort = '0200'.
|
|
CLEAR : ls_where, lv_condition.
|
|
|
|
cl_abap_dyn_prg=>check_column_name( <fs_sel>-fnam ).
|
|
IF <fs_sel>-low <> '*' AND <fs_sel>-high <> '*'.
|
|
|
|
" lt_OR에 <fs_sel>-fnam이 있는 경우 제외
|
|
READ TABLE lt_OR WITH TABLE KEY table_line = <fs_sel>-fnam TRANSPORTING NO FIELDS.
|
|
IF sy-subrc = 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
l_seq += 1.
|
|
|
|
CASE <fs_sel>-option.
|
|
WHEN 'BT'.
|
|
lv_condition = |AND t1~{ <fs_sel>-fnam } BETWEEN '{ <fs_sel>-low }' AND '{ <fs_sel>-high }'|.
|
|
WHEN 'EQ'.
|
|
lv_condition = |AND t1~{ <fs_sel>-fnam } = '{ <fs_sel>-low }'|.
|
|
ENDCASE.
|
|
|
|
ls_where-seq = l_seq. "SQL의 where조건의 순서
|
|
ls_where-condition = lv_condition.
|
|
APPEND ls_where TO lt_where.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
|
|
" WHERE 조건 (SORT=200) - 다중조건 AND ( a OR b ...)
|
|
CLEAR : ls_where, lv_condition.
|
|
LOOP AT it_bpsel ASSIGNING <fs_sel> WHERE sort = '0200'.
|
|
|
|
cl_abap_dyn_prg=>check_column_name( <fs_sel>-fnam ).
|
|
IF <fs_sel>-low <> '*' AND <fs_sel>-high <> '*'.
|
|
|
|
" lt_OR에 <fs_sel>-fnam이 있는 경우 제외
|
|
READ TABLE lt_OR WITH TABLE KEY table_line = <fs_sel>-fnam TRANSPORTING NO FIELDS.
|
|
IF sy-subrc NE 0.
|
|
CONTINUE.
|
|
ENDIF.
|
|
|
|
AT NEW fnam.
|
|
CLEAR : ls_where, lv_condition.
|
|
lb_first = 'X'. "첫번째 item으로 설정
|
|
l_seq += 1.
|
|
lv_condition = |AND ( |.
|
|
ls_where-seq = l_seq. "SQL의 where조건의 순서
|
|
ENDAT.
|
|
|
|
IF lb_first = 'X'.
|
|
CASE <fs_sel>-option.
|
|
WHEN 'BT'.
|
|
lv_condition = lv_condition && |t1~{ <fs_sel>-fnam } BETWEEN '{ <fs_sel>-low }' AND '{ <fs_sel>-high }'|.
|
|
WHEN 'EQ'.
|
|
lv_condition = lv_condition && |t1~{ <fs_sel>-fnam } = '{ <fs_sel>-low }'|.
|
|
ENDCASE.
|
|
ELSE.
|
|
CASE <fs_sel>-option.
|
|
WHEN 'BT'.
|
|
lv_condition = lv_condition && | OR t1~{ <fs_sel>-fnam } BETWEEN '{ <fs_sel>-low }' AND '{ <fs_sel>-high }'|.
|
|
WHEN 'EQ'.
|
|
lv_condition = lv_condition && | OR t1~{ <fs_sel>-fnam } = '{ <fs_sel>-low }'|.
|
|
ENDCASE.
|
|
ENDIF.
|
|
CLEAR : lb_first.
|
|
|
|
AT END OF fnam.
|
|
lv_condition = lv_condition && | )|.
|
|
|
|
ls_where-condition = lv_condition.
|
|
APPEND ls_where TO lt_where.
|
|
CLEAR : ls_where, lv_condition.
|
|
ENDAT.
|
|
|
|
ENDIF.
|
|
ENDLOOP.
|
|
|
|
|
|
|
|
WHEN 'R'. " 리시버 쿼리 구성
|
|
" SELECT 절 (SORT=270/201, LOW=X)
|
|
LOOP AT it_bpsel ASSIGNING <fs_sel> WHERE ( sort = '0270' OR sort = '0201' ) AND low = 'X'.
|
|
lv_select = |{ lv_select } t1~{ <fs_sel>-fnam },|.
|
|
lv_group = |{ lv_group }{ <fs_sel>-fnam },|.
|
|
ENDLOOP.
|
|
|
|
" SUM 필드 추가 (SORT=100, FNAM=WKOFNAM, LOW=X)
|
|
LOOP AT it_bpsel ASSIGNING <fs_sel> WHERE sort = '0100' AND fnam = 'WKOFNAM'. " ★ 수정
|
|
lv_select = |{ lv_select } SUM( t1~{ <fs_sel>-low } ) AS { <fs_sel>-low },|.
|
|
ENDLOOP.
|
|
|
|
* " WHERE 조건 (SORT=0272 → SORT=0274 → SORT=0273 매핑)
|
|
DATA : it_0274 TYPE TABLE OF ty_bpsel,
|
|
it_0273 TYPE TABLE OF ty_bpsel.
|
|
|
|
|
|
FIELD-SYMBOLS: <fs_0272> TYPE ty_bpsel,
|
|
<fs_0273> TYPE ty_bpsel,
|
|
<fs_0274> TYPE ty_bpsel.
|
|
|
|
it_0274 = VALUE #( FOR wa IN it_bpsel WHERE ( sort = '0274' ) ( wa ) ).
|
|
it_0273 = VALUE #( FOR wa IN it_bpsel WHERE ( sort = '0273' ) ( wa ) ).
|
|
|
|
SORT it_0274 BY fnam low.
|
|
SORT it_0273 BY option fnam.
|
|
|
|
"where 조건을 만들어야 하는 필드조건(들)
|
|
LOOP AT it_bpsel ASSIGNING <fs_0272> WHERE sort = '0272'.
|
|
lb_first = 'X'. "첫번째 item으로 설정
|
|
LOOP AT it_0274 ASSIGNING <fs_0274> WHERE low = <fs_0272>-fnam.
|
|
AT NEW fnam.
|
|
CLEAR : ls_where, lv_condition.
|
|
l_seq += 1.
|
|
lv_condition = | AND ( |.
|
|
ls_where-seq = l_seq. "SQL의 where조건의 순서
|
|
ENDAT.
|
|
|
|
LOOP AT it_0273 ASSIGNING <fs_0273> WHERE fnam = <fs_0274>-high.
|
|
IF lb_first = 'X'.
|
|
"첫번째 인 경우
|
|
CASE <fs_0273>-option.
|
|
WHEN 'BT'.
|
|
lv_condition = lv_condition && |t1~{ <fs_0274>-fnam } BETWEEN '{ <fs_0273>-low }' AND '{ <fs_0273>-high }'|.
|
|
WHEN 'EQ'.
|
|
lv_condition = lv_condition && |t1~{ <fs_0274>-fnam } = '{ <fs_0273>-low }'|.
|
|
ENDCASE.
|
|
ELSE.
|
|
"2번째 이상인 경우 (OR 연산자 필요)
|
|
CASE <fs_0273>-option.
|
|
WHEN 'BT'.
|
|
lv_condition = lv_condition && | OR t1~{ <fs_0274>-fnam } BETWEEN '{ <fs_0273>-low }' AND '{ <fs_0273>-high }'|.
|
|
WHEN 'EQ'.
|
|
lv_condition = lv_condition && | OR t1~{ <fs_0274>-fnam } = '{ <fs_0273>-low }'|.
|
|
ENDCASE.
|
|
ENDIF.
|
|
|
|
CLEAR lb_first. "이후에 들어오는 경우는 OR 연결로 처리할 후속 순번.
|
|
ENDLOOP.
|
|
|
|
AT END OF fnam.
|
|
lv_condition = lv_condition && |)|.
|
|
|
|
ls_where-condition = lv_condition.
|
|
APPEND ls_where TO lt_where.
|
|
ENDAT.
|
|
|
|
ENDLOOP.
|
|
|
|
ENDLOOP.
|
|
|
|
|
|
ENDCASE.
|
|
|
|
" 최종 쿼리 정리
|
|
lv_select = replace( val = lv_select sub = ',' with = '' occ = -1 ).
|
|
lv_group = replace( val = lv_group sub = ',' with = '' occ = -1 ).
|
|
|
|
" 동적 SQL 실행
|
|
generate_dynamic_new_sql(
|
|
EXPORTING
|
|
iv_select = lv_select
|
|
iv_from = lv_from
|
|
it_where = lt_where
|
|
iv_group = lv_group
|
|
IMPORTING
|
|
et_data = rt_data
|
|
).
|
|
|
|
" DIST_ID 처리
|
|
CASE iv_type.
|
|
WHEN 'S'.
|
|
LOOP AT rt_data ASSIGNING FIELD-SYMBOL(<fs_sender>).
|
|
<fs_sender>-perio = working_info-perio.
|
|
<fs_sender>-gjahr = working_info-perio(4).
|
|
<fs_sender>-perde = working_info-perio+4(3).
|
|
<fs_sender>-variant = working_info-variant.
|
|
|
|
<fs_sender>-dist_id = generate_dist_id(
|
|
is_data = <fs_sender>
|
|
it_bpsel = it_bpsel
|
|
).
|
|
INSERT VALUE #(
|
|
key_string = build_key_string(
|
|
is_data = <fs_sender>
|
|
it_bpsel = it_bpsel
|
|
iv_type = 'S'
|
|
)
|
|
dist_id = <fs_sender>-dist_id
|
|
) INTO TABLE mt_sender_keys.
|
|
ENDLOOP.
|
|
|
|
WHEN 'R'.
|
|
LOOP AT rt_data ASSIGNING FIELD-SYMBOL(<fs_receiver>).
|
|
lv_seq = lv_seq + 1.
|
|
<fs_receiver>-perio = working_info-perio.
|
|
<fs_receiver>-gjahr = working_info-perio(4).
|
|
<fs_receiver>-perde = working_info-perio+4(3).
|
|
<fs_receiver>-variant = working_info-variant.
|
|
<fs_receiver>-seq = lv_seq.
|
|
DATA(lv_receiver_key) = build_key_string(
|
|
is_data = <fs_receiver>
|
|
it_bpsel = it_bpsel
|
|
iv_type = 'R'
|
|
).
|
|
IF line_exists( mt_sender_keys[ key_string = lv_receiver_key ] ).
|
|
<fs_receiver>-dist_id = mt_sender_keys[ key_string = lv_receiver_key ]-dist_id.
|
|
ELSE.
|
|
<fs_receiver>-dist_id = '999999999'.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
ENDCASE.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD build_fieldlist.
|
|
" 필드리스트 생성 로직
|
|
APPEND VALUE #( fieldname = 'VRGAR' ) TO ct_fieldlist.
|
|
APPEND VALUE #( fieldname = 'BELNR_SENDER' ) TO ct_fieldlist.
|
|
APPEND VALUE #( fieldname = 'POSNR_SENDER' ) TO ct_fieldlist.
|
|
LOOP AT it_catalog INTO DATA(ls_catalog).
|
|
APPEND VALUE #( fieldname = ls_catalog-fieldname ) TO ct_fieldlist.
|
|
ENDLOOP.
|
|
endmethod.
|
|
|
|
|
|
METHOD build_key_string.
|
|
LOOP AT CAST cl_abap_structdescr( cl_abap_structdescr=>describe_by_data( is_data ) )->components
|
|
ASSIGNING FIELD-SYMBOL(<fs_comp>).
|
|
ASSIGN COMPONENT <fs_comp>-name OF STRUCTURE is_data TO FIELD-SYMBOL(<fs_value>).
|
|
|
|
CASE iv_type.
|
|
WHEN 'S'. " 센더: SORT=0270 + LOW=X (SUM 필드 제외)
|
|
READ TABLE it_bpsel TRANSPORTING NO FIELDS
|
|
WITH KEY fnam = <fs_comp>-name
|
|
sort = '0270'
|
|
low = 'X'.
|
|
IF sy-subrc = 0 AND NOT <fs_comp>-name CS 'SUM'.
|
|
rv_key = |{ rv_key }{ <fs_value> }|.
|
|
ENDIF.
|
|
|
|
WHEN 'R'. " 리시버: ★★★ SENDER와 동일한 SORT=270 필드만 사용 ★★★
|
|
READ TABLE it_bpsel TRANSPORTING NO FIELDS
|
|
WITH KEY fnam = <fs_comp>-name
|
|
sort = '0270' " ← 201 제외
|
|
low = 'X'.
|
|
IF sy-subrc = 0.
|
|
rv_key = |{ rv_key }{ <fs_value> }|.
|
|
ENDIF.
|
|
ENDCASE.
|
|
ENDLOOP.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD constructor.
|
|
|
|
DATA: lv_tabname TYPE tabname.
|
|
|
|
" 환경정보에서 관리 테이블명 조회
|
|
CALL FUNCTION 'ZTOPDOWN_ENV'
|
|
IMPORTING
|
|
tb_name = lv_tabname.
|
|
|
|
" 관리 테이블 정보 로딩
|
|
SELECT type,
|
|
tbname,
|
|
text
|
|
FROM (lv_tabname)
|
|
INTO CORRESPONDING FIELDS OF TABLE @gt_mng_table.
|
|
|
|
LOOP AT gt_mng_table INTO DATA(ls_table).
|
|
CASE ls_table-type.
|
|
WHEN '1'. gv_manager = ls_table-tbname.
|
|
WHEN '2'. gv_variant = ls_table-tbname.
|
|
WHEN '3'. gv_sender = ls_table-tbname.
|
|
WHEN '4'. gv_receiver = ls_table-tbname.
|
|
WHEN '5'. gv_result = ls_table-tbname.
|
|
WHEN '6'. gv_target = ls_table-tbname.
|
|
WHEN '7'. gv_distinfo = ls_table-tbname.
|
|
WHEN '8'. gv_distrule = ls_table-tbname.
|
|
ENDCASE.
|
|
ENDLOOP.
|
|
|
|
" 동적 테이블 구조 생성 및 인스턴스 할당 (RETURNING 사용)
|
|
manager_table = me->create_dynamic_table( gv_manager ).
|
|
variant_table = me->create_dynamic_table( gv_variant ).
|
|
sender_table = me->create_dynamic_table( gv_sender ).
|
|
receiver_table = me->create_dynamic_table( gv_receiver ).
|
|
result_table = me->create_dynamic_table( gv_result ).
|
|
* target_table = me->create_dynamic_table( gv_target ). " 필요시 활성화
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD create_dynamic_table.
|
|
DATA: lo_struct_desc TYPE REF TO cl_abap_structdescr,
|
|
lo_table_desc TYPE REF TO cl_abap_tabledescr.
|
|
|
|
TRY.
|
|
lo_struct_desc ?= cl_abap_structdescr=>describe_by_name( iv_tabname ).
|
|
lo_table_desc = cl_abap_tabledescr=>create(
|
|
p_line_type = lo_struct_desc
|
|
p_table_kind = cl_abap_tabledescr=>tablekind_std
|
|
).
|
|
CREATE DATA ro_table TYPE HANDLE lo_table_desc.
|
|
CATCH cx_sy_create_data_error INTO DATA(lx_error).
|
|
MESSAGE lx_error->get_text( ) TYPE 'E'.
|
|
ENDTRY.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD delete_topdown_tb_data.
|
|
|
|
DATA: lv_tabname TYPE tabname,
|
|
l_check TYPE c,
|
|
l_exist TYPE bapiret2.
|
|
|
|
" 1. 필수 파라미터 체크
|
|
IF erkrs IS INITIAL OR perio IS INITIAL OR variant IS INITIAL OR type IS INITIAL.
|
|
gv_message = TEXT-012.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '012' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 2. 삭제 대상 테이블 결정
|
|
CASE type.
|
|
* WHEN '1'. "CBO테이블관리
|
|
WHEN '2'. lv_tabname = gv_variant.
|
|
WHEN '3'. lv_tabname = gv_sender.
|
|
WHEN '4'. lv_tabname = gv_receiver.
|
|
WHEN '5'. lv_tabname = gv_result.
|
|
WHEN '6'. lv_tabname = gv_target.
|
|
WHEN '7'. lv_tabname = gv_distinfo.
|
|
* WHEN '8'. lv_tabname = gv_distrule. "cbo 조건 데이타 삭제 불가. 별도 관리화면에서...
|
|
WHEN OTHERS.
|
|
gv_message = TEXT-019.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '019' message = gv_message ).
|
|
RETURN.
|
|
ENDCASE.
|
|
|
|
" 3. 전표 발행 상태 체크
|
|
SELECT SINGLE post INTO @l_check FROM (gv_variant)
|
|
WHERE perio = @perio AND variant = @variant.
|
|
|
|
IF l_check = 'X'.
|
|
gv_message = TEXT-018.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '018' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 4. 데이터 존재 여부 확인
|
|
CALL METHOD me->get_tb_data_exist_yn
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
variant = variant
|
|
perio = perio
|
|
type = type
|
|
RECEIVING
|
|
result = l_exist.
|
|
|
|
IF l_exist-type = 'E'.
|
|
gv_message = TEXT-007.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '007' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 5. 데이터 삭제
|
|
IF type = '2' OR type = '3' OR type = '4' OR type = '5' OR type = '6'.
|
|
DELETE FROM (lv_tabname)
|
|
WHERE variant = @variant AND perio = @perio.
|
|
|
|
ELSEIF type = '7' OR type = '8'.
|
|
DELETE FROM (lv_tabname)
|
|
WHERE erkrs = @erkrs AND variant = @variant AND perio = @perio.
|
|
|
|
ENDIF.
|
|
|
|
|
|
IF sy-subrc <> 0.
|
|
ROLLBACK WORK.
|
|
gv_message = TEXT-017.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '017' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 6. 상태 플래그 초기화
|
|
CASE type.
|
|
WHEN '3'.
|
|
UPDATE (gv_variant)
|
|
SET sender = ''
|
|
WHERE perio = @perio AND variant = @variant.
|
|
WHEN '4'.
|
|
UPDATE (gv_variant)
|
|
SET receiver = ''
|
|
WHERE perio = @perio AND variant = @variant.
|
|
WHEN '5'.
|
|
UPDATE (gv_variant)
|
|
SET proc_dist = ''
|
|
WHERE perio = @perio AND variant = @variant.
|
|
ENDCASE.
|
|
|
|
IF sy-subrc <> 0.
|
|
ROLLBACK WORK.
|
|
gv_message = TEXT-017.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '017' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
COMMIT WORK.
|
|
|
|
gv_message = TEXT-016.
|
|
result = VALUE #( type = 'S' id = 'SUCCESS' number = '016' message = gv_message ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD execute_topdown_distribute.
|
|
TYPES : BEGIN OF ty_dist.
|
|
INCLUDE TYPE ty_receiver.
|
|
TYPES: srec_waers TYPE waers,
|
|
send_tot TYPE wzgxxx9,
|
|
rrec_waers TYPE waers,
|
|
skf_val TYPE wzgxxx9,
|
|
skf_sum TYPE wzgxxx9,
|
|
END OF ty_dist.
|
|
DATA : lt_data TYPE TABLE OF ty_dist.
|
|
|
|
DATA: lt_source TYPE TABLE OF string,
|
|
lv_prog TYPE progname,
|
|
lv_sender_val TYPE fieldname,
|
|
lv_receiver_val TYPE fieldname.
|
|
|
|
DATA : lt_field TYPE TABLE OF dfies.
|
|
|
|
DATA : l_dist_value TYPE wzgxxx9,
|
|
l_dist_id_sum TYPE wzgxxx9,
|
|
l_dist_done_sum TYPE wzgxxx9,
|
|
l_diff_val TYPE wzgxxx9.
|
|
DATA : l_last_record_yn TYPE boe_bool.
|
|
DATA : lt_result TYPE tt_result,
|
|
ls_result TYPE ty_result.
|
|
|
|
DATA : l_check TYPE c,
|
|
ans TYPE c LENGTH 8.
|
|
|
|
" 1. 필수 파라미터 체크
|
|
IF erkrs IS INITIAL OR perio IS INITIAL OR variant IS INITIAL.
|
|
gv_message = TEXT-012.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '012' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 2. 전표 발행 상태 체크
|
|
SELECT SINGLE post INTO @l_check FROM (gv_variant)
|
|
WHERE perio = @perio AND variant = @variant.
|
|
|
|
IF l_check = 'X'.
|
|
gv_message = TEXT-018.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '018' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 3. 이전 배부 수행 결과가 있을 경우, 삭제 후 재 처리 안내.
|
|
CLEAR : l_check.
|
|
SELECT SINGLE proc_dist INTO @l_check FROM (gv_variant)
|
|
WHERE perio = @perio AND variant = @variant.
|
|
|
|
IF l_check = 'X'.
|
|
CALL FUNCTION 'POPUP_TO_CONFIRM'
|
|
EXPORTING
|
|
titlebar = 'Title POPUP_TO_CONFIRM'
|
|
text_question = TEXT-006
|
|
text_button_1 = 'OK'
|
|
icon_button_1 = 'ICON_CHECKED'
|
|
text_button_2 = 'NO'
|
|
icon_button_2 = 'ICON_NO'
|
|
display_cancel_button = ' '
|
|
popup_type = 'ICON_MESSAGE_ERROR'
|
|
IMPORTING
|
|
answer = ans.
|
|
|
|
IF ans = 2.
|
|
RETURN.
|
|
ELSE. "이전 데이타 삭제.
|
|
CALL METHOD me->delete_topdown_tb_data
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
variant = variant
|
|
perio = perio
|
|
type = '5'
|
|
RECEIVING
|
|
result = result.
|
|
|
|
IF result-type = 'E'.
|
|
gv_message = TEXT-017.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '017' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
ASSIGN ls_result TO FIELD-SYMBOL(<fs_result>).
|
|
|
|
* variant별로 실사용 하는 필드 카탈로그 정보 가져오기.
|
|
CALL METHOD me->get_field_catalog
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
perio = perio
|
|
variant = variant
|
|
IMPORTING
|
|
fieldcatalog = lt_field
|
|
RECEIVING
|
|
result = result.
|
|
|
|
* 카탈로그 중에서, 센더와 리시버의 값필드 확인
|
|
LOOP AT lt_field INTO DATA(ls_field) WHERE inttype IS NOT INITIAL.
|
|
CASE ls_field-inttype.
|
|
WHEN 'T'. "리시버 값필드(배부 기준필드)
|
|
lv_receiver_val = ls_field-fieldname.
|
|
WHEN 'C'. "센더 값필드(배부 할 금액 필드)
|
|
lv_sender_val = ls_field-fieldname.
|
|
ENDCASE.
|
|
ENDLOOP.
|
|
|
|
|
|
* 배부 수행 데이타 생성.
|
|
* 다중 테이블 조인시 동적 쿼리 안되어..부득이 서브루틴풀로 구현.
|
|
APPEND `REPORT ZDYNAMIC_QUERY.` TO lt_source.
|
|
APPEND `FORM select_query CHANGING lt_data TYPE ANY TABLE.` TO lt_source.
|
|
APPEND | SELECT | TO lt_source.
|
|
|
|
LOOP AT lt_field INTO DATA(ls_field_select) WHERE inttype IS INITIAL.
|
|
APPEND | q~{ ls_field_select-fieldname }, | TO lt_source.
|
|
ENDLOOP.
|
|
|
|
APPEND | p~rec_waers as srec_waers, | TO lt_source.
|
|
APPEND | p~{ lv_sender_val } as send_tot, | TO lt_source.
|
|
APPEND | q~rec_waers as rrec_waers, | TO lt_source.
|
|
APPEND | q~{ lv_receiver_val } as skf_val, | TO lt_source.
|
|
APPEND | SUM( q~{ lv_receiver_val } ) OVER( PARTITION BY p~dist_id ) AS skf_sum | TO lt_source.
|
|
APPEND | FROM { gv_sender } AS p | TO lt_source.
|
|
APPEND | LEFT OUTER JOIN { gv_receiver } AS q | TO lt_source.
|
|
APPEND | ON p~perio = q~perio | TO lt_source.
|
|
APPEND | AND p~variant = q~variant | TO lt_source.
|
|
APPEND | AND p~dist_id = q~dist_id | TO lt_source.
|
|
APPEND | WHERE p~perio = '{ perio }' | TO lt_source.
|
|
APPEND | AND p~variant = '{ variant }' | TO lt_source.
|
|
APPEND | INTO CORRESPONDING FIELDS OF TABLE @lt_data. | TO lt_source.
|
|
APPEND `ENDFORM.` TO lt_source.
|
|
|
|
* " 서브루틴 풀 생성
|
|
GENERATE SUBROUTINE POOL lt_source NAME lv_prog.
|
|
IF sy-subrc = 0.
|
|
TRY.
|
|
" CHANGING 파라미터를 통해 데이터 전달
|
|
PERFORM select_query IN PROGRAM (lv_prog) CHANGING lt_data.
|
|
MESSAGE |{ lines( lt_data ) }건 데이터 수신 완료| TYPE 'S'.
|
|
|
|
CATCH cx_sy_dyn_call_error INTO DATA(lx_error).
|
|
MESSAGE |동적 호출 오류: { lx_error->get_text( ) }| TYPE 'E'.
|
|
CLEANUP.
|
|
" 예외 발생 시에도 서브루틴 풀 정리
|
|
DELETE REPORT lv_prog.
|
|
ENDTRY.
|
|
|
|
" 서브루틴 풀 삭제 (메모리에서 제거)
|
|
DELETE REPORT lv_prog.
|
|
IF sy-subrc = 0.
|
|
MESSAGE |동적 프로그램 { lv_prog } 삭제 완료| TYPE 'S'.
|
|
ELSE.
|
|
MESSAGE |동적 프로그램 { lv_prog } 삭제 실패 - 이미 삭제됨| TYPE 'S'.
|
|
ENDIF.
|
|
ELSE.
|
|
MESSAGE |서브루틴 풀 생성 실패: { sy-subrc }| TYPE 'E'.
|
|
ENDIF.
|
|
|
|
" 메모리 정리 (혹시 모를 잔여 데이터 정리)
|
|
CLEAR: lt_source.
|
|
|
|
* 배부 작업 시작 - Record별로 배부하기 용이하게 하기 위하여 위 서브루틴 풀 사용하여 쿼리 수행
|
|
* 레코드 데이타 항목으로 배부 수행 가능.
|
|
|
|
SORT lt_data BY dist_id seq.
|
|
LOOP AT lt_data INTO DATA(ls_data).
|
|
AT NEW dist_id.
|
|
CLEAR : l_dist_id_sum, l_dist_done_sum, l_diff_val, l_last_record_yn .
|
|
ENDAT.
|
|
|
|
CLEAR : l_dist_value.
|
|
MOVE-CORRESPONDING ls_data TO <fs_result>.
|
|
l_dist_id_sum = ls_data-send_tot.
|
|
|
|
"현재 리시버에 할당할 배부 금액 계산
|
|
l_dist_value = ls_data-send_tot * ( ls_data-skf_val / ls_data-skf_sum ).
|
|
|
|
"DIST_ID 별로 실제 배부된 금액 누적(추후 단수 차이 보정용)
|
|
l_dist_done_sum = l_dist_done_sum + l_dist_value.
|
|
|
|
AT END OF dist_id.
|
|
"마지막 레코드인 경우 flag 체크 - 단수차이 조정 대상.
|
|
l_last_record_yn = 'X'.
|
|
ENDAT.
|
|
|
|
IF l_last_record_yn = 'X'.
|
|
l_diff_val = l_dist_id_sum - l_dist_done_sum.
|
|
ENDIF.
|
|
|
|
<fs_result>-rec_waers = ls_data-srec_waers.
|
|
|
|
* 배부 결과 값은 센더의 값필드 항목으로 리시버 데이타에 저장.
|
|
ASSIGN COMPONENT lv_sender_val OF STRUCTURE <fs_result> TO FIELD-SYMBOL(<fs_value>).
|
|
<fs_value> = l_dist_value + l_diff_val.
|
|
|
|
APPEND ls_result TO lt_result.
|
|
ENDLOOP.
|
|
|
|
"결과 저장
|
|
IF save_yn = 'X'.
|
|
INSERT (gv_result) FROM TABLE lt_result.
|
|
IF sy-subrc NE 0.
|
|
ROLLBACK WORK.
|
|
ENDIF.
|
|
|
|
UPDATE (gv_variant)
|
|
SET proc_dist = 'X'
|
|
WHERE perio = perio
|
|
AND variant = variant.
|
|
IF sy-subrc NE 0.
|
|
ROLLBACK WORK.
|
|
ENDIF.
|
|
|
|
COMMIT WORK.
|
|
ENDIF.
|
|
|
|
rt_result[] = lt_result[].
|
|
|
|
|
|
" 성공 메시지 추가
|
|
gv_message = TEXT-016.
|
|
result = VALUE #(
|
|
type = 'S'
|
|
id = 'SUCCESS'
|
|
number = '016'
|
|
message = gv_message ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD generate_dist_id.
|
|
DATA(lv_key) = build_key_string(
|
|
is_data = is_data
|
|
it_bpsel = it_bpsel
|
|
iv_type = 'S' " 센더용 키 생성
|
|
).
|
|
|
|
" 기존 키 존재 시 재사용
|
|
IF line_exists( mt_sender_keys[ key_string = lv_key ] ).
|
|
rv_dist = mt_sender_keys[ key_string = lv_key ]-dist_id.
|
|
ELSE.
|
|
ADD 1 TO gv_dist_counter.
|
|
rv_dist = gv_dist_counter.
|
|
ENDIF.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD generate_dynamic_new_sql.
|
|
|
|
DATA: lt_source TYPE TABLE OF string,
|
|
lv_prog TYPE progname,
|
|
lt_data TYPE tt_receiver.
|
|
|
|
FIELD-SYMBOLS: <ls_row> TYPE any,
|
|
<lv_value> TYPE any.
|
|
|
|
" 임시 프로그램 소스 생성
|
|
APPEND `REPORT ZDYNAMIC_QUERY.` TO lt_source.
|
|
APPEND `FORM execute_query CHANGING ct_result TYPE ANY TABLE.` TO lt_source.
|
|
APPEND ` DATA: lt_data TYPE table of ZSTOP_RECEIVER.` TO lt_source.
|
|
APPEND | SELECT { iv_select }| TO lt_source.
|
|
APPEND | FROM { iv_from } AS t1| TO lt_source.
|
|
|
|
|
|
IF it_where[] IS NOT INITIAL.
|
|
APPEND | WHERE | TO lt_source.
|
|
|
|
LOOP AT it_where ASSIGNING <ls_row>.
|
|
ASSIGN COMPONENT 'CONDITION' OF STRUCTURE <ls_row> TO <lv_value>.
|
|
IF sy-subrc = 0.
|
|
APPEND <lv_value> TO lt_source.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
ENDIF.
|
|
|
|
|
|
IF iv_group IS NOT INITIAL.
|
|
APPEND | GROUP BY { iv_group }| TO lt_source.
|
|
ENDIF.
|
|
APPEND | INTO CORRESPONDING FIELDS OF TABLE @lt_data.| TO lt_source.
|
|
* APPEND | INTO TABLE @data(lt_data).| TO lt_source.
|
|
APPEND ` ct_result = lt_data.` TO lt_source.
|
|
APPEND `ENDFORM.` TO lt_source.
|
|
|
|
" 서브루틴 풀 생성
|
|
GENERATE SUBROUTINE POOL lt_source NAME lv_prog.
|
|
IF sy-subrc = 0.
|
|
TRY.
|
|
" CHANGING 파라미터를 통해 데이터 전달
|
|
PERFORM execute_query IN PROGRAM (lv_prog) CHANGING lt_data.
|
|
|
|
et_data = lt_data.
|
|
MESSAGE |{ lines( et_data ) }건 데이터 수신 완료| TYPE 'S'.
|
|
|
|
CATCH cx_sy_dyn_call_error INTO DATA(lx_error).
|
|
MESSAGE |동적 호출 오류: { lx_error->get_text( ) }| TYPE 'E'.
|
|
|
|
CLEANUP.
|
|
" 예외 발생 시에도 서브루틴 풀 정리
|
|
DELETE REPORT lv_prog.
|
|
ENDTRY.
|
|
|
|
" 서브루틴 풀 삭제 (메모리에서 제거)
|
|
DELETE REPORT lv_prog.
|
|
IF sy-subrc = 0.
|
|
MESSAGE |동적 프로그램 { lv_prog } 삭제 완료| TYPE 'S'.
|
|
ELSE.
|
|
MESSAGE |동적 프로그램 { lv_prog } 삭제 실패 - 이미 삭제됨| TYPE 'S'.
|
|
ENDIF.
|
|
|
|
ELSE.
|
|
MESSAGE |서브루틴 풀 생성 실패: { sy-subrc }| TYPE 'E'.
|
|
ENDIF.
|
|
|
|
" 메모리 정리 (혹시 모를 잔여 데이터 정리)
|
|
CLEAR: lt_data, lt_source.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_copa_doc_list.
|
|
DATA : l_check TYPE c.
|
|
|
|
DATA: lt_source TYPE TABLE OF string,
|
|
lv_prog TYPE progname,
|
|
lv_sender_val TYPE fieldname,
|
|
lv_receiver_val TYPE fieldname.
|
|
|
|
DATA : lt_data TYPE TABLE OF ty_target,
|
|
lt_field TYPE TABLE OF dfies.
|
|
|
|
DATA : ls_doc TYPE ty_target.
|
|
|
|
" 필수 파라미터 점검
|
|
IF erkrs IS INITIAL OR perio IS INITIAL OR variant IS INITIAL.
|
|
gv_message = TEXT-012.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '012' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
"Source 테이블 정보 세팅
|
|
me->get_tabname( EXPORTING erkrs = erkrs IMPORTING tabname = gv_source ).
|
|
|
|
" 전표 발행 상태 체크
|
|
SELECT SINGLE post INTO @l_check FROM (gv_variant)
|
|
WHERE perio = @perio AND variant = @variant.
|
|
|
|
IF l_check NE 'X'.
|
|
gv_message = TEXT-023.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '023' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
|
|
* variant별로 실사용 하는 필드 카탈로그 정보 가져오기.
|
|
me->get_field_catalog( EXPORTING erkrs = erkrs
|
|
perio = perio
|
|
variant = variant
|
|
IMPORTING fieldcatalog = lt_field
|
|
RECEIVING result = result ).
|
|
|
|
* 카탈로그 중에서, 센더와 리시버의 값필드 확인
|
|
LOOP AT lt_field INTO DATA(ls_field) WHERE inttype IS NOT INITIAL.
|
|
CASE ls_field-inttype.
|
|
WHEN 'T'. "리시버 값필드(배부 기준필드)
|
|
lv_receiver_val = ls_field-fieldname.
|
|
WHEN 'C'. "센더 값필드(배부 할 금액 필드)
|
|
lv_sender_val = ls_field-fieldname.
|
|
ENDCASE.
|
|
ENDLOOP.
|
|
|
|
* 배부 수행 데이타 생성.
|
|
* 다중 테이블 조인시 동적 쿼리 안되어..부득이 서브루틴풀로 구현.
|
|
APPEND `REPORT ZDYNAMIC_QUERY.` TO lt_source.
|
|
APPEND `FORM select_query CHANGING lt_data TYPE ANY TABLE.` TO lt_source.
|
|
APPEND | SELECT | TO lt_source.
|
|
|
|
APPEND | p~vrgar, | TO lt_source.
|
|
APPEND | p~belnr, | TO lt_source.
|
|
APPEND | q~belnr AS STO_BELNR, | TO lt_source. "원본전표에 역분개 전표 번호를 위치(standard 전표 상태와 반대로 표기)
|
|
APPEND | p~belnr_sender, | TO lt_source.
|
|
APPEND | p~posnr_sender, | TO lt_source.
|
|
|
|
LOOP AT lt_field INTO DATA(ls_field_select) WHERE inttype IS INITIAL.
|
|
"CO-PA 전표 항목이 아닌 필드는 제외.
|
|
CHECK ls_field_select-fieldname NE 'VARIANT' AND ls_field_select-fieldname NE 'DIST_ID' AND ls_field_select-fieldname NE 'SEQ'.
|
|
APPEND | p~{ ls_field_select-fieldname }, | TO lt_source.
|
|
ENDLOOP.
|
|
|
|
APPEND | p~{ lv_sender_val } | TO lt_source.
|
|
APPEND | FROM { gv_source } AS p | TO lt_source.
|
|
APPEND | LEFT OUTER JOIN { gv_source } AS q | TO lt_source.
|
|
APPEND | ON p~paledger = q~paledger | TO lt_source.
|
|
APPEND | AND p~perio = q~perio | TO lt_source.
|
|
APPEND | AND p~belnr = q~sto_belnr | TO lt_source.
|
|
APPEND | WHERE p~paledger = '01' | TO lt_source.
|
|
APPEND | AND p~perio = '{ perio }' | TO lt_source.
|
|
APPEND | AND p~sto_belnr = ' ' | TO lt_source.
|
|
APPEND | AND p~belnr_sender = '{ variant }' | TO lt_source.
|
|
|
|
IF reverse = 'X'.
|
|
APPEND | AND ( q~belnr is null OR q~belnr is initial ) | TO lt_source.
|
|
ENDIF.
|
|
APPEND | INTO CORRESPONDING FIELDS OF TABLE @lt_data. | TO lt_source.
|
|
APPEND `ENDFORM.` TO lt_source.
|
|
|
|
|
|
* " 서브루틴 풀 생성
|
|
GENERATE SUBROUTINE POOL lt_source NAME lv_prog.
|
|
IF sy-subrc = 0.
|
|
TRY.
|
|
PERFORM select_query IN PROGRAM (lv_prog) CHANGING lt_data.
|
|
MESSAGE |{ lines( lt_data ) }건 데이터 수신 완료| TYPE 'S'.
|
|
CATCH cx_sy_dyn_call_error INTO DATA(lx_error).
|
|
MESSAGE |동적 호출 오류: { lx_error->get_text( ) }| TYPE 'E'.
|
|
ENDTRY.
|
|
DELETE REPORT lv_prog. "무조건 정리
|
|
ENDIF.
|
|
|
|
" 메모리 정리 (혹시 모를 잔여 데이터 정리)
|
|
CLEAR: lt_source.
|
|
|
|
"조회 전표가 없는 경우
|
|
IF lt_data[] IS INITIAL.
|
|
gv_message = TEXT-024.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '024' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
LOOP AT lt_data INTO DATA(ls_data).
|
|
MOVE-CORRESPONDING ls_data TO ls_doc.
|
|
ls_doc-variant = ls_data-belnr_sender.
|
|
ls_doc-dist_id = ls_data-posnr_sender.
|
|
|
|
APPEND ls_doc TO copa_doc_list.
|
|
ENDLOOP.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_custom_table_info.
|
|
DATA : result TYPE bapiret2.
|
|
|
|
IF erkrs IS INITIAL .
|
|
gv_message = TEXT-012.
|
|
MESSAGE gv_message TYPE 'E'.
|
|
ENDIF.
|
|
|
|
* 현재 상태의 정보를 전역 변수에 업데이트.
|
|
* CALL METHOD me->get_package_info
|
|
* EXPORTING
|
|
* erkrs = erkrs
|
|
* RECEIVING
|
|
* result = result.
|
|
|
|
sender = gv_sender.
|
|
receiver = gv_receiver.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_field_catalog.
|
|
|
|
CONSTANTS : lc_sender TYPE tabname VALUE 'SENDER',
|
|
lc_receiver TYPE tabname VALUE 'RECEIVER'.
|
|
|
|
TYPES : BEGIN OF ty_bpsel,
|
|
sort TYPE rke_lfd4,
|
|
fnam TYPE fieldname,
|
|
low TYPE rke_low_l,
|
|
END OF ty_bpsel.
|
|
|
|
DATA : lt_dfies TYPE STANDARD TABLE OF dfies,
|
|
lv_position TYPE tabfdpos VALUE '0000',
|
|
it_bpsel TYPE STANDARD TABLE OF ty_bpsel,
|
|
ls_fieldcatalog TYPE dfies.
|
|
|
|
" 1. 필수 파라미터 체크
|
|
IF erkrs IS INITIAL OR perio IS INITIAL OR variant IS INITIAL.
|
|
gv_message = TEXT-012.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '012' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 2. 조건정보 조회
|
|
SELECT sort, fnam, low
|
|
FROM (gv_distinfo)
|
|
WHERE perio = @perio
|
|
AND variant = @variant
|
|
INTO TABLE @it_bpsel.
|
|
|
|
IF it_bpsel IS INITIAL.
|
|
gv_message = TEXT-007.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '007' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 3. 조건별 필드 카탈로그 생성 (최신 구문 활용)
|
|
LOOP AT it_bpsel INTO DATA(ls_bpsel).
|
|
|
|
IF ls_bpsel-sort = '0270' AND ls_bpsel-low = 'X'.
|
|
fieldcatalog = VALUE #( BASE fieldcatalog
|
|
( fieldname = ls_bpsel-fnam tabname = lc_sender ) ).
|
|
ENDIF.
|
|
|
|
IF ls_bpsel-sort = '0300' AND ls_bpsel-low = 'X'.
|
|
fieldcatalog = VALUE #( BASE fieldcatalog
|
|
( fieldname = ls_bpsel-fnam tabname = lc_sender inttype = 'C' ) ).
|
|
ENDIF.
|
|
|
|
IF ( ls_bpsel-sort = '0270' OR ls_bpsel-sort = '0201' ) AND ls_bpsel-low = 'X'.
|
|
fieldcatalog = VALUE #( BASE fieldcatalog
|
|
( fieldname = ls_bpsel-fnam tabname = lc_receiver ) ).
|
|
ENDIF.
|
|
|
|
IF ls_bpsel-sort = '0100' AND ls_bpsel-fnam = 'WKOFNAM'.
|
|
fieldcatalog = VALUE #( BASE fieldcatalog
|
|
( fieldname = ls_bpsel-low tabname = lc_receiver inttype = 'T' ) ).
|
|
ENDIF.
|
|
|
|
ENDLOOP.
|
|
|
|
" 4. 추가 필수 필드 일괄 추가 (배열 LOOP 활용)
|
|
DATA lt_required_fields TYPE STANDARD TABLE OF fieldname WITH EMPTY KEY.
|
|
lt_required_fields = VALUE #( ( 'PERIO' ) ( 'GJAHR' ) ( 'PERDE' ) ( 'VARIANT' ) ( 'DIST_ID' ) ( 'SEQ' ) ( 'REC_WAERS' ) ).
|
|
|
|
LOOP AT lt_required_fields INTO DATA(lv_field).
|
|
CLEAR ls_fieldcatalog.
|
|
ls_fieldcatalog-fieldname = lv_field.
|
|
ls_fieldcatalog-tabname = COND #( WHEN lv_field = 'SEQ' THEN lc_receiver ELSE lc_sender ).
|
|
APPEND ls_fieldcatalog TO fieldcatalog.
|
|
ENDLOOP.
|
|
|
|
" 5. 중복 제거 및 정렬
|
|
SORT fieldcatalog BY fieldname tabname DESCENDING. "센더/리시버 중복된 필드인 경우, sender(공통) 를 남기기 위해..
|
|
DELETE ADJACENT DUPLICATES FROM fieldcatalog COMPARING fieldname INTTYPE.
|
|
|
|
" 6. DB 테이블 기준 정렬 순서 재정의
|
|
CALL FUNCTION 'DDIF_FIELDINFO_GET'
|
|
EXPORTING
|
|
tabname = gv_receiver
|
|
TABLES
|
|
dfies_tab = lt_dfies
|
|
EXCEPTIONS
|
|
not_found = 1
|
|
OTHERS = 2.
|
|
|
|
IF sy-subrc = 0.
|
|
SORT lt_dfies BY position.
|
|
LOOP AT lt_dfies INTO DATA(ls_dfies).
|
|
READ TABLE fieldcatalog ASSIGNING FIELD-SYMBOL(<fc_catalog>) WITH KEY fieldname = ls_dfies-fieldname.
|
|
IF sy-subrc = 0.
|
|
lv_position += 1.
|
|
<fc_catalog>-position = lv_position.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
ENDIF.
|
|
|
|
SORT fieldcatalog BY position.
|
|
|
|
" 7. 성공 메시지
|
|
gv_message = TEXT-016.
|
|
result = VALUE #( type = 'S' id = 'SUCCESS' number = '016' message = gv_message ).
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_sender_receiver_data.
|
|
|
|
DATA: ls_sender TYPE ty_sender,
|
|
lt_sender TYPE TABLE OF ty_sender,
|
|
lt_sender_buff TYPE TABLE OF ty_receiver, "동적쿼리 수행 구조체는 리시버 구조로 수행.
|
|
lt_receiver TYPE TABLE OF ty_receiver.
|
|
DATA : l_check TYPE bapiret2.
|
|
DATA : it_bpsel TYPE zcl_copa_topdown=>tt_bpsel.
|
|
|
|
CLEAR: gv_dist_counter.
|
|
CALL METHOD me->set_source_info
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
RECEIVING
|
|
result = result.
|
|
|
|
" 공용 정보 세팅
|
|
set_info(
|
|
perio = perio
|
|
variant = variant
|
|
).
|
|
|
|
"이전 처리 내역 확인 ===================================================================
|
|
CALL METHOD me->get_tb_data_exist_yn
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
variant = variant
|
|
perio = perio
|
|
type = '3' "센더 테이블
|
|
RECEIVING
|
|
result = l_check.
|
|
|
|
IF l_check-type = 'S'.
|
|
" 센더 데이타가 이미 존재하는 경우.
|
|
" 실패 메시지 추가
|
|
gv_message = TEXT-020.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '020' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
CALL METHOD me->get_tb_data_exist_yn
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
variant = variant
|
|
perio = perio
|
|
type = '4' "리시버 테이블
|
|
RECEIVING
|
|
result = l_check.
|
|
|
|
IF l_check-type = 'S'.
|
|
" 리시버 데이타가 이미 존재하는 경우.
|
|
" 실패 메시지 추가
|
|
gv_message = TEXT-020.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '020' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" ========================================================================================
|
|
|
|
SELECT sort,
|
|
fnam,
|
|
sign,
|
|
optionn AS option,
|
|
low,
|
|
high
|
|
FROM (gv_distinfo)
|
|
WHERE perio = @perio
|
|
AND variant = @variant
|
|
INTO TABLE @it_bpsel.
|
|
|
|
IF it_bpsel IS INITIAL.
|
|
gv_message = TEXT-007.
|
|
MESSAGE gv_message TYPE 'E'.
|
|
ENDIF.
|
|
|
|
" 센더 데이터 추출 및 DIST_ID 생성
|
|
lt_sender_buff = build_dynamic_query(
|
|
iv_type = 'S'
|
|
it_bpsel = it_bpsel
|
|
).
|
|
|
|
LOOP AT lt_sender_buff INTO DATA(ls_buff).
|
|
MOVE-CORRESPONDING ls_buff TO ls_sender.
|
|
APPEND ls_sender TO lt_sender.
|
|
ENDLOOP.
|
|
|
|
" 리시버 데이터 추출 및 DIST_ID 매핑
|
|
lt_receiver = build_dynamic_query(
|
|
iv_type = 'R'
|
|
it_bpsel = it_bpsel
|
|
).
|
|
|
|
" 데이터 저장
|
|
INSERT (gv_sender) FROM TABLE lt_sender.
|
|
IF sy-subrc NE 0.
|
|
ROLLBACK WORK.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
INSERT (gv_receiver) FROM TABLE lt_receiver.
|
|
IF sy-subrc NE 0.
|
|
ROLLBACK WORK.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
UPDATE (gv_variant)
|
|
SET sender = 'X'
|
|
receiver = 'X'
|
|
WHERE perio = perio
|
|
AND variant = variant.
|
|
IF sy-subrc NE 0.
|
|
ROLLBACK WORK.
|
|
ENDIF.
|
|
|
|
COMMIT WORK.
|
|
" 성공 메시지 추가
|
|
gv_message = TEXT-016.
|
|
result = VALUE #( type = 'S' id = 'SUCCESS' number = '016' message = gv_message ).
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_tabname.
|
|
CONCATENATE 'CE1' erkrs INTO tabname.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_tb_data_exist_yn.
|
|
DATA : l_check TYPE c,
|
|
lv_tabname TYPE tabname.
|
|
|
|
|
|
IF erkrs IS INITIAL OR perio IS INITIAL OR variant IS INITIAL OR type IS INITIAL.
|
|
" 실패 메시지 추가
|
|
gv_message = TEXT-012.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '012' message = gv_message ).
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
CASE type.
|
|
* WHEN '1'. "CBO테이블관리
|
|
WHEN '2'. "배부 기준 정보(월별)
|
|
lv_tabname = gv_variant.
|
|
WHEN '3'. "센더 데이타
|
|
lv_tabname = gv_sender.
|
|
WHEN '4'. "배부 기준 데이타
|
|
lv_tabname = gv_receiver.
|
|
WHEN '5'. "배부 결과 데이타
|
|
lv_tabname = gv_result.
|
|
WHEN '6'. "전표 발행 대상 데이타
|
|
lv_tabname = gv_target.
|
|
WHEN '7'. "배부 기준 세부 정보 테이블
|
|
lv_tabname = gv_distinfo.
|
|
WHEN '8'. "배부 조건 Customizing
|
|
lv_tabname = gv_distrule.
|
|
WHEN OTHERS.
|
|
" 실패 메시지 추가
|
|
gv_message = TEXT-019.
|
|
result = VALUE #( type = 'E' id = 'FAIL' number = '019' message = gv_message ).
|
|
RETURN.
|
|
ENDCASE.
|
|
|
|
IF type = '2' OR type = '3' OR type = '4' OR type = '5' OR type = '6'.
|
|
SELECT SINGLE 'X'
|
|
INTO @l_check
|
|
FROM (lv_tabname)
|
|
WHERE variant = @variant
|
|
AND perio = @perio.
|
|
ELSEIF type = '7' OR type = '8'.
|
|
SELECT SINGLE 'X'
|
|
INTO @l_check
|
|
FROM (lv_tabname)
|
|
WHERE erkrs = @erkrs
|
|
AND variant = @variant
|
|
AND perio = @perio.
|
|
ENDIF.
|
|
|
|
IF l_check = 'X'.
|
|
" 데이타가 존재함.
|
|
result = VALUE #(
|
|
type = 'S'
|
|
id = 'SUCCESS'
|
|
number = '000'
|
|
message = '데이타 조회 완료' ).
|
|
ELSE.
|
|
" 데이타가 존재하지 않음.
|
|
result = VALUE #(
|
|
type = 'E'
|
|
id = 'FAIL'
|
|
number = '000'
|
|
message = '데이타 없음' ).
|
|
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_variant_info.
|
|
|
|
DATA : lv_tabname TYPE tabname.
|
|
|
|
CALL METHOD me->get_tabname
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
IMPORTING
|
|
tabname = lv_tabname.
|
|
|
|
SELECT SINGLE
|
|
applclass,
|
|
subclass,
|
|
tabname,
|
|
func,
|
|
variant
|
|
FROM covad
|
|
WHERE variant = @variant
|
|
AND tabname = @lv_tabname
|
|
INTO CORRESPONDING FIELDS OF @covad.
|
|
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD get_variant_list.
|
|
DATA : l_tabname TYPE string.
|
|
|
|
IF erkrs IS INITIAL.
|
|
gv_message = TEXT-001.
|
|
MESSAGE gv_message TYPE 'E'.
|
|
ENDIF.
|
|
|
|
CONCATENATE 'CE1' erkrs INTO l_tabname.
|
|
|
|
|
|
SELECT 'KE28' AS report,
|
|
p~Variant AS variant,
|
|
q~vtext AS fieldname
|
|
FROM covad AS p
|
|
LEFT OUTER JOIN covat AS q
|
|
ON q~spras = @sy-langu
|
|
AND q~applclass = p~applclass
|
|
AND q~subclass = p~subclass
|
|
AND q~tabname = p~tabname
|
|
AND q~func = p~func
|
|
AND q~variant = p~variant
|
|
WHERE p~applclass = 'KE'
|
|
AND p~subclass = '02'
|
|
AND p~tabname = @l_tabname
|
|
AND p~func = 'GITD'
|
|
INTO CORRESPONDING FIELDS OF TABLE @result
|
|
.
|
|
|
|
IF sy-subrc <> 0.
|
|
RAISE select_err.
|
|
ENDIF.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD map_document_data.
|
|
DATA : l_currency_value TYPE bapicurr_d.
|
|
|
|
|
|
FIELD-SYMBOLS: <ls_source> TYPE any, <l_waers> TYPE any, <lv_value> TYPE any.
|
|
|
|
|
|
|
|
|
|
|
|
LOOP AT it_source ASSIGNING <ls_source>.
|
|
ASSIGN COMPONENT 'REC_WAERS' OF STRUCTURE <ls_source> TO <l_waers>.
|
|
APPEND VALUE #(
|
|
record_id = cv_index
|
|
fieldname = 'VRGAR'
|
|
value = iv_vrgar
|
|
) TO ct_inputdata.
|
|
|
|
LOOP AT it_catalog INTO DATA(ls_catalog).
|
|
ASSIGN COMPONENT ls_catalog-fieldname OF STRUCTURE <ls_source> TO <lv_value>.
|
|
IF sy-subrc = 0.
|
|
IF ls_catalog-inttype IS NOT INITIAL. "값필드 인 경우.
|
|
" 통화키를 적용하여, 금액을 형변환 시켜야 함.
|
|
CLEAR : l_currency_value.
|
|
CALL FUNCTION 'BAPI_CURRENCY_CONV_TO_EXTERNAL'
|
|
EXPORTING
|
|
currency = <l_waers>
|
|
amount_internal = <lv_value>
|
|
IMPORTING
|
|
amount_external = l_currency_value.
|
|
|
|
APPEND VALUE #(
|
|
record_id = cv_index
|
|
fieldname = ls_catalog-fieldname
|
|
* value = COND #( WHEN iv_reverse = abap_true THEN <lv_value> * -1 ELSE <lv_value> )
|
|
value = COND #( WHEN iv_reverse = abap_true THEN l_currency_value * -1 ELSE l_currency_value )
|
|
currency = <l_waers>
|
|
) TO ct_inputdata.
|
|
ELSE.
|
|
CASE ls_catalog-fieldname.
|
|
WHEN 'VARIANT'.
|
|
APPEND VALUE #(
|
|
record_id = cv_index
|
|
fieldname = 'BELNR_SENDER'
|
|
value = <lv_value>
|
|
) TO ct_inputdata.
|
|
WHEN 'DIST_ID'.
|
|
APPEND VALUE #(
|
|
record_id = cv_index
|
|
fieldname = 'POSNR_SENDER'
|
|
value = substring( val = <lv_value> off = strlen( <lv_value> ) - 6 len = 6 )
|
|
) TO ct_inputdata.
|
|
WHEN 'BUDAT'.
|
|
APPEND VALUE #(
|
|
record_id = cv_index
|
|
fieldname = 'BUDAT'
|
|
value = iv_budat
|
|
) TO ct_inputdata.
|
|
WHEN OTHERS.
|
|
APPEND VALUE #(
|
|
record_id = cv_index
|
|
fieldname = ls_catalog-fieldname
|
|
value = <lv_value>
|
|
) TO ct_inputdata.
|
|
ENDCASE.
|
|
ENDIF.
|
|
ENDIF.
|
|
ENDLOOP.
|
|
cv_index = cv_index + 1.
|
|
ENDLOOP.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD post_actual_topdown_documents.
|
|
|
|
CONSTANTS: c_index_init TYPE rke_record_id VALUE '000001'.
|
|
|
|
DATA: lt_inputdata TYPE TABLE OF bapi_copa_data,
|
|
lt_fieldlist TYPE TABLE OF bapi_copa_field,
|
|
ls_return TYPE bapiret2,
|
|
lv_index TYPE rke_record_id VALUE c_index_init.
|
|
|
|
DATA: lt_catalog TYPE tt_dfies,
|
|
lr_sender TYPE REF TO data,
|
|
lr_result TYPE REF TO data.
|
|
|
|
DATA: l_waers TYPE rke_rec_waers,
|
|
lv_exists TYPE abap_bool.
|
|
|
|
DATA : lv_first_day TYPE sy-datum, "전기일자를 위한 기간/년도의 1일
|
|
lv_budat TYPE sy-datum. "전기일자
|
|
|
|
FIELD-SYMBOLS: <lt_sender> TYPE ANY TABLE,
|
|
<ls_sender> TYPE any,
|
|
<lt_result> TYPE ANY TABLE,
|
|
<ls_result> TYPE any.
|
|
|
|
" 필수 파라미터 점검
|
|
IF erkrs IS INITIAL OR perio IS INITIAL OR variant IS INITIAL OR vrgar IS INITIAL.
|
|
gv_message = TEXT-012.
|
|
ls_return = VALUE #( type = 'E' id = 'FAIL' number = '012' message = gv_message ).
|
|
APPEND ls_return TO result.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 레코드 유형 점검 (EXISTS 쿼리)
|
|
SELECT SINGLE @abap_true FROM tvga WHERE vrgar = @vrgar INTO @lv_exists.
|
|
IF lv_exists = abap_false.
|
|
gv_message = TEXT-021.
|
|
ls_return = VALUE #( type = 'E' id = 'FAIL' number = '021' message = gv_message ).
|
|
APPEND ls_return TO result.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 전표 발행 상태 체크
|
|
CLEAR : lv_exists.
|
|
SELECT SINGLE post FROM (gv_variant)
|
|
WHERE perio = @perio AND variant = @variant
|
|
INTO @lv_exists .
|
|
|
|
IF sy-subrc NE 0.
|
|
gv_message = TEXT-007.
|
|
ls_return = VALUE #( type = 'E' id = 'FAIL' number = '007' message = gv_message ).
|
|
APPEND ls_return TO result.
|
|
RETURN.
|
|
ELSEIF lv_exists = 'X'.
|
|
gv_message = TEXT-018.
|
|
ls_return = VALUE #( type = 'E' id = 'FAIL' number = '018' message = gv_message ).
|
|
APPEND ls_return TO result.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
" 1. 동적 테이블 생성 및 할당
|
|
CREATE DATA lr_sender TYPE TABLE OF (gv_sender).
|
|
ASSIGN lr_sender->* TO <lt_sender>.
|
|
CREATE DATA lr_result TYPE TABLE OF (gv_result).
|
|
ASSIGN lr_result->* TO <lt_result>.
|
|
|
|
" 2. 필드 카탈로그 가져오기
|
|
CALL METHOD me->get_field_catalog
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
perio = perio
|
|
variant = variant
|
|
IMPORTING
|
|
fieldcatalog = lt_catalog
|
|
RECEIVING
|
|
result = ls_return.
|
|
|
|
IF ls_return-type = 'E'.
|
|
APPEND ls_return TO result.
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
DELETE lt_catalog WHERE fieldname = 'SEQ' OR inttype = 'T'.
|
|
|
|
"전표 발행을 위한 전기일 필드 추가.
|
|
APPEND VALUE #( tabname = 'RECEIVER' fieldname = 'BUDAT' position = '0000') TO lt_catalog.
|
|
|
|
"전기일자는 기간/년월의 마지막 일자
|
|
CONCATENATE perio(4) perio+5(2) '01' INTO lv_first_day.
|
|
|
|
CALL FUNCTION 'RP_LAST_DAY_OF_MONTHS'
|
|
EXPORTING
|
|
day_in = lv_first_day
|
|
IMPORTING
|
|
last_day_of_month = lv_budat.
|
|
IF sy-subrc <> 0.
|
|
* Implement suitable error handling here
|
|
ENDIF.
|
|
|
|
" 3. 필드리스트 생성(PA 전표 생성 BAPI용 필드리스트)
|
|
CALL METHOD me->build_fieldlist
|
|
EXPORTING
|
|
it_catalog = lt_catalog
|
|
CHANGING
|
|
ct_fieldlist = lt_fieldlist.
|
|
|
|
" 4. 센더 데이터 조회
|
|
SELECT *
|
|
FROM (gv_sender)
|
|
WHERE variant = @variant
|
|
AND perio = @perio
|
|
INTO TABLE @<lt_sender>.
|
|
|
|
" 5. 입력 데이터 매핑 (private 메소드 활용)
|
|
CALL METHOD me->map_document_data
|
|
EXPORTING
|
|
it_source = <lt_sender>
|
|
it_catalog = lt_catalog
|
|
iv_vrgar = vrgar
|
|
iv_reverse = abap_true
|
|
iv_budat = lv_budat
|
|
CHANGING
|
|
ct_inputdata = lt_inputdata
|
|
cv_index = lv_index.
|
|
|
|
" 6. 리시버 데이터 조회
|
|
SELECT *
|
|
FROM (gv_result)
|
|
WHERE variant = @variant
|
|
AND perio = @perio
|
|
INTO TABLE @<lt_result>.
|
|
|
|
" 7. 리시버 입력 데이터 매핑
|
|
CALL METHOD me->map_document_data
|
|
EXPORTING
|
|
it_source = <lt_result>
|
|
it_catalog = lt_catalog
|
|
iv_vrgar = vrgar
|
|
iv_reverse = abap_false
|
|
iv_budat = lv_budat
|
|
CHANGING
|
|
ct_inputdata = lt_inputdata
|
|
cv_index = lv_index.
|
|
|
|
" 8. 불필요 필드 제거
|
|
DELETE lt_fieldlist WHERE fieldname = 'VARIANT' OR fieldname = 'DIST_ID'.
|
|
|
|
" 9. BAPI 호출
|
|
CALL FUNCTION 'BAPI_COPAACTUALS_POSTCOSTDATA'
|
|
EXPORTING
|
|
operatingconcern = erkrs
|
|
testrun = testrun
|
|
TABLES
|
|
inputdata = lt_inputdata
|
|
fieldlist = lt_fieldlist
|
|
return = result.
|
|
|
|
" 10. 결과 처리
|
|
LOOP AT result INTO DATA(ls_bapi_result) WHERE type CA 'EA'.
|
|
WRITE: / '오류:', ls_bapi_result-message.
|
|
RETURN.
|
|
ENDLOOP.
|
|
|
|
IF sy-subrc <> 0 AND testrun = space.
|
|
UPDATE (gv_variant)
|
|
SET post = 'X'
|
|
WHERE perio = @perio AND variant = @variant.
|
|
|
|
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
|
|
EXPORTING
|
|
wait = 'X'.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_audit_fields.
|
|
cs_data-cdate = sy-datum.
|
|
cs_data-ctime = sy-uzeit.
|
|
cs_data-cname = sy-uname.
|
|
cs_data-udate = sy-datum.
|
|
cs_data-utime = sy-uzeit.
|
|
cs_data-uname = sy-uname.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_info.
|
|
working_info-perio = perio.
|
|
working_info-variant = variant.
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_source_info.
|
|
|
|
IF erkrs IS INITIAL .
|
|
gv_message = TEXT-012.
|
|
MESSAGE gv_message TYPE 'E'.
|
|
ENDIF.
|
|
|
|
gv_source = |CE1{ erkrs }|.
|
|
|
|
source_struct_desc ?= cl_abap_typedescr=>describe_by_name( gv_source ).
|
|
" 버퍼 테이블 생성
|
|
DATA(lo_source_type) = cl_abap_tabledescr=>create(
|
|
p_line_type = source_struct_desc
|
|
p_table_kind = cl_abap_tabledescr=>tablekind_std
|
|
).
|
|
CREATE DATA source_table TYPE HANDLE lo_source_type.
|
|
|
|
|
|
IF sy-subrc NE 0.
|
|
" 오류 메시지 추가
|
|
gv_message = TEXT-022.
|
|
result = VALUE #(
|
|
type = 'E'
|
|
id = 'FAIL'
|
|
number = '022'
|
|
message = gv_message ).
|
|
RETURN.
|
|
ELSE.
|
|
" 성공 메시지 추가
|
|
gv_message = TEXT-013.
|
|
result = VALUE #(
|
|
type = 'S'
|
|
id = 'SUCCESS'
|
|
number = '013'
|
|
message = gv_message ).
|
|
ENDIF.
|
|
|
|
|
|
|
|
ENDMETHOD.
|
|
|
|
|
|
METHOD set_variant_desc.
|
|
|
|
DATA: lt_bpsel TYPE kepp_t_sel1,
|
|
et_bpsel TYPE kepp_s_bpsel,
|
|
ls_distinfo TYPE ty_distinfo,
|
|
lt_distinfo TYPE TABLE OF ty_distinfo,
|
|
lt_distrule TYPE SORTED TABLE OF ty_distrule
|
|
WITH UNIQUE KEY erkrs applclass subclass tabname func variant sort fnam sign optionn low,
|
|
ls_covad TYPE covad,
|
|
lt_fnam TYPE kepp_t_fnam,
|
|
ans TYPE c LENGTH 8.
|
|
|
|
" 1. 변형 정보 조회
|
|
CALL METHOD me->get_variant_info
|
|
EXPORTING
|
|
erkrs = erkrs
|
|
variant = variant
|
|
IMPORTING
|
|
covad = ls_covad.
|
|
|
|
IF ls_covad IS INITIAL.
|
|
gv_message = TEXT-003.
|
|
MESSAGE gv_message TYPE 'E'.
|
|
ENDIF.
|
|
|
|
" 2. 표준 변형 세팅 정보(KE28)
|
|
CALL FUNCTION 'RKE_BP_VARIANT_READ_DIRECT'
|
|
EXPORTING
|
|
i_applclass = ls_covad-applclass
|
|
i_subclass = ls_covad-subclass
|
|
i_tabname = ls_covad-tabname
|
|
i_func = ls_covad-func
|
|
i_variant = variant
|
|
IMPORTING
|
|
es_bpsel = et_bpsel
|
|
TABLES
|
|
et_fnam = lt_fnam
|
|
EXCEPTIONS
|
|
not_found = 1
|
|
OTHERS = 2.
|
|
IF sy-subrc <> 0.
|
|
" 적절한 에러 처리 필요
|
|
RETURN.
|
|
ENDIF.
|
|
|
|
lt_bpsel[] = et_bpsel-t_sel1[].
|
|
|
|
" 3. 등록된 CBO 조건 데이터 정보 (Standard 조건보다 우선)
|
|
SELECT *
|
|
FROM (gv_distrule)
|
|
WHERE erkrs = @erkrs
|
|
AND perfrom <= @perio
|
|
AND perto >= @perio
|
|
AND variant = @variant
|
|
INTO CORRESPONDING FIELDS OF TABLE @lt_distrule.
|
|
|
|
" 4. 배부 기준 정보 중복 여부 확인 및 사용자 확인
|
|
SELECT 1
|
|
FROM (gv_distinfo)
|
|
WHERE erkrs = @erkrs
|
|
AND perio = @perio
|
|
AND variant = @variant
|
|
INTO TABLE @DATA(l_chk)
|
|
UP TO 1 ROWS.
|
|
|
|
IF l_chk IS NOT INITIAL.
|
|
CALL FUNCTION 'POPUP_TO_CONFIRM'
|
|
EXPORTING
|
|
titlebar = 'Title POPUP_TO_CONFIRM'
|
|
text_question = TEXT-006
|
|
text_button_1 = 'OK'
|
|
icon_button_1 = 'ICON_CHECKED'
|
|
text_button_2 = 'NO'
|
|
icon_button_2 = 'ICON_NO'
|
|
display_cancel_button = ' '
|
|
popup_type = 'ICON_MESSAGE_ERROR'
|
|
IMPORTING
|
|
answer = ans.
|
|
|
|
IF ans = 2.
|
|
RETURN.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
" 5. 배부 기준 정보 저장 (CBO 우선, 없으면 표준)
|
|
LOOP AT lt_bpsel INTO DATA(ls_data).
|
|
READ TABLE lt_distrule WITH KEY
|
|
erkrs = erkrs
|
|
applclass = ls_covad-applclass
|
|
subclass = ls_covad-subclass
|
|
tabname = ls_covad-tabname
|
|
func = ls_covad-func
|
|
variant = ls_covad-variant
|
|
sort = ls_data-sort
|
|
fnam = ls_data-fnam
|
|
TRANSPORTING NO FIELDS
|
|
BINARY SEARCH.
|
|
|
|
IF sy-subrc = 0.
|
|
LOOP AT lt_distrule INTO DATA(ls_cbo_rule) WHERE erkrs = erkrs
|
|
AND applclass = ls_covad-applclass
|
|
AND subclass = ls_covad-subclass
|
|
AND tabname = ls_covad-tabname
|
|
AND func = ls_covad-func
|
|
AND variant = ls_covad-variant
|
|
AND sort = ls_data-sort
|
|
AND fnam = ls_data-fnam.
|
|
MOVE-CORRESPONDING ls_cbo_rule TO ls_distinfo.
|
|
me->set_audit_fields( CHANGING cs_data = ls_distinfo ).
|
|
APPEND ls_distinfo TO lt_distinfo.
|
|
ENDLOOP.
|
|
ELSE.
|
|
MOVE-CORRESPONDING ls_data TO ls_distinfo.
|
|
ls_distinfo-erkrs = erkrs.
|
|
ls_distinfo-perio = perio.
|
|
ls_distinfo-applclass = ls_covad-applclass.
|
|
ls_distinfo-subclass = ls_covad-subclass.
|
|
ls_distinfo-tabname = ls_covad-tabname.
|
|
ls_distinfo-func = ls_covad-func.
|
|
ls_distinfo-variant = ls_covad-variant.
|
|
ls_distinfo-optionn = ls_data-option.
|
|
|
|
IF ls_distinfo-fnam EQ 'BPERIO'
|
|
OR ls_distinfo-fnam EQ 'REBPERIO'
|
|
OR ls_distinfo-fnam EQ 'REVPERIO'
|
|
OR ls_distinfo-fnam EQ 'VPERIO'.
|
|
ls_distinfo-low = perio.
|
|
ENDIF.
|
|
ENDIF.
|
|
|
|
me->set_audit_fields( CHANGING cs_data = ls_distinfo ).
|
|
APPEND ls_distinfo TO lt_distinfo.
|
|
ENDLOOP.
|
|
|
|
" 6. 기존 데이터 삭제 후 신규 데이터 저장
|
|
DELETE FROM (gv_distinfo) WHERE erkrs = @erkrs
|
|
AND perio = @perio
|
|
AND variant = @variant.
|
|
|
|
MODIFY (gv_distinfo) FROM TABLE lt_distinfo.
|
|
|
|
" 7. 결과 처리
|
|
IF sy-subrc = 0.
|
|
COMMIT WORK.
|
|
gv_message = TEXT-004.
|
|
MESSAGE gv_message TYPE 'S'.
|
|
ELSE.
|
|
ROLLBACK WORK.
|
|
gv_message = TEXT-005.
|
|
MESSAGE gv_message TYPE 'E'.
|
|
ENDIF.
|
|
|
|
ENDMETHOD.
|
|
ENDCLASS.
|