Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
namas1994
Product and Topic Expert
Product and Topic Expert
60,456



Links to other blogs post in this series -

  1. Excel Upload using RAP: Part - 1

  2. Excel Upload using RAP: Part - 2

  3. Excel Upload using RAP: Part - 3






Introduction


One of the most common scenario in the SAP On Premise System is to develop a program in ABAP for uploading data to a custom database table using a Excel or CSV file. I was wondering how to  achieve the same in SAP BTP ABAP Environment.

This will be a series of 3 blog post to develop a solution on uploading data to custom database table using SAP RAP Model using the Fiori Interface.

I will be following the below approach -

  1. Creating an OData Service using SAP RAP Model.

  2. Create a Fiori Element Application for the SAP RAP Model OData Service. ( Excel Upload using RAP: Part -2 | SAP Blogs )

  3. Extending the created Fiori Application with excel upload functionality.






Prerequisites



  • Basic Concept on how to generate an OData Service using RAP

  • For using Late Numbering in Managed RAP BO, SAP BTP ABAP Environment 2111 is required.






References



  1. SAP BTP ABAP Environment – Release 2111 | SAP Blogs

  2. Flight Scenario RAP Service Book

  3. ABAP Platform in SAP S/4HANA 2021 - Overview and Product Highlights






Business Scenario


The requirement to develop an Fiori application for a company whose primary business is to provide accommodation to a person (Paying Guest) in monthly Basis.

This application must have the following features -

  • Generating the Building ID using Number Range using Late Numbering RAP Managed BO.

  • Validation on the filed No of Rooms(n_rooms) of Building Entity - the value of it must lie between 1 and 10.


Basic ER Diagram for this Application is show below, which has three entities Building, Rooms and Beds -


ER Diagram


However in this blog post we will consider only Building Entity and will create an OData Service using Managed RAP BO Runtime




Lets start building the application


Step -1: Creating Database table - ZMN_BUILDINGS
@EndUserText.label : 'PG Building'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zmn_buildings {
key client : abap.clnt not null;
key building_id : abap.char(20) not null;
building_name : abap.char(50);
n_rooms : abap.int1;
address_line : abap.char(100);
city : abap.string(0);
state : abap.string(0);
country : abap.string(0);
created_by : syuname;
created_at : timestampl;
last_changed_by : syuname;
last_changed_at : timestampl;
}

Step - 2: Creating an Interface CDS View

The annotation @EndUserText.label is used for setting the field label in Fiori Application.
I will explain the use of field - ExcelRowNumber, in the upcoming blog post
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Buildings Interface View'
define root view entity zmn_i_buildings
as select from zmn_buildings
{

@EndUserText.label: 'Building ID'
key building_id as BuildingId,
@EndUserText.label: 'Building Name'
building_name as BuildingName,
@EndUserText.label: 'No of Rooms'
n_rooms as NRooms,

@EndUserText.label: 'Address Line'
address_line as AddressLine,
@EndUserText.label: 'City'
city as City,
@EndUserText.label: 'State'
state as State,
@EndUserText.label: 'Country'
country as Country,

@Semantics.user.createdBy: true
@EndUserText.label: 'Created By'
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
@EndUserText.label: 'Created At'
created_at as CreatedAt,
@Semantics.user.lastChangedBy: true
@EndUserText.label: 'Last Changed By'
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.lastChangedAt: true
@EndUserText.label: 'Last Changed At'
last_changed_at as LastChangedAt,

0 as ExcelRowNumber
}

Step - 3: Creating a Consumption View

In this step, using the CDS annotation creating the basic list view report and an object page for the building entity
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Buildings Consumption View'

@UI.headerInfo:{
typeName: 'Building',
typeNamePlural: 'Buildings',
typeImageUrl: 'sap-icon://building',
title: {
type: #STANDARD,
value: 'BuildingName'
},
description.value: 'BuildingId'
}

define root view entity zmn_c_buildings
provider contract transactional_query
as projection on zmn_i_buildings
{
@UI.facet: [{ id: 'Building',
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: 'Building',
position: 10
}, {
id: 'addr',position:20,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Address',
label:'Address'
}, {
id:'log',position:30,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'ChangeLog',
label:'Change Log'
}]

@UI: { lineItem: [{ position: 10 }],
identification: [{ position: 10 }],
selectionField: [{ position: 10 }] }
key BuildingId,
@UI: { lineItem: [{ position: 20 }],
identification: [{ position: 20 }],
selectionField: [{ position: 20 }] }
BuildingName,
@UI: { lineItem: [{ position: 30 }],
identification: [{ position: 30 }] }
NRooms,

@UI.fieldGroup: [{ qualifier: 'Address', position: 10 }]
AddressLine,
@UI.fieldGroup: [{ qualifier: 'Address', position: 20 }]
City,
@UI.fieldGroup: [{ qualifier: 'Address', position: 30 }]
State,
@UI.fieldGroup: [{ qualifier: 'Address', position: 40 }]
Country,

@UI.fieldGroup: [{ qualifier: 'ChangeLog', position: 10 }]
CreatedBy,
@UI.fieldGroup: [{ qualifier: 'ChangeLog', position: 20 }]
CreatedAt,
@UI.fieldGroup: [{ qualifier: 'ChangeLog', position: 30 }]
LastChangedBy,
@UI.fieldGroup: [{ qualifier: 'ChangeLog', position: 40 }]
LastChangedAt,

@UI.hidden: true
ExcelRowNumber
}

Step - 4: Creating the Behavior Definition for the interface View zmn_i_buildings

This consists of

  • Implementing the Late Number Concept for generating the Building ID, and

  • The validation for the field n_rooms which was mentioned earlier.


managed implementation in class zbp_mn_i_buildings unique;
strict;

define behavior for zmn_i_buildings alias Building
persistent table zmn_buildings
lock master
authorization master ( instance )
//etag master <field_name>
{
create;
update;
delete;

field ( readonly ) BuildingId, CreatedBy, CreatedAt, LastChangedBy, LastChangedAt;

validation validateNRooms on save { create; field NRooms; }

mapping for zmn_buildings
{
BuildingId = building_id;
BuildingName = building_name;
NRooms = n_rooms;
AddressLine = address_line;
City = city;
State = state;
Country = country;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
}

}

Step - 5: Creating the Behavior Definition projection on the Consumption View
projection;
strict;

define behavior for zmn_c_buildings alias Building
{
use create;
use update;
use delete;
}

Step - 6: Creating the Behavior Implementation for Late Numbering and Validation Method -

Global Class to implement the behavior specified in the behavior definition
CLASS zbp_mn_i_buildings DEFINITION PUBLIC ABSTRACT FINAL 
FOR BEHAVIOR OF zmn_i_buildings.
ENDCLASS.

CLASS zbp_mn_i_buildings IMPLEMENTATION.
ENDCLASS.

Local handler classes are created in Local Types section of Global Class to implement the business logics.
CLASS lsc_zmn_i_buildings DEFINITION INHERITING FROM cl_abap_behavior_saver.

PROTECTED SECTION.

METHODS adjust_numbers REDEFINITION.

ENDCLASS.

CLASS lsc_zmn_i_buildings IMPLEMENTATION.

* this method using the late numbering concept to assign the building id for the entity
* using number range object
METHOD adjust_numbers.

DATA lv_bldg_num TYPE n LENGTH 5.

LOOP AT mapped-building ASSIGNING FIELD-SYMBOL(<map_building>) WHERE %key-BuildingId IS INITIAL .
TRY.
* using number range to generate the building id
cl_numberrange_runtime=>number_get(
EXPORTING
nr_range_nr = 'N1'
object = 'ZNR_BLD_NO'
quantity = 1
IMPORTING
number = DATA(number)
returncode = DATA(ret_code)
returned_quantity = DATA(ret_qty)
).
lv_bldg_num = number.
<map_building>-%key-BuildingId = |B{ lv_bldg_num }|.
CATCH cx_nr_object_not_found cx_number_ranges INTO DATA(lox_exp).
APPEND VALUE #(
%key = <map_building>-%key
%msg = lox_exp
) TO reported-building.
ENDTRY.
ENDLOOP.

ENDMETHOD.

ENDCLASS.

CLASS lhc_Building DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.

METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Building RESULT result.

METHODS validateNRooms FOR VALIDATE ON SAVE
IMPORTING keys FOR Building~validateNRooms.

ENDCLASS.

CLASS lhc_Building IMPLEMENTATION.

METHOD get_instance_authorizations.
ENDMETHOD.

* method to validate the no of rooms field
METHOD validateNRooms.

* reading the building entites
READ ENTITIES OF zmn_i_buildings IN LOCAL MODE
ENTITY Building
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(buildings)
FAILED DATA(building_failed).

IF building_failed IS NOT INITIAL.
* if the above read fails then return the error message
failed = CORRESPONDING #( DEEP building_failed ).
RETURN.
ENDIF.

LOOP AT buildings ASSIGNING FIELD-SYMBOL(<building>).

IF NOT <building>-NRooms BETWEEN 1 AND 10.

* if bulk upload, then the excel row no field will not be initial,
* creating a message prefix for the output message
DATA(lv_msg) = |No of Rooms must be in Range 1 to 10|.
lv_msg = COND #( WHEN <building>-ExcelRowNumber IS INITIAL
THEN lv_msg
ELSE |Row { <building>-ExcelRowNumber }: { lv_msg }|
).

APPEND VALUE #(
%tky = <building>-%tky
) TO failed-building.

APPEND VALUE #(
%tky = <building>-%tky
%state_area = 'Validate_Rooms'
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = lv_msg
)
%element-NRooms = if_abap_behv=>mk-on
) TO reported-building.
ENDIF.

CLEAR lv_msg.

ENDLOOP.

ENDMETHOD.

ENDCLASS.

Step - 7: Creating Service Definition
@EndUserText.label: 'Building Service'
define service Zmn_building {
expose zmn_c_buildings as Buildings;
}

Step - 8: Creating Service Bindings. In this scenario we will be create a OData V2 Service. I'm skipping this step as I am assuming you know how to do that.




Application Preview



  • List Report Page

  • Building Object Page

  • Validation
    The below screen shows the testing for the validation message.






 

Conclusion


And there you have learned how to create a basic RAP OData service with Late Numbering & Validations Concepts. Along with this, you also had a chance to know about some of the CDS Annotation to design & build the Fiori Element Application (List Report & Object Page).

Thanks for reading this post, I would like to read your thoughts in the comments !!!

In the next blog post, we will be creating a Fiori Elements App for this RAP OData Service using Business application Studio.


 

 

 

 

 
9 Comments