I love enhancing ABAP code and everything concerning the use of the enhancing techniques, so the ABAP Article Implementing a Business Add In an Enhancement with the recent blogs Dangerous Liaisons in User-Exits and How to Avoid Them and Dangerous Liaisons in User-Exits - Revisited on ideas of how to reorganize the user exits, convinced me to share with the great SDN Community an interesting project experience.
Nowadays a lot of companies are involved in business processes characterized by mergers and acquisitions, which require continuous transitions from a vertical organizational structure to another one composed of different organizational units; therefore also the IT systems have to adapt to these changes and if possible, reduce the operating costs.
A few years ago, I was involved in a big IT consolidation project of a German multinational company, leader in the field of chemistry, organized into 17 business units and operating around the world in 18 countries.
As mentioned above, the project goal was the consolidation of the existing SAP ERP landscape by migrating from an architecture structured in several SAP instances to a single one by ensuring data integrity and application stability.
Figure 1 The project strategy
The methodology used to migrate each productive country SAP system into the target harmonized system consisted of the following 4 steps:
- Release Upgrade of the individual country SAP system
- Data Migration (Client Export ) from the productive country system to the target client of merged system
- Workbench Conflict Resolution Analysis: workbench object and cross client customizing objects
- Cross-client objects migration to the target system (customizing, programs and exit)
The request: code cleaning
So, in summary, nothing unusual, a nice and big upgrade project with workbench objects migration and conflict resolution.
But the customer, additionally, asked me to remake the facelift to all exit routines. What does this mean?
This surely means:
- Identify, for each exit-routine, the blocks of source code really used, because many of the individual country SAP systems were created as copy of other systems
- Optimize the source code readability, traceability and maintainability
How to reorganize?
In the target harmonized system, merging the exit routines is not so easy, because although the data are well separated by the client, the countries have to implement their business specific logic while sharing the same programs.
Figure 2 USEREXIT_SAVE_DOCUMENT_PREPARE in SAPMV50A; Implementation taken from the ITALY system
Taking as example the same exit routine implemented in two different local systems, as shown above and in the following screenshot, in the ABAP code of each different implementation you can see that:
- The business logic separation is implemented by testing the values of the organizational units or document types, making an extensive use of the ABAP statements IF, CASE, CHECK !
- The implementation of the same routine is quite different in each local system.
Figure 3 USEREXIT_SAVE_DOCUMENT_PREPARE in SAPMV50A; implementation taken from the UK system
Therefore it's clear that each company (or country) handles its business processes in a different way, so the ability to adjust the user-exit code accordingly is fundamental.
A possible "low cost" approach
Once the map of available user-exits coming from each country system is available, a possible "low cost" approach for the harmonization could be to separate the business logic by implementing a CASE statement on the system variable SY-MANDT.
Figure 4 A simple approach to harmonization
Which are the impacts of such approach in the merged system?
- A rapid deployment of the exit routines
- Local IT Teams often share the same object
- The source code of the exit routine must be enhanced or adjusted at every client creation or deactivation
- Poor readability if modularization techniques are not used
The idea; the approach with BAdI
Everyone knows that Business Add-Ins may also be implemented on the basis of a specific filter value. So taking this in mind, the reorganization solution proposed in this blog is based on 2 main rules:
- Common logic such as filter determination rules and BAdI calls are implemented within the exit routine.
- Business (country specific) logic is encapsulated into distinct implementations created and activated according to the country (filter value).
Figure 5 The BAdI approach
In other words the harmonization of an exit routine is not achieved by collecting, in the same named routine, the single source codes taken from the local systems ; each single routine will be encapsulated in corresponding BAdI methods which belongs to different filter dependent BAdI implementations.
The proposed solution could be applied to classical Userexits, Customer Exits, Field Exits, Substitutions & Validations Exit, BAdIs, and hook enhancement (Source code) with the exception of the VOFM routines.
Since VOFM routines are dynamically called by application programs, they are not well suited to this kind of approach. So, during the harmonization project, I opted for an alternative solution by adopting a system specific name-range, renaming the routines where necessary.
The implementation; what's needed?
Now let me give you a step by step overview of how to implement the harmonization solution.
The demo system is an IDES ECC 6.0 that's very similar to the customer's merged system described at the beginning of this blog.
Figure 6 The IDES ECC 6.0 system used
In the example of this blog, the available clients defined in the demo system should represent the local systems (countries), in accordance with the following schema
First of all, let's start, with the definition of the following required development objects:
1. Filter Type
We know that the filter type must have a search help, a domain with fixed values, or a domain with a value table.
So, in order to represent the individuals local systems , I created a custom data element with a custom domain with a cross client value table . The table entries can be updated by a maintenance view.
Figure 7 Maintain the allowed filter values
2. Filter Value determination table
In my example, the filter value to be determined at runtime, depends on the entries of a client-dependent table with a very simple structure.
Figure 8 DDIC definition of the filter determination table
The aim of this table is to associate a filter value (table field NATIONSYS) to each exit routine name (table key field USX_NAME), where the name of the exit routine is a constant defined in the user exit source code and represents the SAP exit routine that's really implemented (see picture below).
This field is used at runtime to identify which badi implementation has to be called.
Figure 9 Global names of the exit routines
The main advantage of the filter determination table is that it's possible to deactivate, even in a productive environment, the implementation of a single exit routine by removing the filter value or delete the whole record.
Figure 10 Maintain entries in the filter determination table
3. Determination logic of the filter value
Since the example shown in this blog is very simple, I won't discuss about the logic of the determination.
Figure 11 Sample of filter determination method
In order to keep the ABAP code clean inside the exit routine, the determination logic of the filter value should be encapsulated in a public static method, but also a function module is fine.
I leave you the freedom to implement if necessary a more complex logic i.e. by introducing further additional keys such as: SY-REPID SY-CPROG, SY-XPROG etc.
4. BAdI Definition
The BAdI design, such as the definition of methods and parameters, is the part of the harmonization that might require the greatest effort.
Here you can choose whether to create a BAdI implementation for each exit routine or ensure that the BADI serves as a collector of multiple implementation methods (this is my favorite approach), in case the exit is part of a complex enhancement.
Figure 12 Overview of the classical user-exit in SAPMV45A
For instance, in sales and distribution, the program for sales orders processing contains many exit routines as shown in Figure 12.
Therefore, as described before, all the corresponding methods should be placed in the same BAdI definition
Figure 13 Overview of the created BAdI methods
There are no rules to design the BAdI interface, because the method's parameters can be different depending on the type of exit to be reorganized.
Whenever possible I suggest to use the same parameters used by the standard exit-routines. However, the following summary table could be used as a basis for the BAdI design.
Figure 14 Tips for the methods definition of the BAdI interface
5. BAdI Filter Dependent Implementations
Once the BAdI definition is completed, we can proceed with the creation of the filter dependent implementations; a single filter value is specified in the filters combination editor.
Figure 15 BAdI definition and filter dependent implementations
So, assuming that USEREXIT_CHECK_VBAK was implemented in D02 and the USA local systems, as shown in Figure 15, for the same BADI definition ZSDN_BADIDEF_SAPMV45A, two BAdI implementations should be created. The implementation ZSDN_BADIIMPL_SAPMV45A_D02 for the filter value ‘D02' and the implementation ZSDN_BADIIMPL_SAPMV45A_USA for the filter value ‘USA'.
Figure 16 Business specific method implementation of D02
Inside a single BAdI implementation method, the ABAP code becomes a "copy & paste" of the user-exit's source code coming from the original local system, with the slight difference that the source code must be ABAP OO compliant.
Figure 17 Business specific method implementation of USA
6. All the pieces together
Inside the user-exit, the calls to the classical BAdI or the new kernel based BADI are very similar.
Figure 18 User exit revisited in ECC 6.0
The only difference is that with the new BAdIs you may need to specify the fallback class. In our case, I avoided the creation of the fallback class simply by handling the exception BADI_NOT_IMPLEMENTED.
7. Create a new record in the table for determining the filter
Last but not least, in order to trigger the BADI implementation, we need to determine the correct value of the filter; so the update in every client involved of the filter determination table is important.
For each exit implemented, create a record in the table, specify the exit routine name and assign a single filter value (see Figure 10).
- If an implementation class contains some syntax errors, the consistency of the whole application is not compromised for other countries
- No pitfalls due to abap locks during application maintenance
- Source code cleanup as user-exit changes are rarely required. Changes, when needed, are implemented through the various badi implementations without disruptions on the main userexit
- Easy identification using standard tools such as Repository Info System and Enhancement Info System
- Activation and deactivation of single exit routines in production environment
- Filter dependent implementations Interchangeability. (I do not consider this a real advantage, but an option)
Please note that during the project, the latest release available was the SAP R/3 Enterprise 4.7; for the definition of the BAdI, now , it's possible to define both classical BAdIs and BADI using Enhancement Framework
Quite often the creation of exit routines is not made with the proper attention under-evaluating its importance.
In this blog I discussed the use of Filter dependent BadI's as a possible solution to be adopted in order to reorganize the source code inside the exit routines of your SAP ERP system avoiding terrifying situations like the one shown below.
Figure 19 Userexit example which has a strong need for restyling
I hope this blog could be a good starting point to help you in this task.
I would like to thank my colleague @Techedge Sergio Cipolla for his support.