As an experienced ABAP developer at SAP, I am all too aware of the frustration that consumers can feel when confronted with unnecessary complexity. I wanted to illustrate just how straight-forward it can be to make use of the Key User Extensibility available in SAP S/4HANA Cloud.
In my case, I am aiming to restrict myself to only using the applications available within SAP Fiori, such as would be the case if I was using a two-system landscape where I cannot make use of any developer extensibility available through the ABAP Development Tools (ADT).
The Fiori applications that I have chosen to make use of are:
My implementation scenario is a simple one where I would like to be able to generate and store a universally unique identifier (UUID) value for each operation in any production order that I create. I also want to verify that my code is behaving in the way that I expect, so I also want to test it and validate its expected behaviour. I do not want to display this field to users, nor do I want to allow users to edit this field in any way using the UI (but if I did, then I could very easily enable its usage for each UI applicable, as is illustrated in the blog In-App extensibility in S/4 HANA Cloud | Part 1 – Adding a custom field on the UI).
I am assuming that you are already familiar with basic ABAP syntax and the concept of a Business Add-In (BAdI), as well as working with Fiori applications. Additionally, the business roles involving all of the SAP Fiori applications listed must also have already been assigned to your user (relevant business catalog(s) / role(s) can be found within the Implementation Information tabpage under the Configuration section of the SAP Fiori Apps Reference Library, for each application link provided in the list above).
Finding a UUID Generator
From my past experience, I am aware that ABAP systems typically offer some predefined classes that provide common capabilities. Since I am interested in generating a UUID, I searched for ‘UUID’ within the Released ABAP Artifacts application and found that there exists a factory class CL_UUID_FACTORY that I can use.
Since I wanted to make sure that this class would give me what I needed, I clicked on the ‘Document’ image next to the class in order to see its description.
I also needed to know what method I would have to use, so I navigated to the details for this class and went to the Methods tabpage.
Within here, I was also able to consult with the description of the method as well.
And given that this method returns the interface IF_SYSTEM_UUID (which is implemented by class CL_SYSTEM_UUID mentioned in the class description), I then checked to see which method I could make use of in that, by navigating to the CL_SYSTEM_UUID class.
Finding a BAdI
Next, I needed to find a BAdI that I could make use of for populating my custom field. To do this I needed to find the relevant business context, which in my case would center around production orders. The Extensibility Cockpit made this a very easy effort. All I had to do was search for ‘Production Orders’ within the ‘All Business Contexts’ tabpage, and I immediately found a good candidate (i.e. one where both structural and logic enhancements were already supported).
I then navigated to the details page for the ‘Manufacturing: Order Operation’ entry, where I was able to see the BADIs currently available.
I then clicked on the ‘Enhancement Option’ for the first BAdI, and after reviewing the documentation I decided that this would be the one that I would choose to use.
Creating a Custom Field
At this point, I can start my implementation. I went to the Custom Fields application, and searched to see if there was any existing custom field relating to a UUID that I could reuse (but there wasn’t).
To add a new field, I clicked on the ‘+’ icon, which opened a popup window prompting me for the Business Context to use (which would be the one that I already identified previously, which is highlighted below).
I then provided all of the remaining details for my new field, and then clicked on the ‘Create and Edit’ button.
The entry was then generated by the system, with the details shown below (note that the image shows that I already published it, but this would say ‘Created’ instead if you have not yet published the field).
All that was still needed was to enable the use of this field within my expected UI, and then to Publish.
Creating Custom Logic
The final step for my implementation was to define the code needed to populate my custom UUID field, which should be triggered automatically for all new/modified production orders. I went back to my business context within the Extensibility Cockpit and clicked on the ‘Create Enhancement Implementation’ button for the BAdI that would be invoked for creation and modification of manufacturing orders.
Since there were no previously defined implementations, an empty list was shown within the Custom Logic application. I was then able to click on the ‘+’ icon to start the creation of a new enhancement implementation.
A popup was then opened that allowed me to select which BAdI I wished to implement (as a first step).
And then the only other entry required by me was for the implementation description, before I clicked on the ‘Create’ button.
After this step, the implementation is generated and filled with its default code (which I found to be very helpful).
I modified the default code to suit my own specific purposes:
- I removed the CHECK statement at the beginning so that both order creations and modifications would execute my BAdI code
- I added a warning message to the trace log for situations where my UUID value was going to be re-assigned during an order modification
- I added the logic needed for generating a UUID and storing it into the order operation’s new custom field
- I added an error message to the trace log for the exception case when the system’s UUID generator is not working properly
- I added an informational message to the trace log to indicate that my BAdI had completed its execution
And then clicked on the ‘Save Draft’ option, followed by the ‘Publish’ option.
Then, all that remained was to test.
I decided to use the Custom Logic Tracing application, as it would be able to show me all of the information that I needed and I had already put trace logging statements into my code. My plan was the create two traces: one for when I created a new production order; one for when I modified a production order.
After I clicked on the ‘Start Trace’ button, I was prompted for some required information, and then I clicked on the ‘Start’ button, which initiated the trace on my user in the background for then next 15 minutes.
I then went to the Create Production Order application and copied an existing order.
After the successful order creation, I stopped the tracing by clicking on the ‘Finish Trace’ button.
The system then stopped tracing and published my trace file for me to consult.
After I clicked on the trace file entry, it displayed the contents of the file (i.e. my custom logic), including my informational statements.
I was also able to consult the actual values for all parameters used in the BAdI, where I could see that my logic had successfully populated my custom field with a UUID for each order operation.
So all good (so far!).
The final remaining check was for the logic to also execute during production order modifications.
I started another custom logic trace.
I retrieved my order using the Manage Production Orders application, and then clicked on the entry to display its contents.
The contents were displayed and then I clicked on the ‘Edit Order’ button.
I changed the order start and end dates and then clicked on the ‘Save’ button.
At that point, the only step left to do was to stop the trace in the same way as was done previously, which resulted in the new trace file being available in the list.
However, this time, the file has a severity listed as being ‘Warning’.
After I clicked on the entry, the contents were displayed as expected. In addition to my informational message, each operation also generated a warning message due to there already being a UUID present in my custom field (i.e. this was triggered by the IF statement in my custom logic).
And I could see that new UUIDs were in fact generated, when I look at the details for the actual parameter values.
So all really is good!
Getting to the Point
In summary, I was able to identify a useful released ABAP artifact, find a good candidate BAdI to make use of, create a custom field and populate it using some custom code that was then automatically integrated into the standard business process, and verify the overall execution making use of tracing capability, all while only relying on SAP Fiori and its Key User Extensibility.
After walking through the above implementation steps myself, I was left with the following thoughts:
- My new favorite SAP Fiori application is the Extensibility Cockpit
- I love being able to easily access detailed technical documentation for available enhancements and/or classes within the Extensibility Cockpit and Released ABAP Artifacts, respectively
- Tracing custom logic is extremely easy to do
If you too were able to reproduce this scenario, then hopefully you also feel similarly.
In the future, I hope to elaborate further on extensibility capabilities, such as those for Key User or Developer, within the SAP S/4HANA Cloud Extensibility community blogs.
Additionally, I would encourage everyone to post any questions and/or answers within the SAP S/4HANA Cloud Extensibility community, a truly great resource!
Please feel free to share your thoughts or to provide feedback in the comments.
Thanks for your time.