*----------------------------------------------------------------------*
* Author: Edo von Glan
* Version 5 (16.11.2016)
*----------------------------------------------------------------------*
* Known problem:
* - if the transport of copies contains table (TABL) and related table entries (TABU),
* AND the table does not exist in the productive system,
* then we get strange errors when releasing (unknown syntax, table does not exist, ...)
* when we try to release the transport of copies in the P system.
* Solution: manually delete the table contents entry.
* (In the program, we could avoid this situation by
* checking in the RFC in the P system for all TABU records, whether
* the table exists)
*----------------------------------------------------------------------*
REPORT zs_decom_obsol_trans.
TABLES: e070.
SELECT-OPTIONS s_trans FOR e070-trkorr. " Trans.Requests 2 B rolled back
PARAMETERS: p_p_tr TYPE trkorr OBLIGATORY " Transprt of copies on P System
, p_p_sys TYPE rfcdest OBLIGATORY DEFAULT 'MT3_050' " Productive system (RFC-Dest.)
.
CLASS lcl DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.
CLASS-METHODS:
process_trkorr
IMPORTING i_trkorr TYPE trkorr,
prepare_trkorr_ok
IMPORTING i_trkorr TYPE trkorr
RETURNING VALUE(r_is_ok) TYPE abap_bool,
prevent_inactive_objects_ok
IMPORTING i_trkorr TYPE trkorr
RETURNING VALUE(r_is_ok) TYPE abap_bool,
release_ok
IMPORTING i_trkorr TYPE trkorr
RETURNING VALUE(r_is_ok) TYPE abap_bool,
store_pre_decom_version
IMPORTING i_it_e071 TYPE e071_t,
delete_empty_task_request_ok
IMPORTING i_trkorr TYPE trkorr
RETURNING VALUE(r_is_ok) TYPE abap_bool.
CONSTANTS: con_allowed_trfunctions_req TYPE string VALUE 'KW' " workbench&customizing request
, con_allowed_trfunctions_task TYPE string VALUE 'QSXR' " workbench&customizing task, unclassified (empty), repair
.
ENDCLASS.
START-OF-SELECTION.
lcl=>main( ).
CLASS lcl IMPLEMENTATION.
METHOD main.
IF s_trans IS INITIAL.
WRITE / |Selection criteria for transports missing|.
EXIT.
ENDIF.
SELECT trkorr FROM e070
WHERE trkorr IN @s_trans
INTO TABLE @DATA(it_trkorr).
IF sy-subrc <> 0.
WRITE / |No transports found with selection criteria|.
ENDIF.
LOOP AT it_trkorr ASSIGNING FIELD-SYMBOL(<wa_trkorr>).
IF prepare_trkorr_ok( <wa_trkorr>-trkorr ).
process_trkorr( <wa_trkorr>-trkorr ).
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD process_trkorr.
DATA: return_msg TYPE bapiret2
, msg TYPE string
, it_e071 TYPE e071_t
.
SELECT * FROM e071
WHERE trkorr = @i_trkorr
" SCN Version 4 of program (ZS_DECOM_OBSOL_TRANS) had another line here, which is a tiny bug
INTO TABLE @it_e071.
IF sy-subrc <> 0.
" new 18.07.2016: automatically delete empty transport requests
IF delete_empty_task_request_ok( i_trkorr = i_trkorr ).
WRITE |Empty transport request - deleted|.
ELSE.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO msg.
WRITE |FAILED deleting empty transport { i_trkorr }: { msg }, subrc { sy-subrc }|.
RETURN.
ENDIF.
RETURN.
ENDIF.
DELETE it_e071 WHERE pgmid = 'CORR'. " ignore log entries CORR RELE and CORR MERG
SORT it_e071 BY pgmid object obj_name objfunc lockflag gennum lang activity.
DELETE ADJACENT DUPLICATES FROM it_e071 COMPARING pgmid object obj_name objfunc lockflag gennum lang activity.
SELECT * FROM e071k
WHERE trkorr = @i_trkorr
INTO TABLE @DATA(it_e071k). "#ec ci_subrc
CALL FUNCTION 'ZS_DEV_APPEND_TO_TR' DESTINATION p_p_sys
EXPORTING
i_it_e071 = it_e071
i_it_e071k = it_e071k
i_trkorr = p_p_tr
IMPORTING
e_wa_return_msg = return_msg
EXCEPTIONS
communication_failure = 1
system_failure = 2.
IF sy-subrc <> 0.
WRITE |Problem with RFC call to system. Sy-subrc = { sy-subrc }|.
EXIT.
ENDIF.
IF return_msg IS NOT INITIAL.
MESSAGE ID return_msg-id TYPE return_msg-type NUMBER return_msg-number
WITH return_msg-message_v1 return_msg-message_v2 return_msg-message_v3 return_msg-message_v4 INTO msg.
WRITE |FAILED: { msg }|.
ELSE.
store_pre_decom_version( it_e071 ).
WRITE |finished|.
ENDIF.
ENDMETHOD.
METHOD prepare_trkorr_ok.
DATA msg TYPE string.
r_is_ok = abap_false.
WRITE / |{ i_trkorr } |.
SELECT SINGLE trfunction, trstatus FROM e070
WHERE trkorr = @i_trkorr
INTO ( @DATA(trfunction), @DATA(trstatus) ).
ASSERT sy-subrc = 0.
IF trfunction NA con_allowed_trfunctions_req.
WRITE |Wrong type: E070-TRFUNCTION = { trfunction }. Allowed: { con_allowed_trfunctions_req }|.
RETURN.
ENDIF.
IF trstatus <> 'D'. " changeable
WRITE |Wrong status: E070-TRSTATUS = { trstatus }. Needs to be D (changeable)|.
RETURN.
ENDIF.
SELECT trkorr, trfunction, trstatus FROM e070
WHERE strkorr = @i_trkorr
ORDER BY trkorr
into table @DATA(it_dependent). "#ec ci_subrc
LOOP AT it_dependent ASSIGNING FIELD-SYMBOL(<dep>).
IF <dep>-trfunction NA con_allowed_trfunctions_task.
WRITE |Wrong type: E070-TRFUNCTION = { <dep>-trfunction } of dependent transport { <dep>-trkorr }. Allowed: { con_allowed_trfunctions_task }|.
RETURN.
ENDIF.
" new 18.07.2016: automatically delete unclassified, empty transport tasks
IF <dep>-trfunction = 'X'. " unclassified
IF NOT delete_empty_task_request_ok( i_trkorr = <dep>-trkorr ).
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO msg.
WRITE |FAILED deleting empty dependent transport { <dep>-trkorr }: { msg }, subrc { sy-subrc }|.
ENDIF.
CONTINUE.
ENDIF.
CASE <dep>-trstatus.
WHEN 'L' OR 'O'. " changeable locked, or release in progress
WRITE |Wrong status: E070-TRSTATUS = { <dep>-trstatus } of dependent transport { <dep>-trkorr }. Allowed: D, R or N (changeable or released)|.
RETURN.
WHEN 'R' OR 'N'.
CONTINUE.
WHEN 'D'. " changeable
IF release_ok( <dep>-trkorr ).
CONTINUE.
ELSE.
RETURN. " error message has already been written
ENDIF.
WHEN OTHERS.
ASSERT 1 = 0.
ENDCASE.
ENDLOOP.
r_is_ok = prevent_inactive_objects_ok( i_trkorr ).
ENDMETHOD.
METHOD prevent_inactive_objects_ok.
" Warn if there are any inactive objects.
" Return true if everything is active.
DATA: it_log TYPE STANDARD TABLE OF sprot_u
, it_e071 TYPE trwbo_t_e071
, msg_str TYPE string
.
SELECT SINGLE * FROM e070
WHERE trkorr = @i_trkorr
INTO @DATA(e070).
ASSERT sy-subrc = 0.
SELECT * FROM e071
WHERE trkorr = @i_trkorr
INTO CORRESPONDING FIELDS of TABLE @it_e071.
IF sy-subrc = 0.
CALL FUNCTION 'TRINT_CHECK_INACTIVE_OBJECTS'
EXPORTING
is_e070 = e070
it_e071 = it_e071
TABLES
et_log = it_log.
ENDIF.
r_is_ok = abap_true.
LOOP AT it_log ASSIGNING FIELD-SYMBOL(<wa_log>).
IF sy-tabix = 1.
WRITE |Contains inactive objects: |.
ELSE.
WRITE |, |.
ENDIF.
IF <wa_log>-severity = 'E' AND <wa_log>-ag = 'EU' AND <wa_log>-msgnr = 829.
WRITE |{ <wa_log>-var1 } { <wa_log>-var2 }|.
ELSE.
MESSAGE ID <wa_log>-ag TYPE <wa_log>-severity NUMBER <wa_log>-msgnr WITH <wa_log>-var1 <wa_log>-var2 INTO msg_str.
WRITE |"{ msg_str }"|.
ENDIF.
r_is_ok = abap_false.
ENDLOOP.
ENDMETHOD.
METHOD release_ok.
DATA msg TYPE string.
CALL FUNCTION 'TR_RELEASE_REQUEST'
EXPORTING
iv_trkorr = i_trkorr
iv_dialog = abap_false
iv_success_message = abap_false
iv_display_export_log = abap_false
EXCEPTIONS
cts_initialization_failure = 1
enqueue_failed = 2
no_authorization = 3
invalid_request = 4
request_already_released = 5
repeat_too_early = 6
error_in_export_methods = 7
object_check_error = 8
docu_missing = 9
db_access_error = 10
action_aborted_by_user = 11
export_failed = 12
OTHERS = 13.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO msg.
WRITE |FAILED releasing dependent transport { i_trkorr }: { msg }, subrc { sy-subrc }|.
r_is_ok = abap_false.
ELSE.
r_is_ok = abap_true.
ENDIF.
ENDMETHOD.
METHOD store_pre_decom_version.
" this function module stores a version of all versionable
" objects, as if the current version had just been released
" with a transport request
CALL FUNCTION 'SVRS_STORE_VERSION'
EXPORTING
date = sy-datum
time = sy-uzeit
user = sy-uname
korr = 'PRE_DECOMM'
mode = ''
TABLES
e071_tab = i_it_e071.
ENDMETHOD.
METHOD delete_empty_task_request_ok.
SELECT @abap_true FROM e071
WHERE trkorr = @i_trkorr
INTO @DATA(has_content)
UP TO 1 ROWS.
ENDSELECT.
ASSERT has_content = abap_false.
CALL FUNCTION 'TR_CHANGE_USERNAME'
EXPORTING
wi_dialog = abap_false
wi_trkorr = i_trkorr
wi_user = sy-uname
EXCEPTIONS
already_released = 1
e070_update_error = 2
file_access_error = 3
not_exist_e070 = 4
user_does_not_exist = 5
tr_enqueue_failed = 6
no_authorization = 7
wrong_client = 8
unallowed_user = 9
OTHERS = 10.
IF sy-subrc = 0.
CALL FUNCTION 'TR_DELETE_COMM'
EXPORTING
wi_dialog = abap_false
wi_trkorr = i_trkorr
EXCEPTIONS
file_access_error = 1
order_already_released = 2
order_contains_c_member = 3
order_contains_locked_entries = 4
order_is_refered = 5
repair_order = 6
user_not_owner = 7
delete_was_cancelled = 8
ordernumber_empty = 9
tr_enqueue_failed = 10
objects_free_but_still_locks = 11
order_lock_failed = 12
no_authorization = 13
wrong_client = 14
project_still_referenced = 15
successors_already_released = 16
OTHERS = 17.
ENDIF.
r_is_ok = xsdbool( sy-subrc = 0 ).
ENDMETHOD.
ENDCLASS.
* PART 1: Top-Include of Function Pool (Include LZS_DEV_TOOLS_RFCTOP)
FUNCTION-POOL zs_dev_tools_rfc MESSAGE-ID zs_dev_tools.
CLASS lcl DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS:
append_to_tr
IMPORTING i_trkorr TYPE trkorr
i_it_e071 TYPE e071_t
i_it_e071k TYPE e071k_t
EXPORTING e_wa_return_msg TYPE bapiret2.
PRIVATE SECTION.
CLASS-METHODS:
check_transport
IMPORTING i_trkorr TYPE trkorr
EXPORTING e_is_ok TYPE abap_bool
CHANGING c_wa_return_msg TYPE bapiret2,
get_next_as4pos
IMPORTING i_trkorr TYPE trkorr
RETURNING VALUE(r) TYPE e071-as4pos,
determine_as4pos
CHANGING
c_it_e071k TYPE e071k_t.
ENDCLASS.
* PART 2: Function Module (Include LZS_DEV_TOOLS_RFCU01)
* Note that this function module has to be created as an RFC-enabled function
FUNCTION ZS_DEV_APPEND_TO_TR
IMPORTING
VALUE(I_IT_E071) TYPE E071_T
VALUE(I_IT_E071K) TYPE E071K_T
VALUE(I_TRKORR) TYPE TRKORR
EXPORTING
VALUE(E_WA_RETURN_MSG) TYPE BAPIRET2.
lcl=>append_to_tr( EXPORTING i_it_e071 = i_it_e071
i_it_e071k = i_it_e071k
i_trkorr = i_trkorr
IMPORTING e_wa_return_msg = e_wa_return_msg ).
ENDFUNCTION.
* PART 3: Local Class implementation (Include LZS_DEV_TOOLS_RFCP01)
CLASS lcl IMPLEMENTATION.
METHOD append_to_tr.
DATA: it_e071 TYPE e071_t
, it_e071k TYPE e071k_t
, wa_e071 TYPE e071
.
check_transport( EXPORTING i_trkorr = i_trkorr
IMPORTING e_is_ok = DATA(is_ok)
CHANGING c_wa_return_msg = e_wa_return_msg ).
CHECK is_ok = abap_true.
LOOP AT i_it_e071 ASSIGNING FIELD-SYMBOL(<wa_e071>).
MOVE-CORRESPONDING <wa_e071> TO wa_e071.
wa_e071-trkorr = i_trkorr.
wa_e071-as4pos = get_next_as4pos( i_trkorr ).
wa_e071-objfunc = COND #( WHEN wa_e071-objfunc = 'K' THEN 'K' " entry has key records in E071K
ELSE '' ). " other values are only relevant in source system
CLEAR wa_e071-lockflag. " only relevant in source system
APPEND wa_e071 TO it_e071.
ENDLOOP.
INSERT e071 FROM TABLE it_e071.
ASSERT sy-subrc = 0.
it_e071k = VALUE #( FOR wa_e071k IN i_it_e071k ( VALUE #( BASE wa_e071k
trkorr = i_trkorr ) ) ).
determine_as4pos( CHANGING c_it_e071k = it_e071k ).
INSERT e071k FROM TABLE it_e071k.
ASSERT sy-subrc = 0. " there are potential conflicts, if the same e071k entries are added via this method again. The method should not be used like this
COMMIT WORK.
ENDMETHOD.
METHOD check_transport.
e_is_ok = abap_false.
CLEAR c_wa_return_msg.
SELECT SINGLE @abap_true FROM e070 INTO @e_is_ok
WHERE trkorr = @i_trkorr
AND trstatus = 'D'. "#ec ci_subrc D = changeable
IF e_is_ok = abap_false.
MESSAGE e001 WITH i_trkorr INTO c_wa_return_msg-message. " transport not found or not suitable
c_wa_return_msg-type = sy-msgty.
c_wa_return_msg-id = sy-msgid.
c_wa_return_msg-number = sy-msgno.
c_wa_return_msg-message_v1 = sy-msgv1.
c_wa_return_msg-message_v2 = sy-msgv2.
c_wa_return_msg-message_v3 = sy-msgv3.
c_wa_return_msg-message_v4 = sy-msgv4.
ENDIF.
ENDMETHOD.
METHOD get_next_as4pos.
STATICS: last_trkorr TYPE trkorr
, last_as4pos TYPE e071-as4pos
.
IF last_trkorr <> i_trkorr.
SELECT MAX( as4pos ) FROM e071
WHERE trkorr = @i_trkorr
INTO @last_as4pos.
ASSERT sy-subrc = 0. " always 0 for aggregate functions
last_trkorr = i_trkorr.
ENDIF.
r = last_as4pos + 1.
last_as4pos = r.
ENDMETHOD.
METHOD determine_as4pos.
LOOP AT c_it_e071k INTO DATA(wa_temp) GROUP BY ( trkorr = wa_temp-trkorr
pgmid = wa_temp-pgmid
object = wa_temp-object
objname = wa_temp-objname )
ASSIGNING FIELD-SYMBOL(<group>).
SELECT MAX( as4pos ) FROM e071k
WHERE trkorr = @<group>-trkorr
AND pgmid = @<group>-pgmid
AND object = @<group>-object
AND objname = @<group>-objname
INTO @DATA(last_as4pos).
ASSERT sy-subrc = 0. " always 0 for aggregate functions
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<wa_e071k>).
<wa_e071k>-as4pos = last_as4pos + 1.
last_as4pos = <wa_e071k>-as4pos.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
6 | |
5 | |
3 | |
3 | |
2 | |
2 | |
2 | |
2 | |
1 | |
1 |