Time for fun and humor. Dilbert and ERP and software implementation is a nice match.
Author: saptechnicalguru
TRDIR and TADIR: tables behind programs and tables
TRDIR and TADIR are the tables behind programs and table data.
The below section is for experts only. Sometimes direct interception in TRDIR or TADIR is needed to solve nasty upgrade and support package issues. But if you don't know what you are doing: don't touch and raise message to SAP.
TADIR: development objects
TADIR contains the development objects list.
For example you want to know how many Z classes are created in your system, search in TADIR with SE11 and count the records:
Using TADIR with a search on DEVCLASS $TMP will give you a list with all programs in the $TMP (temp) space.
TADIR also has information about the original system. To change: follow the instructions in this blog.
TADIR does not contain a program editor lock. This is stored in table PROGDIR. See more in this blog.
Background notes on TADIR:
- 1660342 – Recreating missing TADIR entry
- 1915543 – An object that has been deleted still exists in TADIR
- 2456803 – ERROR: SAP System not installed properly. Systems name (ABC) is different from name in TADIR (XYZ)
- 2589309 – Fixes to reimplementation handling – Ignore TADIR for new objects and invalid pre-requisite Notes
- 2686235 – How to find OData service objects in TADIR Table?
- 2848317 – Custom-defined routines in VOFM: Repair of TADIR entries
- 3168202 – Deleting include in $ package does not delete TADIR entry
- 3230854 – NZDT Deletion of TADIR entries of logging tables
TRDIR: source code
TRDIR is a view on table REPOSRC. REPOSRC contains the actual ABAP source codes in RAWSTRING format. In some cases inconsistencies between TRDIR and TADIR might happen (mainly during upgrades). Direct interception on TADIR or TRDIR level might be needed, if you know what you are doing.
Transaction STDR can be used to check consistency:
Background notes on TRDIR:
Network performance tips & tricks
One of the most irritating and annoying things in the basis area is when the network gives issues. For whatever reason.
This blog will give hints and tips on how to recognize network issues and options to analyze them.
SAP notes on network performance
Main OSS note is: 1100926 – FAQ: Network performance.
Main SAP wiki on network performance can be found via this link.
Detailed analysis notes:
Specific issues with application to database server issues:
- 2543171 – Latency issue between application server and Database
- Use the ABAPMETER: 2879613 – ABAPMETER in NetWeaver AS ABAP and this blog
Check if database is the issue, or network:
- 2419095 – Performance degraded as DB Time increased
- 3274421 – Easy-start for HANA DB overall system performance issue
Network issues on Azure:
LAN check
Check by ST06: start the LAN check by Ping:
Or directly via transaction OS01:
SAP GUI network issues
If the user is far away from the server, network issues can be cause of slow transactions for the end user.
SAP GUI slow connection can be set on creation of GUI entry, or by right clicking on the GUI entry and then selecting the network option:
FIORI and web developments
FIORI tiles and web developments might be slow with users further away from the server. If the application has many round trips built in the increase network latency will definitely kill the end user performance.
Read more in this blog on how you can simulate a distant user in Chrome to analyze the issue.
Clean ABAP code ATC variant
Clean ABAP is the ABAP variant of the clean code principles. All background on clean ABAP code can be read in this blog.
This blog will explain how to upload the ABAP coding for the Clean ABAP ATC variant in your system and activate it.
Load ABAP Git code
To load the ATC variant code for clean ABAP you first need to install the ABAP Git code. Follow the instructions in this blog to do so. Simplest is the offline variant.
Download the ABAP clean code package
Now go to the Github code pal site for ABAP clean code and download the package:
Select the button Code and choose the option Download ZIP.
Upload the package
Now start the ABAP git that you loaded in your first step. Choose the option New Offline:
Give the repository a name and select a package:
Then push the button Create Offline Repo.
Now select Import Zip:
Import the file you downloaded in step 2 from the code pal site.
Next step is the Pull zip:
You might get a screen with differences. Do not select anything there, only press Ok.
Then wait until all the Y objects are pulled into the system. This might take 5 to 10 minutes.
Activating the SCI checks
Now start transaction SCI. Select menu option Code Inspector, Management of, Tests. Select all the newly load Y checks for Clean ABAP code:
Important now: Save them!
Now you can create a global SCI variant:
Select all the Clean code ABAP checks and save the variant:
You might get weird issues upon saving for other items, like for example missing CL_CI_CATEGORY_TOP. In that case, go to transaction SE16 -> look for table SCITESTS -> and look for CL_CI_CATEGORY_TOP if there is no entry. Enter the table SCITESTS and click "Create Entry", add CL_CI_CATEGORY_TOP entry and save.
Test and usage
Take a program you want check. Then select menu option Program, Check, ABAP Test Cockpit with….:
Select the ZCLEAN_ABAP SCI check we created above. Run the checks.
Results:
Tip: click on the blue line to jump to the Clean Code site exactly explaining about the issue.
Clean ABAP Eclipse plug-in: ABAP cleaner
To speed up clean ABAP in practice, you can install the clean ABAP cleaner plug-in. Read this blog on how to do this.
Clean ABAP
Clean ABAP is the ABAP implementation of Clean code. Clean code is one of the key principles to adhere to when going Agile. Clean code is part of agile software development craftmanship. Read more on clean code in the original book.
Clean ABAP reference site
Clean ABAP is published and maintained on a dedicated Clean ABAP Github site.
The site itself is excellent and also has a special chapter how to best start with Clean ABAP.
The site is extensive and might be overwhelming. If you are a more traditional person, you can also read the SAP Press book on Clean ABAP code.
Blog on SAP site on clean ABAP can be found here and here.
Patterns and anti-patterns
The Clean ABAP explanation on the site contains both patterns (how you should do) and anti-patterns (how you should not do).
Anyhow the Clean ABAP principles are fully built on Object Orientation. That is a must.
Introducing Clean ABAP in your organization
Regardless if your organization is doing Agile or Waterfall development, or other development methodologies, Clean ABAP can be applied anyhow.
First step is to embrace the Clean ABAP as a principle direction. It will take time to get there. Not all developers will pick up as fast as you might want to. It also takes time to refactor old code to the Clean ABAP principles.
Discuss as developers as a team which part of the principles and improvements you want to pick up first. If you master a few, you can make it mandatory. Then take the next set. Some might pick up more at a higher pace. But keep the discussion going to improve and pick up every 2 weeks (sprint) at least 1 improvement item.
For a nice overview: read this SAP blog.
Peer review or pair programming: ATC variant
You can make the Clean ABAP code rules a part of your peer review or pair programming.
There is an ATC variant that can be uploaded that check for the clean ABAP code rules. Read this blog for instructions on how to do this.
Boy Scout rule
The boy scout rule is as follows: leave the place nicer than when you arrived, even though you didn’t make the mess. When you do this repetitively the world becomes a cleaner place.
This also applies to poor code: don’t just do your change, but take along some minor improvements as well. When you do this a couple of times, the poor code will improve every time towards good code.
But this principle you also need to embrace and explain. There might be unlucky situations where the clean up part might cause unexpected bug. This might happen in 0.01% of the cases. When it happens you might get resistance and pushback. But stand up for the principle, and simply correct the bug. It is worth it in the long run.
Clean ABAP Eclipse plug-in: ABAP cleaner
To speed up clean ABAP in practice, you can install the clean ABAP cleaner plug-in. Read this blog on how to do this.
ODATA V4 activation
This blog will explain how to activate ODATA V4.
Questions that will be answered in this blog are:
- How to activate ODATA V4 on your SAP system?
- Does SAP support ODATA V3?
- Do all consuming applications support ODATA V4?
- What are the differences of ODATA V2 and V4?
ODATA V4
In the typical FIORI use case you will activate ODATA V2. SAP has skipped ODATA V3. ODATA V4 is supported by SAP.
Constraints of SAP ODATA V4 are listed in OSS note 2322624 – SAP Gateway SAP_GWFND OData V4 protocol – Known Constraints.
Filtering is powerful in ODATA V4. Read more on this in OSS note 2305033 – SAP Gateway OData V4 $flter Consulting Note.
Keep in mind not all application fully support all aspects of ODATA V4 or might not be able to consume ODATA V4 at all. Check first with the consumer before publishing an ODATA on V4.
Activation of ODATA V4
First step in activation is to check the virus scan settings for ODATA:
Activation of ODATA V4 messages via service administration:
Or use transaction /iwbep/v4_admin:
And for the front end /iwfnd/v4_admin:
Press button Add service groups:
Push the button Get Service Groups:
And select your entry and press Publish Service Groups:
Which one to publish has to be told to you. The consultant requesting it might link to the API hub.
After activation, you can use the Service Test button to check if the activation is ok:
On the screen hit Execute and the result should be a HTTP 200 success message:
OSS notes and background
Background notes:
- 2948977 – How to Register OData V4 Service in SAP Gateway System?
- 3027559 – OData V4 and Client Proxy: Handling of Virus Scanner related issues
- 3037006 – How to unpublish ODATA V4 service groups?
- 3101976 – Publishing OData V4 service is throwing error: Publishing of XXXXXXXXXX in Customizing client not allowed
- 3145233 – Unsupported Front-end/Hub version.
- 3220333 – How to transport ODATA V4 Service group registration?
- 3245194 – How to distinguish the version of OData – V2 or V4
- 3247965 – How to Transport OData V4 Service Groups?
- 3248335 – Transport Request screen is not appearing when publishing the OData V4 Service Groups
Bug fix OSS notes:
- 3031742 – Shortdump ASSERTION_FAILED in /IWBEP/CL_V4_MED_MODEL_FACTORY
- 3125215 – Accept Blank if-match headers
- 3143041 – Partial-busi-data flag is set incorrectly by old front-end / hub systems in remote scenario
- 3232327 – Fix for stateful tracelogs in Gateway Odata V4
- 3236604 – ContentID in error message spelled wrong
- 3243730 – Nullable Action Parameter causes dump
- 3260505 – Service Feature: Flag Framework calculated properties as provided
Useful background blogs:
Differences between ODATA V2 and V4
For UI consumption differences between ODATA V2 and V4 read this SAP help file.
Generic blog on main differences ODATA V2 and V4: read here.
Or read this SAP blog on differences ODATA V2 and V4 for SAP specific.
Deleting SAP office documents
In your system the amount of SAP office documents is consuming more and more space. You want to clean up these tables: BCST_CAM, BCST_SR, SOC3, SOFFCONT1, SOFM, SOOD, SOOS, SOST. This blog will explain how.
Questions that will be answered are:
- How to reduce size of tables BCST_CAM, BCST_SR, SOC3, SOFFCONT1, SOFM, SOOD, SOOS, SOST?
- How to run the clean up programs before running RSBCS_REORG?
- How to run program RSBCS_REORG?
SAP office documents to content server
If table SOFFCONT1 is growing fast, you can migrate data to the content server. This might be the easiest solution. Read more in this blog.
See also note 1634908 – Reduce the number of entries of table SOFFCONT1.
See OSS note 3225275 – BC-SRV-COM Guided Answer for the guided Q&A.
Preparations before running RSBCS_REORG
SAP office documents are stored in table SOFFCONT1, and can be deleted with program RSBCS_REORG. See note 966854 – Reorganization – new report. Note 988057 – Reorganization – information contained in the past a very useful PDF document that explains what to do in cases that RSBCS_REORG is not directly can delete an SAP office document. This was removed, but you can download it here:
In most cases you have to run a special program that breaks the link between the document and the data. After that is done you can delete the content. Extra explanation is in OSS note 1641830 – Reorganization of Business Communication Services data (RSBCS_REORG).
Set expiration date
Run program RSBCS_SREQ_EXPIRE (see OSS note 1478279 – Deleting send requests that have not expired) to set the expiration date when needed:
This will remove the expiry dates.
Release the send requests
Run program RSBCS_SREQ_RELEASE (see OSS note 1238740 – Deleting unreleased send requests):
Don’t select too much data, otherwise the program will dump (see note 3033843 – Program RSBCS_SREQ_RELEASE failed with dump TSV_TNEW_PAGE_ALLOC_FAILED).
This will release the send requests for deletion.
But it will only do so if a document is attached. Apply OSS note 3256308 – Initial send requests are not released to get new program RSBCS_SREQ_INITIAL_RELEASE:
This will also release the send request for deletion in case there is no document attached.
Unlink document from application
Run program RSBCS_SREQ_UNLINK (see note 1276402 – Send requests cannot be deleted due to links) to unlink the the document from the object:
Document is in SAP connect queue
Documents might still be in the SAP connect queue. Use program RSBCS_DELETE_QUEUE (see OSS note 1244680 – Deleting send requests from the queue) to remove the queue for the documents:
Document is in a folder
If the document is in a folder it might be in different sort of folder:
- Hidden folder
- Private folder
- Document has GOS link
Document is in a hidden folder
Run program RSSODFRE (see OSS note 567975 – Hidden folder: Reorganization) to delete documents from the hidden folders:
Document is in a private folder
Run program RSSO_DELETE_PRIVATE (see OSS note 922671 – Deleting folder entries) to delete from private folder:
Document has GOS link
To be able to delete document with GOS link, run program RSGOSRE01 (see OSS notes 569123 – Reorganizing documents from generic object services, 1641800 – How to delete ‘Has links to GOS/Document not sent’ documents from the Hidden folder and 2016688 – RSGOSRE01: New selection parameters):
Or run program RSGOSRE02 (OSS note 2031234 – RSGOSRE02: Reorganizing documents from generic object services):
Running RSBCS_REORG
Program RSBCS_REORG will not archive, but only delete.
Test this first and check with the data owner that the documents are no longer needed.
Program RSBCS_REORG selection criteria:
Output:
Double clicking on the line will show the details for the issue why you cannot delete.
Bug fix OSS notes for RSBCS_REORG:
ABAP to content server check
A content server can be used to store attachments and other documents. In some cases both the ABAP stack and content server are up and running, but the connection between the two is broken for some reason.
This blog will provide a check program which you can plan in a batch job to check the connection between the ABAP stack content repository and the the content server.
Questions that will be answered in this blog are:
- How can I automate the content server check?
- How can I be alerted if the connection between ABAP stack and content server is broken?
The OAC0 connection check
In transaction OAC0 for maintaining the content server link there is a check button:
We will use the function module SCMS_HTTP_PING which is behind this button for our custom code ABAP test program.
Custom code ABAP check program for testing the ABAP to content server connection
Load this ABAP code into your system and create the texts:
*&---------------------------------------------------------------------*
*& Report ZCSCHECK
*&---------------------------------------------------------------------*
REPORT ZCSCHECK.
DATA: z_ok TYPE boolean.
CONSTANTS: c_mesid TYPE char3 VALUE 'ZZZ', "system log message ID defined in SE92
c_zero TYPE string VALUE '0 ',
c_secirity_n TYPE c VALUE 'N',
c_secirity_s TYPE c VALUE 'S'.
PARAMETERS p_crep TYPE scms_crep MATCHCODE OBJECT h_crep_http.
* initialize ok code
z_ok = abap_true.
*Fetch http server details
SELECT SINGLE crep_id, http_serv, http_port, http_sport, http_scrpt, version
FROM crep_http INTO @DATA(ls_crep)
WHERE crep_id = @p_crep.
IF sy-subrc EQ 0.
IF NOT ls_crep-http_port CO c_zero OR
ls_crep-http_sport CO c_zero.
CALL FUNCTION 'SCMS_HTTP_PING'
EXPORTING
crep_id = ls_crep-crep_id
http_serv = ls_crep-http_serv
http_port = ls_crep-http_port
http_sport = ls_crep-http_sport
http_scrpt = ls_crep-http_scrpt
version = ls_crep-version
security = c_secirity_n"'N'
EXCEPTIONS
error_http = 1
OTHERS = 2.
IF sy-subrc <> 0.
z_ok = abap_false. "not ok
ENDIF.
ENDIF.
*Check Security with S
IF z_ok <> abap_false AND NOT ls_crep-http_sport CO c_zero.
CALL FUNCTION 'SCMS_HTTP_PING'
EXPORTING
crep_id = ls_crep-crep_id
http_serv = ls_crep-http_serv
http_port = ls_crep-http_port
http_sport = ls_crep-http_sport
http_scrpt = ls_crep-http_scrpt
version = ls_crep-version
security = c_secirity_s"'S'
EXCEPTIONS
error_http = 1
OTHERS = 2.
IF sy-subrc <> 0.
z_ok = abap_false. "not ok
ENDIF.
ENDIF.
IF z_ok = abap_false. "not ok
* write to SM21 system log
WRITE: / TEXT-004. "ping not ok
CALL FUNCTION 'RSLG_WRITE_SYSLOG_ENTRY'
EXPORTING
sl_message_area = c_mesid(2)
sl_message_subid = c_mesid+2
data_word1 = ls_crep-crep_id
EXCEPTIONS
data_missing = 1
data_words_problem = 2
other_problem = 3
pre_params_problem = 4
OTHERS = 5.
IF sy-subrc EQ 0.
WRITE: / TEXT-001 , ls_crep-crep_id. "succes to write to SM21
ELSE.
WRITE: / TEXT-002 , ls_crep-crep_id. "fail to write to SM21
ENDIF.
ELSE.
WRITE: / TEXT-003 , ls_crep-crep_id. "ping ok
ENDIF.
ELSE.
WRITE: / TEXT-004 , ls_crep-crep_id. "Ping to webservice not ok
ENDIF.
The program uses function module SCMS_HTTP_PING to test the connection. In case of issues it will write an entry to the application log. Use SE92 to create a new system log message. You can choose to replace this code by sending a mail or do anything else.
Running the check program
Running the program is simple:
If the connection fails it writes an entry to SM21.
In case you have multiple content repositories to check: create multiple variants and run the program in background with multiple steps.
Data archiving: CO Order data
This blog will explain how to archive CO Order data via object CO_ORDER. Generic technical setup must have been executed already, and is explained in this blog.
Object CO_ORDER
Go to transaction SARA and select object CO_ORDER.
Dependency schedule:
This means you must first archive relevant purchase requisitions, purchaser orders and financial documents relating to the CO order..
Tables that are archived:
Most important:
- COEP: CO line items
Technical programs and OSS notes
Pre-processing program: RKOREO01
Write program: RKAARCWR
Delete program: RKAARCD1
Read program: RKAARCS1
Relevant OSS notes:
Application specific customizing
In the application specific customizing for CO_ORDER you have to set two retention periods per CO order type:
Residence time 1 determines the time interval (in calendar months) that must elapse between setting the delete flag (step 1) and setting the deletion indicator (step 2).
Residence time 2 determines the time (in calendar months) that must elapse between setting the deletion indicator (step 2) and reorganizing the object (step 3).
Executing the pre-processing run
The pre-processing run will set the deletion indicator for the CO Orders:
The output is a list of orders that are processed, and if not processed, the reason of blocking is written down.
Executing the write run and delete run
In transaction SARA, CO_ORDER select the write run:
Select your data, save the variant and start the archiving write run.
Give the archive session a good name that describes date range. This is needed for data retrieval later on.
After the write run is done, check the logs. CO_ORDER archiving has average speed, but high percentage of archiving (up to 100%). Reason is that all filtering and checking is already done by the pre-processing program.
Deletion run is standard by selecting the archive file and starting the deletion run.
Data retrieval
Start the data retrieval program and fill selection criteria:
Result is a list. From the list double click on the order. You can see the order now in normal GUI layout.
Custom program to mass cancel workflow items
Mass cancellation of work items is possible with the SWIA transaction as explained in this blog.
This blog will explain how you can use Z program to mass close like SWIA, but then in batch job mode, and automatically without user interaction.
The custom program
The custom program ZRSWIWILS_WI_CANCEL is basically a copy of standard SAP program RSWIWILS.
You can copy and paste the code from below source code text and add the text symbols and selection screen parameter text.
Start screen has 1 extra option more than standard SAP:
The program working explained
When the new option is selected, after the data fetching, the program simply calls function module SWW_WI_ADMIN_CANCEL to cancel the item. Since it is done in loop and without user interaction, the program can run in batch mode.
The custom program source code text
* Report ZRSWIWILS_WI_CANCEL *----------------- Standard program RSWIWILS copy ---------------------* *---------- This code is to extend existing functionality--------------* REPORT zrswiwils_wi_cancel MESSAGE-ID swf_rep_base. INCLUDE rswlfcod. INCLUDE rswuincl. CLASS cl_swf_rdg_dispatcher DEFINITION LOAD. ************************************************************************ * Begin of Data * ************************************************************************ DATA: g_list_cnt TYPE sy-tabix. DATA: zlt_wiheader TYPE swfatalvitm. DATA: int TYPE REF TO if_swf_rep_workitem_selection. DATA: tcode LIKE sy-tcode. DATA: g_windows_titlebar TYPE string. CONSTANTS: zlc_tcode TYPE sytcode VALUE 'SWIA'. *- type pools TYPE-POOLS: slis. TABLES: swfawrkitm. *- select options SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-a01. SELECT-OPTIONS: id FOR swfawrkitm-wi_id. SELECTION-SCREEN END OF BLOCK b1. SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-a02. SELECT-OPTIONS: type FOR swfawrkitm-wi_type, state FOR swfawrkitm-wi_stat, prio FOR swfawrkitm-wi_prio, dhsta FOR swfawrkitm-wi_dh_stat, task FOR swfawrkitm-wi_rh_task, taskg FOR swfawrkitm-wi_rh_task NO INTERVALS. PARAMETERS: top_only TYPE xfeld. SELECTION-SCREEN END OF BLOCK b2. SELECTION-SCREEN BEGIN OF BLOCK b3 WITH FRAME TITLE TEXT-a03. SELECT-OPTIONS: cd FOR swfawrkitm-wi_cd, ct FOR swfawrkitm-wi_ct NO-EXTENSION. SELECTION-SCREEN END OF BLOCK b3. SELECTION-SCREEN BEGIN OF BLOCK b6 WITH FRAME TITLE TEXT-a06. PARAMETERS: p_cancel TYPE xfeld DEFAULT ' '. SELECTION-SCREEN END OF BLOCK b6. SELECTION-SCREEN BEGIN OF BLOCK b4 WITH FRAME TITLE TEXT-a04. PARAMETERS: p_more TYPE swi_params-option AS CHECKBOX. PARAMETERS: filter TYPE swf_utl002-clsname NO-DISPLAY. PARAMETERS: p_swia TYPE xfeld NO-DISPLAY DEFAULT space. " note 1274031 SELECTION-SCREEN END OF BLOCK b4. SELECTION-SCREEN BEGIN OF BLOCK b5 WITH FRAME TITLE TEXT-a05. PARAMETERS: p_maxsel TYPE tbmaxsel. SELECTION-SCREEN END OF BLOCK b5. *------------------------------------------------------------- INITIALIZATION. *------------------------------------------------------------- cd-low = sy-datum. cd-sign = 'I'. cd-option = 'EQ'. APPEND cd. *------------------------------------------------------------- *- F4 functionality *------------------------------------------------------------- AT SELECTION-SCREEN ON VALUE-REQUEST FOR task-low. DATA: act_object_ext TYPE rhobjects-object. CALL FUNCTION 'RH_SEARCH_TASK' IMPORTING act_object_ext = act_object_ext EXCEPTIONS no_active_plvar = 1 no_org_object_selected = 2 no_valid_task_type = 3 OTHERS = 4. IF sy-subrc EQ 0. task-low = act_object_ext. ENDIF. AT SELECTION-SCREEN ON VALUE-REQUEST FOR task-high. DATA: act_object_ext TYPE rhobjects-object. CALL FUNCTION 'RH_SEARCH_TASK' IMPORTING act_object_ext = act_object_ext EXCEPTIONS no_active_plvar = 1 no_org_object_selected = 2 no_valid_task_type = 3 OTHERS = 4. IF sy-subrc EQ 0. task-high = act_object_ext. ENDIF. *------------------------------------------------------------- START-OF-SELECTION. *------------------------------------------------------------- PERFORM main USING p_more p_maxsel. *---------------------------------------------------------------------* * FORM MAIN * *---------------------------------------------------------------------* * ........ * *---------------------------------------------------------------------* FORM main USING p_more TYPE xfeld p_maxsel TYPE tbmaxsel. DATA: field_lst TYPE slis_t_fieldcat_alv, field_cat TYPE slis_fieldcat_alv, is_layout TYPE slis_layout_alv, is_variant LIKE disvariant, it_sort TYPE slis_t_sortinfo_alv, l_string TYPE string, l_grid_title TYPE lvc_title. *- prepare the list format (determine columns...) PERFORM prepare_format CHANGING field_lst field_cat is_layout it_sort. is_variant-report = sy-repid. *- get the list from the database. PERFORM get_workitem_header USING p_more p_maxsel CHANGING zlt_wiheader. *- check empty DATA: hits TYPE i. DESCRIBE TABLE zlt_wiheader LINES hits. IF NOT hits IS INITIAL. *- set table layout is_layout-cell_merge = 'X'. *- set title is_layout-window_titlebar = 'Workitems Cancel'(001). g_windows_titlebar = is_layout-window_titlebar. PERFORM get_title USING hits g_windows_titlebar l_grid_title. is_layout-window_titlebar = l_grid_title. IF p_cancel IS NOT INITIAL AND zlt_wiheader IS NOT INITIAL. * Cancel the work item PERFORM cancel_workitem TABLES zlt_wiheader. ENDIF. *- call the CO function to display the list. CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY' EXPORTING i_callback_program = CONV syrepid( 'ZRSWIWILS_WI_CANCEL' ) i_callback_user_command = 'CALL_UCOMM_WILIST' is_layout = is_layout it_fieldcat = field_lst it_sort = it_sort is_variant = is_variant TABLES t_outtab = zlt_wiheader EXCEPTIONS OTHERS = 1. ELSE. MESSAGE s003. ENDIF. ENDFORM. "main *---------------------------------------------------------------------* * FORM PREPARE_FORMAT * *---------------------------------------------------------------------* * ........ * *---------------------------------------------------------------------* * --> FIELD_LST * * --> FIELD_CAT * * --> IS_LAYOUT * *---------------------------------------------------------------------* FORM prepare_format CHANGING field_lst TYPE slis_t_fieldcat_alv field_cat TYPE slis_fieldcat_alv is_layout TYPE slis_layout_alv it_sort TYPE slis_t_sortinfo_alv. DATA: is_sort LIKE LINE OF it_sort. DATA: structure_name TYPE dd02l-tabname VALUE 'SWFAWRKITM'. DATA: lt_fieldcat TYPE lvc_t_fcat. DATA: ls_fieldcat TYPE lvc_s_fcat. DATA: wf_settings TYPE swp_admin. DATA: lh_aging_services TYPE REF TO cl_sww_daag_services. FIELD-SYMBOLS: <field_lst> LIKE LINE OF field_lst. is_layout-box_fieldname = 'B_MARKED'. is_layout-box_tabname = 'WIHEADER'. *- prepare sort PERFORM set_sort_tab CHANGING it_sort. *- get fieldcatalog CALL FUNCTION 'LVC_FIELDCATALOG_MERGE' EXPORTING i_structure_name = structure_name CHANGING ct_fieldcat = lt_fieldcat EXCEPTIONS inconsistent_interface = 1 program_error = 2 OTHERS = 3. LOOP AT lt_fieldcat INTO ls_fieldcat. IF ls_fieldcat-fieldname EQ 'WI_RHTEXT'. ls_fieldcat-lowercase = 'X'. ENDIF. MOVE-CORRESPONDING ls_fieldcat TO field_cat. field_cat-seltext_s = ls_fieldcat-scrtext_s. field_cat-seltext_l = ls_fieldcat-scrtext_l. field_cat-seltext_m = ls_fieldcat-scrtext_m. APPEND field_cat TO field_lst. ENDLOOP. *- no reference for B_MARKED CLEAR field_cat-ref_tabname. field_cat-tech = 'X'. field_cat-fieldname = 'B_MARKED'. APPEND field_cat TO field_lst. CLEAR field_cat-tech. *- set columns positions LOOP AT field_lst ASSIGNING <field_lst>. CASE <field_lst>-fieldname. WHEN 'WI_ID'. <field_lst>-col_pos = 1. WHEN 'WI_STAT'. <field_lst>-col_pos = 2. WHEN 'WI_CHCKWI'. <field_lst>-col_pos = 3. WHEN 'TYPETEXT'. <field_lst>-col_pos = 4. <field_lst>-outputlen = 15. WHEN 'WI_RH_TASK'. <field_lst>-col_pos = 5. <field_lst>-outputlen = 11. WHEN 'WI_CD'. <field_lst>-col_pos = 6. <field_lst>-outputlen = 10. WHEN 'WI_CT'. <field_lst>-col_pos = 7. <field_lst>-outputlen = 8. WHEN 'WI_TEXT'. <field_lst>-col_pos = 8. <field_lst>-outputlen = 80. WHEN 'WI_CONFIRM'. <field_lst>-col_pos = 9. WHEN 'WI_REJECT'. <field_lst>-col_pos = 10. WHEN 'WI_PRIOTXT'. <field_lst>-col_pos = 11. WHEN 'RETRY_CNT'. <field_lst>-col_pos = 12. WHEN 'TOP_TASK'. <field_lst>-col_pos = 13. WHEN OTHERS. <field_lst>-col_pos = 999999. ENDCASE. ENDLOOP. SORT field_lst BY col_pos. LOOP AT field_lst ASSIGNING <field_lst>. <field_lst>-col_pos = sy-tabix. ENDLOOP. *- set standard layout CLEAR field_cat. field_cat-no_out = 'X'. MODIFY field_lst FROM field_cat TRANSPORTING no_out WHERE fieldname EQ 'WI_LANG' OR fieldname EQ 'WI_TYPE' OR fieldname EQ 'VERSION' OR fieldname EQ 'WI_PRIO' OR fieldname EQ 'NOTE_CNT' OR fieldname EQ 'WI_RELEASE' OR fieldname EQ 'STATUSTEXT' OR fieldname EQ 'TCLASS' OR fieldname EQ 'WI_DH_STAT' OR fieldname EQ 'RETRY_CNT' OR fieldname EQ 'WLC_FLAGS' OR fieldname EQ 'TOP_TASK' OR fieldname EQ 'AGING_STATE' OR fieldname EQ 'AGING_TEMPERATURE'. *- delete aging fields if not applicable lh_aging_services = cl_sww_daag_services=>get_instance( ). IF lh_aging_services->aging_enabled( ) NE 'X'. DELETE field_lst WHERE fieldname EQ 'AGING_STATE' OR fieldname EQ 'AGING_TEMPERATURE'. ENDIF. *- set checkboxes CLEAR field_cat. field_cat-checkbox = 'X'. MODIFY field_lst FROM field_cat TRANSPORTING checkbox WHERE fieldname EQ 'WI_CONFIRM' OR fieldname EQ 'WI_REJECT' OR fieldname EQ 'WI_DEADEX' OR fieldname EQ 'NOTE_EXIST' OR fieldname EQ 'ASYNCAGENT'. IF tcode = 'SWI2_ADM1'. " workitems ohne bearbeiter CLEAR field_cat. field_cat-col_pos = '0'. field_cat-key = 'X'. MODIFY field_lst FROM field_cat TRANSPORTING col_pos key WHERE fieldname EQ 'ASYNCAGENT'. ELSE. CLEAR field_cat. field_cat-tech = 'X'. MODIFY field_lst FROM field_cat TRANSPORTING tech WHERE fieldname EQ 'ASYNCAGENT'. ENDIF. *- delete agents if necessary CALL FUNCTION 'SWP_ADMIN_DATA_READ' IMPORTING wf_settings = wf_settings EXCEPTIONS OTHERS = 1. IF wf_settings-no_agents = 'X'. field_cat-tech = 'X'. MODIFY field_lst FROM field_cat TRANSPORTING tech WHERE fieldname EQ 'EXEUSER' OR fieldname EQ 'FORW_BY'. ENDIF. ENDFORM. "prepare_format *---------------------------------------------------------------------* * FORM CALL_UCOMM_WILIST * *---------------------------------------------------------------------* * Dynamic call to process the keyboard input. * *---------------------------------------------------------------------* * --> UCOMM * * --> SELFIELD * *---------------------------------------------------------------------* FORM call_ucomm_wilist USING ucomm TYPE syucomm selfield TYPE slis_selfield. DATA: old_list_cnt LIKE g_list_cnt, s_return LIKE swl_return, line_idx LIKE sy-tabix, l_tabix LIKE sy-tabix, linesel_cnt LIKE sy-tabix, b_line_selected LIKE sy-binpt, ls_wiheader TYPE LINE OF swfatalvitm. DATA: lt_wrkitm TYPE swfatwrkitm. DATA: delta_list_cnt TYPE sytabix. DATA: ls_por TYPE sibflpor. DATA: lt_por TYPE sibflport. DATA: lv_ucomm TYPE syucomm. DATA: l_excp TYPE REF TO cx_swf_ifs_exception. DATA: ls_suspend TYPE swp_suspen. DATA: ls_swwwidh TYPE swwwidh. DATA: l_wi_index TYPE sytabix. DATA: lh_grid TYPE REF TO cl_gui_alv_grid. DATA: l_grid_title TYPE lvc_title. DATA: l_count TYPE sytabix. PERFORM pick_line USING selfield-tabindex zlt_wiheader CHANGING line_idx linesel_cnt b_line_selected. LOOP AT zlt_wiheader INTO ls_wiheader WHERE b_marked EQ 'X'. ls_por-catid = swfco_objtype_bc. ls_por-instid = ls_wiheader-wi_id. APPEND ls_por TO lt_por. ENDLOOP. IF lt_por[] IS INITIAL. READ TABLE zlt_wiheader INDEX line_idx INTO ls_wiheader. ls_por-catid = swfco_objtype_bc. ls_por-instid = ls_wiheader-wi_id. APPEND ls_por TO lt_por. ENDIF. ************************************************************************ * Refresh Instancemanager * ************************************************************************ TRY. CALL METHOD cl_swf_run_wim_factory=>initialize( ). CATCH cx_swf_ifs_exception INTO l_excp. CALL METHOD cl_swf_utl_message=>send_message_via_exception( l_excp ). ENDTRY. CASE ucomm. ************************************************************************ * Filter * ************************************************************************ WHEN '&ILT'. ************************************************************************ * Refresh * ************************************************************************ WHEN '1REF'. CALL METHOD int->refresh IMPORTING ex_delta_count = delta_list_cnt. CALL METHOD int->get_entries IMPORTING ex_wientries = lt_wrkitm. CLEAR zlt_wiheader[]. PERFORM convert_to_alv_list USING lt_wrkitm p_more CHANGING zlt_wiheader. MESSAGE s811(w8) WITH delta_list_cnt. selfield-refresh = 'X'. selfield-row_stable = 'X'. ************************************************************************ * Pick * ************************************************************************ WHEN '&IC1'. IF linesel_cnt > 1. MESSAGE s201(wi). EXIT. ENDIF. IF line_idx = 0. MESSAGE s004(0k). EXIT. ENDIF. READ TABLE zlt_wiheader INDEX line_idx INTO ls_wiheader. ls_por-catid = 'BC'. ls_por-instid = ls_wiheader-wi_id. IF ls_wiheader-wi_type = wi_flow. lv_ucomm = function_wi_workflow_display. ELSE. lv_ucomm = cl_swf_rdg_dispatcher=>c_function_wi_display. ENDIF. CALL METHOD cl_swf_rdg_dispatcher=>execute_dialog_request EXPORTING im_por = ls_por im_function = lv_ucomm EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. WHEN OTHERS. * IF line_idx = 0. "--- OSS note 1422569 --- IF linesel_cnt = 0. MESSAGE s004(0k). EXIT. ENDIF. CALL METHOD cl_swf_rdg_dispatcher=>execute_dialog_request_multi EXPORTING im_por = lt_por im_function = ucomm EXCEPTIONS OTHERS = 1. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ENDCASE. DATA: ls_layout TYPE slis_layout_alv. DATA: lt_filtered_entries TYPE slis_t_filtered_entries. DATA: l_lines TYPE i. CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_GET' IMPORTING es_layout = ls_layout et_filtered_entries = lt_filtered_entries EXCEPTIONS OTHERS = 1. IF sy-subrc EQ 0. DESCRIBE TABLE lt_filtered_entries LINES l_lines. DESCRIBE TABLE zlt_wiheader LINES l_count. l_count = l_count - l_lines. PERFORM get_title USING l_count g_windows_titlebar l_grid_title. ls_layout-window_titlebar = l_grid_title. CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_SET' EXPORTING is_layout = ls_layout. ENDIF. ENDFORM. "call_ucomm_wilist *&---------------------------------------------------------------------* *& Form set_sort_tab *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->P_IT_SORT sorttab (ALV format) *----------------------------------------------------------------------* FORM set_sort_tab CHANGING p_it_sort TYPE slis_t_sortinfo_alv. DATA: is_sort TYPE slis_sortinfo_alv. REFRESH p_it_sort. is_sort-tabname = 'WIHEADER'. is_sort-spos = 1. is_sort-fieldname = 'WI_CD'. is_sort-down = 'X'. APPEND is_sort TO p_it_sort. is_sort-spos = 2. is_sort-fieldname = 'WI_CT'. is_sort-down = 'X'. APPEND is_sort TO p_it_sort. is_sort-spos = 3. is_sort-fieldname = 'WI_ID'. is_sort-down = 'X'. APPEND is_sort TO p_it_sort. ENDFORM. " set_sort_tab *&---------------------------------------------------------------------* *& Form get_workitem_header *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->P_WI_HEADER text *----------------------------------------------------------------------* FORM get_workitem_header USING p_more TYPE xfeld p_maxsel TYPE tbmaxsel CHANGING p_wi_header TYPE swfatalvitm. DATA: rangetab_for_id TYPE swfartwiid. DATA: rangetab_for_type TYPE swfartwitp. DATA: rangetab_for_creation_date TYPE swfartcrdat. DATA: rangetab_for_creation_time TYPE swfartcrtim. DATA: rangetab_for_task TYPE swfartrhtsk. DATA: rangetab_for_state TYPE swfartwista. DATA: rangetab_for_priority TYPE swfartprio. DATA: rangetab_for_dhsta TYPE swfartdhsta. DATA: lt_wrkitm TYPE swfatwrkitm. DATA: ls_wrkitm TYPE LINE OF swfatwrkitm. DATA: ls_alvitm TYPE LINE OF swfatalvitm. IF int IS INITIAL. int = cl_swf_rep_manager=>get_instance( ). ENDIF. *- set selection properties IF p_more EQ 'X'. CALL METHOD int->set_property EXPORTING im_name = if_swf_rep_workitem_selection=>c_get_administrator im_value = 'X'. ENDIF. *- convert parameters rangetab_for_id[] = id[]. rangetab_for_type[] = type[]. rangetab_for_creation_date[] = cd[]. rangetab_for_creation_time[] = ct[]. rangetab_for_task[] = task[]. rangetab_for_state[] = state[]. rangetab_for_priority[] = prio[]. rangetab_for_dhsta[] = dhsta[]. CALL METHOD int->clear( ). CALL METHOD int->set_filter_strategy( filter ). CALL METHOD int->set_range_tab( rangetab_for_id ). CALL METHOD int->set_range_tab( rangetab_for_type ). CALL METHOD int->set_range_tab( rangetab_for_creation_date ). CALL METHOD int->set_range_tab( rangetab_for_creation_time ). CALL METHOD int->set_range_tab( rangetab_for_task ). CALL METHOD int->set_range_tab( rangetab_for_state ). CALL METHOD int->set_range_tab( rangetab_for_priority ). CALL METHOD int->set_range_tab( rangetab_for_dhsta ). CALL METHOD int->set_only_top_wi( top_only ). CALL METHOD int->set_maxsel( p_maxsel ). CALL METHOD int->read( ). CALL METHOD int->get_entries IMPORTING ex_wientries = lt_wrkitm. PERFORM convert_to_alv_list USING lt_wrkitm p_more CHANGING p_wi_header. ENDFORM. " get_workitem_header *---------------------------------------------------------------------* * FORM convert_to_alv_list * *---------------------------------------------------------------------* * ........ * *---------------------------------------------------------------------* * --> WIHEADER * * --> WIALVITM * *---------------------------------------------------------------------* FORM convert_to_alv_list USING wiheader TYPE swfatwrkitm more TYPE xfeld CHANGING wialvitm TYPE swfatalvitm. DATA: ls_wrkitm TYPE LINE OF swfatwrkitm. DATA: ls_alvitm TYPE LINE OF swfatalvitm. DATA: lv_wi_handle TYPE REF TO if_swf_run_wim_internal. DATA: ls_admin TYPE swhactor. DATA: lt_agents TYPE tswhactor. LOOP AT wiheader INTO ls_wrkitm. MOVE-CORRESPONDING ls_wrkitm TO ls_alvitm. IF ls_wrkitm-wlc_flags O swfcr_p_asynchronous_rule. ls_alvitm-asyncagent = 'X'. ENDIF. IF more EQ 'X' AND ls_alvitm-wi_type EQ swfco_wi_flow. TRY. CALL METHOD cl_swf_run_wim_factory=>find_by_wiid EXPORTING im_wiid = ls_wrkitm-wi_id RECEIVING re_instance = lv_wi_handle. lt_agents = lv_wi_handle->get_administrator_agents( ). READ TABLE lt_agents INDEX 1 INTO ls_admin. ls_alvitm-adm_agent = ls_admin. CATCH cx_swf_run_wim. ENDTRY. ENDIF. IF top_only IS INITIAL. APPEND ls_alvitm TO wialvitm. ELSE. IF ls_alvitm-wi_chckwi IS INITIAL. APPEND ls_alvitm TO wialvitm. ENDIF. ENDIF. ENDLOOP. ENDFORM. "convert_to_alv_list *---------------------------------------------------------------------* * FORM PICK_LINE * *---------------------------------------------------------------------* * ........ * *---------------------------------------------------------------------* * --> SELFIELD_IDX * * --> WIHEADER * * --> INDEX * * --> LINESEL_CNT * * --> B_OK * *---------------------------------------------------------------------* FORM pick_line USING selfield_idx LIKE sy-tabix wiheader TYPE swfatalvitm CHANGING index LIKE sy-tabix linesel_cnt LIKE sy-tabix b_ok LIKE sy-binpt. DATA: lines_marked LIKE sy-tabix, marked_idx LIKE sy-tabix, cursor_line LIKE sy-binpt. IF selfield_idx > 0. READ TABLE wiheader INDEX selfield_idx TRANSPORTING NO FIELDS. IF sy-subrc = 0. cursor_line = 'X'. ENDIF. ENDIF. LOOP AT wiheader TRANSPORTING NO FIELDS WHERE b_marked = 'X'. ADD 1 TO lines_marked. marked_idx = sy-tabix. ENDLOOP. ************************************************************************ * List tool algorithm * ************************************************************************ IF cursor_line = 'X'. index = selfield_idx. IF lines_marked < 2. linesel_cnt = 1. ELSE. linesel_cnt = lines_marked. ENDIF. b_ok = 'X'. ELSEIF lines_marked = 1. index = marked_idx. linesel_cnt = 1. b_ok = 'X'. ELSEIF lines_marked > 1. linesel_cnt = lines_marked. b_ok = 'X'. ENDIF. ENDFORM. "pick_line *&---------------------------------------------------------------------* *& Form GET_TITLE *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->P_HITS text * -->P_L_STRING text *----------------------------------------------------------------------* FORM get_title USING p_hits TYPE sytabix p_title_template TYPE string p_title TYPE lvc_title. DATA: l_string TYPE string. DATA: l_count(10) TYPE n. IF p_hits > 1. l_string = '(&1 entries)'(014). ELSEIF p_hits EQ 1. l_string = '(1 entry)'(015). ENDIF. l_count = p_hits. SHIFT l_count LEFT DELETING LEADING '0'. CONCATENATE p_title_template l_string INTO p_title SEPARATED BY space. REPLACE '&1' IN p_title WITH l_count. ENDFORM. " GET_TITLE *&---------------------------------------------------------------------* *& Form CANCEL_WORKITEM *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->P_ZLT_WIHEADER text *----------------------------------------------------------------------* FORM cancel_workitem TABLES p_zlt_wiheader TYPE swfatalvitm. TYPES: zlty_status TYPE RANGE OF sww_wistat. DATA: zlt_r_status TYPE RANGE OF sww_wistat. CONSTANTS: zlc_stat_complete TYPE sww_statxt VALUE 'COMPLETED', zlc_stat_cancel TYPE sww_statxt VALUE 'CANCELLED', zlc_sign TYPE ddsign VALUE 'I', zlc_options TYPE ddoption VALUE 'EQ'. zlt_r_status = VALUE zlty_status( LET s = zlc_sign o = zlc_options IN sign = s option = o ( low = zlc_stat_complete ) ( low = zlc_stat_cancel ) ). *//Keep only the work items which has to be CANCELLED DELETE p_zlt_wiheader WHERE wi_stat IN zlt_r_status. IF p_zlt_wiheader[] IS NOT INITIAL. LOOP AT p_zlt_wiheader ASSIGNING FIELD-SYMBOL(<zlfs_wiheader>). TRY. CALL FUNCTION 'SWW_WI_ADMIN_CANCEL' EXPORTING wi_id = <zlfs_wiheader>-wi_id do_commit = abap_true IMPORTING new_status = <zlfs_wiheader>-wi_stat EXCEPTIONS update_failed = 1 no_authorization = 2 infeasible_state_transition = 3 OTHERS = 4. *- exception handling CATCH cx_swf_run_wim INTO DATA(lv_excp). DATA: zlr_txmgr TYPE REF TO cl_swf_run_transaction_manager. CALL METHOD zlr_txmgr->rollback( ). ENDTRY. ENDLOOP. ENDIF. ENDFORM.
add parameter
call SWW_WI_ADMIN_CANCEL in loop