BTP - Business Configuration (Adaptation)
What do adjustments to the RAP business object actually look like in the context of the business configuration? More information in this article.
Table of contents
What does the adaptability of a business configuration object actually look like? Today we'll take a look at the possibilities and what we as developers can still influence in order to adapt the object to our standards and make more functions available to the user.
Introduction
The business configuration is a RAP business object that is created in the system via the ADT Wizard and follows a certain structure according to the settings. After the generation, the object is freely available for editing; it is then no longer so easy to regenerate properties or fields. Accordingly, we as developers now have the opportunity to make further adjustments.
Structure
The first step is to understand what we actually generated in the system last time. The following graphic shows the structure of the business object.
The RAP BO is shown in the front part, which has a singleton as a ROOT entity, an entity that only has one entry that is statically linked. Our actual maintenance table is created as a child entity, which is linked to the singleton via the SingletonID. This attribute is required for navigation. For example, the information about the transport order is stored in the singleton, which will later be used to record the changes. Each entity has a draft table where temporary changes are saved. Our actual table with the data is then at the end of the chain.
The construct is used to store general information, such as the transport order, but also to be able to edit the table directly via Fiori Elements in edit mode.
Adaptations
In the following sections we want to extend the business object with various adjustments. Basically, all expansion and customization mechanisms of the ABAP RESTful programming model are available to you.
Texts
In the first step, we want to adjust the column headings so that the user knows what is behind the individual settings. At the moment the generated texts are being used. In principle, we can also create data elements for each column so that we can maintain the texts there.
In our case, we extend the Metadata Extension and add annotations to the corresponding fields. Here is an example for two fields:
@EndUserText.label: 'Is Used'
IsUsed;
@EndUserText.label: 'Is Mandatory'
IsMandatory;
Now that we have expanded most of the fields with new labels, we get a new image and better-described columns in the maintenance interface that help our users with maintenance.
Validation
In the next step we need to ensure that the fields receive the correct values. To do this, we can, for example, implement a validation that ensures that the number of processes is greater than zero. To do this, we define a new validation in the behavior definition.
validation ValidateProccesesAreSet on save { field Processes; create; update; }
We still have to transfer this validation to the prepare phase in order to trigger the message when saving.
draft determine action Prepare {
validation BusinessConfigurati ~ ValidateProccesesAreSet;
}
Using CTRL + 1 we create the implementation of the method and then implement the test logic. We read the relevant data via the RAP BO and then check the data records. If the processes are not maintained, we generate an error and fill the FAILED and REPORTED structure.
METHOD ValidateProccesesAreSet.
READ ENTITIES OF zbs_i_swcbc_s IN LOCAL MODE
ENTITY BusinessConfigurati
FIELDS ( Processes ) WITH CORRESPONDING #( it_keys )
RESULT DATA(lt_entries).
LOOP AT lt_entries INTO DATA(ls_entry).
IF ls_entry-Processes = 0.
INSERT VALUE #( configid = ls_entry-ConfigId ) INTO TABLE failed-businessconfigurati.
INSERT VALUE #( configid = ls_entry-ConfigId
%msg = new_message_with_text( text = 'Field need at least one process' )
%element-Processes = if_abap_behv=>mk-on ) INTO TABLE reported-businessconfigurati.
ENDIF.
ENDLOOP.
ENDMETHOD.
Let's now create a new data set in which the processes are maintained with zero. We get the corresponding error message and cannot save the data.
Value help
As a final adjustment, we want to provide value help for the class so that the user can choose from the existing classes. To do this, in the first step we need a search help, which we implement as a custom entity.
@EndUserText.label: 'Working Classes VH'
@ObjectModel.query.implementedBy: 'ABAP:ZCL_BS_SWC_WORKING_QRY'
define custom entity ZBS_I_SWCWorkingClassesVH
{
key WorkingClass : abap.char(32);
Description : abap.char(60);
}
In the Query class we implement a simple logic that manually builds our results table and makes it available as value help. The implementation is quite simple, which means that sorting, filtering and other features do not work. For the full range of functions, you would have to create a lot more logic.
CLASS zcl_bs_swc_working_qry DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_rap_query_provider.
ENDCLASS.
CLASS zcl_bs_swc_working_qry IMPLEMENTATION.
METHOD if_rap_query_provider~select.
DATA lt_result TYPE STANDARD TABLE OF ZBS_I_SWCWorkingClassesVH.
DATA(ld_skip) = io_request->get_paging( )->get_offset( ).
DATA(ld_top) = io_request->get_paging( )->get_page_size( ).
DATA(lt_sorted) = io_request->get_sort_elements( ).
lt_result = VALUE #( ( WorkingClass = 'ZCL_BS_DEMO_PROCESS' Description = 'Automation process' )
( WorkingClass = 'ZCL_BS_DEMO_NO_ONE' Description = 'One automation' )
( WorkingClass = 'ZCL_TEST' Description = 'Test class' ) ).
IF io_request->is_total_numb_of_rec_requested( ).
io_response->set_total_number_of_records( 3 ).
ENDIF.
IF io_request->is_data_requested( ).
io_response->set_data( lt_result ).
ENDIF.
ENDMETHOD.
ENDCLASS.
Finally, we integrate the view into the field as an input help in our entity.
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZBS_I_SWCWorkingClassesVH', element: 'WorkingClass' } }]
working_class as WorkingClass,
In maintenance, the button for value help is now displayed behind the field.
If we call up the input help, we can now select from the existing classes, which will then be adopted as a value in the table.
Hint: If you later want to use the value help in testing and production, you must also release the CDS view in the service definition (expose).
Informations (Header)
As a final point, we want to adjust the header on the object page and adopt the description under the identification. At the moment the header looks like this.
In the Metadata Extension we can now expand the header.
@UI: {
headerInfo: {
typeName: 'BusinessConfigurati',
typeNamePlural: 'BusinessConfiguratis',
title: {
type: #STANDARD,
label: 'Business Configuration',
value: 'ConfigId'
},
description: {
value: 'Description'
}
}
}
After adding the DESCRIPTION and connecting it to the corresponding field of the CDS entity, we will get a new image after reloading the object page.
Full example
You can find all changes to the various objects in the GitHub repository of the software component (SWC) in the corresponding commit. The structure of the GitHub repository is very different from the structure of a repository created via abapGit and is not quite as easy to read.
Conclusion
We can easily adapt the object and even have to do it ourselves to make maintenance more user-friendly. According to the capabilities of RAP, we have all options available to validate the data or offer additional value helps.