
This blog is a detailed technical guide for the use of the Developer Extensibility option to develop an E2E Application deployed and running on SAP Public Cloud launchpad with the help of the Restful Application Programming Model (RAP).
Create a custom Fiori application to save product data, the app would simply do the following:
We will go through some stages to have the final result:
@EndUserText.label : 'Products Table'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #ALLOWED
define table zproducts {
key client : abap.clnt not null;
key product_uuid : sysuuid_x16 not null;
product_name : abap.char(40);
product_description : abap.char(120);
@Semantics.amount.currencyCode : 'zproducts.product_currency'
product_price : abap.curr(23,2);
product_currency : abap.cuky;
@Semantics.quantity.unitOfMeasure : 'zproducts.product_uom'
product_qty : abap.quan(23,2);
product_uom : meins;
@Semantics.amount.currencyCode : 'zproducts.product_currency'
total_amount : abap.curr(23,2);
ready_for_sale : abap_boolean;
last_changed_at : timestampl;
local_last_changed_at : timestampl;
}
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Products Interface View'
define root view entity zi_products
as select from zproducts
{
key product_uuid as ProductUuid,
product_name as ProductName,
product_description as ProductDescription,
product_price as ProductPrice,
product_currency as ProductCurrency,
product_qty as ProductQuantity,
product_uom as ProductUOM,
total_amount as TotalAmount,
ready_for_sale as ReadyForSale,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as LocalLastChangedAt
}
@EndUserText.label: 'Products Consumption View'
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Search.searchable: true
@Metadata.allowExtensions: true
define root view entity zc_products
provider contract transactional_query
as projection on zi_products as Products
{
@EndUserText.label: 'Product ID'
key ProductUuid,
@Search.defaultSearchElement: true
@EndUserText.label: 'Product Name'
ProductName,
@EndUserText.label: 'Product Description'
ProductDescription,
@EndUserText.label: 'Product Price'
ProductPrice,
@EndUserText.label: 'Product Currency'
ProductCurrency,
@EndUserText.label: 'Product Quantity'
ProductQuantity,
@EndUserText.label: 'Product UOM'
ProductUOM,
@EndUserText.label: 'Total Amount'
TotalAmount,
@EndUserText.label: 'Product is Ready for Sale'
ReadyForSale,
LastChangedAt,
LocalLastChangedAt
}
@Metadata.layer: #CORE
@UI:{ headerInfo:{ typeName:'Products',
typeNamePlural:'Products',
title:{ type: #STANDARD , label: 'Products' } } }
annotate view zc_products with
{
@UI.facet: [{ id:'Products' , purpose: #STANDARD , type: #IDENTIFICATION_REFERENCE , label: 'Product Details', position: 10 }]
@UI:{ lineItem: [{ position: 1 }, { type: #FOR_ACTION,
dataAction: 'setToReadyForSale' ,
label: 'Ready For Sale' , invocationGrouping: #CHANGE_SET } ] ,
identification: [ { position: 1 } ] }
ProductUuid;
@UI: { lineItem: [ { position: 2 } ],
identification: [ { position: 2 } ],
selectionField: [ { position: 2 } ] }
ProductName;
@UI: { lineItem: [ { position: 3 } ],
identification: [ { position: 3 } ],
selectionField: [ { position: 3 } ] }
ProductDescription;
@UI: { lineItem: [ { position: 4 } ],
identification: [ { position: 4 } ] }
ProductPrice;
@UI: { lineItem: [ { position: 5 } ],
identification: [ { position: 5 } ] }
ProductCurrency;
@UI: { lineItem: [ { position: 6 } ],
identification: [ { position: 6 } ] }
ProductQuantity;
@UI: { lineItem: [ { position: 7 } ],
identification: [ { position: 7 } ] }
ProductUOM;
@UI: { lineItem: [ { position: 8 } ],
identification: [ { position: 8 } ] }
TotalAmount;
@UI: { lineItem: [ { position: 9 } ],
identification: [ { position: 9 } ] ,
selectionField: [ { position: 9 } ] }
ReadyForSale;
@UI.hidden: true
LastChangedAt;
@UI.hidden: true
LocalLastChangedAt;
}
managed implementation in class zbp_i_products unique;
strict ( 2 );
define behavior for zi_products alias products
with additional save
persistent table zproducts
lock master
authorization master ( global )
etag master LocalLastChangedAt
{
field ( readonly ) ReadyForSale, TotalAmount, LastChangedAt, LocalLastChangedAt;
field ( numbering : managed , readonly ) ProductUuid;
create;
update;
delete;
action ( features : instance ) setToReadyForSale result [1] $self;
determination calcTotalAmount on save { field ProductPrice , ProductQuantity ; }
validation validatePrice on save { field ProductPrice; create; }
validation validateQTY on save { field ProductQuantity; create; }
mapping for zproducts
{
ProductUuid = product_uuid;
ProductName = product_name;
ProductDescription = product_description;
ProductPrice = product_price;
ProductCurrency = product_currency;
ProductQuantity = product_qty;
ProductUOM = product_uom;
TotalAmount = total_amount;
ReadyForSale = ready_for_sale;
LastChangedAt = last_changed_at;
LocalLastChangedAt = local_last_changed_at;
}
}
projection;
strict ( 2 );
define behavior for zc_products alias Products
{
use create;
use update;
use delete;
use action setToReadyForSale;
}
CLASS lhc_products DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR products RESULT result.
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR products RESULT result.
METHODS settoreadyforsale FOR MODIFY
IMPORTING keys FOR ACTION products~settoreadyforsale RESULT result.
METHODS calctotalamount FOR DETERMINE ON SAVE
IMPORTING keys FOR products~calctotalamount.
METHODS validateprice FOR VALIDATE ON SAVE
IMPORTING keys FOR products~validateprice.
METHODS validateqty FOR VALIDATE ON SAVE
IMPORTING keys FOR products~validateqty.
ENDCLASS.
CLASS lhc_products IMPLEMENTATION.
METHOD get_instance_features.
ENDMETHOD.
METHOD get_global_authorizations.
ENDMETHOD.
METHOD settoreadyforsale.
MODIFY ENTITIES OF zi_products IN LOCAL MODE
ENTITY products
UPDATE FIELDS ( readyforsale )
WITH VALUE #( FOR key IN keys
( %key = key-%key
readyforsale = 'X' ) )
FAILED failed
REPORTED reported .
ENDMETHOD.
METHOD calctotalamount.
READ ENTITIES OF zi_products IN LOCAL MODE
ENTITY products
FIELDS ( productprice productquantity ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_products) .
LOOP AT lt_products INTO DATA(ls_prd) .
DATA(lv_result) = ls_prd-productprice * ls_prd-productquantity .
MODIFY ENTITIES OF zi_products IN LOCAL MODE
ENTITY products UPDATE
FIELDS ( totalamount ) WITH VALUE #( ( %key = ls_prd-%key
totalamount = lv_result ) ) .
ENDLOOP.
ENDMETHOD.
METHOD validateprice.
READ ENTITIES OF zi_products IN LOCAL MODE
ENTITY products
FIELDS ( productprice ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_products) .
LOOP AT lt_products INTO DATA(ls_prd) .
IF ls_prd-productprice < 1 .
APPEND VALUE #( %tky = ls_prd-%tky ) TO failed-products .
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD validateqty.
READ ENTITIES OF zi_products IN LOCAL MODE
ENTITY products
FIELDS ( productquantity ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_products) .
LOOP AT lt_products INTO DATA(ls_prd) .
IF ls_prd-productquantity < 1 .
APPEND VALUE #( %tky = ls_prd-%tky ) TO failed-products .
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
CLASS lsc_zi_products DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS save_modified REDEFINITION.
METHODS cleanup_finalize REDEFINITION.
ENDCLASS.
CLASS lsc_zi_products IMPLEMENTATION.
METHOD save_modified.
ENDMETHOD.
METHOD cleanup_finalize.
ENDMETHOD.
ENDCLASS.
@EndUserText.label: 'Products Service definition'
define service ZD_products {
expose zc_products as Products;
}
Field Name | Value |
Name | <YOUR_SYSTEMS_ID>_SAML_ASSERTION |
Type | HTTP |
Description | SAML Assertion Destination to SAP S/4HANA Cloud system <YOUR_SYSTEMS_ID> |
URL | In the SAP S/4HANA Cloud system, navigate to the Communication Systems app and copy the Host Name from Own SAP Cloud System = Yes
and paste it with prefix https:// for example https://my12345-api.s4hana.ondemand.com. |
Proxy Type | Internet |
Authentication | SAMLAssertion |
Audience | Enter the URL of your system and remove -api, for example https://my12345.s4hana.ondemand.com. |
AuthnContextClassRef | urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession |
Select New Property and maintain the following Additional Properties and values.
Field Name | Value |
HTML5.DynamicDestination | true |
HTML5.Timeout | 60000 |
WebIDEEnabled | true |
WebIDEUsage | odata_abap,dev_abap |
nameIDFormat | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress |
At the end I hope this blog was helpful and detailed for the whole process of creating Cloud Application. In the coming blogs we will build more complex Application which is interacted with standard entities such as (Purchase order , Sales orders , etc...)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
21 | |
19 | |
9 | |
7 | |
5 | |
5 | |
5 | |
5 | |
4 | |
4 |