Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Clemenss
Active Contributor

Execute ABAP Program Automatically After Transport Request Import

  <<< sorry I can't use this editor very well -coukd not attach pdf to see the screen shots - scn is not too much fun any more pls.mail me at clemens.li@gmx.de to receive a copy of the pdf >>>

After importing objects to integration or productive system it may be required to adapt the system.

A well-known situation is the change of conditions and formulas for pricing. If you create a new VOFM object, the system will automatically attach RVH80HGEN to the transport request.

If you change an existing object, you should include Report RVH80HGEN as XPRA - Execute Program after Import.

Display the object list of your transport request or task. Switch to Change mode.

Insert row

Enter Program ID R3TR Object Type XPRA Object Name RV80HGEN, hit Enter

That's it.

Now some words about what happens and what you can do further.

The XPRA object is an executable ABAP program that will run after all objects included in the transport request have been imported. It is run regardsless of any import errors for other included objects. The program does not require a selection screen as it run as is. We can not supply any parameters or a variant for execution.

When the import is completed, you will find the execution of the program in the transport log in the Method Execution section.

Expand the log to check the execution of XPRA report

Between the report  started and report ended entries you can find all messages written by the XPRA program to the transport log - see below.

If you want to create your own XPRA, be aware that it is executed in Client 000. This is OK for generation of programs. But if you want to change any data, then all database operations must be done with the addition CLIENT SPECIFIED. In this case the program must use the CLIENT value where the changes are expected.

Here is an application example.

A customer-specific customizing table should be changed so that all values specified for a specifiy key become time-dependent .

We added a valid-from date field to the key and a valid to date field to the non-key attributes.

The adaptation of the maintenance view ensuring non-overlapping time slices without gaps and the correctv use of the table is not covered in this article.

After the table is changed and adjusted with the import, the a valid-from date field and the valid to date field are initial. We want to define an initial validity from January 1st, 1900 to december 31st, 9999.

As it is not possible to change the value of a key field (valid-from date) we created a program to adapt our two tables.

The form routine can be (re-)used for any table. Information messages are written directly to the transport log. To simplify the process of collecting and retrieving messages,  we use our own class zclbc_appl_log. This class has one to create a SAP application log, anotherm to add a message  tom the log by evaluating the repective SYST fields (SY-MSGID , SY_MSGTY,...) and a method to retrieve the messages in a table like a RETURN table of a BAPI function. The messages are written to the transport log  using function 'TR_APPEND_LOG'.

Here is the code:

*&---------------------------------------------------------------------*
*&      Form  UPDATE_INITIAL_TIMESLICE
*&---------------------------------------------------------------------*
FORM update_initial_timeslice
USING tabname TYPE tabname.
DATA:
lr_tab     
TYPE REF TO data,
lr_tabd   
TYPE REF TO data,
lr_tabi   
TYPE REF TO data,
lt_sprot_u 
TYPE STANDARD TABLE OF sprot_u,
lr_log     
TYPE REF TO zclbc_appl_log,
lt_bapiret2
TYPE bapiret2_t,
lv_mandt   
TYPE sy-mandt.
FIELD-SYMBOLS:
<table>   
TYPE STANDARD TABLE,
<tabld>   
TYPE STANDARD TABLE,
<tabli>   
TYPE STANDARD TABLE,
<record>   
TYPE any,
<datab>   
TYPE datab,
<datbi>   
TYPE datbi,
<sprot_u> 
TYPE sprot_u,
<bapiret2> 
TYPE bapiret2.
* use client system-dependent
CASE sy-sysid.
WHEN 'T05'.
lv_mandt
= '010'.
WHEN OTHERS.
lv_mandt
= '001'.
ENDCASE.
* create internal tables for original, to-be-inserted and to-be-deleted records
CREATE DATA:
lr_tab 
TYPE STANDARD TABLE OF (tabname),
lr_tabd
TYPE STANDARD TABLE OF (tabname),
lr_tabi
TYPE STANDARD TABLE OF (tabname).
* Use field-symbols for table access
ASSIGN:
lr_tab
->TO <table>,
lr_tabd
->* TO <tabld>,
lr_tabi
->* TO <tabli>.
* Create SAP application log - no object and sub-object as we don't save it
lr_log
= zclbc_appl_log=>create( ).
* Select original records
SELECT *
INTO CORRESPONDING FIELDS OF TABLE <table>
FROM (tabname)
CLIENT SPECIFIED
WHERE mandt = lv_mandt.
* log information
MESSAGE s627(je) WITH sy-dbcnt tabname INTO lr_log->mv_message..
*  &1 records were read from table/view &2
lr_log
->add_sy_msg( ).
* SORT is not required but alway helpful, specially in debugger
SORT <table>.
* process table
LOOP AT <table> ASSIGNING <record>.
* assign the date-from and to field to field-symbols
ASSIGN COMPONENT 'DATAB' OF STRUCTURE <record> TO <datab>.
* abort and dump if field is not present in table
ASSERT sy-subrc = 0.
ASSIGN COMPONENT 'DATBI' OF STRUCTURE <record> TO <datbi>.
ASSERT sy-subrc = 0.
* Only records not yet processed are adapted
IF ( <datab> IS NOT INITIAL AND <datab> <> space ) OR
( <datbi> IS NOT INITIAL AND <datbi> <> space ).
* done already, skip to next record
CONTINUE.
ENDIF.
* original record to delete
APPEND <record> TO <tabld>.
* set initial validity
<datab>
= '19000101'.
<datbi>
= '99991231'.
* record for insertion
APPEND <record> TO <tabli>.
ENDLOOP."AT lt_table
* insert the adapted records into database table
INSERT (tabname) CLIENT SPECIFIED FROM TABLE <tabli>.
* log information
MESSAGE s268(63) WITH lv_mandt sy-dbcnt tabname INTO lr_log->mv_message.
*  Client &: & records inserted in table &
lr_log
->add_sy_msg( ).
* delete orignal records from database
DELETE (tabname) CLIENT SPECIFIED FROM TABLE <tabld> .
* log information
MESSAGE s267(63) WITH lv_mandt sy-dbcnt tabname INTO lr_log->mv_message.
*  Client &: & existing records deleted from table &
lr_log
->add_sy_msg( ).
* get all logged mesages
lt_bapiret2
= lr_log->get_msg_table( ).
* transfer the message table to table of type SPROT_U
LOOP AT lt_bapiret2 ASSIGNING <bapiret2>.
APPEND INITIAL LINE TO lt_sprot_u ASSIGNING <sprot_u>.
<sprot_u>
-level    = 1.
<sprot_u>
-severity = space.
<sprot_u>
-langu    = sy-langu.
<sprot_u>
-ag      = <bapiret2>-id.
<sprot_u>
-msgnr    = <bapiret2>-number.
<sprot_u>
-newobj  = space.
<sprot_u>
-var1    = <bapiret2>-message_v1.
<sprot_u>
-var2    = <bapiret2>-message_v2.
<sprot_u>
-var3    = <bapiret2>-message_v3.
<sprot_u>
-var4    = <bapiret2>-message_v4.
ENDLOOP."AT lt_bapiret2
* write messages to the transport log
CALL FUNCTION 'TR_APPEND_LOG'
TABLES
xmsg         
= lt_sprot_u
EXCEPTIONS
file_not_found
= 1
wrong_call   
= 2
OTHERS        = 3.
* Not written successfully? Should not happen
IF sy-subrc <> 0.
RETURN.
ELSE.
* Flush the log
CALL FUNCTION 'TR_FLUSH_LOG'.
ENDIF.
ENDFORM.                    " UPDATE_INITIAL_TIMESLICE

2 Comments