Client copy 후 번호범위 자동 조정 프로그램
RFC_READ_TABLE
SCC9를 통해 운영에서 QA로 Remote Copy 시 운영 클라이언트를 잠그지 않고 복사를 하면, 복사 후에 QA클라이언트의 번호범위 테이블의 현재값과 실제 각 테이블(COBK, MLDOC, BKPF 등등)의 마지막 번호가 불일치하는 경우가 발생합니다.
이럴 경우 DUPLICATE_KEY_ERROR가 발생하게 되며, SM13과 SCMP를 이용하여 하나씩 찾아서 수정하면 되긴 하지만,
저희 회사 같은 경우는 테스트를 위해 QA 클라이언트를 매월초에 카피를 하다보니 생각 이상으로 번거롭도 시간도 꽤 소요가 되었습니다.
클라이언트 카피 후 실행하면 소스 클라이언트 기준으로 번호범위를 일괄 조정하는 Report 프로그램을 만들었습니다.
소스코드를 보시면 알겠지만, 별 내용은 없습니다....
RFC_READ_TABLE 펑션으로 운영서버의 NRIV 테이블 데이터를 읽어와서 로컬시스템(QA)의 NRIV 테이블 데이터와 비교 후 갱신해 주는 방식입니다.
#1. ABAP 소스코드
REPORT ZCMR9003.
INCLUDE ZCM_PROGRESS.
CLASS LCL_HANDLE_EVENTS DEFINITION.
PUBLIC SECTION.
METHODS:
ON_USER_COMMAND FOR EVENT ADDED_FUNCTION OF CL_SALV_EVENTS
IMPORTING E_SALV_FUNCTION.
ENDCLASS.
CLASS LCL_HANDLE_EVENTS IMPLEMENTATION.
METHOD ON_USER_COMMAND.
PERFORM HANDLE_USER_COMMAND USING E_SALV_FUNCTION.
ENDMETHOD.
ENDCLASS.
DATA: GR_EVENTS TYPE REF TO LCL_HANDLE_EVENTS.
DATA: GR_SALV TYPE REF TO CL_SALV_TABLE.
TYPES: BEGIN OF T_NRIV.
INCLUDE STRUCTURE NRIV.
TYPES: NRLEVEL_LC TYPE NRIV-NRLEVEL,
BUFFER TYPE TNRO-BUFFER,
NOIVBUFFER TYPE TNRO-NOIVBUFFER,
STATUS TYPE ICONNAME.
TYPES: END OF T_NRIV.
DATA: GT_REMOT TYPE STANDARD TABLE OF T_NRIV.
PARAMETERS P_DEST TYPE RFCDES-RFCDEST OBLIGATORY MEMORY ID RFC.
SELECTION-SCREEN SKIP.
PARAMETERS CH_DIF AS CHECKBOX DEFAULT ABAP_TRUE.
INITIALIZATION.
PERFORM INITIALIZATION.
START-OF-SELECTION.
PERFORM READ_NRIV_DATA.
*&---------------------------------------------------------------------*
*& Form READ_NRIV_DATA
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM READ_NRIV_DATA .
DATA: LT_OPTIONS TYPE STANDARD TABLE OF RFC_DB_OPT,
LT_FIELDS TYPE STANDARD TABLE OF RFC_DB_FLD,
LT_DATA TYPE STANDARD TABLE OF TAB512.
CONSTANTS LC_TABLE TYPE DD02L-TABNAME VALUE 'NRIV'.
CLEAR GT_REMOT[].
"운영에서는 실행 금지
SELECT SINGLE
CCCATEGORY
FROM T000
WHERE MANDT EQ @SY-MANDT
INTO @DATA(LV_CCT).
IF LV_CCT EQ 'P'.
MESSAGE A000(OO) WITH '운영 클라이언트 에서는 실행할 수 없습니다'.
EXIT.
ENDIF.
CALL FUNCTION 'RFC_READ_TABLE'
DESTINATION P_DEST
EXPORTING
QUERY_TABLE = LC_TABLE
* DELIMITER = ' '
* NO_DATA = ' '
* ROWSKIPS = 0
* ROWCOUNT = 0
TABLES
OPTIONS = LT_OPTIONS
FIELDS = LT_FIELDS
DATA = LT_DATA
EXCEPTIONS
TABLE_NOT_AVAILABLE = 1
TABLE_WITHOUT_DATA = 2
OPTION_NOT_VALID = 3
FIELD_NOT_VALID = 4
NOT_AUTHORIZED = 5
DATA_BUFFER_EXCEEDED = 6
OTHERS = 7.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
DATA: LS_REMOT LIKE LINE OF GT_REMOT,
LT_LOCAL TYPE SORTED TABLE OF NRIV WITH UNIQUE KEY OBJECT
SUBOBJECT
NRRANGENR
TOYEAR,
LT_TNRO TYPE SORTED TABLE OF TNRO WITH UNIQUE KEY OBJECT.
FIELD-SYMBOLS <LFS> TYPE ANY.
"리모트 데이터 정리
LOOP AT LT_DATA INTO DATA(LS_DATA).
LOOP AT LT_FIELDS INTO DATA(LS_FIELDS).
DATA(LV_FIELDNAME) = 'LS_REMOT-' && LS_FIELDS-FIELDNAME.
ASSIGN (LV_FIELDNAME) TO <LFS>.
IF <LFS> IS ASSIGNED.
<LFS> = LS_DATA-WA+LS_FIELDS-OFFSET(LS_FIELDS-LENGTH).
ENDIF.
ENDLOOP.
APPEND LS_REMOT TO GT_REMOT. CLEAR LS_REMOT.
ENDLOOP.
"로컬 데이터 조회
SELECT * FROM NRIV WHERE EXTERNIND EQ @SPACE INTO CORRESPONDING FIELDS OF TABLE @LT_LOCAL.
"번호범위 오브젝트
SELECT OBJECT, BUFFER, NOIVBUFFER FROM TNRO
INTO CORRESPONDING FIELDS OF TABLE @LT_TNRO.
"데이터 비교
LOOP AT GT_REMOT INTO LS_REMOT.
DATA(LV_TABIX) = SY-TABIX.
READ TABLE LT_TNRO INTO DATA(LS_TNRO) WITH TABLE KEY OBJECT = LS_REMOT-OBJECT.
IF SY-SUBRC NE 0.
DELETE GT_REMOT INDEX LV_TABIX.
CONTINUE.
ENDIF.
READ TABLE LT_LOCAL INTO DATA(LS_LOCAL) WITH TABLE KEY OBJECT = LS_REMOT-OBJECT
SUBOBJECT = LS_REMOT-SUBOBJECT
NRRANGENR = LS_REMOT-NRRANGENR
TOYEAR = LS_REMOT-TOYEAR.
IF SY-SUBRC NE 0 OR
( SY-SUBRC EQ 0 AND CH_DIF EQ ABAP_TRUE AND LS_REMOT-NRLEVEL <= LS_LOCAL-NRLEVEL ).
DELETE GT_REMOT INDEX LV_TABIX.
CONTINUE.
ENDIF.
LS_REMOT-NRLEVEL_LC = LS_LOCAL-NRLEVEL.
LS_REMOT-BUFFER = LS_TNRO-BUFFER.
LS_REMOT-NOIVBUFFER = LS_TNRO-NOIVBUFFER.
MODIFY GT_REMOT FROM LS_REMOT INDEX LV_TABIX.
ENDLOOP.
"RFC 정보
DATA: LV_ALV_TITLE TYPE LVC_TITLE,
LS_RFCINFO TYPE CMPWL_SYSTEM_INFO_TYPE.
CALL FUNCTION 'SCT4_GET_RFC_INFO'
EXPORTING
IV_RFC_DEST = P_DEST
CHANGING
CS_SYSTEM_INFO = LS_RFCINFO
EXCEPTIONS
RFC_DEST_NOT_FOUND = 1
COMM_FAILURE = 2
SYST_FAILURE = 3
OTHERS = 4.
IF SY-SUBRC EQ 0.
CONCATENATE '비교시스템:' ` ` LS_RFCINFO-SYSTEM_NAME_REMOTE '/' LS_RFCINFO-CLIENT_REMOTE
` ` '<->' ` `
'로컬시스템:' ` `SY-SYSID '/' SY-MANDT
INTO LV_ALV_TITLE.
ENDIF.
PERFORM CALL_SALV TABLES GT_REMOT
USING GR_SALV LV_ALV_TITLE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form CALL_SALV
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM CALL_SALV TABLES FT_ITAB
USING LR_SALV TYPE REF TO CL_SALV_TABLE
FV_TITLE.
DATA : LR_FUNCTIONS TYPE REF TO CL_SALV_FUNCTIONS_LIST,
LS_FUNCTION TYPE REF TO CL_SALV_FUNCTION,
LR_DISPLAY TYPE REF TO CL_SALV_DISPLAY_SETTINGS,
LR_LAYOUT TYPE REF TO CL_SALV_LAYOUT,
LS_PROGRAM TYPE SALV_S_LAYOUT_KEY,
LR_COLUMNS TYPE REF TO CL_SALV_COLUMNS_TABLE,
LR_COLUMN TYPE REF TO CL_SALV_COLUMN_TABLE,
LS_COLOR TYPE LVC_S_COLO,
LR_SELECTION TYPE REF TO CL_SALV_SELECTIONS,
LR_SORTS TYPE REF TO CL_SALV_SORTS,
LR_AGGR TYPE REF TO CL_SALV_AGGREGATIONS,
LR_FILTER TYPE REF TO CL_SALV_FILTERS,
LR_EVENT_TAB TYPE REF TO CL_SALV_EVENTS_TABLE.
DATA: LV_LVC_TITLE TYPE LVC_TITLE.
MOVE FV_TITLE TO LV_LVC_TITLE.
"ALV 생성
CALL METHOD CL_SALV_TABLE=>FACTORY
IMPORTING
R_SALV_TABLE = LR_SALV
CHANGING
T_TABLE = FT_ITAB[].
"ALV 의 기능키 표시
* LR_FUNCTIONS = LR_SALV->GET_FUNCTIONS( ).
** LR_FUNCTIONS->SET_DEFAULT( ).
* LR_FUNCTIONS->SET_ALL( ).
LR_SALV->SET_SCREEN_STATUS(
PFSTATUS = 'SALV_STATUS'
REPORT = SY-REPID
SET_FUNCTIONS = LR_SALV->C_FUNCTIONS_ALL ).
"ALV 선택 모드 설정
LR_SELECTION = LR_SALV->GET_SELECTIONS( ).
LR_SELECTION->SET_SELECTION_MODE( IF_SALV_C_SELECTION_MODE=>ROW_COLUMN ).
"ALV의 레이아웃 셋팅(줄무늬 패턴, 헤더 텍스트 등)
LR_DISPLAY = LR_SALV->GET_DISPLAY_SETTINGS( ).
LR_DISPLAY->SET_STRIPED_PATTERN( CL_SALV_DISPLAY_SETTINGS=>TRUE ).
LR_DISPLAY->SET_LIST_HEADER( LV_LVC_TITLE ).
"ALV의 레이아웃 저장 기능 활성화
LR_LAYOUT = LR_SALV->GET_LAYOUT( ).
LS_PROGRAM-REPORT = SY-REPID.
LS_PROGRAM-HANDLE = SY-DYNNR.
LR_LAYOUT->SET_KEY( LS_PROGRAM ).
LR_LAYOUT->SET_DEFAULT( ABAP_TRUE ).
LR_LAYOUT->SET_SAVE_RESTRICTION( CL_SALV_LAYOUT=>RESTRICT_NONE ). "기본값 및 사용자 레이아웃 제한 없음
"ALV 열(필드카타로그) 설정
LR_COLUMNS = LR_SALV->GET_COLUMNS( ).
LR_COLUMNS->SET_OPTIMIZE( ABAP_TRUE ). "열 너비 최적화
LR_COLUMN ?= LR_COLUMNS->GET_COLUMN( 'NRLEVEL' ).
LR_COLUMN->SET_LONG_TEXT( '비교시스템-' && LR_COLUMN->GET_LONG_TEXT( ) ).
LR_COLUMN->SET_MEDIUM_TEXT( '비교시스템-' && LR_COLUMN->GET_MEDIUM_TEXT( ) ).
LR_COLUMN->SET_SHORT_TEXT( '비교시스템-' && LR_COLUMN->GET_SHORT_TEXT( ) ).
LS_COLOR = VALUE #( COL = 3 INT = 0 INV = 0 ).
LR_COLUMN->SET_COLOR( LS_COLOR ).
LR_COLUMN ?= LR_COLUMNS->GET_COLUMN( 'NRLEVEL_LC' ).
LR_COLUMN->SET_LONG_TEXT( '로컬시스템-' && LR_COLUMN->GET_LONG_TEXT( ) ).
LR_COLUMN->SET_MEDIUM_TEXT( '로컬시스템-' && LR_COLUMN->GET_MEDIUM_TEXT( ) ).
LR_COLUMN->SET_SHORT_TEXT( '로컬시스템-' && LR_COLUMN->GET_SHORT_TEXT( ) ).
LS_COLOR = VALUE #( COL = 5 INT = 0 INV = 0 ).
LR_COLUMN->SET_COLOR( LS_COLOR ).
LR_COLUMN ?= LR_COLUMNS->GET_COLUMN( 'STATUS' ).
LR_COLUMN->SET_LONG_TEXT( '처리상태' ).
LR_COLUMN->SET_MEDIUM_TEXT( '처리상태' ).
LR_COLUMN->SET_SHORT_TEXT( '처리상태' ).
LR_COLUMN ?= LR_COLUMNS->GET_COLUMN( 'EXTERNIND' ).
LR_COLUMN->SET_TECHNICAL( 'X' ).
LR_COLUMN ?= LR_COLUMNS->GET_COLUMN( 'BUFFER' ).
LR_COLUMN->SET_TECHNICAL( 'X' ).
LR_COLUMN ?= LR_COLUMNS->GET_COLUMN( 'NOIVBUFFER' ).
LR_COLUMN->SET_TECHNICAL( 'X' ).
"ALV 정렬
LR_SORTS = LR_SALV->GET_SORTS( ).
LR_SORTS->ADD_SORT( 'OBJECT' ).
"ALV 이벤트
LR_EVENT_TAB = LR_SALV->GET_EVENT( ).
CREATE OBJECT GR_EVENTS.
SET HANDLER GR_EVENTS->ON_USER_COMMAND FOR LR_EVENT_TAB.
"ALV 표시
LR_SALV->DISPLAY( ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form HANDLE_USER_COMMAND
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> E_SALV_FUNCTION
*&---------------------------------------------------------------------*
FORM HANDLE_USER_COMMAND USING I_UCOMM TYPE SALV_DE_FUNCTION.
CASE I_UCOMM.
WHEN 'ADJUST'.
PERFORM ADJUST_LAST_NUMBER.
ENDCASE.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form ADJUST_LAST_NUMBER
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM ADJUST_LAST_NUMBER .
DATA: LR_SELECTIONS TYPE REF TO CL_SALV_SELECTIONS.
DATA: LT_ROWS TYPE SALV_T_ROW.
DATA: LV_NUMBER TYPE NRIV-NRLEVEL,
LV_QUANTITY TYPE INRI-QUANTITY.
DATA: LT_ERROR_IV TYPE STANDARD TABLE OF INRIV,
LT_INTERVAL TYPE STANDARD TABLE OF INRIV,
LS_INTERVAL LIKE LINE OF LT_INTERVAL.
LR_SELECTIONS = GR_SALV->GET_SELECTIONS( ).
LT_ROWS = LR_SELECTIONS->GET_SELECTED_ROWS( ).
IF LT_ROWS[] IS INITIAL.
MESSAGE I006(0K).
EXIT.
ENDIF.
PERFORM INITIAL_PROGRESS_VARIANT.
G_PROGRESS_TOTAL = LINES( LT_ROWS ).
LOOP AT LT_ROWS INTO DATA(LS_ROWS).
READ TABLE GT_REMOT INTO DATA(LS_REMOT) INDEX LS_ROWS.
IF SY-SUBRC NE 0.
CONTINUE.
ENDIF.
DATA(LV_TXT) = LS_REMOT-OBJECT && ` ` && '번호 조정중...'.
PERFORM SET_PROGRESS_WITH_PERCENT USING LV_TXT.
IF LS_REMOT-STATUS IS NOT INITIAL OR LS_REMOT-NRLEVEL <= LS_REMOT-NRLEVEL_LC.
CONTINUE.
ENDIF.
CLEAR : LT_ERROR_IV, LT_INTERVAL.
MOVE-CORRESPONDING LS_REMOT TO LS_INTERVAL.
LS_INTERVAL-PROCIND = 'U'.
APPEND LS_INTERVAL TO LT_INTERVAL.
CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE'
EXPORTING
OBJECT = LS_REMOT-OBJECT
* CHECK_AT_ALL_EVENTS = ' '
SUBOBJECT = LS_REMOT-SUBOBJECT
* CALLED_FROM_AIM =
* CLIENT_AIM =
* INIT_ACT = ' '
* IMPORTING
* ERROR =
* ERROR_OCCURED =
* WARNING_OCCURED =
TABLES
ERROR_IV = LT_ERROR_IV
INTERVAL = LT_INTERVAL
EXCEPTIONS
OBJECT_NOT_FOUND = 1
OTHERS = 2
.
IF SY-SUBRC NE 0.
CONTINUE.
ENDIF.
CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE'
EXPORTING
OBJECT = LS_REMOT-OBJECT
* INTERVALS =
* CALLED_FROM_AIM =
* CLIENT_AIM =
* CHDO_RAP =
* COMMIT =
EXCEPTIONS
NO_CHANGES_MADE = 1
OBJECT_NOT_INITIALIZED = 2
OTHERS = 3
.
IF SY-SUBRC EQ 0.
COMMIT WORK AND WAIT.
ELSEIF SY-SUBRC > 1.
CONTINUE.
ENDIF.
LS_REMOT-NRLEVEL_LC = LS_REMOT-NRLEVEL.
LS_REMOT-STATUS = ICON_OKAY.
MODIFY GT_REMOT FROM LS_REMOT INDEX LS_ROWS.
ENDLOOP.
GR_SALV->REFRESH( ).
MESSAGE S018(00).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form INITIALIZATION
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM INITIALIZATION .
DATA LV_RFC TYPE RFCDES-RFCDEST.
GET PARAMETER ID 'RFC' FIELD LV_RFC.
IF LV_RFC IS INITIAL.
P_DEST = 'PS4'.
ENDIF.
ENDFORM.
#2. GUI Status
'ABAP > 소스코드' 카테고리의 다른 글
[Class] SALV Display - SALV 간단 출력 Class - ZCL_SALV_OUTPUT (0) | 2023.05.27 |
---|---|
[Class] Progress Indicator 처리용 Common Class (0) | 2023.05.24 |
[Include] Progress Indicator 처리용 Common Include (0) | 2023.05.10 |
[ABAP] HMAC 암호화(HMACSHA256) 소스코드 (0) | 2023.05.09 |
[SAP/Report] Table/Structure 의 필드 리스트 조회 (2) | 2023.05.07 |
댓글