Posts

Showing posts from April, 2023

Timestamp with Time Zone Annotation in Fiori Elements

Image
Assumption: UTC timestamp data is stored in the DB table Default Logic: Without any additional tweaking, UTC timestamp is sent to SAPUI5. SAPIU5 converts it to a time zone either set by FLP or by local operation system. For example, timestamp 202304200800.000000 is stored in the table and its metadata data type is Edm.DataTimeOffset. The time zone of the operation system is Europe/Berlin. Then it will be displayed as 2023-04-20 10:00:00(formate is determined by locale or FLP setting). The logic is very common and SAPUI5 supports this since from early versions. With Specified Time Zone: But there could also be requirements that to present certain timestamp values in dedicated time zones. Or display the same time in different concerned time zones on the UI. Think about a row of clocks which are showing time for cites New York, Berlin, Shanghai and Tokyo. They are running the same UTC time but in differnt time zones. With timezone relevant annotations, we can not achive this without any a...

Calling Function and Action in OData V4

In OData V2, there is only on concept called 'Function' or 'Function Import'. But in V4, this is divided into two categories by different purposes for which they are expected to serve.  According to the standard OData specification, functions MUST NOT have side-effects, which means it should not make any changes to current data. On the contrary, actions can be used to modify data. This note tries to document ways of calling them. And both are called operation. Unbound Function Unbound function can be used to do something based on all data of the connected entity, such as CalculateAveragePrice, CalculateStockAvailability etc..   Sample URL for calling it: https://abc.com/sap/opu/odata4/sap/zui_v4_test/srvd/sap/zsd_xc_test/0001/FunctionDemo/ com.sap.gateway.srvd.zsd_xc_test.v0001 .calculateTotal() The trick point here is to add the namespace before the actual function name. Unbound Action A typical example of an unbound action is creating a new instance of the connected e...

SAP Fiori Elements with Annotation Expression

Image
To note down annotation expression examples I have used and proved workable. Unfortunately, I didn't find any official documents so far. Will update here if I get any. Apply a Function A function can be used to calculate wanted value for a specified UI place. The example below is use 'odata.concat' to concatenate three fields with '-' as the separator, and display it as the title of the object page. Without this approach, backend service needs to add a dedicated field and do the concatenation at the backend. But I found that this doesn't work in DataField. I think the reason may be there is annotation ConnectedField for this purpose. This tested successfully with FE V2. IF-ELSE For some simple dynamic control cases, it is much easier to determine the result on the client side instead of the backend side. Below is an example of a general case that to display or hide a form group according to a field value. It evaluates a value from the field specified with tag ...

Inconsistent CDS Annotation Between DEV and QAS Systems

Months back I received an incident regarding a Fiori Elements application missed one field in QAS system, but worked correctly in DEV system. The FE app was developed by using ABAP Programing Model for SAP Fiori(CDS+BOPF). The disappeared field is rendered via standard annotation which is composed in ABAP CDS view. Investigations: Examine annotations which are derived from CDS view and consumed by FE. By comparing annotations generated by both system, I can see the missed field is not presented in the annotation's LineItem section. Thus I am confident FE works as expected; the issue was not caused by frontend. Instead, the QAS backend server was not providing a correct annotation file as defined in the CDS view. Debug ABAP code of generating annotations based on CDS view. After hours of debugging, I located the main code of generating annotations from CDS view definition. The core method is  CL_DD_DDL_ANNOTATION_SERVICE->GET_ANNOS. It receives the CDS view name and exports rudim...

OData V4: Use Fields from Child Entity as Filters

Think about a simple data model with a header entity(Header) and a child entity(Text) which are connected with navigations. And we want to provide fields from the child entity as possbile filters for query. With OData V2, we need to use virtual element and implement SADL filter exit to achive this. But in V4, we don't need self-implementation anymore since it is supported in nature.  In V4 it is called Lambda Operators, includes 'any' and 'all'. Details can be found from official document:  OData Version 4.0. Part 2: URL Conventions Plus Errata 03 (oasis-open.org) The 'Text' entity has a field named 'Language'. I want to get all 'Header' entity instances which its child entity 'Text' has records with 'Language' equals to 'DE'. This a simple INNER JOIN in SQL world. In OData V4, the URL syntax should have below pattern. https://host/odata/srv/Header? $filter= _Text/ any (d:d/Language eq 'DE') &$count=true ...

Create OPA Tests for SAP Fiori Elements V4-based List Report Application(WIP)

Image
This is to summarize key points during development of OPA tests for SAP FE V4-based LROR(list report&object page) applications; content will be updated continuously. SAPUI5 provides FE V4 OPA libraries for better supporting creation of OPA tests; and it is under namespace sap.fe.test. Two keywords: action and assertion. Start FE V4 Based Application The first step of running OPA tests is the launch of the application. Same as running a SAPUI5 application, it can be started either by an standalone entry HTML file or by a Fiori Launchpad. One of the advantages of the latter option is Shell functionalities, such as navigation back(iNavigateBack), can be used during tests running. Standalone HTML file. Need to create an entry HTML such as index.html if it doesn't exist. Then specify the relatvive path and name of the file in the starting file. Launchpad sandbox. Same as index.html, need to create one if not exist yet. Then specify the same in the starting file. Same code as below. ...