https://raw.githubusercontent.com/ajmaradiaga/feeds/main/scmt/topics/OData-blog-posts.xml SAP Community - OData 2024-05-20T11:11:25.117252+00:00 python-feedgen OData blog posts in SAP Community https://community.sap.com/t5/technology-blogs-by-sap/using-sap-datasphere-consumption-apis-in-sap-build-a-3-legged-authorization/ba-p/13585134 Using SAP Datasphere Consumption APIs in SAP Build - A 3-legged Authorization Flow Setup 2024-02-26T08:51:25.688000+01:00 gustavokath https://community.sap.com/t5/user/viewprofilepage/user-id/513684 <P>One of the challenges of data-driven decision making is to present complex and diverse data in a way that is easy to access and understand to act upon. SAP Datasphere delivers seamless and scalable access to mission-critical business data from multiple sources, accessing this data everywhere has the power to ease decision making and speed up business processes. In this context, SAP Build plays vital role to accelerate the apps development and making data accessible on the go. In this blog post, you will learn how to create an SAP Build app that integrates with SAP Datasphere as a centralized data source. This is achieved through the use of SAP Datasphere Consumption oData APIs. SAP Build benefits from SAP Datasphere's authentication model using a centralized Identity Provider (IdP) to grant access to the app and its contents. The blog post will guide you through the following steps: &nbsp;</P><OL><LI>Understanding the authentication flow</LI><LI>Developing the BTP Authorization Backend</LI><LI>Creating OAuth Client &amp; Destination</LI><LI>Modeling an SAP Datasphere view to be used on SAP Build</LI><LI>Configuring SAP Build Authentication</LI><LI>Setup SAP Build App&nbsp; Data Model</LI></OL><P style=" text-align: center; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="gustavokath_0-1708796554511.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/70410i4FE09073E81867EE/image-size/medium?v=v2&amp;px=400" role="button" title="gustavokath_0-1708796554511.png" alt="gustavokath_0-1708796554511.png" /></span></P><H2 id="toc-hId-964906402">1. Understanding the authentication flow</H2><P>The most complex and crucial step in integrating these two systems is the authentication process. SAP Datasphere Consumption APIs necessitate a three-legged OAuth2.0 flow with the "Authorization Code" grant type, which needs manual user interaction with the configured Identity Provider (IdP). For more information on the protocol, please refer to our reference page <A href="https://www.oauth.com/oauth2-servers/server-side-apps/authorization-code/" target="_blank" rel="noopener nofollow noreferrer">here</A>.</P><P>However, SAP Build does not natively support this type of authentication, neither using SAP BTP authentication type. The solution for such problem can accomplished by starting the App login step in a browser based view (aka: WebView) in the App opening to the SAP Datasphere authorization URL. This will initiate communication with the configured IdP in your SAP Datasphere (such as SAP ID, Office 365, etc), displaying its login page. Upon successful provision of user credentials, the OAuth Client redirect URI will be invoked.</P><P>For the entire process to operate securely and correctly, the OAuth Client redirect URI must be configured for the backend application API. Within the scope of this blog post, a BTP application will be created for this specific purpose. This backend application will utilize the OAuth Client ID and secret to generate the SAP Datasphere access token, which will then be sent back to the SAP Build Application.</P><P>The image bellow illustrates this flow:<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="auth_model.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55223i185C80EB4C1DD488/image-size/large?v=v2&amp;px=999" role="button" title="auth_model.png" alt="auth_model.png" /></span></P><P><IMG border="0" alt="" />This authentication process is inspired on the one described in the <A href="https://github.com/SAP-samples/appgyver-auth-flows#authentication-and-authorization-using-the-authorization-code-flow" target="_blank" rel="noopener nofollow noreferrer">SAP Build Samples GitHub</A>. To avoid the Client ID and Secret to be stored on device the "Authorization Backend" was introduced, so sensitive information could be stored into the BTP Destination Service.</P><H2 id="toc-hId-768392897">2. Developing the BTP Authorization Backend</H2><P>The "Authorization Backend" was introduced to ensure sensitive information is securely stored on the server. This blog post will detail the deployment of a new BTP application in NodeJS as an example, but the same steps can be applied to any new or existing backend service running on BTP or in another cloud environment. &nbsp;</P><P>The application need to realize 3 main tasks:</P><OL><LI>Receive the redirect URI API call and extract the authorization code</LI><LI>Handle OAuth2.0 token request</LI><LI>Return the access token to the client</LI></OL><H3 id="toc-hId-700962111">2.1. Receive the redirect URI API call and extract the authorization code</H3><P>Receiving the Redirect URI call in the service requires exposing an unauthenticated route that matches the path used in the OAuth Client configuration (Step 3.1). In this example <STRONG>"/oauth/callback" </STRONG>(<FONT color="#FF0000">&lt;callback-api-path&gt;</FONT>)&nbsp;will be used.</P><P>The authorization code, generated once the IdP login is successful, will be received as the "code"&nbsp; query parameter on the callback route, it will be used later for OAuth token request.</P><P><SPAN>Redirect URL Example:</SPAN></P><PRE><SPAN>https://auth-backend.hana.ondemand.com/oauth/callback?code=lxuC1347ZLcNg3gjqFHKjAc6gT4iB0hp</SPAN></PRE><P>NodeJS Code sample:<BR />[File: index.js]</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import express, { Request, Response } from "express"; const port = process.env.PORT || 3000; const app = express(); app.get("/oauth/callback", async (req: Request, res: Response try { const code = req.query.code as string; } catch (e) { res.status(500).json(e.message); } }); app.listen(port, () =&gt; { console.log("Server listening on " + port); });</code></pre><P>&nbsp;</P><P>&nbsp;</P><H3 id="toc-hId-504448606">2.2 Handle OAuth2.0 token request</H3><P>After obtaining the authorization code, the next step in the <A href="https://www.oauth.com/oauth2-servers/access-tokens/authorization-code-request/" target="_blank" rel="noopener nofollow noreferrer">OAuth protocol</A> is requesting the access token. On this blog post the SAP BTP Destination Service will be used for storing the OAuth Client ID and Secret, as well as for requesting the access token. Some dependencies to this process such as BTP destination and Client ID and Secret will be explained and later created on section 3.</P><P>The process for requesting the access token uses the <A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/oauth-authorization-code-authentication?#calling-%22find-destination%22" target="_blank" rel="noopener noreferrer">"Find Destination" API</A> from SAP BTP Destination Service. It requires the authorization code received earlier, the destination name (set up as an environment variable), It is crucial that the BTP Application is linked with the destination service. Instructions for these steps are also detailed on the SAP Help pages <A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/calling-destination-service-rest-api" target="_blank" rel="noopener noreferrer">[1]</A><A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/oauth-authorization-code-authentication?#calling-%22find-destination%22" target="_blank" rel="noopener noreferrer">[2]</A><A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/find-destination-response-structure#loio83a3f3b9cd314618aba651044ed5b9df__structure" target="_blank" rel="noopener noreferrer">[3]</A>, used as reference for this blog post.</P><P>The outcome of this request is the access and refresh tokens which will be used for authenticating all Consumption API request. The code snippet bellow shows how to configure such request in as part of the App created.</P><P>[File: destination-service.js]</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import * as xsenv from "@sap/xsenv"; import axios from "axios"; export const findDestination = async ( destinationName: string, code: string, redirectHost: string ) =&gt; { const credentials = xsenv.cfServiceCredentials({ tag: "dest const token = await getDestinationServiceToken(); const response = await axios({ method: "get", url:`${credentials.uri}/destination-configuration/v1/des headers: { Authorization: `Bearer ${token}`, "X-code": code, "X-redirect-uri": redirectHost, }, }); if (!response.data.authTokens || response.data.authTokens.l throw new Error(`Failed to fetch destination, ${response. } const tokenObject = response.data.authTokens[0]; if (tokenObject.error) { throw new Error(`Failed to fetch destination, ${tokenObje } else if (tokenObject.expires_in !== "0") { delete tokenObject["http_header"]; return tokenObject; } throw new Error(`Failed to fetch destination, invalid token }; const getDestinationServiceToken = async () =&gt; { const credentials = xsenv.cfServiceCredentials({ tag: "dest const response = await axios({ method: "post", url:`${credentials.url}/oauth/token`, headers: { Authorization: `Basic ${Buffer.from(`${credentials.clientid}:${credentials.clientsecret}`).toString("base64")}`, "Content-Type": "application/x-www-form-urlencoded", }, data: { client_id: credentials.clientid, grant_type: "client_credentials", }, }); if (response.status !== 200) { throw new Error(`Failed to fetch destination service access token, ${req}); } return response.data.access_token; };</code></pre><P>&nbsp;</P><P>&nbsp;</P><H3 id="toc-hId-307935101">2.3. Return the access token to the client</H3><P>The last responsibility of the backend application is to return the token back to the client (SAP Build App), which started the authentication flow, in a way it could read and use. In the context of SAP Build Apps which will be using a web browser for all authentication process a straightforward approach is for the server to redirect the request to another URL it has (/oauth/token) in this blog post and provide the access token as part of the query parameters (as implemented in this blog) or within the body.</P><P>Some adjustments are required in the index.js file for calling the methods created above</P><P>[File: index.js]</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import express, { Request, Response } from "express"; const { findDestination } = require("./destination-service"); const port = process.env.PORT || 3000; const app = express(); app.get("/oauth/callback", async (req: Request, res: Response try { const code = req.query.code; const destinationName = process.env.DESTINATION_NAME; const redirectUri = `https://${req.hostname}/oauth/callba const datasphereToken = await findDestination(destinationName,code,redirectUri); res.redirect(`/oauth/token?access_token=${datasphereToken.value}`); } catch (e) { res.status(500).json(e.message); } }); app.get("/token", async function (req, res) { res.status(200).send(); });</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>This is an example of how a BTP backend application can be developed to serve as authentication middleware between SAP build, functioning as a client, and the destination service in BTP. The only step missing is to deploy the application to BTP and use it - follow BTP guidance on how to deploy an application.</P><P>For the next step we will need some information created on this section save for later:</P><UL><LI>Host of your BTP application - referenced as <FONT color="#FF0000"><SPAN>&lt;backend-app-host&gt;</SPAN></FONT></LI><LI>Callback API Path - referenced as <FONT color="#FF0000"><SPAN><SPAN>&lt;callback-api-path&gt;</SPAN></SPAN></FONT></LI></UL><H2 id="toc-hId--17661123">3. Creating OAuth Client &amp; Destination</H2><P>The first thing to be realized for allowing integration with SAP Datasphere Consumption APIs involves creating an OAuth Client within the SAP Datasphere. This action generates the "ClientID" and "Client Secret" necessary for subsequent steps.</P><H3 id="toc-hId--85091909">3.1. Create an OAuth Client in SAP Datasphere</H3><OL><LI>Go to your SAP Datasphre Administration page<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="settings.png" style="width: 300px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55226i851B257268A243FA/image-size/medium?v=v2&amp;px=400" role="button" title="settings.png" alt="settings.png" /></span><IMG border="0" alt="" /></LI><LI>Open “App Integration” tab</LI><LI>Create a New OAuth Client to be used later</LI><OL><LI>Set the name of your OAuth Client</LI><LI>In&nbsp;<STRONG>Purpose&nbsp;</STRONG>field&nbsp;set “Interactive Usage”</LI><LI>In<STRONG><STRONG>&nbsp;Redirect URI&nbsp;</STRONG></STRONG>field set the URL of the callback API created on section 2, it should be <FONT color="#FF0000">&lt;backend-app-host&gt;</FONT>/<FONT color="#FF0000"><FONT color="#FF0000">&lt;callback-api-path&gt;<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="client.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55228i001BD676859EEBE0/image-size/medium?v=v2&amp;px=400" role="button" title="client.png" alt="client.png" /></span></FONT></FONT><P>&nbsp;</P><IMG border="0" alt="" /></LI></OL></OL><P>&nbsp; For the next step we will need some information created on this section save for later:</P><UL><LI>Client ID - referenced as<FONT color="#FF0000"><SPAN> &lt;client-id&gt;</SPAN></FONT></LI><LI>Client Secret - referenced as <FONT color="#FF0000"><SPAN>&lt;client-secret&gt;</SPAN></FONT></LI><LI>SAP Datasphere Authorization URL - referenced as <FONT color="#FF0000"><SPAN>&lt;datasphere-authorization-url&gt;</SPAN></FONT></LI><LI>SAP Datasphere Token URL - referenced as <FONT color="#FF0000"><SPAN><SPAN>&lt;datasphere-token-url&gt;</SPAN></SPAN></FONT></LI></UL><H3 id="toc-hId--281605414">3.2. Creating OAuth2AuthorizationCode Destination</H3><P>The authentication method supported by SAP Datasphere Consumption APIs is the three-legged OAuth2.0 flow with "Authorization Code". However, this authentication method is not supported by BTP Destinations when created via the cockpit, as detailed on this <A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/oauth-authorization-code-authentication" target="_blank" rel="noopener noreferrer">SAP Help Page</A>. In this case, the only viable creation method is through the SAP Destination Service API, as described <A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/oauth-authorization-code-authentication" target="_blank" rel="noopener noreferrer">here</A>. In this blog post we will use a HTTP client (eg: Postman) the request should look like:</P><P data-unlink="true"><STRONG>URL: </STRONG>https://<FONT color="#FF0000">&lt;destination-service-url&gt;</FONT>/destination-configuration/v1/subaccountDestinations/&nbsp;<BR /><STRONG><SPAN><STRONG>Method: </STRONG></SPAN></STRONG>POST<BR /><STRONG><SPAN><STRONG><STRONG>Headers:</STRONG></STRONG></SPAN></STRONG></P><UL><LI>Authentication: Bearer &lt;token&gt; - Follow steps <A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/calling-destination-service-rest-api" target="_blank" rel="noopener noreferrer">here</A> for generating authentication token</LI><LI>Content-Type: application/json</LI></UL><P><STRONG>Body:</STRONG></P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "Name": "DWC_Sales_OrdersTypeCode", "Type": "HTTP", "URL": "&lt;your-datasphere-url&gt;" //Doesn't matter in this case, "Authentication": "OAuth2AuthorizationCode", "ProxyType": "Internet", "tokenServiceURLType": "Dedicated", "HTML5.DynamicDestination": "true", "clientId": "&lt;client-id&gt;", "clientSecret": "&lt;client-secret&gt;", "AppgyverEnabled": "true", "tokenServiceURL": "&lt;datasphere-token-url&gt;", "WebIDEUsage": "true" }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>Note: <FONT color="#FF0000">&lt;destination-service-url&gt;</FONT> can be found in the binding between any BTP App and the Destination Service in the BTP cockpit (some more details on this <A href="https://help.sap.com/docs/connectivity/sap-btp-connectivity-cf/calling-destination-service-rest-api#2.-get-credentials" target="_blank" rel="noopener noreferrer">SAP Help Page</A>)</P><H2 id="toc-hId--607201638">4. Modeling an SAP Datasphere view to be used on SAP Build</H2><P>Upon completing the pre-requirements setup in sections 2 and 3, focus can then be shifted to developing the SAP Datasphere view according to individual business needs. This blog post primarily addresses the integration between SAP Datasphere and SAP Build, hence this section will cover a basic setup of a view intended to be accessed by SAP Build.</P><P>The most crucial part of creating an app involves understanding the problem that needs solved, as this will drive how data, views and analytic models should be modeled on SAP Dataspehre. In the context of this blog, for example, the SAP Build app will expose a list of countries and the sales value of each of them, also allowing to drill down into each one to check details of the specific product sales in each country.</P><P>On this blog a simple view named "CountrySales" containing 2 measures and 3 attributes. The measures will aggregate the data allowing to extract value from it in later in the SAP Build App, the image bellow shows a bit more about the modeling of the view. Also, don't forget to mark your view as "Exposed for Consumption", as required by Consumption APIs and import data into your base local or remote tables, more details can be found <A href="https://help.sap.com/docs/SAP_DATASPHERE/c8a54ee704e94e15926551293243fd1d/1f15a29a25354ec28392ab10ca4e9350.html" target="_blank" rel="noopener noreferrer">here.</A></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="view-modeling.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55229iA10E5E3516B0879E/image-size/large?v=v2&amp;px=999" role="button" title="view-modeling.png" alt="view-modeling.png" /></span></P><P>After deploying the view it becomes accessible through the Consumption OData APIs of SAP Datasphere. The a catalog request can be used check all available assets for consumption. &nbsp;</P><P>Asset Catalog request: <A target="_blank" rel="noopener">https://&lt;your-datasphere-url&gt;/api/v1/dwc/catalog/assets</A></P><P>There are 2 ways of consuming the exposed view via relational or analytical type of consumption, in this blog post we will use the first one due to some limitations on SAP Build to handle analytical consumption type. An example of the consumption URL that will be used later on is defined bellow - it will be references as <FONT color="#FF0000">&lt;country-sales-consumption-api&gt;</FONT></P><PRE>https://&lt;your-datasphere-host&gt;/api/v1/dwc/consumption/&lt;mySpace&gt;/CountrySales/&nbsp;</PRE><P>For learning more about SAP Datasphere consumption APIs, <A href="https://blogs.sap.com/2024/01/08/sap-datasphere-analytical-and-relational-odata-apis/" target="_blank" rel="noopener noreferrer">checkout Mirko's blog post</A>.</P><H2 id="toc-hId--803715143">5. Configuring SAP Build Authentication</H2><P>To start configuring the SAP Build App the first task to be executed is setting up the authentication and authorization using the Authorization Code flow within the App. To achieve this, we will create a page containing a webview component for an in-app browser experience. This webview will open the <SPAN><FONT color="#FF0000">&lt;datasphere-authorization-url&gt;</FONT> to start the authentication process explained on section 1. Once this flow concludes in the browser, we will add specific logic within SAP Build to capture the returned token and assign it to variables for later use.</SPAN></P><H3 id="toc-hId--946377298">5.1. Configuring the WebView component</H3><OL><LI>Create a new SAP Build Page, lets call it "Datasphere Auth Page"</LI><LI>Set this page as the initial page of your application</LI><LI>Add a "WebView" component to the empty page just created:<OL class="lia-list-style-type-lower-roman"><LI>Set the<SPAN><SPAN>&nbsp;URL with pattern (replace parts in red) - in the example a SAP Build variable was used:&nbsp;<BR /></SPAN></SPAN><SPAN><SPAN><SPAN><SPAN><FONT color="#FF0000">&lt;datasphere-authorization-url&gt;</FONT>/response_type=code&amp;client_id=<SPAN><SPAN><SPAN>&lt;client-id&gt;</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN><UL><LI><PRE><SPAN><SPAN><SPAN><SPAN><SPAN><SPAN><SPAN><SPAN>https:/your-dwc-tenant.authentication....sap/oauth/authorize?response_type=code&amp;client_id=sb-5a0f6ce9-3ac2-4425-9d27-1d78ce6be785!b13811%7Cclient!b2319</SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></SPAN></PRE></LI><LI>Note: In case you have a bad request error, replace the | (pipe) in the clientID by %7C<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="build-webview.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55231i2AB189B2124A46C5/image-size/large?v=v2&amp;px=999" role="button" title="build-webview.png" alt="build-webview.png" /></span></LI></UL></LI><LI>As outcome of this step when you open your app it should show up the login screen of the Identity Provider (IdP) linked with your SAP Datasphere application.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="build-idp-login.png" style="width: 223px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55258i663F77126963C1BE/image-size/medium?v=v2&amp;px=400" role="button" title="build-idp-login.png" alt="build-idp-login.png" /></span><P>&nbsp;</P></LI></OL></LI></OL><P class="">After the login on the IdP is performed a blank screen should be displayed, which is the redirect page developed on section 2.3.</P><H3 id="toc-hId--1142890803">5.2. Handling After Login action</H3><P class="">The concept behind the after login logic is to detect when the page displayed on the webview matches the pattern of the redirect URL used on section 2.3, in this case “/oauth/token?access_token=*” . When this happens the access token can be extracted from the URL query parameter, stored into an App variable and the page redirected to the fist content page of the App.</P><P class="">For the logic setup, open the "Logic Canvas" of the "Webview"&nbsp;component and follow the steps, at the end it should look similar to the image:</P><OL><LI><P class="">Start with the event “Component onLocationChange”</P></LI><LI><P class="">Include some Javascript code to detect the URL pattern and extract the access token:</P></LI></OL><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>if(inputs.input1.url.includes('/oauth/token?access_token')){ var code = inputs.input1.url.split('access_token=')[1].split('&amp;')[0]; return { code: code, codeAvailable: true } }else{ return { codeAvailable: false, debug: JSON.stringify(inputs.input1) } }</code></pre><P>&nbsp;</P><P>&nbsp;</P><UL><LI><P class=""><SPAN>Use an "IF" to check if the access token is available</SPAN></P><OL class="lia-list-style-type-lower-roman"><LI><P class="">In case it is available:</P><OL class="lia-list-style-type-lower-alpha"><LI><P>Set it into an App variable – this will be referenced as <FONT color="#FF0000">&lt;app-var-access-token&gt;</FONT></P></LI><LI>Change page to next one</LI><LI>Dismiss the current authentication view</LI></OL><P>&nbsp;</P></LI><LI>In case not available, rise an error</LI></OL></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="build-webview-logic.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55259i1C30AE4A5E84181E/image-size/large?v=v2&amp;px=999" role="button" title="build-webview-logic.png" alt="build-webview-logic.png" /></span></P><P>&nbsp;</P><H2 id="toc-hId--1046001301">6. Setup SAP Build App Data Model</H2><P class="">The last step to make the App usable is to create pages and make request to Datasphere Consumption APIs to fetch the data and make it available on the App screen.</P><H3 id="toc-hId--1535917813">6.1. Creating the Data Model</H3><P class="">For that SAP Build data entities need to be configured for each of the assets of SAP Datasphere that will be required in the App. Once the data models are configured they can be easily bound to list, tables and charts on the App. The steps bellow explain how to configure a data model:</P><OL><LI>Open data tab on SAP Build</LI><LI>Create a data entity of type "OData Integration"<OL><LI>As Authorization chose "Bearer Token"</LI><LI>Generate an OAuth2.0 Bearer token using the information from SAP Datasphere – this is only required for SAP Build to fetch the model metadata.</LI><LI>Provide the Consumption URL of the SAP Datasphere view<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="build-data-model.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55260i2F4CF0A6F72CE721/image-size/large?v=v2&amp;px=999" role="button" title="build-data-model.png" alt="build-data-model.png" /></span><P>&nbsp;</P></LI><LI>Click verify URL and the metadata of the view should be available</LI><LI>Save the data model, it will be called "CountrySales"</LI></OL></LI></OL><H3 id="toc-hId--1732431318">6.2. Using the Data Model</H3><P class="">To use the data models created a request for the records need to be added to the life cycle of a page and the authorization token of this request should be set correctly using the <FONT color="#FF0000"><SPAN class="">&lt;app-var-access-token&gt;</SPAN></FONT> as part of the headers.</P><P class="">The steps bellow explain how to create a page, configure the data model and use the filter or parameter capabilities of SAP Datasphere to search for specific data:</P><OL><LI>Create or use the page redirected after login</LI><LI>Go to the variables tab section<OL><LI>Create a Data Variable for storing the model data that will be fetched – lets call it &lt;data-var-country-sales&gt;</LI><LI>Create a page variable for storing the search text field value – lets call it &lt;page-var-search&gt;</LI></OL></LI><LI>On the page add some components:<OL class="lia-list-style-type-lower-alpha"><LI>Add a “Large Image List Item” component<OL class="lia-list-style-type-lower-roman"><LI>As “Repeat With” set <FONT color="#FF0000">&lt;data-var-country-sales&gt;</FONT> variable</LI><LI>As “Title Label” set “current.CountryName” , so the country name will appear as title of the list item</LI><LI>As “Description T ext” set a formula with the following content (to format the monetary information)<UL><LI><PRE>"Amount: $" + FORMAT_LOCALIZED_DECIMAL(NUMBER(repeated.current.Weighted_Value), "en", 2)</PRE></LI></UL></LI><LI><P class="">As “Image Source” set the formula bellow just make the list a bit prettier (It will render country code as colored image:</P><UL><LI><PRE>"https://ui-avatars.com/api/?rounded=true&amp;background=5F308E&amp;&amp;color=FFFFFF&amp;size=64&amp;name=" + ENCODE_FOR_URL(repeated.current.CountryCode)</PRE></LI></UL></LI></OL></LI><LI>Add a Spinner component to serve as busy indicator for the request</LI></OL></LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="build-countries-page.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/55261i241612A8528D1D2A/image-size/large?v=v2&amp;px=999" role="button" title="build-countries-page.png" alt="build-countries-page.png" /></span></P><P>When the App components have been added in the place they belong on the screen. The missing part is to add behaviour and load data to each of them. First when the page loads the data from the Data Model created on the step before needs to be loaded, also some caveat needs to be added for showing a "spinner" during loading time. Follow the steps bellow for setting this.</P><OL><LI>Add an Event "Page Mounted"</LI><LI>Set an Page Variable &lt;is_loading&gt; to true</LI><LI>Link it to a "Get Record Collection" data block, with settings<OL><LI>As Resource Name: Use the "CountrySales" model created on step 6.1</LI><LI><SPAN>As: Bearer token authentication: Use a custom object with, type "Bearer" and token the variable&nbsp;<FONT color="#FF0000">&lt;app-var-access-token&gt;</FONT>, created on step 5.2.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="build-request-api-auth.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/59813iD55FAC0EED29D2C7/image-size/large?v=v2&amp;px=999" role="button" title="build-request-api-auth.png" alt="build-request-api-auth.png" /></span><BR /></SPAN></LI></OL></LI><LI><SPAN>Link it "Set Data Variable" block to store the request result into the&nbsp;</SPAN><FONT color="#FF0000">&lt;data-var-country-sales&gt;</FONT><SPAN> variable</SPAN></LI><LI><SPAN>Link it to a "</SPAN>Set an Page Variable" setting &lt;is_loading&gt; to false, as loading is completed</LI></OL><P>This finishes the development of a simple SAP Build app fully integrated with SAP Datasphere via its Consumption APIs, a video of an extended version of the App is available bellow.</P><P>&nbsp;</P><P>To conclude, this blog post serves as an exhaustive guide for the integration of an SAP Build app with SAP Datasphere, while also laying the foundational knowledge for applying these steps to integrate other products and clients that support OAuth authentication with Authorization Code grant type. The elaborate instructions encompass crucial processes such as understanding the authentication flow, making effective use of the Consumption oData APIs, shaping the BTP Authorization Backend, setting up secure authentication, creating an OAuth Client &amp; Destination, and establishing the SAP Build App Data Model.</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P> 2024-02-26T08:51:25.688000+01:00 https://community.sap.com/t5/application-development-blog-posts/converting-soap-api-to-rest-api-for-post-method/ba-p/13608640 Converting SOAP API to REST API FOR POST METHOD 2024-03-06T15:15:06.197000+01:00 VishnuTeja https://community.sap.com/t5/user/viewprofilepage/user-id/823397 <P>we have soap API in se37 FM - <STRONG>Z_VENDOR_GETDETAILS</STRONG> convert to REST API by Using ODATA.</P><P>Advantages :</P><P>Using REST endpoints offers simplicity and security.It simplifies API requests, making them quick and easy to manage.<BR />Additionally, security benefits can be achieved through role access functions, allowing control over user access to specific services.</P><P>SE37 - SOAP API</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_0-1708217270334.png" style="width: 770px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/66855i28A75DF79D2DA6C7/image-dimensions/770x410?v=v2" width="770" height="410" role="button" title="9989445837_0-1708217270334.png" alt="9989445837_0-1708217270334.png" /></span></P><P>Code snippet for SOAP API :</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-abap"><code>IF ip_lifnr IS NOT INITIAL AND ip_ebeln IS INITIAL. CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT' EXPORTING input = ip_lifnr IMPORTING output = ip_lifnr. SELECT * FROM ekko INTO TABLE et_po_hdr WHERE lifnr = ip_lifnr. IF et_po_hdr[] IS INITIAL. ep_msg = 'No purchase order found'. ENDIF. ELSEIF ip_lifnr IS NOT INITIAL AND ip_ebeln IS NOT INITIAL. SELECT * FROM ekpo INTO table et_po_item WHERE ebeln = ip_ebeln. IF et_po_item[] IS INITIAL. ep_msg = 'No purchase order found'. ENDIF. ENDIF.</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;We have to import SOAP API by using RFC/BOR interface in SEGW&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_1-1708217961663.png" style="width: 780px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/66857i0814D9A1D9034E17/image-dimensions/780x388?v=v2" width="780" height="388" role="button" title="9989445837_1-1708217961663.png" alt="9989445837_1-1708217961663.png" /></span></P><P><SPAN>Once you defined the all entity types make sure that artifacts must be generated.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_2-1708218433580.png" style="width: 907px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/66872i73D6AD1AA67800F9/image-dimensions/907x344?v=v2" width="907" height="344" role="button" title="9989445837_2-1708218433580.png" alt="9989445837_2-1708218433580.png" /></span></P><P><SPAN>Once&nbsp; your entities methods are getting generated based on your entities inside&nbsp;</SPAN><STRONG>DPC_EXT</STRONG><SPAN>&nbsp;Class so just provide the implementation /IWBEP/IF_MGW_APPL_SRV_RUNTIME~CREATE_DEEP_ENTITY (redefine) method to perform the operation.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_3-1708218702410.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/66878i6399460B6350473B/image-size/large?v=v2&amp;px=999" role="button" title="9989445837_3-1708218702410.png" alt="9989445837_3-1708218702410.png" /></span></P><P>We have to call our main entity set and call our own method to read the data.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_4-1708219159669.png" style="width: 1046px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/66887i518BC1479EF7F49D/image-dimensions/1046x569?v=v2" width="1046" height="569" role="button" title="9989445837_4-1708219159669.png" alt="9989445837_4-1708219159669.png" /></span></P><P>Code snippet for create_deep_entity method.</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-abap"><code>METHOD /iwbep/if_mgw_appl_srv_runtime~create_deep_entity. CLEAR er_deep_entity. CASE iv_entity_set_name. WHEN'VendorSet'. er_deep_entity = _vendorgetdetails( io_data_provider ). ENDCASE. ENDMETHOD.</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>Create own method to perform the operation.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_5-1708219463333.png" style="width: 1036px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/66896iF18576A7E854A490/image-dimensions/1036x467?v=v2" width="1036" height="467" role="button" title="9989445837_5-1708219463333.png" alt="9989445837_5-1708219463333.png" /></span></P><P>import and export parameters of _vendordetails method</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_6-1708219639540.png" style="width: 1012px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/66901i2418D47EB141A5DB/image-dimensions/1012x460?v=v2" width="1012" height="460" role="button" title="9989445837_6-1708219639540.png" alt="9989445837_6-1708219639540.png" /></span></P><P>&nbsp;</P><P>To Define the structures and navigation names and calling soap API inside the method _vendorgetdetails&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-abap"><code>METHOD _vendorgetdetails. **-- Data Declaration DATA : BEGIN OF ls_entity. INCLUDE TYPE zcl_zvendor_getdetail_mpc_ext=&gt;ts_vendor. DATA : vendorHeader TYPE zcl_zvendor_getdetail_mpc=&gt;tt_vendorheader, vendorItem TYPE zcl_zvendor_getdetail_mpc=&gt;tt_vendoritem. DATA : END OF ls_entity, lo_message_container TYPE REF TO /iwbep/if_message_container. **--constants CONSTANTS: lc_type TYPE bapi_mtype VALUE 'E', lc_id TYPE symsgid VALUE '01', lc_number TYPE symsgno VALUE '02'. **--intialize io_data_provider-&gt;read_entry_data( IMPORTING es_data = ls_entity ). **--Raising exception IF ls_entity-ip_lifnr IS INITIAL. lo_message_container = me-&gt;mo_context-&gt;get_message_container( ). DATA(ls_return) = VALUE bapiret2( type = lc_id number = lc_number message = TEXT-010 ). lo_message_container-&gt;add_message( EXPORTING iv_msg_type = ls_return-type " Message Type iv_msg_id = ls_return-id " Message Class iv_msg_number = ls_return-number " Message Number iv_msg_text = ls_return-message " Message Text ). RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception EXPORTING message_container = lo_message_container. ENDIF. **--Calling existing RFC CALL FUNCTION 'ZVENDOR_GETDETAIL' EXPORTING ip_lifnr = ls_entity-ip_lifnr ip_ebeln = ls_entity-ip_ebeln IMPORTING ep_msg = ls_entity-ep_msg et_po_hdr = ls_entity-vendorheader et_po_item = ls_entity-vendoritem. copy_data_to_ref( EXPORTING is_data = ls_entity CHANGING cr_data = rx_deep_entity ). ENDMETHOD.</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>Once you done with your implementation just maintain and activate your service in Gateway Builder.</SPAN></P><P><BR /><SPAN>Click on Register Button it will open new session there provide your package and click on Continue to activate the service.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_0-1709676129453.png" style="width: 734px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/75368i260ACF5C3782B9CA/image-dimensions/734x94?v=v2" width="734" height="94" role="button" title="9989445837_0-1709676129453.png" alt="9989445837_0-1709676129453.png" /></span></P><P><SPAN>Once your service Registered successfully select your service and click on&nbsp;</SPAN><STRONG>SAP Gateway Client.</STRONG></P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_1-1709676294596.png" style="width: 802px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/75375i398F6D6951D16D5E/image-dimensions/802x407?v=v2" width="802" height="407" role="button" title="9989445837_1-1709676294596.png" alt="9989445837_1-1709676294596.png" /></span></P><P>After Execute you will get vendor header and vendor item details in http response.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9989445837_2-1709676550498.png" style="width: 769px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/75384i2BBA2F68B5FDB82E/image-dimensions/769x367?v=v2" width="769" height="367" role="button" title="9989445837_2-1709676550498.png" alt="9989445837_2-1709676550498.png" /></span></P><P>&nbsp;</P><P><SPAN>Conclusion:</SPAN><BR /><BR /><SPAN>this requirement basically helps in converting SOAP API to REST API to improving performance and web service based also we can use.</SPAN></P><P><BR /><SPAN>Hope I find it will we be helpful. If any queries please welcome on comment sections.</SPAN><BR /><BR /><SPAN>Regards,</SPAN><BR />Vishnu Teja.</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P> 2024-03-06T15:15:06.197000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/develop-and-deploy-a-html-angular-vue-react-app-on-sap-btp-access-s-4-op/ba-p/13633299 Develop and deploy a HTML (Angular/Vue/React) app on SAP BTP access S/4 OP, Part III 2024-03-11T09:50:37.733000+01:00 Hongjun_Qian https://community.sap.com/t5/user/viewprofilepage/user-id/343240 <P><SPAN>See my previous blogs for the context:</SPAN></P><P><SPAN><A href="https://community.sap.com/t5/technology-blogs-by-sap/develop-and-deploy-a-html-angular-vue-react-app-on-sap-btp-cloud-foundry/ba-p/13565116" target="_blank">Part I: Develop and deploy a HTML (Angular/Vue/React) app ... - SAP Community</A></SPAN></P><P><A href="https://community.sap.com/t5/technology-blogs-by-sap/develop-and-deploy-a-html-angular-vue-react-app-on-sap-btp-cloud-foundry/ba-p/13565139" target="_blank">Part II: Develop and deploy a HTML (Angular/Vue/React) app ... - SAP Community</A></P><P>This post provides detail step to develop and deploy a HTML app (based on Angular) which deployed to SAP BTP via SAP CAP and access data from one single source:</P><UL><LI>S/4 On-premise system;</LI></UL><H3 id="toc-hId-1117942237">Step 1. Create an Web-API OData Service in S/4 On-premise System.</H3><P><SPAN>It is suggested to use RAP for such development in ABAP development world, but it depends on personal choices.</SPAN></P><P><SPAN>During create service binding, it is recommended to use 'OData V4 - Web API'.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Hongjun_Qian_0-1710145230519.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78147i11CBE4A3F5BEC0A3/image-size/medium?v=v2&amp;px=400" role="button" title="Hongjun_Qian_0-1710145230519.png" alt="Hongjun_Qian_0-1710145230519.png" /></span></P><P>And you can launch the 'Test' button on this API definition, it will launch a Swagger UI as following:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Hongjun_Qian_1-1710145398865.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78151i6BD5AD40731435DC/image-size/medium?v=v2&amp;px=400" role="button" title="Hongjun_Qian_1-1710145398865.png" alt="Hongjun_Qian_1-1710145398865.png" /></span></P><P>Click on the link 'ABAP Documentation' to show the metadata file. Sometime the linkage itself cannot be opened successfully, copy the link and open the Tab in your browser.</P><P>The metadata shall be displayed, save the content to a separate file via 'Save as...'.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Hongjun_Qian_2-1710145630268.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78154iF69E98423DCB48AA/image-size/medium?v=v2&amp;px=400" role="button" title="Hongjun_Qian_2-1710145630268.png" alt="Hongjun_Qian_2-1710145630268.png" /></span></P><P>Assume the file as `API_DEF.xml`.</P><H3 id="toc-hId-921428732"><BR /><SPAN>Step 2. Create new CAP project (Nodejs based) and Import API.</SPAN></H3><P><SPAN>Refer to&nbsp;<A href="https://cap.cloud.sap/docs/get-started/jumpstart" target="_blank" rel="noopener nofollow noreferrer">Jumpstart &amp; Grow as You Go | CAPire (cloud.sap)</A>&nbsp;for the prerequisites and recommended IDE before creating a new CAP project (Nodejs based).</SPAN></P><P><SPAN>Using following commands to create a CAP project named 'demoapp':</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>cds init demoapp</code></pre><P>&nbsp;</P><P><SPAN>Then, imports the `API_DEF.xml` via following command lines:&nbsp;</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>cds import API_DEF.xml --force --as cds</code></pre><P>&nbsp;</P><P><SPAN>Via this importing, the CDS will create an folder named `external` under `srv`:</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Hongjun_Qian_3-1710146204548.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78170i26E84342A0C2AE24/image-size/medium?v=v2&amp;px=400" role="button" title="Hongjun_Qian_3-1710146204548.png" alt="Hongjun_Qian_3-1710146204548.png" /></span></P><H3 id="toc-hId-724915227">Step 3. Complete the CAP Service development.</H3><P>Enhance the CAP project by definition it's service:</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>using { API_DEF as external } from '../srv/external/API_DEF'; service MyAPIService @(impl: 'srv/impl/myapi-service.js') { @readonly entity MyAPI as projection on external.MyEntity; }</code></pre><P>&nbsp;</P><P>Then, update your `myapi-service.js`:</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>"use strict"; const cds = require('@sap/cds'); class MyAPIService extends cds.ApplicationService { init() { this.on('READ', 'MyAPI', async req =&gt; { const apiodata = await cds.connect.to("API_DEF"); const { MyEntity } = apiodata.entities; const results = await apiodata.run(SELECT.from (MyEntity)); return results; }); } } module.exports = { MyAPIService }</code></pre><P>&nbsp;</P><P>We need specify a destination (defined in your BTP subaccount) to let CAP know where to fetch the data.</P><P>In the `package.json`, section `cds`:</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code> "API_DEF": { "kind": "odata", "model": "srv/external/API_DEF", "csrf": true, "csrfInBatch": true, "[production]": { "credentials": { "destination": "MYERP_DEST", "path": "/sap/opu/odata4/sap/API_DEF/0001" } } },</code></pre><P>&nbsp;</P><P>The path here refer to the path in your S/4 OP system.&nbsp;</P><P>Now, your CAP service will automatically (if your configured your destination and connectivty service correctly) when you fetch a `GET` on the MyAPI.</P><H3 id="toc-hId-528401722">Step 4. Create your HTML app (in this case, use Angular).</H3><P>You just need create your HTML app in folder `app` and consume the service in `srv` folder.</P><P>Refer to Step 4 in my article&nbsp;<A href="https://community.sap.com/t5/technology-blogs-by-sap/develop-and-deploy-a-html-angular-vue-react-app-on-sap-btp-cloud-foundry/ba-p/13565139" target="_blank">Develop and deploy a HTML (Angular/Vue/React) app ... - SAP Community&nbsp;</A></P><P>You don't need additional (for consuming Dest and Conn) logic in `approuter` any more.</P><P>&nbsp;</P><P>Enjoy your coding then.</P><P>&nbsp;</P> 2024-03-11T09:50:37.733000+01:00 https://community.sap.com/t5/financial-management-blogs-by-members/inbound-interface-to-receive-the-uuid-pdf-and-xml-details-through-odata/ba-p/13637696 Inbound Interface to receive the UUID, PDF and XML details through ODATA - MEXICO 2024-03-15T11:00:09.958000+01:00 d4449 https://community.sap.com/t5/user/viewprofilepage/user-id/144905 <H2 id="toc-hId-988982523">Requirement</H2><P>In Mexico, it is necessary that all companies receive tax authority validated XML and PDF files that contain the details of the payment made to vendors.</P><P>Its mandatory to extract the UUID number from the file that is received from the vendors and save it in a way that makes it easily accessible, in S4 it would be easier to store it in a custom table.</P><P>The importance of this interface is to store UUID in S4 system in order to facilitate users identify which invoices were payed to which vendors as well as reconciliation between EDICOM Portal and S4 system. The risk of not having this interface, is that files (PDF and XML) and UUID data will only be stored in EDICOM Portal and reconciliation to corresponding payments would be time consuming for users.&nbsp;&nbsp;&nbsp;</P><H2 id="toc-hId-792469018">Technical Requirement</H2><P>Interaction of SAP with EDICOM portal where SAP CPI is the middleware which sends the XML, PDF to S4. The technical requirement was to create a ODATA which can receive XML and PDF, also should extract UUID details from XML structure and update it to the respective document.</P><P>Simple flow chart:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_0-1710394374539.jpeg" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80376i2B821A1012A14C62/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_0-1710394374539.jpeg" alt="d4449_0-1710394374539.jpeg" /></span></P><P>Detailed Flow chart:</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</P><H2 id="toc-hId-595955513">Technical Solution</H2><P>To receive and extract the details from XML file, ODATA interface is developed and the received XML and PDF files are attached to the respective FI document.</P><P>XML and PDF files are sent in base64 encoded format from SAP CPI then in S4 we make use of various function modules to convert it and make the attachment.</P><P>Created ODATA service in tcode SEGW - <STRONG>ZFI_PAYMENT_COMPLEMENT_002</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_1-1710394472271.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80377i0BAB77F38F83D1E0/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_1-1710394472271.png" alt="d4449_1-1710394472271.png" /></span></P><P>In Data model the custom table ZFI_IF020_PAYCOM is used to give ODATA the reference structure. The last two fields ZPDF &amp; ZXML are created in RAWSTRING format to store the XML and PDF files.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_2-1710394501348.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80378iF0286B4B47588873/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_2-1710394501348.png" alt="d4449_2-1710394501348.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_3-1710394536606.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80379iCEB53401EB9F2ACF/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_3-1710394536606.png" alt="d4449_3-1710394536606.png" /></span></P><P>Regenerate the Runtime Artifact ZCL_ZFI_PAYMENT_COM_01_DPC_EXT</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_4-1710394558273.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80380iD064CA6CA87E74F5/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_4-1710394558273.png" alt="d4449_4-1710394558273.png" /></span></P><P>This gives us the class where we can write the required logic, here we have redefined the method PAY_COMPSET_CREATE_ENTITY – holds the logic to validate the inputs received from SAP CPI and the logic to add PDF and XML to the FI document.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_5-1710394576668.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80381i72DD2D5FCE09D59C/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_5-1710394576668.png" alt="d4449_5-1710394576668.png" /></span></P><P>FI_DOCUMENT_CHANGE FM is used to update UUID to the respecting FI document.</P><P>The above FM is passed with the required importing parameters.</P><P>PDF Attachment:</P><P>PDF file is sent in Base64 format from CPI to S4.</P><UL><LI>SCMS_XSTRING_TO_BINARY – using this FM the received base64 format is converted to binary</LI><LI>ARCHIV_CREATE_TABLE – using this FM the converted binary file is attached to the FI document</LI></UL><P>XML Attachment:</P><P>XML is also sent in Base64 format from CPI to S4.</P><UL><LI>SCMS_XSTRING_TO_BINARY – using this FM the received base64 format is converted to binary</LI><LI>SO_CONVERT_CONTENTS_BIN – to get the binary file in tab format</LI><LI>SO_FOLDER_ROOT_ID_GET – this FM is used to fetch the folder ID</LI><LI>SO_OBJECT_INSERT – used to insert the converted XML file</LI><LI>BINARY_RELATION_CREATE_COMMIT – create relation between attachment and the document (Reference code is attached)</LI></UL><P>If there is any error in the attachment the file is sent to AL11.</P><P>All the received inputs including XML and PDF are saved in a custom table.</P><P>Report:</P><P>Tcode - ZFI_PAYCOMP_MONITOR</P><P>A report is created to display the details received using custom table in which the entries made through ODATA Service and displayed in ALV format.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_6-1710394659675.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80383iDC2EEEF48F9B63B7/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_6-1710394659675.png" alt="d4449_6-1710394659675.png" /></span></P><P>User can view the error details in description and also can select and reprocess the particular file after updating the missed details.</P><P>Created and activated the service <STRONG>ZFI_PAYMENT_COMPLEMENT_002_SRV</STRONG> in following tcode /n/iwfnd/maint_service</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="d4449_7-1710394683788.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/80384i8AF112BF888E7F49/image-size/medium?v=v2&amp;px=400" role="button" title="d4449_7-1710394683788.png" alt="d4449_7-1710394683788.png" /></span></P><P>The ICF Node should be in active status as shown in the screenshot.<BR /><BR />Hope this helps someone!&nbsp;<span class="lia-unicode-emoji" title=":smiling_face_with_smiling_eyes:">😊</span></P><P>&nbsp;</P><P><a href="https://community.sap.com/t5/c-khhcw49343/OData/pd-p/551580658536717501828021060147962" class="lia-product-mention" data-product="323-1">OData</a>&nbsp;<a href="https://community.sap.com/t5/c-khhcw49343/NW+ABAP+Gateway+%252528OData%252529/pd-p/181161894649260056016734803547327" class="lia-product-mention" data-product="1007-1">NW ABAP Gateway (OData)</a>&nbsp;&nbsp;</P> 2024-03-15T11:00:09.958000+01:00 https://community.sap.com/t5/application-development-blog-posts/fiori-analytical-list-page-using-cds-annotations-to-display-as-charts/ba-p/13632009 Fiori Analytical List Page using CDS Annotations to Display as Charts 2024-03-15T11:53:44.741000+01:00 Arun_21 https://community.sap.com/t5/user/viewprofilepage/user-id/1413983 <H2 id="toc-hId-988827526">Goal</H2><P>Create an Analytical List Page like the one below.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_0-1709884299107.png" style="width: 832px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77474iFEB9419FD7E40CA0/image-dimensions/832x374?v=v2" width="832" height="374" role="button" title="Arun_21_0-1709884299107.png" alt="Arun_21_0-1709884299107.png" /></span></P><P><STRONG>Development environment</STRONG></P><UL><LI>Frontend: &nbsp;BTP</LI><LI>Backend: S/4HANA</LI></UL><H2 id="toc-hId-792314021">Data model</H2><P>The data model has a simple structure as shown below. The base has a table for recording expenditures (ZMY_EXPENSES) and an expenditure category master (ZEXCATEGORYTEXT). The views used in ALP are the same analytical views used in the query browser. The top view&nbsp;<a href="https://community.sap.com/t5/user/viewprofilepage/user-id/15206">@analytics</a>.query: trueis annotated with , and the base view below it&nbsp;<a href="https://community.sap.com/t5/user/viewprofilepage/user-id/15206">@analytics</a>.dataCategory: #CUBEis annotated with (or FACT, DIMENSION, HIERARCHY depending on the purpose).</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_0-1709885061373.png" style="width: 524px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77477iDA43C2F6C836F21E/image-dimensions/524x368?v=v2" width="524" height="368" role="button" title="Arun_21_0-1709885061373.png" alt="Arun_21_0-1709885061373.png" /></span></P><P>ZMY_EXPENSES</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_1-1709885061381.png" style="width: 783px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77478i3E3AD08CCB4CE600/image-dimensions/783x214?v=v2" width="783" height="214" role="button" title="Arun_21_1-1709885061381.png" alt="Arun_21_1-1709885061381.png" /></span></P><P>The data is in the following format.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_2-1709885061384.png" style="width: 781px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77476iDDFC925E88E5E71D/image-dimensions/781x166?v=v2" width="781" height="166" role="button" title="Arun_21_2-1709885061384.png" alt="Arun_21_2-1709885061384.png" /></span></P><P>ZEXCATEGORYTEXT</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_3-1709885061389.png" style="width: 782px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77480i343C7CFB76C4B77A/image-dimensions/782x221?v=v2" width="782" height="221" role="button" title="Arun_21_3-1709885061389.png" alt="Arun_21_3-1709885061389.png" /></span></P><P>For simplicity, we will only have Five Categories.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_4-1709885061391.png" style="width: 570px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77479iD1094043F90ABD72/image-dimensions/570x239?v=v2" width="570" height="239" role="button" title="Arun_21_4-1709885061391.png" alt="Arun_21_4-1709885061391.png" /></span></P><P><STRONG>Steps</STRONG></P><OL><LI>Creating a CDS view</LI><LI>Output charts and tables</LI></OL><H3 id="toc-hId-724883235">1. Creating a CDS view</H3><H4 id="toc-hId-657452449">Expense Category View: ZI_Category_Text</H4><P>Create a view to retrieve expenditure categories.</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-abap"><code>@AbapCatalog.sqlViewName: 'ZITEXTCAT' @AbapCatalog.compiler.compareFilter: true @AbapCatalog.preserveKey: true @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Text Category' @ObjectModel.dataCategory: #TEXT @ObjectModel.representativeKey: 'category' define view ZI_Category_Text as select from zexcategorytext { key category, @Semantics.language: true key language, @Semantics.text: true text }</code></pre><P>&nbsp;</P><P>&nbsp;</P><H4 id="toc-hId-460938944">Cube View for aggregation: ZI_Cube_MyExpenses</H4><P>Create a Cube View for aggregation. I_CalendarDate is a standard view that allows you to convert a date to year, year month, etc. I want to be able to select the year and month with the ALP filter, so I have I_CalendarDate and Association.</P><P>ZI_Cube_MyExpenses</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-abap"><code>@AbapCatalog.sqlViewName: 'ZIMYEXP' @AbapCatalog.compiler.compareFilter: true @AbapCatalog.preserveKey: true @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Cube for My Expenses' @Analytics.dataCategory: #CUBE define view ZI_Cube_MyExpenses as select from zmy_expenses association [0..1] to ZI_Category_Text as _Text on $projection.Cateogry = _Text.category association [0..1] to I_CalendarDate as _CalendarDate on $projection.PostingDate = _CalendarDate.CalendarDate { @ObjectModel.foreignKey.association: '_CalendarDate' posting_date as PostingDate, @ObjectModel.text.association: '_Text' category as Cateogry, @Semantics.amount.currencyCode: 'Currency' @DefaultAggregation: #SUM amount as Amount, @Semantics.currencyCode: true currency as Currency, _CalendarDate._CalendarYear.CalendarYear, _CalendarDate._YearMonth.YearMonth, _Text, _CalendarDate }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>The annotations required for use with ALP are as follows.</P><P>@Analytics.dataCategorySet&nbsp;to make it a view for analysis .&nbsp;Category is a combined view of transaction data (expenditures) and master data (expenditure categories)&nbsp;#CUBE.</P><P><SPAN>@</SPAN><SPAN>Analytics</SPAN><SPAN>.</SPAN><SPAN>dataCategory</SPAN><SPAN>:</SPAN> <SPAN>#</SPAN><SPAN>CUBE</SPAN></P><P>The analysis view must have items to be aggregated (measures).&nbsp;@DefaultAggregationItems marked with are subject to aggregation.</P><P><SPAN>@</SPAN><SPAN>DefaultAggregation</SPAN><SPAN>:</SPAN> <SPAN>#</SPAN><SPAN>SUM</SPAN>&nbsp;&nbsp;&nbsp; <SPAN>amount</SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN>as</SPAN> <SPAN>Amount</SPAN><SPAN>,</SPAN></P><P><STRONG>Consumption View</STRONG><STRONG>:</STRONG><STRONG>ZC_MY_Expenses</STRONG></P><P>Finally, create the top view that will be the source of the OData.</P><P>ZC_MY_Expenses</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-abap"><code>@AbapCatalog.sqlViewName: 'ZCMYEXP' @AbapCatalog.compiler.compareFilter: true @AbapCatalog.preserveKey: true @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'My Expenses' @Analytics.query: true @OData.publish: true @Metadata.allowExtensions: true define view ZC_MY_Expenses as select from ZI_Cube_MyExpenses { PostingDate, @AnalyticsDetails.query.display: #KEY_TEXT Cateogry, Amount, Currency, @Semantics.calendar.year: true CalendarYear, @Semantics.calendar.yearMonth: true YearMonth }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>The important thing here&nbsp;@Analytics.query: true is the annotation. This view does not have a key, but it&nbsp;@Analytics.query: true is acceptable without a key.</P><P>Another important point is the following annotation.</P><P>&nbsp;&nbsp;&nbsp; @Semantics.calendar.year: true</P><P>&nbsp;&nbsp;&nbsp; CalendarYear,</P><P>&nbsp;&nbsp;&nbsp; @Semantics.calendar.yearMonth: true</P><P>&nbsp;&nbsp;&nbsp; YearMonth</P><P>The OData type for CalendarYear (year) and YearMonth (year and month) is edm.string. If left as is, it will not be recognized as a time-related item, so&nbsp;@Semantics.calendarit is necessary to add .</P><H3 id="toc-hId-135342720">2. Output charts and tables</H3><P>Next, let's create an app by adding the minimum annotations to output charts and tables.<BR />Create a Metadata Extension for ZC_MY_Expenses. First, define the selection field (selectionField) and the table column item (lineItem).</P><P>@Metadata.layer: #CORE</P><P>annotate view ZC_MY_Expenses</P><P>&nbsp;&nbsp;&nbsp; with</P><P>{</P><P>&nbsp;&nbsp;&nbsp; @UI:{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lineItem: [{ position: 10 }]</P><P>&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp; PostingDate;</P><P>&nbsp;&nbsp;&nbsp; @UI:{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selectionField: [{position: 10 }],</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lineItem: [{ position: 20 }]</P><P>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;</P><P>&nbsp;&nbsp;&nbsp; Cateogry;</P><P>&nbsp;&nbsp;&nbsp; @UI:{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lineItem: [{ position: 30 }]</P><P>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;</P><P>&nbsp;&nbsp;&nbsp; Amount;</P><P>&nbsp;&nbsp;&nbsp; @UI:{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selectionField: [{position: 20 }]</P><P>&nbsp;&nbsp;&nbsp; }&nbsp;</P><P>&nbsp;&nbsp;&nbsp; CalendarYear;</P><P>&nbsp;&nbsp;&nbsp; @UI:{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selectionField: [{position: 30 }]</P><P>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;</P><P>&nbsp;&nbsp;&nbsp; YearMonth;&nbsp;&nbsp;</P><P>}</P><P>Next, set the annotation to display the chart. Add the following above annotate view ZC_MY_Expenses...</P><P>This is an annotation that determines the display variant (presentationVariant) and selection variant (selectionVariant) when the app is opened. A qualifier (ID) of 'Default' is specified for each.</P><P>@UI.selectionPresentationVariant: [{</P><P>&nbsp;&nbsp;&nbsp; qualifier: 'Default',</P><P>&nbsp;&nbsp;&nbsp; presentationVariantQualifier: 'Default',</P><P>&nbsp;&nbsp;&nbsp; selectionVariantQualifier: 'Default'&nbsp;&nbsp;&nbsp;</P><P>&nbsp;}]</P><P>The contents of the actual variant are defined below.</P><P>presentationVariant indicates how the data is presented, that is, it is displayed as a chart (type:</P><P>@UI.presentationVariant: [{</P><P>&nbsp;&nbsp;&nbsp; qualifier: 'Default',</P><P>&nbsp;&nbsp;&nbsp; visualizations: [{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: #AS_CHART,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qualifier: 'ChartDefault'</P><P>&nbsp;&nbsp;&nbsp; }]</P><P>&nbsp;}]</P><P>@UI.selectionVariant: [{</P><P>&nbsp;&nbsp;&nbsp; qualifier: 'Default',</P><P>&nbsp;&nbsp;&nbsp; text: 'Default'</P><P>&nbsp;}]</P><P>Finally, let's define the chart. Create a stacked bar graph for each year and month and expense category.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_0-1709886806898.png" style="width: 783px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77492i4C6097D605021F44/image-dimensions/783x141?v=v2" width="783" height="141" role="button" title="Arun_21_0-1709886806898.png" alt="Arun_21_0-1709886806898.png" /></span></P><P>@UI.chart: [{</P><P>&nbsp;&nbsp;&nbsp; qualifier: 'ChartDefault',</P><P>&nbsp;&nbsp;&nbsp; chartType: #COLUMN_STACKED,</P><P>&nbsp;&nbsp;&nbsp; dimensions: ['Cateogry', 'YearMonth'],</P><P>&nbsp;&nbsp;&nbsp; measures: ['Amount'],</P><P>&nbsp;&nbsp;&nbsp; dimensionAttributes: [{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimension: 'Cateogry',</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; role: #SERIES</P><P>&nbsp;&nbsp;&nbsp;&nbsp; },{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dimension: 'YearMonth',</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; role: #CATEGORY</P><P>&nbsp;&nbsp;&nbsp;&nbsp; }],</P><P>&nbsp;&nbsp;&nbsp; measureAttributes: [{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; measure: 'Amount',</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; role: #AXIS_1</P><P>&nbsp;&nbsp;&nbsp;&nbsp; }]</P><P>&nbsp; }]</P><P>The meanings of the items are as follows.</P><TABLE><TBODY><TR><TD><P><STRONG>project</STRONG></P></TD><TD><P><STRONG>explanation</STRONG></P></TD></TR><TR><TD><P>qualifier</P></TD><TD><P>Chart ID. Same as qualifier specified in presentationVariant</P></TD></TR><TR><TD><P>chartType</P></TD><TD><P>Chart type. #COLUM_STACKED is a stacked bar graph</P></TD></TR><TR><TD><P>dimensions</P></TD><TD><P>Specify the analysis axis. Multiple specifications can be specified depending on the chart type.</P></TD></TR><TR><TD><P>measures</P></TD><TD><P>Specify the numeric item to be analyzed. Multiple specifications can be specified depending on the chart type.</P></TD></TR><TR><TD><P>dimensionAttributes</P></TD><TD><P>Specify the role (use) for each analysis axis (*)</P></TD></TR><TR><TD><P>measureAttributes</P></TD><TD><P>Specify the role (purpose) for each numerical item. Specify which axis</P></TD></TR></TBODY></TABLE><P>*Meaning of role in dimension</P><UL><LI>category: Set for the dimension that is the X axis in a bar graph</LI><LI>series: Use when you want to separate classifications (colors) within the same category</LI><LI>category2: Second axis used in heatmap etc.</LI></UL><P>Creating &nbsp;an ALP with BTP(SAP Business Technology Platform)</P><P>Let's make OData public. TR - &gt; ( /IWFND/MAINT_SERVICE )</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_1-1709886806919.png" style="width: 780px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77493i871BED2044054BF8/image-dimensions/780x316?v=v2" width="780" height="316" role="button" title="Arun_21_1-1709886806919.png" alt="Arun_21_1-1709886806919.png" /></span></P><P>Select the Analytical List Page template.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_0-1709888407457.png" style="width: 781px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77504iBE1FED8ACAB2DB5F/image-dimensions/781x334?v=v2" width="781" height="334" role="button" title="Arun_21_0-1709888407457.png" alt="Arun_21_0-1709888407457.png" /></span></P><P>Provide the OData Service URL</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_1-1709888407476.png" style="width: 777px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77506i20C8BBEC732046C7/image-dimensions/777x338?v=v2" width="777" height="338" role="button" title="Arun_21_1-1709888407476.png" alt="Arun_21_1-1709888407476.png" /></span><BR />Specify the qualifier of the selection Presentation Variant set in step 2 in Qualifier.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_2-1709888407486.png" style="width: 773px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77505i2F94500CE989A759/image-dimensions/773x582?v=v2" width="773" height="582" role="button" title="Arun_21_2-1709888407486.png" alt="Arun_21_2-1709888407486.png" /></span></P><P>Next we have to provide the Project Attributes</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_3-1709888407493.png" style="width: 775px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77507iAC60E89D86746340/image-dimensions/775x428?v=v2" width="775" height="428" role="button" title="Arun_21_3-1709888407493.png" alt="Arun_21_3-1709888407493.png" /></span></P><P>On the Project2 we have to choose Preview Application here we have to Click on the Start Fiori Run First option in Dropdown.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_4-1709888407499.png" style="width: 776px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77508iE6D666876BBB7E63/image-dimensions/776x324?v=v2" width="776" height="324" role="button" title="Arun_21_4-1709888407499.png" alt="Arun_21_4-1709888407499.png" /></span></P><P>At this point, the pages section of manifest.json looks like this:-</P><P>manifest.json</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "pages": {</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "AnalyticalListPage|ZC_MYEXPENSES": {</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "entitySet": "ZC_MYEXPENSES",</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "component": {</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "name": "sap.suite.ui.generic.template.AnalyticalListPage",</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "list": true,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "settings": {</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "condensedTableLayout": true,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;"showGoButtonOnFilterBar": true,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "tableType": "ResponsiveTable",</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "multiSelect": false,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "qualifier": "Default",</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "autoHide": true,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "smartVariantManagement": true,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "keyPerformanceIndicators": {}</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "pages": {</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "ObjectPage|ZC_MYEXPENSES": {</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "entitySet": "ZC_MYEXPENSES",</P><P>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"component": {</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "name": "sap.suite.ui.generic.template.ObjectPage"</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</P><P><STRONG>Execution result</STRONG></P><P>Nothing is displayed when it starts up.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_5-1709888407507.png" style="width: 778px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77509iBB5BF1B5E5955B9D/image-dimensions/778x391?v=v2" width="778" height="391" role="button" title="Arun_21_5-1709888407507.png" alt="Arun_21_5-1709888407507.png" /></span></P><P><BR />When you press Go, the chart and table are displayed.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_6-1709888407514.png" style="width: 782px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77511i275260A264CBDF74/image-dimensions/782x400?v=v2" width="782" height="400" role="button" title="Arun_21_6-1709888407514.png" alt="Arun_21_6-1709888407514.png" /></span></P><P>&nbsp;When you press the Compact Filter button on the top right, the filter items defined in selection Field will be displayed.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Arun_21_7-1709888407517.png" style="width: 784px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77510iF498E184613C16EC/image-dimensions/784x96?v=v2" width="784" height="96" role="button" title="Arun_21_7-1709888407517.png" alt="Arun_21_7-1709888407517.png" /></span></P><P>Arrange graphs in year/month order</P><P>Add sort Order to presentation Variant. Arrange them in ascending order by Year Month and descending order by Posting Date. The reason why I include Posting Date is because this sort order also affects how the table looks, so I want the latest records to be at the First.</P><P>@UI.presentationVariant: [{</P><P>&nbsp;&nbsp;&nbsp; qualifier: 'Default',</P><P>&nbsp;&nbsp;&nbsp; sortOrder: [{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by: 'PostingDate',</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; direction: #DESC</P><P>&nbsp;&nbsp;&nbsp;&nbsp; },{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by: 'YearMonth',</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; direction: #ASC</P><P>&nbsp;&nbsp;&nbsp;&nbsp; }],&nbsp;&nbsp;&nbsp;</P><P>&nbsp;&nbsp;&nbsp; visualizations: [{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: #AS_CHART,</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qualifier: 'ChartDefault'</P><P>&nbsp;&nbsp;&nbsp; }]</P><P>&nbsp;}]</P><P>Also add YearMonth to line Item. This is because an error will occur if the item specified in sort Order is not included in line Item.</P><P>&nbsp;&nbsp;&nbsp; @UI:{</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selectionField: [{position: 30 }],</P><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lineItem: [ { position: 40 } ]</P><P>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;</P><P>&nbsp;&nbsp;&nbsp; YearMonth;&nbsp;&nbsp;&nbsp;</P><P><STRONG>Conclusion.</STRONG></P><P>My impressions after creating ALP for the first time were that it was relatively easy to do in general, but I had a hard time with the small details (default filter, criticality settings, etc.). This time, I envisioned what I wanted to create and researched how to make it happen, so it was good that I realized what ALP can do and its limitations.</P><P><STRONG>Reference</STRONG></P><P><STRONG>blog</STRONG></P><UL><LI><A href="https://blogs.sap.com/2018/04/04/create-an-analytical-list-page-using-abap-cds-views-and-annotations/" target="_blank" rel="noopener noreferrer">Create an Analytical List Page using ABAP CDS views and annotations</A></LI><LI><A href="https://blogs.sap.com/2018/03/18/create-an-analytical-model-based-on-abap-cds-views/" target="_blank" rel="noopener noreferrer">Create an analytical model based on ABAP CDS views</A></LI><LI><A href="https://blogs.sap.com/2019/08/13/configuring-filters-area-of-an-analytical-list-page-alp-application/" target="_blank" rel="noopener noreferrer">Configuring filters area of an Analytical List Page (ALP) application</A></LI></UL><P>Document</P><UL><LI><A href="https://sapui5.hana.ondemand.com/#/topic/3d33684b08ca4490b26a844b6ce19b83" target="_blank" rel="noopener nofollow noreferrer">Analytical List Page</A></LI><LI><A href="https://help.sap.com/viewer/468a97775123488ab3345a0c48cadd8f/7.51.6/en-US/68e62adedfd44cd48cb6ebc418c8d95a.html" target="_blank" rel="noopener noreferrer">Chart Cards Used in Overview Pages</A></LI></UL><P><STRONG>Appendix</STRONG></P><P>Metadata Extension:-</P><P>&nbsp;</P><pre class="lia-code-sample language-abap"><code>@Metadata.layer: #CORE @UI.presentationVariant: [{ qualifier: 'Default', sortOrder: [{ by: 'PostingDate', direction: #DESC },{ by: 'YearMonth', direction: #ASC }], visualizations: [{ type: #AS_CHART, qualifier: 'ChartDefault' }] }] @UI.chart: [{ qualifier: 'ChartDefault', chartType: #COLUMN_STACKED, dimensions: ['Cateogry', 'YearMonth'], measures: ['Amount'], dimensionAttributes: [{ dimension: 'Cateogry', role: #SERIES },{ dimension: 'YearMonth', role: #CATEGORY }], measureAttributes: [{ measure: 'Amount', role: #AXIS_1 }] }] annotate view ZC_MY_Expenses with { @UI:{ lineItem: [{ position: 10 }] } PostingDate; @UI:{ selectionField: [{position: 10 }], lineItem: [{ position: 20 }] } Cateogry; @UI:{ lineItem: [{ position: 30 }], dataPoint: { criticalityCalculation: { improvementDirection: #MINIMIZE, toleranceRangeHighValue: 100000, deviationRangeHighValue: 150000 } } } Amount; @UI:{ selectionField: [{position: 20 }] } CalendarYear; @UI:{ selectionField: [{position: 30 }], lineItem: [ { position: 40 } ] } YearMonth; }</code></pre><P>&nbsp;</P><P>&nbsp;</P> 2024-03-15T11:53:44.741000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-8-use-graph-with-odata-v4/ba-p/13641190 Graph intro series, part 8: Use Graph With OData v4 2024-03-19T14:21:24.058000+01:00 florian_moritz https://community.sap.com/t5/user/viewprofilepage/user-id/748729 <P><EM>What you will learn: use OData v4 to fetch data and explore the structure of the connected data model exposed by Graph.</EM></P><P>Hello!</P><P>In this part of the tutorial on Graph we will focus on the OData protocol that Graph exposes and how to explore the structure of the data model of a business data graph. OData is one of the two data protocols supported by Graph - next to <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-9-use-graph-with-graphql/ba-p/13623717" target="_self">GraphQL</A>.</P><P><SPAN>For an overview of other parts of this series, check out the</SPAN><SPAN>&nbsp;</SPAN><A href="https://community.sap.com/t5/technology-blogs-by-sap/information-map-end-to-end-tutorial-graph-in-sap-integration-suite/ba-p/13614448" target="_blank">Information Map.</A><SPAN> </SPAN></P><P>Graph is built on open standards and technologies. Clients can communicate with Graph using the<SPAN>&nbsp;</SPAN><A href="http://docs.oasis-open.org/odata/odata/v4.01/os/part1-protocol/odata-v4.01-os-part1-protocol.html" target="_blank" rel="nofollow noopener noreferrer">Open Data v4 Protocol</A><SPAN>&nbsp;</SPAN>(OData). This is a<SPAN>&nbsp;</SPAN><A href="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=odata" target="_blank" rel="nofollow noopener noreferrer">standardized RESTful HTTP protocol</A><SPAN>&nbsp;</SPAN>with defined semantics that help promote interoperability between services.</P><P>OData is centered around resources (data entities), which are identified by URLs. In Graph, there are for example the Customer, Product, or SalesQuote entities. The structure of these entities is defined in an Entity Data Model (EDM) which can be inspected by clients. OData provides many operations to filter or search in entity collections, to navigate between associated entities and to adapt the response shape.</P><P>We will now look at examples on how to formulate OData requests for Graph.</P><H2 id="toc-hId-989722487">&nbsp;</H2><H2 id="toc-hId-793208982">Tutorial Setup</H2><P>To keep things simple, we will be using the Graph sandbox business data graph (BDG). All you need to use it is your favorite HTTP tool, for example Postman, and your API key from<SPAN>&nbsp;</SPAN><A href="https://api.sap.com/" target="_blank" rel="noopener noreferrer">SAP Business Accelerator Hub</A>. To retrieve your API key, log into SAP Business Accelerator Hub, go to<SPAN>&nbsp;</SPAN><A href="https://api.sap.com/settings" target="_blank" rel="noopener noreferrer">settings</A><SPAN>&nbsp;</SPAN>and copy your API key from the Show API Key button.</P><P>To make requests against the Graph sandbox BDG, add your API key as an HTTP header in your requests:<BR /><FONT face="terminal,monaco" color="#800000">apiKey: &lt;your API key&gt;</FONT></P><P>Then you can use the Graph sandbox BDG through the following endpoint:</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>https://sandbox.api.sap.com/sapgraph/</code></pre><P>&nbsp;</P><DIV class=""><BLOCKQUOTE><P>Note: The API key is just used for the purposes of this sandbox endpoint and not relevant in the context of OData requests or productive Graph instances.</P></BLOCKQUOTE><H2 id="toc-hId-596695477">Exploring the OData data model</H2><P>OData defines an Entity Data Model that describes the structure of all known entities. This helps developers and clients alike to reason about the available entities and their structure. The data model and further metadata can be inspected through a special<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$metadata</FONT><SPAN>&nbsp;</SPAN>resource. Graph makes metadata available for each namespace, such as<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">sap.graph</FONT><SPAN>&nbsp;</SPAN>for the unified Graph data model.</P><P>To retrieve the metadata of the unified data model in Graph, make the following request, which will return an EDMX specification (an XML dialect for describing OData Entity Data Models).</P></DIV><P>&nbsp;</P><pre class="lia-code-sample language-yaml"><code>https://sandbox.api.sap.com/sapgraph/sap.graph/$metadata</code></pre><P>&nbsp;</P><P><SPAN>In the response, we can inspect the structure of all the entities (and sub-entities) that are described as EntityType entries as well as other metadata. Let's have a closer look at the definition of the SalesQuote entity type in this extract from the sales domain metadata:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>&lt;EntityType Name="SalesQuote"&gt; &lt;Key&gt; &lt;PropertyRef Name="id"/&gt; &lt;/Key&gt; &lt;Property Name="id" Type="Edm.String" MaxLength="82" Nullable="false"/&gt; &lt;Property Name="displayId" Type="Edm.String"/&gt; &lt;Property Name="netAmount" Type="Edm.Decimal" Scale="6" Precision="22"/&gt; &lt;Property Name="pricingDate" Type="Edm.DateTimeOffset"/&gt; &lt;Property Name="netAmountCurrency" Type="Edm.String" MaxLength="5"/&gt; &lt;NavigationProperty Name="_netAmountCurrency" Type="sap.graph.Currency"/&gt; &lt;NavigationProperty Name="items" Type="Collection(sap.graph.SalesQuote_items)" Partner="up_" ContainsTarget="true"/&gt; &lt;Property Name="soldToParty" Type="Edm.String" MaxLength="10"/&gt; &lt;NavigationProperty Name="_soldToParty" Type="sap.graph.Customer"/&gt; &lt;NavigationProperty Name="_cxsales" Type="sap.cxsales.SalesQuoteCollection"/&gt; ... &lt;/EntityType&gt;</code></pre><P>&nbsp;</P><P>We can see that a SalesQuote has several properties of different types, such as String or Decimal, but also more complex structured types like the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">items</FONT><SPAN>&nbsp;</SPAN>property, which is a collection of several<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">sap.graph.SalesQuote_items</FONT>, that are also defined in the same data model. Furthermore, we see that the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">id</FONT><SPAN>&nbsp;</SPAN>property is referenced as key for this entity type. Navigation Properties allow for navigation to a related entity. The<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">items</FONT><SPAN>&nbsp;</SPAN>property is a navigation property because the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">sap.graph.SalesQuote_items</FONT><SPAN>&nbsp;</SPAN>is modeled as a separate entity type in the metadata.</P><P>Let's look at an example. Add the following query path to the sandbox endpoint to make the request. This will retrieve one SalesQuote entity (here we add<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top=1</FONT><SPAN>&nbsp;</SPAN>to limit the result set to one entity):</P><P>&nbsp;</P><pre class="lia-code-sample language-yaml"><code>/sap.graph/SalesQuote?$top=1</code></pre><P>&nbsp;</P><P>From inspecting the metadata, we have learned that SalesQuotes have items, however when comparing with the response from the example, no items are included in the response.</P><P>The reason for this is that OData has a mechanism for the client to control which navigation properties are included as part of the response. This is called expanding a property. By default, Graph returns responses non-expanded if not specified by the client. In addition to expanding the response, OData also allows for restricting it to requested values only. We will have a look at these mechanisms next.</P><DIV class=""><H2 id="toc-hId-400181972">Expanding and restricting the response</H2><P>OData allows clients to adapt the response format in two ways. Clients can restrict the response to a set of specified properties via<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT>. And they can expand the response by including referenced entities inline as part of the response via<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$expand</FONT>.</P><P>If we only require the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount</FONT><SPAN>&nbsp;</SPAN>of a SalesQuote, we can restrict the response by adding it to the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT><SPAN>&nbsp;</SPAN>query parameter:</P></DIV><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount</code></pre><P>&nbsp;</P><P>This will return only the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount</FONT><SPAN>&nbsp;</SPAN>property along with the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">id</FONT>, as it is the key attribute and therefore always included.</P><P>If we also require the items of a SalesQuote, we need to expand the response (as it is a navigation property) by adding it to the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$expand</FONT><SPAN>&nbsp;</SPAN>query parameter:</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount&amp;$expand=items</code></pre><P>&nbsp;</P><P>This will result in the items array being returned as part of the SalesQuote response as illustrated here:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="expand-items-1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83064i8DCDA62DE7F4CBC2/image-size/large?v=v2&amp;px=999" role="button" title="expand-items-1.png" alt="expand-items-1.png" /></span></P><P>If we have a look at a response snippet, this is what is being returned:</P><DIV class="">&nbsp;</DIV><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "@odata.context": "$metadata#SalesQuote(netAmount,id,items())", "value": [ { "id": "cxsales~1", "netAmount": 890, "items": [ { "itemId": "10", "parentItemId": "", "alternativeToItemId": "", "itemCategory": "AGN", "itemText": "Green Emission Calculator", "product": "P300100", "soldToPartyProductId": "", "quantity": 1, "quantityUnit": "EA", "grossWeight": 0, "grossWeightUnit": "", "netWeight": 0, "netWeightUnit": "", "volume": 0, "volumeUnit": "", "plant": "", "netAmount": 890, "netAmountCurrency": "USD", "pricingProduct": "", "incotermsClassification": "", "incotermsLocation": "", "processingStatus": "1", "cancellationReason": "" } ] } ] }</code></pre><P>&nbsp;</P><P>Note that we do not have to specify expanded properties explicitly as part of<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT>.</P><P>We see that the item in the example above has a property product that references an id. When we inspect the metadata of the items by searching for the EntityType<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">SalesQuote_items</FONT>. We see that the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">product</FONT><SPAN>&nbsp;</SPAN>property represents the referenced product with a string value and the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>navigation property references the connected <FONT face="terminal,monaco" color="#800000">sap.graph.Product</FONT> entity.</P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>&lt;EntityType Name="SalesQuote_items"&gt; &lt;Key&gt; &lt;PropertyRef Name="itemId"/&gt; &lt;/Key&gt; &lt;Property Name="itemId" Type="Edm.String" MaxLength="10" Nullable="false"/&gt; &lt;Property Name="itemText" Type="Edm.String"/&gt; &lt;Property Name="product" Type="Edm.String"/&gt; &lt;NavigationProperty Name="_product" Type="sap.graph.Product"/&gt; ... &lt;/EntityType&gt;</code></pre><P>&nbsp;</P><P>To also include this<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>as part of the response, we can expand it inside the already expanded <FONT face="terminal,monaco" color="#800000">items</FONT>: a nested expand.</P><DIV class="">&nbsp;</DIV><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount&amp;$expand=items($expand=_product)</code></pre><P>&nbsp;</P><P>Which will include the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>response inline in the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">item</FONT><SPAN>&nbsp;</SPAN>of the SalesQuote response.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="nested-expand-1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83066i62D6195D5E9449B9/image-size/large?v=v2&amp;px=999" role="button" title="nested-expand-1.png" alt="nested-expand-1.png" /></span></P><P><SPAN>If we also want to adapt the format of the expanded product we can nest a&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT><SPAN>&nbsp;query parameter in parentheses after the product. To restrict the nested product to the <FONT face="terminal,monaco" color="#800000">displayId</FONT>, for example:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount&amp;$expand=items($expand=_product($select=displayId))</code></pre><P>&nbsp;</P><P><SPAN>If we also want to select more properties, such as&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmountCurrency</FONT><SPAN>, we can just add them to the&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT><SPAN>&nbsp;query parameter targeting the SalesQuote, separated by commas:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount,netAmountCurrency&amp;$expand=items($expand=_product($select=displayId))</code></pre><P>&nbsp;</P><P>The response for the SalesQuote with included<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmountCurrency</FONT>,<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">items</FONT><SPAN>&nbsp;</SPAN>and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>now looks like this:</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "@odata.context": "$metadata#SalesQuote(netAmount,netAmountCurrency,id,items(_product(displayId,id)))", "value": [ { "id": "cxsales~1", "netAmount": 890, "netAmountCurrency": "USD", "items": [ { "itemId": "10", "parentItemId": "", "alternativeToItemId": "", "itemCategory": "AGN", "itemText": "Green Emission Calculator", "product": "P300100", "_product": { "id": "cxsales~P300100", "displayId": null }, "soldToPartyProductId": "", "quantity": 1, "quantityUnit": "EA", "grossWeight": 0, "grossWeightUnit": "", "netWeight": 0, "netWeightUnit": "", "volume": 0, "volumeUnit": "", "plant": "", "netAmount": 890, "netAmountCurrency": "USD", "pricingProduct": "", "incotermsClassification": "", "incotermsLocation": "", "processingStatus": "1", "cancellationReason": "" } ] } ] }</code></pre><P>&nbsp;</P><H2 id="toc-hId-203668467">Working with collections: filtering, ordering and pagination</H2><P>When working with collections of entities, we typically want to filter the entities by some criteria or arrange them in a specific order. In OData this is supported via the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$filter</FONT><SPAN>&nbsp;</SPAN>and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$orderby</FONT><SPAN>&nbsp;</SPAN>query parameters. With<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top</FONT><SPAN>&nbsp;</SPAN>and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$skip</FONT><SPAN>&nbsp;</SPAN>we can additionally define a sliding window over the result to implement pagination.</P><P>To continue with our example above, let's remove the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top=1</FONT><SPAN>&nbsp;</SPAN>we added initially to now retrieve a collection of SalesQuotes. Say we want to retrieve all SalesQuotes with a value greater than 100 U.S. Dollars.</P><P>The value condition can be formulated with the greater equal operator:<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount ge 100</FONT>. For the currency condition we need to compare it with a string (enclosed in single quotes) for equality:<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmountCurrency eq 'USD'</FONT>. We then combine these conditions with a logical and expression and add it to the example query below. We also define an ordering on the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount</FONT><SPAN>&nbsp;</SPAN>property with the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$orderby</FONT><SPAN>&nbsp;</SPAN>query parameter, which is ascending by default.</P><BLOCKQUOTE><P>Note: OData operators are lower-case and space-separated. This requires URL encoding. If you are using Postman for this tutorial you don't need to worry as Postman automatically applies URL encoding.&nbsp;</P></BLOCKQUOTE><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$select=netAmount,netAmountCurrency&amp;$expand=items($expand=_product($select=displayId))&amp;$filter=netAmount ge 100 and netAmountCurrency eq 'USD'&amp;$orderby=netAmount</code></pre><P>&nbsp;</P><BLOCKQUOTE><P>Note: OData only supports writing filter expressions using a small vocabulary of filter operators. See here for a full list.</P></BLOCKQUOTE><P>As a last step, we will now define a paging-window over all results. This can be achieved with the query parameters<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top</FONT>, which specifies how many result entities should be returned: the page size, and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$skip</FONT>, which defines how many result entities should be skipped from the beginning of the ordering. Hence, we describe the page size with<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top</FONT><SPAN>&nbsp;</SPAN>and index the single pages with multiples of the page size in<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$skip</FONT>. For the second page of five entities each, this would translate to our example as follows:</P><DIV class="">&nbsp;</DIV><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$select=netAmount,netAmountCurrency&amp;$expand=items($expand=_product($select=displayId))&amp;$filter=netAmount ge 100 and netAmountCurrency eq 'USD'&amp;$orderby=netAmount&amp;$top=5&amp;$skip=5</code></pre><P>&nbsp;</P><H2 id="toc-hId-7154962">Summary</H2><P>In this tutorial we had a look at OData, one of the two data protocols used by Graph. We covered all the features that you as a developer working with Graph need to know, like how to:</P><UL><LI>formulate complex queries</LI><LI>inspect the metadata and structure of the unified data model</LI><LI>expand and restrict responses</LI><LI>work with collections</LI></UL><P>OData itself offers much more than what we showed in this tutorial. You can read more about it in the<SPAN>&nbsp;</SPAN><A href="https://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html" target="_blank" rel="nofollow noopener noreferrer">standard</A>.</P><P>With Graph, you as a developer now have one data protocol you can use together with one API to retrieve data in one unified format, no matter the source system.</P><P>---<BR />Florian Moritz</P><P>&nbsp;</P> 2024-03-19T14:21:24.058000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/how-to-enable-an-odata-v4-service-for-anonymous-access/ba-p/13643572 How to enable an OData V4 service for anonymous access? 2024-03-19T21:57:57.546000+01:00 Andre_Fischer https://community.sap.com/t5/user/viewprofilepage/user-id/55 <H1 id="toc-hId-860703134">Introduction</H1><P>This requirement stems from a customer that asked how to publish an OData V4 service in an SAP S/4HANA on premise system such that it could be used on a public web site without the need to provide any authentication.</P><P>With OData V2 this requirement can be achieved more easily since here every service has it's own SICF node where it would be possible to store credentials just for this service.</P><P>In OData V4 we have only one SICF node, namely&nbsp;<STRONG>/sap/opu/odata4/.</STRONG></P><P>This is obviously a problem since there is no service specific node available in SICF.</P><H1 id="toc-hId-664189629">Solution</H1><P>The problem can be solved using the following approach.</P><OL><LI>Create a role that only contains the <STRONG>S_START</STRONG> authorization for the one single OData V4 service we want to publish ,&nbsp;<BR /><A href="https://help.sap.com/doc/saphelp_nw75/7.5.5/de-DE/c6/dd838722ce4b8d9cc4a0741d93d864/frameset.htm" target="_blank" rel="noopener noreferrer">help.sap.com/doc/saphelp_nw75/7.5.5/de-DE/c6/dd838722ce4b8d9cc4a0741d93d864/frameset.htm</A></LI><LI>Create a technical user that has only the authorization to access the single OData V4 service we want to make accessible.</LI><LI>Create an alias in SICF for the node&nbsp;<STRONG>/sap/opu/odata4/&nbsp;</STRONG></LI><LI>Store the credentials of the aforementioned user in the alias</LI><LI>Test the service&nbsp;&nbsp;</LI></OL><H1 id="toc-hId-467676124">Result</H1><P>As we can see accessing the service&nbsp;<STRONG>zrap630ui_shop_o4_05a</STRONG> via the alias <STRONG>zodatav4_2&nbsp;</STRONG>works.</P><P><A href="https://10.79.21.221:44301/sap/opu/zodatav4/sap/zrap630ui_shop_o4_05a/srvd/sap/zrap630ui_shop_o4_05a/0001/?sap-client=100" target="_blank" rel="noopener nofollow noreferrer">https://10.79.21.221:44301/sap/opu/zodatav4/sap/zrap630ui_shop_o4_05a/srvd/sap/zrap630ui_shop_o4_05a/0001/?sap-client=100</A></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="100_test_service_1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83418i76C5523CCA831AAC/image-size/large?v=v2&amp;px=999" role="button" title="100_test_service_1.png" alt="100_test_service_1.png" /></span></P><P>Whereas accessing a second OData V4 service&nbsp;<STRONG>zrap630ui_shop_o4_05b</STRONG> via the alias <STRONG>zodatav4_2&nbsp;</STRONG>does <STRONG>NOT work</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="110_test_service_1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83419i3EE98F3B6179053B/image-size/large?v=v2&amp;px=999" role="button" title="110_test_service_1.png" alt="110_test_service_1.png" /></span></P><P>This has been achieved by assigne the follwoing role the technical user which only contains the authorization to start the first service based on the authorization object <STRONG>S_START</STRONG>.</P><P style=" padding-left : 30px; "><STRONG>Please note:</STRONG><BR />Since OData V4 service use the authorization object S_START which is based on the service name it would for example be possible to publish several services that are in the same name range like</P><P style=" padding-left : 30px; ">zrap630ui_shop_o4_<STRONG>05A</STRONG>,&nbsp;zrap630ui_shop_o4_<STRONG>05B</STRONG>, ...&nbsp;zrap630ui_shop_o4_<STRONG>05Z</STRONG>,&nbsp;&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="120_role_2.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83420i0B3411C8E6E88B6F/image-size/large?v=v2&amp;px=999" role="button" title="120_role_2.png" alt="120_role_2.png" /></span></P><H1 id="toc-hId-271162619"><STRONG>How to section</STRONG></H1><H3 id="toc-hId-332814552"><STRONG>Create the role</STRONG></H3><P>Using PFCG and the role template <SPAN class="">/IWBEP/RT_MGW_USR we create a role as shown in the screen shot above that only contains the S_START authorization of one OData V4 service called&nbsp;ZRAP630UI_SHOP_O4_05A.<BR /></SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="120_role_1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83433iF66B19D135CCA30E/image-size/large?v=v2&amp;px=999" role="button" title="120_role_1.png" alt="120_role_1.png" /></span></P><H3 id="toc-hId-136301047"><STRONG>Create</STRONG> the<STRONG> user</STRONG></H3><P>As a user we create a technical user whose credentials will be stored in the system alias.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="130_technical_user.png" style="width: 876px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83436iC507E93B64E11FAF/image-size/large?v=v2&amp;px=999" role="button" title="130_technical_user.png" alt="130_technical_user.png" /></span></P><H3 id="toc-hId--60212458"><STRONG>Create the system alias</STRONG></H3><P>1. We start by right-clicking on the node <STRONG>opu</STRONG> and choose <STRONG>New subelement</STRONG>.</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="010_Create_Alias.png" style="width: 643px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83424i3B2863743E4C897D/image-size/large?v=v2&amp;px=999" role="button" title="010_Create_Alias.png" alt="010_Create_Alias.png" /></span></STRONG></P><P>2. We create a new service element called <STRONG>ZODATAV4_2&nbsp;</STRONG>and choose the option <STRONG>Alias to an existing service</STRONG>.</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="020_create_alias.png" style="width: 877px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83423i28731E07AD83EAC7/image-size/large?v=v2&amp;px=999" role="button" title="020_create_alias.png" alt="020_create_alias.png" /></span></STRONG></P><P>3. We choose the tab <STRONG>Target</STRONG>, select the node <STRONG>OdataV4</STRONG> by double-clicking on it.</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="030_create_alias.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83426i2C2315451CB01CBA/image-size/large?v=v2&amp;px=999" role="button" title="030_create_alias.png" alt="030_create_alias.png" /></span></STRONG></P><P>4. We navigate to the tab <STRONG>Logon Data</STRONG>, choose <STRONG>Alternative Logon Procedure</STRONG> and enter the credentials of our service user.</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="050_create_alias.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83427iF7847BF82D023A46/image-size/large?v=v2&amp;px=999" role="button" title="050_create_alias.png" alt="050_create_alias.png" /></span></STRONG></P><P>5. We navigate down and remove all logon procedures beside <STRONG>Logon using service data</STRONG>.</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="060_create_alias.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83428i4185C25916590275/image-size/large?v=v2&amp;px=999" role="button" title="060_create_alias.png" alt="060_create_alias.png" /></span></STRONG></P><P>6. Do not forget to activate the link in SICF.</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="070_create_alias.png" style="width: 484px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83429i1BBD6FF69034F2EA/image-size/large?v=v2&amp;px=999" role="button" title="070_create_alias.png" alt="070_create_alias.png" /></span><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="080_create_alias.png" style="width: 747px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83430i0F969188176ECB1E/image-size/large?v=v2&amp;px=999" role="button" title="080_create_alias.png" alt="080_create_alias.png" /></span></STRONG></P><P>7. Check the result</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="090_create_alias.png" style="width: 909px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83431i5366E830240FD49A/image-size/large?v=v2&amp;px=999" role="button" title="090_create_alias.png" alt="090_create_alias.png" /></span></STRONG></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P> 2024-03-19T21:57:57.546000+01:00 https://community.sap.com/t5/human-capital-management-blogs-by-members/escaping-special-character-in-sf-odata-api/ba-p/13644726 Escaping special character in SF OData API 2024-03-21T14:56:42.267000+01:00 akash8960 https://community.sap.com/t5/user/viewprofilepage/user-id/12740 <P>While querying the data from SF OData API of the base entity FOCostCenter i did receive the following error -&nbsp;</P><PRE>&lt;?xml version="1.0" encoding="utf-8" standalone="yes"?&gt;<BR />&lt;error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"&gt;<BR />&lt;code&gt;BadRequestException&lt;/code&gt;<BR />&lt;message lang="en-US"&gt;Invalid quote usage detected, quotes need to be in pairs.&lt;/message&gt;<BR />&lt;/error&gt;</PRE><P>This did lead me to a spiral of what went wrong, after a bit of head scratching i did figure out my SF OData API query was :&nbsp;</P><PRE><BR />/FOCostCenter?$select=externalCode,name&amp;$filter=externalCode eq 'A &amp; B'&nbsp;</PRE><P>&nbsp;Well, the issue here is with having "&amp;" between A and B. OData API parser by default expect to have a <STRONG>'&nbsp;</STRONG>after A and before B. In order to handle this we need to escape &amp; symbol. As usual i escaped it by replacing &amp; with&nbsp;&amp;amp; but then it did not work.&nbsp;</P><P>Understanding the protocol of OData API i was led to beleive escaping needs to supported by ASCII format which is <STRONG>%26&nbsp;</STRONG>which helped us to solve the problem.&nbsp;</P><P>Updated query condition which solved the problem is here.&nbsp;</P><PRE>/FOCostCenter?$select=externalCode,name&amp;$filter=externalCode eq 'A %26 B'&nbsp;</PRE><P>&nbsp;</P><P>End of the long story - if you need to escape special characters within filter condition of OData then please use ASCII encoding.&nbsp;</P> 2024-03-21T14:56:42.267000+01:00 https://community.sap.com/t5/technology-blogs-by-members/consuming-odata-url-in-cpi-with-get-method/ba-p/13642867 Consuming OData URL in CPI with GET Method 2024-03-21T15:17:20.893000+01:00 sangeeta_06 https://community.sap.com/t5/user/viewprofilepage/user-id/166499 <P><FONT size="2">In this blog article, we will walk you through the process of consuming an OData service in the SAP Integration Suite, with a focus on configuring the OData adapter.</FONT></P><P><FONT size="2">Before you start the integration process, ensure you have the following prerequisites in place:</FONT></P><UL><LI><FONT size="2"><STRONG>SAP Integration Suite</STRONG>: Access to the SAP Integration Suite is necessary.</FONT></LI><LI><FONT size="2"><STRONG>OData service URL</STRONG>: Know the URL of the OData service you intend to consume.</FONT></LI></UL><P><FONT size="2">&nbsp;Firstly, we need to understand what OData is:</FONT><BR /><FONT size="2"><STRONG>OData</STRONG>: The OData adapter allows you to communicate with an&nbsp;<SPAN>OData API</SPAN>&nbsp;using OData protocol. You can use messages in ATOM or JSON format for communication.</FONT></P><OL><LI><FONT size="2">Click on "Create" to initiate a new Integration Flow.</FONT></LI><LI><FONT size="2">Define the integration flow details, such as name and description.</FONT></LI></OL><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_28-1710848023562.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/82985i06222E0E638026C7/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_28-1710848023562.png" alt="sangeeta_06_28-1710848023562.png" /></span></FONT></P><P><FONT size="2">Open &amp; click on edit&nbsp;</FONT></P><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_29-1710848023572.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/82986iE4C96156895AB88D/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_29-1710848023572.png" alt="sangeeta_06_29-1710848023572.png" /></span></FONT></P><P>&nbsp;</P><P><FONT size="2">As Start event should have an incoming message use Timer event instead of Start Event</FONT></P><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_30-1710848023579.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/82987i0C703E1AC618ED3F/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_30-1710848023579.png" alt="sangeeta_06_30-1710848023579.png" /></span></FONT></P><P>&nbsp;</P><P><FONT size="2">Now add a Request reply to consume the OData service.</FONT></P><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_31-1710848023586.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/82988i0B90252FEDF8CDA3/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_31-1710848023586.png" alt="sangeeta_06_31-1710848023586.png" /></span></FONT></P><P><FONT size="2">Now connect your request reply with the Receiver by using the OData V2 as message protocol.</FONT></P><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_32-1710848023593.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/82989iF89644B47D065259/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_32-1710848023593.png" alt="sangeeta_06_32-1710848023593.png" /></span></FONT></P><P><FONT size="2">Now, configure the OData adapter with the necessary details:</FONT></P><P><FONT size="2"><STRONG>1. Endpoint</STRONG>: Enter the URL of the OData service you want to consume.</FONT></P><P><FONT size="2">The Service URL for an OData service typically includes the following components:</FONT></P><P><FONT size="2"><STRONG>ODATA URL: </STRONG><A href="https://host:port/sap/opu/odata/sap/ZMM_INVOIC_PEARL_INBOUND_SRV/InvoicerejheadSet?$expand=ASSREJITEM&amp;$format=json" target="_blank" rel="noopener nofollow noreferrer">https://host:port/sap/opu/odata/sap/ZMM_INVOIC_PEARL_INBOUND_SRV/InvoicerejheadSet?$expand=ASSREJITEM&amp;$format=json</A></FONT></P><UL><LI><FONT size="2"><STRONG>Protocol: https://</STRONG> This indicates that the communication will be secured using HTTP Secure (HTTPS), which encrypts the data transferred between the client (your browser or application) and the server.</FONT></LI><LI><FONT size="2"><STRONG>Host:</STRONG> This is the IP address of the server hosting the OData service.</FONT></LI><LI><FONT size="2"><STRONG>Port:</STRONG> &nbsp;The port number on which the OData service is listening. The default ports are 80 for HTTP and 443 for HTTPS.</FONT></LI><LI><FONT size="2"><STRONG>PATH: </STRONG><A href="https://10.145.2.12:44380/sap/opu/odata/sap/ZMM_INVOIC_PEARL_INBOUND_SRV/InvoicerejheadSet?$expand=ASSREJITEM&amp;$format=json" target="_blank" rel="noopener nofollow noreferrer"><STRONG>/sap/opu/odata/sap/ZMM_INVOIC_PEARL_INBOUND_SRV</STRONG></A><STRONG>: </STRONG>This is the base path for the OData service. It identifies the service and specifies the namespace for the entities exposed by the service. <STRONG>ZMM_INVOIC_PEARL_INBOUND_SRV</STRONG> is likely the name of the OData service, and <STRONG>/sap/opu/odata/sap/</STRONG> is a common prefix for SAP OData services.</FONT></LI><LI><FONT size="2"><STRONG>Entity set: InvoicerejheadSet: </STRONG>This is the entity set being accessed. In OData, an entity set is a collection of entities of the same type. Here, <STRONG>InvoicerejheadSet</STRONG> seems to represent a collection of invoice rejection headers.</FONT></LI><LI><FONT size="2"><STRONG>Sublevel: $expand: </STRONG>a "sublevel" typically refers to the depth of nested entities or related data that can be expanded in an OData query. When you perform an OData query with the <STRONG>$expand</STRONG> option, you can specify which related entities you want to include in the response. Each entity that you expand represents a level of depth in the data hierarchy.</FONT></LI></UL><P><STRONG><FONT size="2">2.&nbsp;</FONT><FONT size="2">Select the proxy type:&nbsp;</FONT></STRONG></P><UL><LI><FONT size="2"><STRONG>Internet</STRONG>: Internet proxy type is suitable when your OData service is externally hosted or available on the Internet. It allows the adapter to communicate with the service over the public network.</FONT></LI><LI><STRONG>On-Premise</STRONG><SPAN>: The on-Premise proxy type is suitable for scenarios where the OData service is hosted within your organization's network. It allows the adapter to establish a connection within the internal network, ensuring secure and controlled access.</SPAN></LI></UL><P style=" text-align : left; "><FONT size="2"><STRONG>3. Authentication</STRONG>: Specify the authentication method (e.g., Basic Authentication, OAuth) and provide the required credentials.</FONT></P><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_33-1710848023606.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/82990i7887F2696327316A/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_33-1710848023606.png" alt="sangeeta_06_33-1710848023606.png" /></span></FONT></P><P><FONT size="2">In the processing tab configure as shown below</FONT></P><UL><LI><FONT size="2"><STRONG>Operation Details</STRONG>: Define the specific OData operations (GET, POST, PUT, DELETE) required for your integration scenario.</FONT></LI><LI><FONT size="2"><STRONG>Resource</STRONG> <STRONG>Path</STRONG>:&nbsp; Set the Resource Path based on the Entity Set and navigation properties relevant to your scenario.</FONT></LI></UL><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_34-1710848023615.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/82991i888ED16DCC17C036/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_34-1710848023615.png" alt="sangeeta_06_34-1710848023615.png" /></span></FONT></P><P><FONT size="2">After selecting it will take you to another screen as below. So, don’t change anything in Step 1 keep it as it is.</FONT></P><P><FONT size="2"><STRONG>STEP 1: </STRONG><STRONG>Connect to System</STRONG></FONT></P><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_42-1710848599508.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83014i406CABC5C03ED746/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_42-1710848599508.png" alt="sangeeta_06_42-1710848599508.png" /></span></FONT></P><P><FONT size="2"><FONT color="#FF0000">NOTE</FONT><STRONG>: </STRONG>When you access the URL in your step 1, typically the service will respond with metadata about the available entity sets, properties, relationships, and operations exposed by the service. The metadata document describes the structure and capabilities of the OData service, allowing clients to understand how to interact with it programmatically.</FONT></P><P><FONT size="2"><STRONG>In summary, when you access the full URL, you'll receive metadata and information about the available resources and operations provided by the OData service, not just the raw data from the InvoicerejheadSet entity set</STRONG>.</FONT></P><P><FONT size="2"><STRONG>Step-2:&nbsp;</STRONG>Now click on <STRONG>Step-2</STRONG> and select the Operation as Query as we are fetching Data.</FONT><BR /><BR /><FONT size="2">In Entity, search for Entity and select it. Also, check all the checkboxes against all fields, you can also check Generate XML schema Definition if you want xsd of it.</FONT></P><DIV class=""><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_43-1710848652798.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83017iF95DEB0E0C2DD535/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_43-1710848652798.png" alt="sangeeta_06_43-1710848652798.png" /></span></FONT></DIV><P><FONT size="2"><STRONG>Step 3:</STRONG><STRONG> Configure Filter &amp; Sorting: </STRONG>These steps help you refine your query to retrieve only the specific data you need. This step is available only for data fetch operations, where you can define the order in which the records are fetched in the response payload and filter for the fields that you require.</FONT></P><P><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_44-1710848981645.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83032iD7A31AA18A0FCB54/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_44-1710848981645.png" alt="sangeeta_06_44-1710848981645.png" /></span></FONT></P><P><FONT size="2"><SPAN>After <STRONG>step-3</STRONG> click on Finish. It will automatically generate a query as below based on our filter conditions.</SPAN></FONT></P><P><FONT size="2">After all this configuration you will get one EDMX file and an XSD file.</FONT></P><P><FONT size="2"><FONT color="#FF0000"><STRONG>EDMX (Entity Data Model XSD) File</STRONG></FONT>: EDMX is an XML-based file that encapsulates the metadata of an OData service. It includes information about entities, properties, relationships, and other aspects of the service's data model.</FONT></P><P><FONT size="2">Leave the remaining fields as empty as they are not mandatory.</FONT></P><P>&nbsp;</P><DIV class=""><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_45-1710849079344.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83033i52270FB9BA23F49D/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_45-1710849079344.png" alt="sangeeta_06_45-1710849079344.png" /></span></FONT></DIV><DIV class=""><FONT size="2"><SPAN>Now save and deploy the I-Flow. Always, change the Log level from info to Trace to see all the Message Processing steps.</SPAN></FONT><P>&nbsp;</P></DIV><DIV class="">&nbsp;</DIV><DIV class=""><FONT size="2"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="sangeeta_06_46-1710849126453.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83035iCE7993CC79536B70/image-size/medium?v=v2&amp;px=400" role="button" title="sangeeta_06_46-1710849126453.png" alt="sangeeta_06_46-1710849126453.png" /></span></FONT><P><FONT size="2">Once I-Flow gets started you can see the payload at the End of Step.</FONT></P></DIV> 2024-03-21T15:17:20.893000+01:00 https://community.sap.com/t5/technology-blogs-by-members/managing-recurring-pay-components-in-successfactors-using-batch-upsert/ba-p/13643292 Managing Recurring Pay Components in SuccessFactors Using Batch Upsert 2024-03-21T15:17:35.137000+01:00 ankitkumarpatel https://community.sap.com/t5/user/viewprofilepage/user-id/936889 <H3 id="toc-hId-1118865751"><STRONG><U>Introduction:</U></STRONG></H3><P style=" text-align : justify; padding-left : 30px; ">In this blog, we will delve into the intricacies of managing recurring pay components and explore their implications if they persist beyond specific events such as employee rehires. Understanding and effectively managing recurring pay components are crucial for seamless payroll processing and mitigating potential unwanted consequences.</P><P style=" text-align : justify; padding-left : 30px; ">In the realm of integration scenarios, where SuccessFactors Employee Central portlets are managed and updated through third-party systems via Inbound Integration, the utilization of CPI as a middleware can sometimes lead to overlooked compensation updates. This blog addresses the use of CPI to effectively delimit previous non-effective pay components, particularly in the context of rehires.</P><P style=" text-align : justify; padding-left : 30px; ">Why Rehires?</P><P style=" text-align : justify; padding-left : 30px; ">Rehires present unique scenarios where updates to employees' employment, job, or compensation details render previous information obsolete. When records are populated or updated from a third-party system into SuccessFactors, the job or compensation record may be updated with the rehire event, thereby overwriting previous history. However, in the case of recurring pay components, the previous pay component may carry forward to the new event. While the pay components may be valid for the new event in some cases, the automatic propagation of recurring pay components can result in financial discrepancies in payroll processing. This can lead to overpayment or incorrect payment to employees due to the inclusion of both new and previous pay components in the compensation calculation.</P><P style=" text-align : justify; padding-left : 30px; ">The image below illustrates the behaviour of recurring pay components with changes in each event for an employee. If pay components are not end-dated, they continue to forward propagate even after a rehire event, as highlighted in red below. These pay components may become invalid with effective dated changes, yet they persist due to lack of manual intervention or automation. Consequently, managing updates to pay components or delimiting those no longer valid for an employee becomes crucial, especially if payroll is linked with SuccessFactors Compensation Information</P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ankitkumarpatel_0-1710860042240.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83302i68851E21041EB3E4/image-size/large?v=v2&amp;px=999" role="button" title="ankitkumarpatel_0-1710860042240.png" alt="ankitkumarpatel_0-1710860042240.png" /></span></P><P style=" text-align: center; padding-left : 30px; "><EM>Fig 1. Pay Component Recurring with Event Changes</EM></P><P style=" padding-left : 30px; text-align : justify; ">The Delimiting option for Pay Component Recurring is demonstrated in below sections considering CPI (Inbound Integration) as a middleware, source system as Third-Party system and target system for payroll as SuccessFactors.</P><H3 id="toc-hId-922352246"><STRONG><U>Problem Statement:</U></STRONG></H3><P style=" padding-left : 30px; ">Delimiting and Handling Pay Component Recurring portlet updates and forward propagation.</P><H3 id="toc-hId-725838741"><STRONG><U>Resolution:</U></STRONG></H3><P style=" padding-left : 30px; text-align : justify; ">The resolution for this issue may vary depending on data policies and compliance in SuccessFactors. However, it can be addressed within the integration itself and automated for efficiency. By utilizing event or event reasons from source systems, changes in pay components under Compensation information can be identified. In the case of a rehire scenario, where pay components might be updated, this approach becomes particularly relevant.</P><P style=" padding-left : 30px; text-align : justify; ">&nbsp;To handle compensation and pay component recurring information during a rehire, all pay component recurring records can be delimited. This action wipes out pay components associated with base salary, incentives, variable pay, benefits, bonuses, etc. Subsequently, the rehire panel updates are added to the Compensation information. To illustrate this process, let's refer back to the example introduced in the introduction.</P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ankitkumarpatel_1-1710860042305.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83301i25F6B1ACB6C56989/image-size/large?v=v2&amp;px=999" role="button" title="ankitkumarpatel_1-1710860042305.png" alt="ankitkumarpatel_1-1710860042305.png" /></span></P><P style=" padding-left : 30px; text-align: center; "><EM>Fig 2. Delimiting Pay Components before Rehire event update</EM></P><P style=" text-align : justify; padding-left : 30px; ">On the left side, we have the event changes for an employee under 'Employee Event Changes,' while the pay component recurring changes, i.e., Compensation Information event changes, are depicted on the right side.</P><P style=" text-align : justify; padding-left : 30px; ">For instance, at the time of termination, the employee had five pay components: Base Salary, Car Allowance, Meal Allowance, Accident Insurance, and Transportation. However, these pay components become non-eligible for future payroll consideration upon rehire, effective as of February 01, 2024. Despite this, due to forward propagation, these pay components may persist and get added with the new event changes in compensation information, as shown in Figure 1.</P><P style=" text-align : justify; padding-left : 30px; ">To address this issue, a batch upsert operation with the DELIMIT operation can be performed. Below is the payload used for the upsert operation</P><P>&nbsp;</P><PRE>&lt;batchParts&gt; &lt;batchChangeSet&gt; &lt;batchChangeSetPart&gt; &lt;method&gt;UPSERT&lt;/method&gt; &lt;uri&gt;EmpPayCompRecurring(payComponent='CAR_DE',startDate=datetimeoffset'2024-02-01T00:00:00',userId='mjones',seqNumber=1L)&lt;/uri&gt; &lt;EmpPayCompRecurring&gt; &lt;EmpPayCompRecurring&gt; &lt;payComponent&gt;CAR_DE&lt;/payComponent&gt; &lt;seqNumber&gt;1&lt;/seqNumber&gt; &lt;userId&gt;mjones&lt;/userId&gt; &lt;frequency&gt;Monthly&lt;/frequency&gt; &lt;paycompvalue&gt;20&lt;/paycompvalue&gt; &lt;currencyCode&gt;EUR&lt;/currencyCode&gt; &lt;startDate&gt;2024-02-01T00:00:00&lt;/startDate&gt; &lt;operation&gt;DELIMIT&lt;/operation&gt; &lt;/EmpPayCompRecurring&gt; &lt;/EmpPayCompRecurring&gt; &lt;/batchChangeSetPart&gt; &lt;/batchChangeSet&gt; &lt;/batchParts&gt;</PRE><P style=" text-align: center; ">&nbsp;<EM>Payload for DELIMIT in pay comp recurring via Batch Upsert</EM></P><P style=" text-align : justify; padding-left : 30px; ">Similarly, the payload is prepared for all pay components. After running the Integration in CPI, the pay components are wiped out as shown in the Fig 2.</P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ankitkumarpatel_2-1710860041838.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83300iCCBDF4B779BE9BBB/image-size/large?v=v2&amp;px=999" role="button" title="ankitkumarpatel_2-1710860041838.png" alt="ankitkumarpatel_2-1710860041838.png" /></span></P><P style=" text-align: center; padding-left : 30px; "><EM>Fig 4. SF panel after Delimiting Pay Components</EM></P><P style=" text-align : justify; padding-left : 30px; ">Once all the pay components are removed, we can now insert the new ones with Upsert (POST) method in CPI using SuccessFactors ODATA V2 adapter, the payload for the UPSERT is shown below for reference,</P><P>&nbsp;</P><PRE>&lt;batchParts&gt; &lt;batchChangeSet&gt; &lt;batchChangeSetPart&gt; &lt;method&gt;UPSERT&lt;/method&gt; &lt;uri&gt;EmpPayCompRecurring(payComponent='BASESAL_DE',startDate=datetimeoffset'2024-02-01T00:00:00',userId='mjones',seqNumber=1L)&lt;/uri&gt; &lt;EmpPayCompRecurring&gt; &lt;EmpPayCompRecurring&gt; &lt;payComponent&gt;BASESAL_DE&lt;/payComponent&gt; &lt;seqNumber&gt;1&lt;/seqNumber&gt; &lt;userId&gt;mjones&lt;/userId&gt; &lt;frequency&gt;Monthly&lt;/frequency&gt; &lt;paycompvalue&gt;7000&lt;/paycompvalue&gt; &lt;currencyCode&gt;EUR&lt;/currencyCode&gt; &lt;startDate&gt;2024-02-01T00:00:00&lt;/startDate&gt; &lt;/EmpPayCompRecurring&gt; &lt;/EmpPayCompRecurring&gt; &lt;/batchChangeSetPart&gt; &lt;/batchChangeSet&gt; &lt;/batchParts&gt;</PRE><P style=" text-align: center; "><EM>Payload example for creating Pay Components in SF via Batch Upsert</EM></P><P style=" padding-left : 30px; text-align : justify; ">After running the Integration in CPI, the new pay components get added to the Rehire panel under Compensation as shown below,</P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="ankitkumarpatel_3-1710860041719.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83303iAC6FCA539985F8B2/image-size/large?v=v2&amp;px=999" role="button" title="ankitkumarpatel_3-1710860041719.png" alt="ankitkumarpatel_3-1710860041719.png" /></span></P><P style=" text-align: center; padding-left : 30px; "><EM>Fig 6. Compensation after adding Pay Components via Batch Upsert</EM></P><H3 id="toc-hId-529325236"><STRONG><U>Conclusion:</U></STRONG></H3><P style=" padding-left : 30px; text-align : justify; ">Updating and maintaining pay components is essential to ensure accurate payroll-related information remains available for clients. In scenarios where SuccessFactors is not the source of data, dependency on other systems for accuracy persists. This blog sheds light on the relationship between compensation events and pay compensation changes, particularly during major event changes, and their impact on salary calculations. Similar approaches can be adopted to address other scenarios not covered here. Thank you for taking the time to read through this blog.</P> 2024-03-21T15:17:35.137000+01:00 https://community.sap.com/t5/technology-blogs-by-members/accessing-s4hana-tables-via-an-odata-connection-from-a-user-portal/ba-p/13649009 Accessing S4HANA tables via an OData connection from a user-portal 2024-03-25T19:57:51.735000+01:00 Shamscharma https://community.sap.com/t5/user/viewprofilepage/user-id/195369 <P>Hi Friends,</P><P>I am new to OData.</P><P>I need to create an OData service (URL) that will allow external users logged in via a portal to access data from an S4 System and pull selected information.&nbsp;</P><P>What are the components, and steps? Is there a port involved? Is there a token involved?</P><P>If someone can provide a step by step help, that would be great.</P><P>Any help would be highly appreciated.</P><P>Best,<BR />RS</P> 2024-03-25T19:57:51.735000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/integrating-with-sap-datasphere-consumption-apis-using-saml-bearer/ba-p/13647905 Integrating with SAP Datasphere Consumption APIs using SAML Bearer Assertion 2024-03-28T14:14:29.084000+01:00 gustavokath https://community.sap.com/t5/user/viewprofilepage/user-id/513684 <P>SAP Datasphere facilitates smooth and scalable access to business data, thereby supporting the business data fabric architecture. SAP Datasphere's is committed to data openness and freedom of choice for analytical frontend solutions and allow development of customized applications connected to it.</P><P>The Consumption OData API serves as a prime example of this, providing access to all model types from Facts via relational data access to Analytic Models in analytical mode. Some of this was covered by Mirko Link <A href="https://community.sap.com/t5/technology-blogs-by-sap/sap-datasphere-analytical-and-relational-odata-apis/ba-p/13573797" target="_self">here</A>.</P><P>When integrating SAP Datasphere to other applications the authentication methods are vital to deliver a good customer experience. With the use of SAML Bearer Assertion propagation is possible to forward the IdP authentication from a browser based third-party application to SAP Datasphere without any extra user interaction. Leveraging federated data and Data Access Controls applied to any SAP Datasphere model, the only requirement is that the user must be registered in both applications.</P><P><SPAN>This blog post aims to guide you through the setup of integrating a NodeJS application from SAP Business Technology Platform (BTP) with SAP Datasphere using SAML Bearer Assertion destinations. It will cover the following steps:</SPAN></P><OL><LI>Configure Identity Provider Custom User Attribute</LI><LI>Establish Trust between BTP Destinations and SAP Datasphere</LI><LI>Create SAP Datasphere OAuth Client&nbsp;</LI><LI>Setup Destination to SAP Datasphere Consumption APIs</LI><LI>Create XSUAA and Destination Service Instances</LI><LI>Develop BTP Application connected to SAP Datasphere</LI></OL><P>The initial 3 steps detail the necessary requirements for integrating any system with SAP Datasphere using SAML Bearer Assertion principal propagation. Steps 4,5, and 6 specifically address how BTP Apps can be correctly configured for successful integration with SAP Datasphere.</P><H3 id="toc-hId-1118991366">1.&nbsp;Configure Identity Provider &amp; User Attribute Setup</H3><P>To allow the SAML Bearer propagation attributes to be recognized its is important that the IdP used in your application to configure the user attributes with <STRONG>"Groups"</STRONG> value equal to <STRONG>"sac"</STRONG>.&nbsp;</P><P>In this blog, we will be using the SAP Identity Authentication Service (IAS). However, the procedure should be similar with any other Identity Provider.</P><OL><LI>Open the SAP BTP Cockpit on the subaccount level</LI><LI>Go to Trust Configurations</LI><LI>Click on "New SAML Trust Configuration" to trust your IdP on BTP Platform.<BR />More details can be found on this <A href="https://developers.sap.com/tutorials/abap-custom-ui-trust-cf.html" target="_self" rel="noopener noreferrer">tutorial</A>. After doing this it should look like bellow:<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="gustavokath_1-1711328505640.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/85676iD344009B04994DD7/image-size/large?v=v2&amp;px=999" role="button" title="gustavokath_1-1711328505640.png" alt="gustavokath_1-1711328505640.png" /></span><P>&nbsp;</P></LI><LI>Open Your IAS Administrator panel&nbsp;</LI><LI>Go to Applications &amp; Resources</LI><LI>Select the Application of your subaccount</LI><LI>Open the "Attributes" menu</LI><LI>Add the <STRONG>"Groups"</STRONG> attribute with static value <STRONG>"sac"</STRONG><BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="gustavokath_2-1711328905873.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/85677i3BF7EF29E613343E/image-size/large?v=v2&amp;px=999" role="button" title="gustavokath_2-1711328905873.png" alt="gustavokath_2-1711328905873.png" /></span><P>&nbsp;</P></LI></OL><H3 id="toc-hId-922477861">2. Establish Trust between BTP Destinations and SAP Datasphere</H3><P>Another important requirement is establishing trust between SAP Datasphere and SAP BTP Destinations. This specifies which sources SAP Datasphere can rely on and accept the SAML propagated tokens. This requires providing specific sub-account information for the SAML Bearer Assertion principal propagation flow. Follow the steps below to setup:</P><OL><LI>Open SAP BTP subaccount</LI><LI>Go to "Destinations" tab</LI><LI>Click on "Download IDP Metadata"<BR />This will download a XML file containing the Trust Identity Provider name and&nbsp;s<SPAN>igning</SPAN> certificate, copy those 2 fields<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Trust Metadata.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/86221iD0B7443AD46EFFDE/image-size/large?v=v2&amp;px=999" role="button" title="Trust Metadata.png" alt="Trust Metadata.png" /></span></LI><LI>Open SAP Datasphere Administration Page</LI><LI>Go to "App Integration" tab</LI><LI>On "Trusted Identity Providers" click on "Add a Trusted Identity Provider"<BR />Give a name to the new trusted IdP and add&nbsp;Provider Name and&nbsp;<SPAN>Signing</SPAN> certificate copied from the XML file<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="DSP Trusted IDP.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/85685i3E6EFDBB7F18E6DF/image-size/large?v=v2&amp;px=999" role="button" title="DSP Trusted IDP.png" alt="DSP Trusted IDP.png" /></span></LI></OL><H3 id="toc-hId-725964356">3. Create SAP Datasphere OAuth Client</H3><P><SPAN>To setup the connection to SAP Datasphere Consumption APIs it is needed to generate an OAuth Client which contains the information required to authenticate via OAuth2.0 protocol.</SPAN></P><OL><LI><SPAN>Go to your SAP Datasphere Administration page</SPAN></LI><LI>Open "App Integration" tab</LI><LI><SPAN>On the&nbsp;<STRONG>OAuth Client</STRONG>&nbsp;section, you will find important URLs for generating the OAuth credentials, save it for later. Later on this blog when there is a reference to the bellow tags replace it by its correspondent:</SPAN><BR /><UL><LI>&lt;oauth2_saml_token_url&gt;: OAuth2SAMLTokenURL<SPAN><BR /></SPAN></LI><LI>&lt;<SPAN>oauth2_saml_audience</SPAN>&gt;: <SPAN>OAuth2SAMLAudience</SPAN></LI></UL></LI><LI><SPAN>Create a New OAuth Client to be used later</SPAN><OL><LI>Set the name of your OAuth Client</LI><LI>In<SPAN>&nbsp;</SPAN><STRONG>Purpose<SPAN>&nbsp;</SPAN></STRONG>field&nbsp;set "Interactive Usage"</LI><LI><SPAN><STRONG>Redirect URI&nbsp;</STRONG>field can be left blank</SPAN></LI><LI><SPAN>Click Save</SPAN></LI></OL></LI><LI><SPAN><SPAN>Copy the Client ID (oauth_clientId) and Client Secret (oauth_secret) which appear in the pop and save them somewhere safe. They will be used later.<BR /></SPAN></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="OAuth Client.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/85712i93437153AFF19ECA/image-size/large?v=v2&amp;px=999" role="button" title="OAuth Client.png" alt="OAuth Client.png" /></span></LI></OL><H3 id="toc-hId-529450851">4.&nbsp;Setup Destination to SAP Datasphere Consumption APIs</H3><P>Next, we must establish a SAML Bearer Assertion destination. This will manage the authentication propagation and facilitate communication with the SAP Datasphere Consumption APIs.</P><OL><LI>Open SAP BTP subaccount cockpit on Destinations page</LI><LI>Click "Create Destination" and fill the required information as follows:<UL><LI>Name: &lt;name&gt; - Provide a name to the destination</LI><LI>Type: HTTP</LI><LI>URL: &lt;sap_datasphere_url&gt; - Consumption API URL to be consumed<PRE>&nbsp;http://&lt;datasphere-host&gt;/api/v1/dwc/consumption/analytical/&lt;space&gt;/&lt;asset&gt;/&lt;asset&gt;</PRE></LI><LI><SPAN>Proxy Type: Internet</SPAN></LI><LI><SPAN>Authentication:&nbsp;OAuth2SAMLBearerAssertion</SPAN></LI><LI><SPAN>Audience: &lt;oauth2_saml_audience&gt; - OAuth2SAMLAudience copied on step 3</SPAN></LI><LI><SPAN>AuthnContextClassRef:&nbsp;urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession</SPAN></LI><LI><SPAN>Client Key: &lt;oauth_clientId&gt; - OAuth Client ID from step 3</SPAN></LI><LI><SPAN>Token Service URL:&nbsp;&lt;oauth2_saml_token_url&gt; - OAuth2SAMLTokenURL from step 3</SPAN></LI><LI><SPAN>Token Service User:&nbsp;&lt;oauth_clientId&gt; - OAuth Client ID from step 3</SPAN></LI><LI><SPAN>Token Service Password: &lt;oauth_secret&gt; - OAuth Secret from step 3</SPAN></LI></UL></LI><LI><SPAN><SPAN>Save<BR /></SPAN></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Destination.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/85720iE2B4C8580F5926B9/image-size/large?v=v2&amp;px=999" role="button" title="Destination.png" alt="Destination.png" /></span><P> </P></LI></OL><H3 id="toc-hId-332937346">5. Create XSUAA and Destination Service Instances</H3><P>In order to ensure the application we develop in the next section properly validates authenticated users, checks permissions, and consumes the destinations, we need to create service instances for XSUAA and Destination Service. These will be bound to our backend and Approuter applications</P><H4 id="toc-hId-265506560">5.1. Create XSUAA Service Instance</H4><OL><LI>Open BTP Cockpit on sub-account level</LI><LI>Go to "Instances and Subscriptions"</LI><LI>Click "Create" button</LI><LI>Fill the creation form with the following<UL><LI><SPAN>Service:&nbsp;Authorization and Trust Management Service</SPAN></LI><LI><SPAN>Plan:&nbsp;application</SPAN></LI><LI><SPAN>Runtime Environment:&nbsp;Cloud Foundry</SPAN></LI><LI><SPAN>Space: &lt;space_name&gt; - The space name where your application will be deployed</SPAN></LI><LI><SPAN><SPAN>Instance Name: &lt;uaa_instance_name&gt; - The name of the XSUAA instances created to be bound to the future app<BR /></SPAN></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="XSUAA Instance.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/86218i8BAEF954DD86285A/image-size/large?v=v2&amp;px=999" role="button" title="XSUAA Instance.png" alt="XSUAA Instance.png" /></span></LI></UL></LI><LI>Click "Next" and provide the bellow entry in the JSON configuration<BR /><PRE>{ "tenant-mode": "dedicated" }​</PRE></LI><LI><P>Finish clicking "Create" on the dialog</P></LI></OL><H4 id="toc-hId-68993055">5.2. Create Destination Service Instance</H4><OL><LI>As the previous step, open BTP Cockpit and go to "Instances and Subscriptions"</LI><LI>Click "Create" button</LI><LI>Fill the creation form with the following<UL><LI><SPAN>Service: Destination Service</SPAN></LI><LI><SPAN>Plan: lite</SPAN></LI><LI><SPAN>Runtime Environment:&nbsp;Cloud Foundry</SPAN></LI><LI><SPAN>Space: &lt;space_name&gt; - The space name where your application will be deployed</SPAN></LI><LI><SPAN><SPAN><SPAN>Instance Name: &lt;destination_instance_name&gt; - The name of the XSUAA instances created to be bound to the future app<BR /></SPAN></SPAN></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Destination Instance.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/86220iAF3CBCA37D68D0E2/image-size/large?v=v2&amp;px=999" role="button" title="Destination Instance.png" alt="Destination Instance.png" /></span></LI></UL></LI><LI>Finish clicking "Create" on the dialog&nbsp;</LI></OL><H3 id="toc-hId--256603169">6.&nbsp;Develop BTP Application connected to SAP Datasphere</H3><P>To finish this blog post we will develop a simple suite of BTP Applications. These will simulate any custom-developed, browser-based app on BTP that can call one or multiple SAP Datasphere Consumption APIs. The applications in development are based on the tutorial <A href="https://developers.sap.com/tutorials/cp-cf-security-xsuaa-create.html" target="_self" rel="noopener noreferrer">"Secure a Basic Node.js App with the Authorization and Trust Management Service (XSUAA)"</A>. Some details may be omitted to simplify this blog post's content and focus more on the SAP Datasphere integration rather than the XSUAA setup. For any queries, please refer to the complete tutorial.</P><P>The architecture of the sample app comprehends a NodeJS-express based application, which serves as a proxy to consume SAP Datasphere models exposed via the Consumption APIs. A SAP approuter-based application will sit above this, taking responsibility for routing, authorization, and handling frontend UI5 assets.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="saml-blog-post.drawio.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/86231i9685B5D380E07582/image-size/large?v=v2&amp;px=999" role="button" title="saml-blog-post.drawio.png" alt="saml-blog-post.drawio.png" /></span></P><H4 id="toc-hId--324033955">6.1 Exposing an route to SAP Datasphere in your application</H4><P>Once you complete the tutorial, which should take approximately 25 minutes, we can start making modifications to facilitate calling SAP Datasphere. For flexibility, we will expose one API designed to forward any requests to the SAP Datasphere Consumption APIs (/datapshere/*). The same logic can be applied for integrating any required business logic.</P><P>First we need to install the axios library which will be used to make request to Destination Service and SAP Datasphere</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>npm add --save axios</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>On myapp/index.js include de following code expose the SAP Datasphere route and consume Destination Service properly (For the blog, all functions have been placed in the index.js - in a productive code it could be organized properly)</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>... app.get('/datasphere/*', checkReadScope, async (req, res) =&gt; { // Get the user token from the request const userToken = (req.headers["authorization"]).split(" ")[1]; // Get the destination for calling the Datasphere API const datasphereToken = await findDestinationSAML( "Datasphere_Strakiller_2TAPI", userToken ); const path = Object.values(req.params).join("/"); const response = await axios({ method: "get", url: `${process.env.DATASPHERE_HOST}/${path}`, headers: { Authorization: `Bearer datasphereToken.value`, "Content-Type": "application/json", }, }); res.status(response.status).json(response.data); }); async function findDestinationSAML(destinationName, userToken) { const credentials = xsenv.cfServiceCredentials({ tag: "destination" }); const token = await getDestinationServiceToken(); const response = await axios({ method: "get", url: `${credentials.uri}/destination-configuration/v1/destinations/${destinationName}`, headers: { Authorization: `Bearer ${token}`, "X-user-token": userToken, }, }); if (!response.data.authTokens || response.data.authTokens.length === 0) { throw new Error(`Failed to fetch destination, ${response.data}`); } return response.data.authTokens[0]; }; async function getDestinationServiceToken() { const credentials = xsenv.cfServiceCredentials({ tag: "destination" }); const response = await axios({ method: "post", url: `${credentials.url}/oauth/token`, headers: { Authorization: `Basic ${Buffer.from( `${credentials.clientid}:${credentials.clientsecret}` ).toString("base64")}`, "Content-Type": "application/x-www-form-urlencoded", }, data: { client_id: credentials.clientid, grant_type: "client_credentials", }, }); if (response.status !== 200) { throw new Error( `Failed to fetch destination service access token, ${response.data}` ); } return response.data.access_token; }; ...</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>On the manifest.yml file under the backend app include the destination service binding</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-yaml"><code>- name: saml-blog-app ... services: - saml-blog-app-uaa - destination</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>Then deploy the changes running:</P><PRE>cf push</PRE><P>Through these modifications, we have established the /products/datasphere/* route in our backend application, which will forward any content provided in the "*" to the SAP Datasphere Consumption APIs. For this to function correctly, the route pattern should align exactly with the Consumption API routes as detailed in the <A href="https://help.sap.com/docs/SAP_DATA_WAREHOUSE_CLOUD/c8a54ee704e94e15926551293243fd1d/7a453609c8694b029493e7d87e0de60a.html" target="_self" rel="noopener noreferrer">SAP Help</A> and <A href="https://api.sap.com/package/sapdatasphere/overview" target="_self" rel="noopener noreferrer">SAP Business Accelerator Hub</A>. For instance, when the route below is activated, it will list all the SAP Datasphere assets that my user account can access.</P><PRE>https://saml-blog-approuter.cfapps.sap.hana.ondemand.com/products/datasphere/api/v1/dwc/catalog/assets</PRE><H4 id="toc-hId--520547460">6.2 SAP Datasphere Model for Products</H4><P>The tutorial currently pulls product data from a static JSON file stored in the repository. This could be enhanced by consuming an SAP Datasphere model to deliver this information via OData APIs. As such, a View or Analytic Model containing product details could be displayed. We'll use the static JSON data to construct a comparable view within SAP Datasphere.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="View.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/86234i26489DC7591F81B2/image-size/large?v=v2&amp;px=999" role="button" title="View.png" alt="View.png" /></span></P><P> </P><P>The Product View can be accessed by invoking the URL mentioned below. To display data from SAP Datasphere, update this URL in the UI5 code and make minor adjustments to the JSONModel.</P><PRE><A href="https://saml-blog-approuter.cfapps.sap.hana.ondemand.com/products/datasphere/api/v1/dwc/consumption/relational" target="_blank" rel="noopener nofollow noreferrer">https://saml-blog-approuter.cfapps.sap.hana.ondemand.com/products/datasphere/api/v1/dwc/consumption/relational/&lt;space&gt;/&lt;asserName&gt;/&lt;assetName&gt;</A></PRE><H2 id="toc-hId--627972046">Conclusion</H2><P>In conclusion, SAP Datasphere facilitates streamlined and scalable access to business data, supporting the business data fabric architecture and promoting data openness and a freedom of choice for analytical frontend solutions. Through its use, businesses can develop customized applications tailored to fit their unique needs. This blog post provided an in-depth guide on how to set up an integration of an SAP Business Technology Platform (BTP) NodeJS application to SAP Datasphere using SAML Bearer Assertion destinations. Among the crucial steps involved in this process include configuring the identity provider, establishing trust, creating an OAuth client, setting up a destination to SAP Datasphere consumption APIs, and ultimately developing a BTP application connected to SAP Datasphere. With this setup, businesses can enhance their customer experience by uplifting their authentication methods through integrations to other applications.</P><P>&nbsp;</P><P>&nbsp;</P> 2024-03-28T14:14:29.084000+01:00 https://community.sap.com/t5/application-development-blog-posts/fiori-elements-display-tree-structure-using-odata-annotation-code-based/ba-p/13645333 Fiori Elements: Display Tree-Structure using OData Annotation (Code Based) 2024-04-03T10:48:38.613000+02:00 MR_srinivas https://community.sap.com/t5/user/viewprofilepage/user-id/1421435 <P style=" text-align : justify; "><SPAN>First of all, I would like to explain some libraries to Display tree</SPAN></P><UL style=" text-align : justify; "><LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sap: hierarchy-node-for&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></LI><LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sap: hierarchy-level-for</SPAN></LI><LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sap: hierarchy-parent-node-for</SPAN></LI><LI><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sap: hierarchy-drill-state-for</SPAN></LI></UL><P style=" text-align : justify; "><SPAN>Requirement</SPAN></P><P style=" text-align : justify; "><SPAN>We had a requirement to display the projects and WBS Element information that is created in CJ20N Transaction in the Tree format, it felt quite challenging when I tried the first time. We have to display the WBS elements based on respected projects using OData annotations.</SPAN></P><P style=" text-align : justify; "><SPAN>Let’s begin with an example,</SPAN></P><P style=" text-align : justify; "><SPAN>I have used simple data to display in a tree</SPAN></P><P style=" text-align : justify; "><SPAN>Data base tables: zabdemonode</SPAN></P><P style=" text-align : justify; "><SPAN>Define your data base table</SPAN></P><P style=" text-align : justify; ">@EndUserText.label : 'Node structure of a simple tree'</P><P style=" text-align : justify; "><U>@AbapCatalog.enhancementCategory</U> <U>:</U> <U>#NOT_CLASSIFIED</U></P><P style=" text-align : justify; ">@AbapCatalog.tableCategory : #TRANSPARENT</P><P style=" text-align : justify; ">@AbapCatalog.deliveryClass : #A</P><P style=" text-align : justify; ">@AbapCatalog.dataMaintenance : #RESTRICTED</P><P style=" text-align : justify; "><STRONG>define</STRONG> <STRONG>table</STRONG> <U>zabdemonode</U> <STRONG>{</STRONG></P><P style=" text-align : justify; ">&nbsp; <STRONG>key</STRONG> mandt&nbsp;&nbsp;&nbsp; <STRONG>:</STRONG> mandt <STRONG>not</STRONG> <STRONG>null;</STRONG></P><P style=" text-align : justify; ">&nbsp; <STRONG>key</STRONG> node_key <STRONG>:</STRONG> tv_nodekey <STRONG>not</STRONG> <STRONG>null;</STRONG></P><P style=" text-align : justify; ">&nbsp; relatkey&nbsp;&nbsp;&nbsp;&nbsp; <STRONG>:</STRONG> tv_nodekey<STRONG>;</STRONG></P><P style=" text-align : justify; ">&nbsp; isfolder&nbsp;&nbsp;&nbsp;&nbsp; <STRONG>:</STRONG> as4flag<STRONG>;</STRONG></P><P style=" text-align : justify; ">&nbsp; expander&nbsp;&nbsp;&nbsp;&nbsp; <STRONG>:</STRONG> as4flag<STRONG>;</STRONG></P><P style=" text-align : justify; ">&nbsp; text&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <STRONG>:</STRONG> text40<STRONG>;</STRONG></P><P style=" text-align : justify; ">&nbsp; seq_no&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <STRONG>:</STRONG> abap<STRONG>.</STRONG>char<STRONG>(</STRONG>5<STRONG>);</STRONG></P><P style=" text-align : justify; "><STRONG>}</STRONG></P><P style=" text-align : justify; "><SPAN>I have prepared some test data statically to display</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_10-1711014564124.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84306i116049CE953896BA/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_10-1711014564124.png" alt="MR_srinivas_10-1711014564124.png" /></span></P><P style=" text-align : justify; "><SPAN>After defining your CDS view, here I have defined the view using one base view.</SPAN></P><P style=" text-align : justify; ">@AbapCatalog.viewEnhancementCategory: [#NONE]</P><P style=" text-align : justify; ">@AccessControl.authorizationCheck: #NOT_REQUIRED</P><P style=" text-align : justify; ">@EndUserText.label: 'Hierarchy Display'</P><P style=" text-align : justify; ">@Metadata.ignorePropagatedAnnotations: true</P><P style=" text-align : justify; ">@ObjectModel.usageType:{</P><P style=" text-align : justify; ">&nbsp;&nbsp;&nbsp; serviceQuality: #X,</P><P style=" text-align : justify; ">&nbsp;&nbsp;&nbsp; sizeCategory: #S,</P><P style=" text-align : justify; ">&nbsp;&nbsp;&nbsp; dataClass: #MIXED</P><P style=" text-align : justify; ">}</P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">@Search.searchable: true</P><P style=" text-align : justify; "><STRONG>define</STRONG> <STRONG>root</STRONG> <STRONG>view</STRONG> <STRONG>entity</STRONG> zc_hierarchy_demo</P><P style=" text-align : justify; "><STRONG>as</STRONG> <STRONG>select</STRONG> <STRONG>from</STRONG> zi_hierarchy_demo</P><P style=" text-align : justify; "><STRONG>{</STRONG></P><P style=" text-align : justify; ">@UI.facet: [{ id: 'ID1',type: #IDENTIFICATION_REFERENCE,position: 10,label: 'Project Details' }]</P><P style=" text-align : justify; ">@UI:{lineItem: [{ position: 20,label: 'WBS Element ID'}],</P><P style=" text-align : justify; ">identification: [{ position: 10,label: 'WBS Element ID' }],</P><P style=" text-align : justify; ">selectionField: [{ position: 20 }]}</P><P style=" text-align : justify; ">@EndUserText.label: 'Project'</P><P style=" text-align : justify; ">@Search:{defaultSearchElement: true,fuzzinessThreshold: 0.9,ranking: #MEDIUM}</P><P style=" text-align : justify; "><STRONG>key</STRONG>&nbsp;&nbsp; NODE_KEY<STRONG>,</STRONG></P><P style=" text-align : justify; ">@UI:{lineItem: [{ position: 50,label: 'Relative Key' }],</P><P style=" text-align : justify; ">identification: [{ position: 20,label: 'Reference WBS Element ID' }]}</P><P style=" text-align : justify; ">@Consumption.valueHelpDefinition: [{ entity:{name: 'ZI_hierarchy_view',element: 'NODE_KEY'} }]</P><P style=" text-align : justify; ">@Search:{defaultSearchElement: true,fuzzinessThreshold: 0.9,ranking: #MEDIUM}</P><P style=" text-align : justify; ">RELATKEY</P><P style=" text-align : justify; ">@UI.lineItem: [{ position: 30,label: 'OpenFolder' }]</P><P style=" text-align : justify; ">ISFOLDER<STRONG>,</STRONG></P><P style=" text-align : justify; ">@UI:{lineItem: [{ position: 40,label: 'ExpanderCheck'}]}</P><P style=" text-align : justify; ">EXPANDER<STRONG>,</STRONG></P><P style=" text-align : justify; ">@UI:{lineItem: [{ position: 10,type: #WITH_URL,label: 'WBS Element'}],selectionField: [{ position: 30 }],identification: [{ position: 30,label: 'WBS Element' }]}</P><P style=" text-align : justify; ">@EndUserText.label: 'WBS Element'</P><P style=" text-align : justify; ">@Consumption.valueHelpDefinition: [{ entity:{name: 'ZI_Dimension_view',element: 'TEXT'} }]</P><P style=" text-align : justify; ">TEXT&nbsp;<STRONG>as</STRONG> Name<STRONG>,</STRONG></P><P style=" text-align : justify; ">@UI:{lineItem: [{ position: 50,label: 'Drill Down State' }],identification: [{ position: 40,label: 'Drill Down State' }]}</P><P style=" text-align : justify; ">@Consumption.valueHelpDefinition: [{ entity:{name: 'zi_get_sqno',element: 'Number1'} }]</P><P style=" text-align : justify; ">seq_no&nbsp;<STRONG>as</STRONG> SeqNo<STRONG>,</STRONG></P><P style=" text-align : justify; ">@UI.lineItem: [{ type: #FOR_ACTION,dataAction: 'View',label: 'View' }</P><P style=" text-align : justify; "><STRONG>cast(</STRONG>'expanded' <STRONG>as</STRONG> <EM>abap</EM><STRONG>.</STRONG><EM><U>char</U></EM><STRONG>(</STRONG> 285 <STRONG>))</STRONG> <STRONG>as</STRONG> drill_state</P><P style=" text-align : justify; "><STRONG>}</STRONG></P><P style=" text-align : justify; "><SPAN>Once you activate the view by following the Gateway Builder (SEGW) transaction create your project.</SPAN></P><P style=" text-align : justify; "><SPAN>Then define your entities by using CDS view</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_9-1711014519454.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84304iEB3FBAE25E88403B/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_9-1711014519454.png" alt="MR_srinivas_9-1711014519454.png" /></span></P><P style=" text-align : justify; "><SPAN>It asks you the CDS view name in the pop-up screen enter your view click on next then define your key field there and click on the finish button</SPAN></P><P style=" text-align : justify; "><SPAN>after you define the entity generate artifacts by clicking the button ‘Generate Runtime Artifacts’</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_8-1711014478254.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84303i3398D670B1AC98B5/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_8-1711014478254.png" alt="MR_srinivas_8-1711014478254.png" /></span></P><P style=" text-align : justify; "><SPAN>once done open your MPC_EXT class and redefine the Define method to define the annotation code based</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_7-1711014449877.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84302i6C7F764ADAD6BC0F/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_7-1711014449877.png" alt="MR_srinivas_7-1711014449877.png" /></span></P><P style=" text-align : justify; "><SPAN>Follow the below code to Specifies the hierarchy annotation for a specific field</SPAN></P><P style=" text-align : justify; "><SPAN>method&nbsp;define</SPAN><SPAN>.</SPAN><BR />super<SPAN>-&gt;</SPAN><SPAN>define</SPAN><SPAN>(&nbsp;).</SPAN><BR />&nbsp;&nbsp;</P><P style=" text-align : justify; "><SPAN>data&nbsp;</SPAN><SPAN>:</SPAN>lr_entity&nbsp;&nbsp;&nbsp;<SPAN>type&nbsp;ref&nbsp;to&nbsp;</SPAN>/iwbep/if_mgw_odata_entity_typ<SPAN>.</SPAN><BR /><SPAN>data&nbsp;</SPAN><SPAN>:</SPAN>lr_property&nbsp;<SPAN>type&nbsp;ref&nbsp;to&nbsp;</SPAN>/iwbep/if_mgw_odata_property<SPAN>.</SPAN><BR /><SPAN>data&nbsp;</SPAN><SPAN>:</SPAN>lr_annno&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<SPAN>type&nbsp;ref&nbsp;to&nbsp;</SPAN>/iwbep/if_mgw_odata_annotation<SPAN>.</SPAN></P><P style=" text-align : justify; ">lr_entity&nbsp;<SPAN>=&nbsp;</SPAN>model<SPAN>-&gt;</SPAN>get_entity_type<SPAN>(&nbsp;</SPAN>iv_entity_name&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'zc_hierarchy_demoType'&nbsp;</SPAN><SPAN>).</SPAN><BR /><SPAN>if&nbsp;</SPAN>lr_entity&nbsp;<SPAN>is&nbsp;bound</SPAN><SPAN>.</SPAN></P><P style=" text-align : justify; ">&nbsp;lr_property&nbsp;<SPAN>=&nbsp;</SPAN>lr_entity<SPAN>-&gt;</SPAN>get_property<SPAN>(&nbsp;</SPAN>iv_property_name&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'NODE_KEY'&nbsp;</SPAN><SPAN>).</SPAN></P><P style=" text-align : justify; ">lr_annno<SPAN>=</SPAN>lr_property<SPAN>-&gt;</SPAN>/iwbep/if_mgw_odata_annotatabl<SPAN>~</SPAN>create_annotation<SPAN>(&nbsp;</SPAN>iv_annotation_namespace&nbsp;<SPAN>=&nbsp;</SPAN>/iwbep/if_mgw_med_odata_types<SPAN>=&gt;</SPAN>gc_sap_namespace&nbsp;<SPAN>).</SPAN></P><P style=" text-align : justify; "><BR />lr_annno<SPAN>-&gt;</SPAN><SPAN>add</SPAN><SPAN>(&nbsp;</SPAN>iv_key&nbsp;&nbsp;<SPAN>=&nbsp;</SPAN>/iwbep/if_ana_odata_types<SPAN>=&gt;</SPAN>gcs_ana_odata_annotation_key<SPAN>-</SPAN>hierarchy_node_for&nbsp;iv_value&nbsp;&nbsp;&nbsp;&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'NODE_KEY'&nbsp;</SPAN><SPAN>).</SPAN></P><P style=" text-align : justify; ">lr_property&nbsp;<SPAN>=&nbsp;</SPAN>lr_entity<SPAN>-&gt;</SPAN>get_property<SPAN>(&nbsp;</SPAN>iv_property_name&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'SeqNo'&nbsp;</SPAN><SPAN>).</SPAN><BR />lr_annno<SPAN>=</SPAN>lr_property</P><P style=" text-align : justify; "><SPAN>&gt;</SPAN>/iwbep/if_mgw_odata_annotatabl<SPAN>~</SPAN>create_annotation<SPAN>(&nbsp;</SPAN>iv_annotation_namespace&nbsp;<SPAN>=&nbsp;</SPAN>/iwbep/if_mgw_med_odata_types<SPAN>=&gt;</SPAN>gc_sap_namespace&nbsp;<SPAN>).</SPAN></P><P style=" text-align : justify; "><BR />lr_annno<SPAN>-&gt;</SPAN><SPAN>add</SPAN><SPAN>(&nbsp;</SPAN>iv_key&nbsp;<SPAN>=&nbsp;</SPAN>/iwbep/if_ana_odata_types<SPAN>=&gt;</SPAN>gcs_ana_odata_annotation_key<SPAN>-</SPAN>hierarchy_level_for&nbsp;iv_value&nbsp;&nbsp;&nbsp;&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'NODE_KEY'&nbsp;</SPAN><SPAN>).</SPAN></P><P style=" text-align : justify; ">lr_property&nbsp;<SPAN>=&nbsp;</SPAN>lr_entity<SPAN>-&gt;</SPAN>get_property<SPAN>(&nbsp;</SPAN>iv_property_name&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'RELATKEY'&nbsp;</SPAN><SPAN>).</SPAN><BR />lr_annno<SPAN>=</SPAN>lr_property<SPAN>-</SPAN></P><P style=" text-align : justify; "><SPAN>&gt;</SPAN>/iwbep/if_mgw_odata_annotatabl<SPAN>~</SPAN>create_annotation<SPAN>(&nbsp;</SPAN>iv_annotation_namespace&nbsp;<SPAN>=&nbsp;</SPAN>/iwbep/if_mgw_med_odata_types<SPAN>=&gt;</SPAN>gc_sap_namespace&nbsp;<SPAN>).</SPAN></P><P style=" text-align : justify; ">lr_annno<SPAN>-&gt;</SPAN><SPAN>add</SPAN><SPAN>(&nbsp;</SPAN>iv_key&nbsp;<SPAN>=&nbsp;</SPAN>/iwbep/if_ana_odata_types<SPAN>=&gt;</SPAN>gcs_ana_odata_annotation_key<SPAN>-</SPAN>hierarchy_parent_node_for&nbsp;iv_value&nbsp;&nbsp;&nbsp;&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'NODE_KEY'&nbsp;</SPAN><SPAN>).</SPAN></P><P style=" text-align : justify; ">lr_property&nbsp;<SPAN>=&nbsp;</SPAN>lr_entity<SPAN>-&gt;</SPAN>get_property<SPAN>(&nbsp;</SPAN>iv_property_name&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'drill_state'&nbsp;</SPAN><SPAN>).</SPAN></P><P style=" text-align : justify; ">lr_annno<SPAN>=</SPAN>lr_property<SPAN>-&gt;</SPAN>/iwbep/if_mgw_odata_annotatabl<SPAN>~</SPAN>create_annotation<SPAN>(&nbsp;</SPAN>iv_annotation_namespace&nbsp;<SPAN>=&nbsp;</SPAN>/iwbep/if_mgw_med_odata_types<SPAN>=&gt;</SPAN>gc_sap_namespace&nbsp;<SPAN>).</SPAN></P><P style=" text-align : justify; ">lr_annno<SPAN>-&gt;</SPAN><SPAN>add</SPAN><SPAN>(</SPAN>iv_key<SPAN>=</SPAN>/iwbep/if_ana_odata_types<SPAN>=&gt;</SPAN>gcs_ana_odata_annotation_key<SPAN>-</SPAN>hierarchy_drill_state_for&nbsp;iv_value&nbsp;&nbsp;&nbsp;&nbsp;<SPAN>=&nbsp;</SPAN><SPAN>'NODE_KEY'&nbsp;</SPAN><SPAN>).</SPAN></P><P style=" text-align : justify; "><SPAN>endif</SPAN><SPAN>.</SPAN><BR /><SPAN>endmethod</SPAN><SPAN>.</SPAN></P><P style=" text-align : justify; "><SPAN>After Save (Ctlr+s) and Activate (Ctrl+F3) MPC_EXT and Generate your artifacts. Once done register your service and generate the metadata, here in the metadata file, you can notice one thing, the property that you have mentioned for hierarchy should display.</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_6-1711014393836.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84300i153F84CCA2CEA563/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_6-1711014393836.png" alt="MR_srinivas_6-1711014393836.png" /></span></P><P style=" text-align : justify; "><SPAN>If not, the tree table will not display your hierarchy.</SPAN></P><P style=" text-align : justify; "><SPAN>Let’s create a Fiori Application</SPAN></P><P style=" text-align : justify; "><SPAN>Before starting the process, make sure to have the extension packages in VS code then only we can create the Fiori app.</SPAN></P><P style=" text-align : justify; "><SPAN>Open VS Code Goto view in the menu and click on command palette(ctrl+shift+P), after search</SPAN></P><P style=" text-align : justify; "><SPAN>Fiori: Open Application Generator; it will open the template Wizard</SPAN></P><P style=" text-align : justify; "><SPAN>Select one template based on your requirement</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_5-1711014369860.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84299iDB8AAA5150FC498B/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_5-1711014369860.png" alt="MR_srinivas_5-1711014369860.png" /></span></P><P style=" text-align : justify; "><SPAN>Then Connect your backend system</SPAN></P><P style=" text-align : justify; "><SPAN>If you are not registered you have to register your backend system else you can go with OData service directly.</SPAN></P><P style=" text-align : justify; "><SPAN>After providing your OData service name and clicking on the next button</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_4-1711014347658.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84298i720B46E5DCC7CDD5/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_4-1711014347658.png" alt="MR_srinivas_4-1711014347658.png" /></span></P><P style=" text-align : justify; "><SPAN>Then select your main entity and provide the project name after clicking on the Finish button</SPAN></P><P style=" text-align : justify; "><SPAN>Then it will install some required dependencies for the Fiori Application, once done it will open the application info inside and click on ‘open page map’</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_3-1711014326662.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84296iD99EEE5A2011DBD8/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_3-1711014326662.png" alt="MR_srinivas_3-1711014326662.png" /></span></P><P style=" text-align : justify; "><SPAN>Inside that edit your object page then click on the table option. It will open some </SPAN><SPAN>properties related to the list report page there you have to change the type of your table.</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_2-1711014293122.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84295i7DBB14071AC4C68E/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_2-1711014293122.png" alt="MR_srinivas_2-1711014293122.png" /></span></P><P style=" text-align : justify; "><SPAN>After previewing your application you can see the expected outcomes</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_1-1711014265063.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84294iC19CE6F79B31194C/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_1-1711014265063.png" alt="MR_srinivas_1-1711014265063.png" /></span></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MR_srinivas_0-1711014178233.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84293i8E2E46DD3A114343/image-size/medium?v=v2&amp;px=400" role="button" title="MR_srinivas_0-1711014178233.png" alt="MR_srinivas_0-1711014178233.png" /></span></P><P style=" text-align : justify; "><SPAN>Conclusion: </SPAN></P><P style=" text-align : justify; "><SPAN>this requirement helps in displaying the Hierarchy format using the Tree table in the Fiori application.</SPAN></P><P style=" text-align : justify; "><SPAN>Hope I find it will we be helpful. If any queries please welcome on comment sections.</SPAN></P><P style=" text-align : justify; "><SPAN>Note: All the images shown in this blog are the snapshots that are taken from my PC.</SPAN></P><P style=" text-align : justify; "><SPAN>Regards,</SPAN></P><P style=" text-align : justify; "><SPAN>Srinivasa M R</SPAN></P> 2024-04-03T10:48:38.613000+02:00 https://community.sap.com/t5/technology-blogs-by-sap/integrate-c4p-resource-management-with-sap-analytics-cloud-or-sap/ba-p/13659581 Integrate C4P-Resource Management with SAP Analytics Cloud or SAP DataSphere 2024-04-04T22:27:35.922000+02:00 Wu-Dongxue https://community.sap.com/t5/user/viewprofilepage/user-id/144417 <H3 id="toc-hId-1119970869">Summary</H3><P><SPAN>Embarking on the journey of leveraging SAP S/4HANA Cloud for Projects, Resource Management (C4P), this blog simplifies the process of accessing its APIs, with a focus on the Resource Request functionality. Beginning with preparations, where we gather key information like API URL and credentials, we then explore the capabilities of the Resource Request API in the Business Accelerator Hub. We break down how to find the right URL for accessing resource requests and demonstrate how to connect these APIs to tools like SAP Analytics Cloud or SAP DataSphere. By following these steps, users can seamlessly integrate data from C4P into their analytics workflow, enabling better decision-making and operational efficiency.</SPAN></P><H3 id="toc-hId-923457364"><STRONG>Preparation Step:</STRONG></H3><P>You have to&nbsp;<A href="https://help.sap.com/docs/PPRM_OD/a2ad92d065e04e8393d72cace620e0be/24b5d0bbc0c442a5a8d258f7c17cd393.html" target="_self" rel="noopener noreferrer">Set Up&nbsp;the API Access for&nbsp;for SAP S/4HANA Cloud for Projects, Resource Management</A></P><P>And at step <STRONG>7</STRONG> of <A href="https://help.sap.com/docs/PPRM_OD/a2ad92d065e04e8393d72cace620e0be/79143e31846b4275a1fc0e07925bec69.html" target="_self" rel="noopener noreferrer">Creating a Service Key</A>, please note down all of the information mentioned in the table below. We will use them to fill in the connection information in either SAP Analytics Cloud or SAP DataSphere later.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_21-45-26.png" style="width: 770px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91599i25E323DF75774D1A/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_21-45-26.png" alt="Snipaste_2024-04-04_21-45-26.png" /></span></P><P>For example:</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "apiUrl": https://resource-management-api-projectscloud.cfapps.eu10.hana.ondemand.com, "uaa": { "clientid": "sb-............................................................265", "clientsecret": "49...............................................................vc=", "url": https://cp..........w.authentication.eu10.hana.ondemand.com, "identityzone": "cp..........w",</code></pre><P>&nbsp;</P><P>apiUrl: is the main part of the OData Service URL and we will add path to this URL in the later step.</P><P>clientid: is OAuth Client ID in SAC OData Service Connection dialog</P><P>clientsecret: is Secret in SAC OData Service Connection dialog</P><P>url: is the base of token URL. The full token URL should be:&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>https://cp..............w.authentication.eu10.hana.ondemand.com/oauth/token</code></pre><P>&nbsp;</P><P>In&nbsp;<A href="https://api.sap.com/package/SAPS4HANACloudForProjectsResourceManagement/odatav4" target="_self" rel="noopener noreferrer">Business Accelerator Hub</A>, you will see four cards. Each of them contains a collection of request methods based on OData API. However, only Assignment and Resource Request contain GET method. Project Experience and Workforce Availability don't support GET method. Hence, only queries from Assignment and Resource Request can be imported and consumed in SAP Analytics Cloud and DataSphere. And this blog will take the Resource Request OData API as an example.<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_19-55-30.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91571i1E0F96D4D99994BA/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_19-55-30.png" alt="Snipaste_2024-04-04_19-55-30.png" /></span></P><H3 id="toc-hId-726943859">Step1: Check API Reference and Capability</H3><OL><LI>Click on the card of Resource Request &gt; Click on API Reference<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_20-09-45.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91573iDED40B252B58DBF8/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_20-09-45.png" alt="Snipaste_2024-04-04_20-09-45.png" /></span></LI><LI>You will see the GET method is supported for Resource Request.<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_20-12-03.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91575i886B2D79DD599C36/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_20-12-03.png" alt="Snipaste_2024-04-04_20-12-03.png" /></span></LI></OL><P style=" padding-left : 30px; ">However, in the Workforce Availability. Only POST method is supported. This is the reason that we are not able to leverage this endpoint in the Analysis Application<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_20-13-48.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91577i0E1BFC28A1EC0F04/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_20-13-48.png" alt="Snipaste_2024-04-04_20-13-48.png" /></span></P><H3 id="toc-hId-530430354">Step2: Find OData Service URL for Resource Request</H3><OL><LI>Click on the card of Resource Request &gt; Click on Try Out<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_20-06-43.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91579iD918DAA0A95C9770/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_20-06-43.png" alt="Snipaste_2024-04-04_20-06-43.png" /></span></LI><LI>Select&nbsp;/ResourceRequests from the method section &gt; click on Environment: Sandbox &gt; Select Add New Environment<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_20-24-34.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91581i5D38D7F48596B846/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_20-24-34.png" alt="Snipaste_2024-04-04_20-24-34.png" /></span></LI><LI>In the prompt window &gt; find <STRONG>Starting URL. </STRONG>By following the format,&nbsp;you can add the path of <STRONG>/ResourceRequestService/v1</STRONG> to the end of the <STRONG>apiUrl</STRONG> which you noted down at the preparation step. For example, like the screenshot below. (In the same vein, the URL logic also applies to Assignment)<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Untitled0404.png" style="width: 795px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91582i48F97A44D82FDA1D/image-size/large?v=v2&amp;px=999" role="button" title="Untitled0404.png" alt="Untitled0404.png" /></span></LI></OL><P style=" padding-left : 60px; ">(This apiUrl will be used for connection later.)</P><H3 id="toc-hId-333916849">Step3: Build Connection in SAC</H3><P>Now, you have obtained all required the information. And you can build the OData Services Connection in SAP Analytics Cloud or SAP DataSphere. For example, like below screenshot.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Snipaste_2024-04-04_22-13-33.png" style="width: 427px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91639i41AF35F240195495/image-size/large?v=v2&amp;px=999" role="button" title="Snipaste_2024-04-04_22-13-33.png" alt="Snipaste_2024-04-04_22-13-33.png" /></span></P><P>OData Service Connection supports scheduling import in SAP Analytics Cloud. You can leverage this feature to update the data in the model.&nbsp;</P><H3 id="toc-hId-137403344">Tips:&nbsp;</H3><UL><LI>If you have DataSphere, you can use DataSphere to restructure the query and then visualize the data in SAP Analytics Cloud.</LI><LI>If you find the data from one single query is not enough and you don't have DataSphere. You can leverage the data blending feature in SAP Analytics Cloud to combine the data visualization from different sources.</LI></UL><P>&nbsp;</P> 2024-04-04T22:27:35.922000+02:00 https://community.sap.com/t5/technology-blogs-by-members/how-to-develop-customer-creation-application-in-sap-build-apps-with-odata/ba-p/13659201 How to develop Customer creation Application in SAP Build Apps with OData service 2024-04-05T16:34:12.935000+02:00 Chetan_Bhatt https://community.sap.com/t5/user/viewprofilepage/user-id/1429690 <P><STRONG>Objective: -</STRONG></P><P>Implementing SAP OData URI &nbsp;to SAP Build and Creating Customers in SAP BUILD which can replicate to SAP System</P><P>&nbsp;</P><P><STRONG>Business Scenario: -</STRONG></P><P>&nbsp;How to create Customers using SAP Build Apps and OData Service.</P><P>&nbsp;</P><P><STRONG>Prerequisites: -</STRONG></P><P>-&gt; You Have an SAP BTP account or trial account.</P><P>-&gt; Inside the BTP account, go to Instances and Subscriptions and create an instance of SAP Build Apps</P><P>-&gt; Now go to Security -&gt; Users Tab and assign Role to the user for SAP BUILD Apps</P><P>&nbsp;</P><P><STRONG>Now, we have to create the SAP Backend connection to SAP BTP : -</STRONG></P><P>Before mapping data from S4H or our SAP System to Build Apps, we need to create a Destination in the BTP and give the required details of the S4H system with ODATA Uri too which we will consume (BTP-&gt;Connectivity-&gt;Destination )</P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_0-1712235368204.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91402i20FA8162E495345A/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_0-1712235368204.png" alt="Chetan_Bhatt_0-1712235368204.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>Connection is now established to that service.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_1-1712235368416.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91403i24C441B2C4D96AEB/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_1-1712235368416.png" alt="Chetan_Bhatt_1-1712235368416.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>Now go to SAP Build Apps and navigate to Create to create a project.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_2-1712235368206.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91404iC5BDF8520954AEFB/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_2-1712235368206.png" alt="Chetan_Bhatt_2-1712235368206.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>Now click on Build an Application to create a Application</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_3-1712235368548.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91405iCB04B12AB7452313/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_3-1712235368548.png" alt="Chetan_Bhatt_3-1712235368548.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>Now Click on Web &amp; Mobile Application</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_4-1712235368519.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91407iC7A40A64D5FFEE47/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_4-1712235368519.png" alt="Chetan_Bhatt_4-1712235368519.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>Now Give the project name and Description and You are good to go.</P><P>Inside the app you are working on SAP Build App go to the Authentication section and implement authentication</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_5-1712235368532.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91406iFF6519951546DD32/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_5-1712235368532.png" alt="Chetan_Bhatt_5-1712235368532.png" /></span></P><P>&nbsp;</P><P>Now create an App Variable that holds all fields that are present in our OData service.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_6-1712235368498.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91409i259161295DFB6B8D/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_6-1712235368498.png" alt="Chetan_Bhatt_6-1712235368498.png" /></span></P><P>&nbsp;</P><P>Now create a page and install a template from the marketplace which is Basic List and implement your UI for Customer Creation and a home page where all customers are displayed.</P><P>Now go to the DATA Section then go to SAP Systems and connect to your s4h System and the service that you called from the destination &nbsp;from SAP BTP will be available to you now.</P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_7-1712235368450.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91408iB0410E5B62D70707/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_7-1712235368450.png" alt="Chetan_Bhatt_7-1712235368450.png" /></span></P><P>&nbsp;</P><P>Now Click on this list go to ‘list resource’ fill in all the fields and configure authentication from Properties</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_8-1712235368551.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91410iDCCF8A0A48917F3E/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_8-1712235368551.png" alt="Chetan_Bhatt_8-1712235368551.png" /></span></P><P>&nbsp;</P><P>Now Go to the Logic section of List and implement logic like this</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_9-1712235368437.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91411i0C3148A4A08D8301/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_9-1712235368437.png" alt="Chetan_Bhatt_9-1712235368437.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>Now click on the Create button go to Show logic for Button then implement this logic</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_10-1712235368445.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91413i9C8ABB3B05009FBB/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_10-1712235368445.png" alt="Chetan_Bhatt_10-1712235368445.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>Now create another page as shown below and build a form to create Customer Data using input fields.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_11-1712235368504.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91412iF20FC7FA457B3947/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_11-1712235368504.png" alt="Chetan_Bhatt_11-1712235368504.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>Now do data binding to all fields by clicking on it and then assigning value to it</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_12-1712235368473.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91414iC9FEB2213A9EA1F4/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_12-1712235368473.png" alt="Chetan_Bhatt_12-1712235368473.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>Now do a similar mapping for every field</P><P>Also, implement a condition to alert that an empty value is not allowed.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_13-1712235368467.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91416iB8266D4F228176E1/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_13-1712235368467.png" alt="Chetan_Bhatt_13-1712235368467.png" /></span></P><P>&nbsp;</P><P>Now on the submit button implement logic that submit the data and updates the data to that OData service and thus will be reflected in the database table too</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_14-1712235368546.jpeg" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91415iCB780E20D3FCBC60/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_14-1712235368546.jpeg" alt="Chetan_Bhatt_14-1712235368546.jpeg" /></span></P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_15-1712235368475.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91418i6406EAC9E0F90CD4/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_15-1712235368475.png" alt="Chetan_Bhatt_15-1712235368475.png" /></span></P><P>&nbsp;</P><P><STRONG>Preview Your Developments: -</STRONG></P><P>Now when everything is done go to the Launch section then Preview your app.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_16-1712235368543.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91417iD43A34EB5CCDFC02/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_16-1712235368543.png" alt="Chetan_Bhatt_16-1712235368543.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>By this, we can preview our application either on the web or can be previewed in Smartphones.</P><P>Our Application Now looks like-</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_17-1712235368488.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91419iFD8BF13DB9A04ABC/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_17-1712235368488.png" alt="Chetan_Bhatt_17-1712235368488.png" /></span></P><P>&nbsp;</P><P>When we click on the create button the second page appears</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_18-1712235368552.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91420i8CD970CFDF5BF011/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_18-1712235368552.png" alt="Chetan_Bhatt_18-1712235368552.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P>Fill out details and now our customer is created.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_19-1712235368470.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91422i7E5AC9C926F24443/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_19-1712235368470.png" alt="Chetan_Bhatt_19-1712235368470.png" /></span></P><P>&nbsp;</P><P>So now your customer is created in your database table &nbsp;which you can check by going to se11-&gt;KNA1</P><P>And you can see your entry got updated in table KNA1</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_20-1712235368518.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/91421i47CAC4464ECCE8E6/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_20-1712235368518.png" alt="Chetan_Bhatt_20-1712235368518.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P> 2024-04-05T16:34:12.935000+02:00 https://community.sap.com/t5/technology-blogs-by-members/consuming-capm-application-s-odata-service-into-sap-fiori-application-in/ba-p/13667392 Consuming CAPM Application's OData service into SAP Fiori Application in Business Application Studio 2024-04-16T12:50:31.978000+02:00 Chetan_Bhatt https://community.sap.com/t5/user/viewprofilepage/user-id/1429690 <P style=" text-align : justify; "><STRONG>OBJECTIVE-:</STRONG></P><P style=" text-align : justify; ">Consuming OData Service of CAPM Application into SAP Fiori Application in Business Application Studio.</P><P style=" text-align : justify; "><STRONG>CAPM (Cloud Application Programming Model)-:</STRONG></P><P style=" text-align : justify; ">It is an open-source framework that uses tools, libraries, and languages to create applications that can be used across multiple SAP products. CAPM is a multi-target application that runs at different times, with the persistence layer running in the HANA DB run time, the server layer running in the Node.js run time, and the UI/UX layer running in the browser run time.</P><P style=" text-align : justify; ">CAPM is one of the approaches to developing cloud applications using the BTP platform. CAPM offers a more structured and seamless framework for data modelling and enhancing integration with services.</P><P style=" text-align : justify; "><STRONG>Advantage of CAPM over other approaches-:</STRONG></P><UL style=" text-align : justify; "><LI>It enables full-stack development in the same environment. (BAS), eliminating the need to switch between different environments for the backend and frontend development.</LI><LI>It offers flexibility in language selection, allowing developers to work with multiple languages according to their needs. BAS provides easy connectivity to required extensions for this purpose.</LI><LI>Seamless integration with git and other applications via APIs facilitating extension or development of the application.</LI><LI>Automatically handling dependencies to a certain extent, reducing frustration, and improving development speed. For example, handling the OData after exposing all entities and making it easier to consume in the UI.</LI></UL><P style=" text-align : justify; "><STRONG>Prerequisites-:</STRONG></P><UL style=" text-align : justify; "><LI>Create a CAPM project.</LI><LI>Log in to Cloud Foundry Credentials.</LI><LI>Ensure the HANA Database is created and running (I Used it for storage and data creation).</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_0-1712859475702.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95284iF96BE8EFB182149E/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_0-1712859475702.png" alt="Chetan_Bhatt_0-1712859475702.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_1-1712859475728.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95285iC96312CDDC8F56E6/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_1-1712859475728.png" alt="Chetan_Bhatt_1-1712859475728.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Set up a Dev Space.</LI><LI>Create a SAP Build Work Zone instance to act as a Fiori Launchpad for the CAPM Application</LI></UL><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; "><STRONG>You Have to create a new Destination in BTP (Connectivity -&gt; Destination)-:</STRONG></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_2-1712859475732.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95283i2F37A3A4212C375A/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_2-1712859475732.png" alt="Chetan_Bhatt_2-1712859475732.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">This destination will be used for passing system information when creating a Fiori Application.</P><P style=" text-align : justify; ">For the URL, DEPLOY YOUR APPLICATION IN CLOUD FOUNDRY (Cloud Foundry -&gt;Spaces -&gt;Dev (Space Name)-&gt;Your Service (here it is CAPMChetan-srv) and copy Application Routes).</P><P style=" text-align : justify; ">This URL will be shown only when you deploy your CAPM Application in Cloud Foundry-&gt; A new blog will be there to deploy the CAPM Application.</P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_3-1712859475740.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95288i831E1DE5FA2B9750/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_3-1712859475740.png" alt="Chetan_Bhatt_3-1712859475740.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">For Authorization, use the same authorization as created in the package.json -&gt; a new blog will create a security configuration.</P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">Now that the destination for the service is configured, proceed to create a FIORI APP: -</P><UL style=" text-align : justify; "><LI>Open SAP BAS (Business Application Studio).</LI><LI>Open DEV Space where you want to create a Fiori Application.</LI><LI>Go to File -&gt; New Project From template.</LI><LI>Choose a project from the Template (SAP Fiori Application).</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_4-1712859475749.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95287i3F3554B2250D61A3/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_4-1712859475749.png" alt="Chetan_Bhatt_4-1712859475749.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Choose any Template of your choice.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_5-1712859475756.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95286iD67EBDD9E6AB118C/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_5-1712859475756.png" alt="Chetan_Bhatt_5-1712859475756.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>In Data Source choose to connect to a system.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_6-1712859475760.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95290iDCCA5D3A65D7000B/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_6-1712859475760.png" alt="Chetan_Bhatt_6-1712859475760.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_7-1712859475765.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95289i29335856F2EFABAA/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_7-1712859475765.png" alt="Chetan_Bhatt_7-1712859475765.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Specify the Destination created earlier.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_8-1712859475769.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95291i0B4CF5E35759FC40/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_8-1712859475769.png" alt="Chetan_Bhatt_8-1712859475769.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>In the service path, specify the service path of the OData service that can be obtained by running the command “cds watch –profile hybrid” in your CAPM Project.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_9-1712859475773.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95292i7F0BC76D1160938D/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_9-1712859475773.png" alt="Chetan_Bhatt_9-1712859475773.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Click on next.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_10-1712859475781.jpeg" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95293i7930C75401EC6C12/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_10-1712859475781.jpeg" alt="Chetan_Bhatt_10-1712859475781.jpeg" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Select any entity from the given list of entities &nbsp;you created in your project.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_11-1712859475788.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95294i28FD073ED8BABEB0/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_11-1712859475788.png" alt="Chetan_Bhatt_11-1712859475788.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Customize the project attributes.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_12-1712859475796.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95295i56DC0BF8208D9582/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_12-1712859475796.png" alt="Chetan_Bhatt_12-1712859475796.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Choose the target as Cloud Foundry and select the Destination name among the list of destination names (You can go with either Local CAPM Project API and the name of your destination too).</LI></UL><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_13-1712859475804.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95297i448D5B4C126A031A/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_13-1712859475804.png" alt="Chetan_Bhatt_13-1712859475804.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Now, your FIORI project is created and is ready to use.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_14-1712859475814.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95296i4C2BAADDC20B1DDD/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_14-1712859475814.png" alt="Chetan_Bhatt_14-1712859475814.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>Go to run configuration and start the project as usual.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_15-1712859475821.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95298i8507FAEBE3A69EB2/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_15-1712859475821.png" alt="Chetan_Bhatt_15-1712859475821.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><UL style=" text-align : justify; "><LI>You can now run this Fiori Application which is the result of an Application created from CAPM.</LI></UL><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Chetan_Bhatt_16-1712859475830.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/95299iEBFF2F273E03EB7A/image-size/medium?v=v2&amp;px=400" role="button" title="Chetan_Bhatt_16-1712859475830.png" alt="Chetan_Bhatt_16-1712859475830.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P style=" text-align : justify; ">&nbsp;</P> 2024-04-16T12:50:31.978000+02:00 https://community.sap.com/t5/technology-blogs-by-members/syniti-rdg-streamlines-creation-and-configuration-of-mdc-process-templates/ba-p/13695687 Syniti RDG streamlines creation and configuration of MDC process templates. 2024-05-14T10:41:20.003000+02:00 JuanAlonso https://community.sap.com/t5/user/viewprofilepage/user-id/1384553 <P style=" text-align : justify; "><SPAN><A href="https://store.sap.com/dcp/en/product/display-2001014736_live_v1/syniti-rapid-data-governance" target="_blank" rel="noopener noreferrer">Syniti Rapid Data Governance (RDG)</A> is an SAP-endorsed Cloud-Based UI5 application built on the SAP Business Technology Platform (BTP). SAP Master Data Governance is a powerful solution to improve the quality and consistency of information across organizations by consolidating and centrally governing master data. Syniti RDG’s MDC tile streamlines the creation and setup of process templates and the configuration of its process steps. </SPAN></P><P style=" text-align : justify; "><SPAN>Master Data Consolidation (MDC) refers to the process of combining and centralizing master data from disparate sources into a single System. This ensures that there is a consistent and accurate version of master data, such as customer, product, or supplier information, across an organization. </SPAN></P><P style=" text-align : justify; "><SPAN>In SAP, Process Templates are predefined sets of steps and configurations that standardize the master data consolidation process. The Process Template you choose during a consolidation process specifies whether and in what order certain process steps are executed and what configurations apply for each step. </SPAN></P><P style=" text-align : justify; "><SPAN>By utilizing process templates, organizations can accelerate the master data consolidation process and maintain data integrity across different systems and business units within the SAP landscape. Additionally, process templates facilitate compliance with regulatory requirements and supports ongoing data governance efforts by establishing standardized procedures for managing master data consolidation activities.</SPAN></P><P style=" text-align : justify; "><SPAN>To create a process template, traditionally a user had to follow the standard guide to setup process templates:</SPAN></P><UL><LI>Select <EM>New Entries</EM>.</LI><LI>Enter a <EM>Process Type ID</EM>, a corresponding <EM>Description</EM>, select the <EM>Business Object Type</EM>, and the <EM>Workflow Template</EM> WS54500001.</LI><LI>In the <EM>Process Goal</EM> field, select the goal of a consolidation process.</LI><LI>Decide for the Default Template and the Delete Source indicators.</LI><LI>Save your entries.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_0-1715196188607.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107693i777F456349375DDA/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_0-1715196188607.png" alt="JuanAlonso_0-1715196188607.png" /></span></P><P style=" text-align : justify; "><SPAN>Then to configure said process template a user would have to follow the standard guide to setup its process steps.</SPAN></P><UL><LI>Mark a process type template and choose <EM>Process Template Step</EM></LI><LI>Select <EM>New Entries</EM>.</LI><LI>Enter a <EM>Step Number</EM>.</LI><LI>Select a <EM>Process Step Type</EM> using the input help.</LI><LI>Select a corresponding <EM>Adapter </EM>using the input help.</LI><LI>Select a corresponding <EM>Configuration ID</EM>.</LI><LI>If you want the process to stop after finalizing this process step set the <EM>Check Point</EM> indicator.</LI><LI>If you want to assign an <EM>Authorization Group </EM>to the process step use the entry help to select an authorization group.</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_1-1715196371939.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107694iA55B1DCBD5823976/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_1-1715196371939.png" alt="JuanAlonso_1-1715196371939.png" /></span></P><P style=" text-align : justify; "><SPAN>Pertinent configurations specific to each step type are identified by the Configuration ID. If a user would like to visualize the details for each configuration or create a new one, they would have to navigate to the MDCIMG t-code and select the activity related to the step type desired to configure.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_2-1715196421394.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107695i143D6A750ACA376B/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_2-1715196421394.png" alt="JuanAlonso_2-1715196421394.png" /></span></P><P style=" text-align : justify; "><SPAN>Then a user would have to navigate the list of configurations and select the config id chosen in the process template and double-click it to visualize its detailed settings.</SPAN></P><P style=" text-align: center; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JuanAlonso_3-1715196906890.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107698i2F655A31351A7768/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_3-1715196906890.png" alt="JuanAlonso_3-1715196906890.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_4-1715197157355.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107700i08F2A08B59A4CC24/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_4-1715197157355.png" alt="JuanAlonso_4-1715197157355.png" /></span></P><P style=" text-align : justify; "><SPAN>The Master Data Consolidation (MDC) tile on RDG streamlines this whole process by allowing users to create and delete process templates, process steps and its configurations within a single and intuitive screen and define a specific template that outlines the steps and configurations for executing a master data consolidation process.</SPAN></P><P style=" text-align : justify; "><SPAN>STEP 1. On the Main screen click on the MDC Tile.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_5-1715197283057.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107701iBBDEFB89E1309B18/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_5-1715197283057.png" alt="JuanAlonso_5-1715197283057.png" /></span></P><P style=" text-align : justify; ">STEP 2. Click on the plus icon to add a new process template.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_6-1715197380984.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107702iA75CB27BEA7FFE6C/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_6-1715197380984.png" alt="JuanAlonso_6-1715197380984.png" /></span></P><P style=" text-align : justify; "><SPAN>STEP 3. Input process template name and description and choose a Business Object Type (BO Type).</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_7-1715197522464.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107703iE4C6A9F304D0BDF8/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_7-1715197522464.png" alt="JuanAlonso_7-1715197522464.png" /></span></P><P style=" text-align : justify; "><SPAN>STEP 4. Select a process goal and </SPAN>decide for the Default Template and the Delete Source indicators.</P><P style=" text-align : justify; "><SPAN>Process Goal refer to the specific objectives or outcomes that organizations aim to achieve through the implementation of process templates. Depending on the goal selected the user might need to also select a strategy.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_8-1715197564214.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107704iDB9C47392AA3AAF0/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_8-1715197564214.png" alt="JuanAlonso_8-1715197564214.png" /></span></P><P style=" text-align : justify; "><SPAN>STEP 5. To add a process step click on the Add button, select a step type, input a description and make selections for Adapter, Config ID, Action Control and Authorization Group.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_9-1715197607965.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107705iE791EC213BBC10DA/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_9-1715197607965.png" alt="JuanAlonso_9-1715197607965.png" /></span></P><P style=" text-align : justify; "><SPAN>STEP 6. Add extra process steps to meet the business requirement and goal of the consolidation prosses.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_10-1715197647986.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107706i35FA640BEEBB24E9/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_10-1715197647986.png" alt="JuanAlonso_10-1715197647986.png" /></span></P><P style=" text-align : justify; "><SPAN>STEP 7. If needed, user can create and/or visualize the configurations for steps. To visualize the details of a selected configuration, click on the View Details pencil icon. To create a configuration, select “Custom – Create configuration” from the list of configurations. </SPAN></P><P style=" text-align : justify; "><FONT size="3">NOTE: At the time of publishing this blog, RDG supports configurations for steps of type: <STRONG>Activation</STRONG>, <STRONG>Filter</STRONG> <STRONG>and</STRONG> <STRONG>Remove</STRONG>, <STRONG>Best Record Calculation</STRONG> and <STRONG>Evaluation</STRONG>. More to come in future updates.</FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_11-1715198020316.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107710iFBD92888922975BA/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_11-1715198020316.png" alt="JuanAlonso_11-1715198020316.png" /></span></P><P style=" text-align : justify; "><SPAN>Details of a Best Record Calculation configuration:</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_13-1715198090351.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107712i6DB4DDB953434F2D/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_13-1715198090351.png" alt="JuanAlonso_13-1715198090351.png" /></span></P><P style=" text-align : justify; "><SPAN>Details of a Filter and Remove configuration:</SPAN></P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_14-1715198132457.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107713iD3A32F9427DFA002/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_14-1715198132457.png" alt="JuanAlonso_14-1715198132457.png" /></span></P><P style=" text-align : justify; "><SPAN>Details of an Activation configuration:</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_15-1715198202258.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107714iFBF67E3F2010DC35/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_15-1715198202258.png" alt="JuanAlonso_15-1715198202258.png" /></span></P><P style=" text-align : justify; ">STEP 8. Click on save and select a customizing transport from the available list.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_16-1715198424591.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107718i47205F17E1B89AB2/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_16-1715198424591.png" alt="JuanAlonso_16-1715198424591.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="JuanAlonso_17-1715198447393.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107719i6FC2ED4AF45EF096/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_17-1715198447393.png" alt="JuanAlonso_17-1715198447393.png" /></span></P><P style=" text-align : justify; "><SPAN>Using the MDC Tile users can maintain and create process templates in a streamlined and intuitive manner.</SPAN></P><P style=" text-align : justify; ">&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JuanAlonso_18-1715198487923.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107721i015110084F7090C6/image-size/medium?v=v2&amp;px=400" role="button" title="JuanAlonso_18-1715198487923.png" alt="JuanAlonso_18-1715198487923.png" /></span></P><P>&nbsp;</P><P style=" text-align : justify; "><SPAN><A href="https://store.sap.com/dcp/en/product/display-2001014736_live_v1/syniti-rapid-data-governance" target="_blank" rel="noopener noreferrer">Syniti RDG</A></SPAN> <SPAN>is a certified SAP BTP solution and is available on</SPAN> <SPAN><A href="https://store.sap.com/dcp/en/" target="_blank" rel="noopener noreferrer">SAP App Store</A>.&nbsp;</SPAN></P><P style=" text-align : justify; "><SPAN>&nbsp;To know more details about the product, check the blog</SPAN> <SPAN><A href="https://blogs.sap.com/2021/02/05/how-partner-add-on-solutions-enhance-saps-master-data-governance/" target="_blank" rel="noopener noreferrer">Partner Add-on Solutions</A>.&nbsp;</SPAN></P><P style=" text-align : justify; "><SPAN>Your opinions and feedback are highly appreciated and feel free to post them in comment section.&nbsp;</SPAN></P><P style=" text-align : justify; "><SPAN>Please follow and read more interesting blogs on</SPAN> <SPAN><A href="https://blogs.sap.com/tags/67837800100800004488/" target="_blank" rel="noopener noreferrer">SAP Master Data Governance | SAP | SAP Blogs.</A></SPAN></P><P style=" text-align : justify; "><SPAN>You can also find and post questions about the product here:</SPAN> <SPAN><A href="https://answers.sap.com/tags/67837800100800004488" target="_blank" rel="noopener noreferrer">SAP Master Data Governance Community.</A></SPAN></P><P>&nbsp;</P><P>&nbsp;</P> 2024-05-14T10:41:20.003000+02:00 https://community.sap.com/t5/technology-blogs-by-members/syniti-rdg-provides-an-effortless-way-to-create-data-model-extension/ba-p/13696183 Syniti RDG provides an effortless way to create Data Model extension. 2024-05-16T09:08:22.041000+02:00 HectorHerGar https://community.sap.com/t5/user/viewprofilepage/user-id/1389702 <P style=" text-align : justify; "><SPAN>In SAP Master Data Governance data can be stored in a staging or active area. Extending the data model with custom attributes or tables involves changes to the data structures in both the active and staging areas and defining a mapping between these data structures.</SPAN></P><P style=" text-align : justify; "><SPAN>T</SPAN><SPAN>raditionally, a user must perform the following steps to assign&nbsp;to do this configuration&nbsp;in SAP MDG System.&nbsp;&nbsp;</SPAN></P><UL style=" text-align : justify; "><LI><SPAN>Extending active area data model</SPAN></LI><LI><SPAN>Extending staging area data model</SPAN></LI><LI><SPAN>Generating MDG tables</SPAN></LI><LI><SPAN>Defining mapping from Staging to Active area</SPAN></LI><LI><SPAN>Defining mapping from Active to Staging area</SPAN></LI></UL><P style=" text-align : justify; "><SPAN>RDG provides the solution to extend SMT Mapping with an intuitive, user-friendly, and graphical interface.</SPAN></P><P style=" text-align : justify; "><SPAN>After a custom attribute is created and activated in either Business Partner or Material data models, an entity table for SMT mapping will be shown if applicable.&nbsp;</SPAN><SPAN>(SMT mapping is not relevant for attributes created under all entities).</SPAN></P><P style=" text-align : justify; ">&nbsp;</P><OL style=" text-align : justify; "><LI><SPAN>After custom attribute is created and activation is complete&nbsp;</SPAN><SPAN>mapping table will be shown.</SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="HectorHerGar_0-1715248529844.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107919iD5263910CBBC92D0/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_0-1715248529844.png" alt="HectorHerGar_0-1715248529844.png" /></span><P>&nbsp;</P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="HectorHerGar_1-1715248529739.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107920iBD1520882E0042F9/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_1-1715248529739.png" alt="HectorHerGar_1-1715248529739.png" /></span></LI><LI><SPAN>Complete the mapping table by selecting a mapping step and structure to extend for each row. Source and Target will automatically populate. Click&nbsp;</SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="HectorHerGar_2-1715248529518.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107921iC1E522D76F487E46/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_2-1715248529518.png" alt="HectorHerGar_2-1715248529518.png" /></span><P>&nbsp;</P><SPAN>&nbsp;at the end of each row.<BR /></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="HectorHerGar_3-1715248529922.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107922i370A90B9C82D44AA/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_3-1715248529922.png" alt="HectorHerGar_3-1715248529922.png" /></span></LI><LI><SPAN>Click Done. Processing may take some time to complete. Click Refresh&nbsp;</SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="HectorHerGar_4-1715248529520.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107924iD1AA2BD5A1DCA6CF/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_4-1715248529520.png" alt="HectorHerGar_4-1715248529520.png" /></span><SPAN>&nbsp;when ready and receive success messages. If running the application using a cloud platform, additional notifications will be given to help you track the process</SPAN><SPAN>.&nbsp; &nbsp;</SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="HectorHerGar_5-1715248529777.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107923i5BA26E1B9C24B901/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_5-1715248529777.png" alt="HectorHerGar_5-1715248529777.png" /></span></LI><LI>Extension, transformation and mapping are created correctly</LI></OL><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="HectorHerGar_6-1715248529745.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107926iEB1FD6B339D778F0/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_6-1715248529745.png" alt="HectorHerGar_6-1715248529745.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="HectorHerGar_7-1715248529933.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107927i22CADBE6141F3311/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_7-1715248529933.png" alt="HectorHerGar_7-1715248529933.png" /></span></P><P style=" text-align : justify; ">&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="HectorHerGar_8-1715248529789.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/107925i518D022AD102053E/image-size/medium?v=v2&amp;px=400" role="button" title="HectorHerGar_8-1715248529789.png" alt="HectorHerGar_8-1715248529789.png" /></span></P><P style=" text-align : justify; "><A href="https://store.sap.com/dcp/en/product/display-2001014736_live_v1/syniti-rapid-data-governance" target="_blank" rel="noopener noreferrer"><SPAN>Syniti RDG</SPAN></A><SPAN> is a certified SAP BTP&nbsp;</SPAN><SPAN>solution</SPAN><SPAN>&nbsp;on the </SPAN><A href="https://store.sap.com/dcp/en/" target="_blank" rel="noopener noreferrer"><SPAN>SAP App Store</SPAN></A><SPAN>.</SPAN><SPAN>&nbsp;</SPAN></P><P style=" text-align : justify; "><SPAN>To know more details about the product, check the blog </SPAN><A href="https://blogs.sap.com/2021/02/05/how-partner-add-on-solutions-enhance-saps-master-data-governance/" target="_blank" rel="noopener noreferrer"><SPAN>Partner Add-on Solutions</SPAN></A><SPAN>.</SPAN><SPAN>&nbsp;</SPAN></P><P style=" text-align : justify; "><SPAN>Your opinions and feedback are highly appreciated, and feel free to post them in the comment section.</SPAN><SPAN>&nbsp;</SPAN></P><P style=" text-align : justify; "><SPAN>Please follow and read more interesting blogs on </SPAN><A href="https://blogs.sap.com/tags/67837800100800004488/" target="_blank" rel="noopener noreferrer"><SPAN>SAP Master Data Governance | SAP | SAP Blogs</SPAN></A><SPAN>&nbsp;</SPAN></P><P style=" text-align : justify; "><SPAN>You can also find and post questions about the product here: </SPAN><A href="https://answers.sap.com/tags/67837800100800004488" target="_blank" rel="noopener noreferrer"><SPAN>SAP Master Data Governance Community</SPAN></A><SPAN>&nbsp;</SPAN></P> 2024-05-16T09:08:22.041000+02:00 https://community.sap.com/t5/technology-blogs-by-members/how-to-use-the-odata-api-for-exchanging-messages-from-logs-and-the/ba-p/13700347 How to use the OData-API for exchanging Messages from Logs and the Datastore in Integration Suite 2024-05-16T09:36:10.757000+02:00 JoergHopmann https://community.sap.com/t5/user/viewprofilepage/user-id/1427690 <P>In this blog I will show the basic steps and components to access the&nbsp;<EM>MessageProcessingLog</EM> and the attached messages, wether they are stored in the log itself, in the <EM>MessageStore</EM> or in the <EM>DataStore.</EM></P><P><EM>Later in further blogs I will go into details and show some specific implementations and will compare the different types of message-stores. So please be patient and check back for further information.</EM></P><P><EM>The starting point is in the&nbsp;<A title="SAP Business Accelerator Hub" href="https://api.sap.com/" target="_blank" rel="noopener noreferrer">SAP Business Accelerator Hub</A>.</EM>&nbsp;There is an API package&nbsp;<EM>SAP Cloud Integration</EM> which offers some OData APIs in Version 2. We are focussing on the&nbsp;<EM>Message Processing Logs and download the definition of, what is called here a vdm - virtual data model. I don't want to go deeper in the edmx, only so far, if you search on your fav. search-engine you may get the following statement:</EM></P><P style=" padding-left : 30px; "><EM>edmx file is&nbsp;<STRONG>an XML file that defines an Entity Data Model (EDM), describes the target database schema, and defines the mapping between the EDM and the database</STRONG>.</EM></P><P>On the Business Accelerator Hub you can find tons of documentation about how to use the source code generator in maven, on how to build up (in this case) java-classes, test the API online, with a sandbox or with your own tenant and even code-snippets in many different languages can be downloaded.</P><P>In our scenario we build a client in the Netweaver Development Studio. Then maven-support is initially not part of it but can be added. Search for the keyword M2E. A good starting point on how to generate the client classes (vdm - virtual data model) and how to generate a project from a Maven archetype is on&nbsp;<A title="SAP GitHub" href="https://sap.github.io/cloud-sdk/docs/java/getting-started" target="_blank" rel="noopener nofollow noreferrer">sap.github.io</A>&nbsp;.</P><P>The overall framework for the implementation here is an OnPremise fat-client, but everything can run deployed on a BTP tenant, only the GUI frontend needs to be changed.</P><P>What you get when generating the sources for your client is the following helper-packages and classes and a&nbsp;<EM>MessageProcessingLogsService</EM>:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MessageProcessingLogs.jpg" style="width: 357px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/110098i575C94E176F082B6/image-dimensions/357x349?v=v2" width="357" height="349" role="button" title="MessageProcessingLogs.jpg" alt="MessageProcessingLogs.jpg" /></span></P><P>There are several steps to consider for enhancing your pom-file: Dependencies and plugins. E.g. here:&nbsp;<A href="https://community.sap.com/t5/technology-blogs-by-sap/sap-cloud-application-programming-model-deep-insert-5-consume-remote/ba-p/13419185" target="_blank">SAP Cloud Application Programming Model: Deep Insert (5) Consume Remote Service with SAP Cloud SDK</A>&nbsp;</P><P>The starting point here is the method getAllMessageProcessingLogs()</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="methods.jpg" style="width: 361px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/110106i339EF188623F8803/image-dimensions/361x432?v=v2" width="361" height="432" role="button" title="methods.jpg" alt="methods.jpg" /></span></P><P>Depending on wether the code runs on your local laptop or in the cloud, you have to create a destination first:</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-java"><code>import com.sap.cloud.sdk.cloudplatform.connectivity.AuthenticationType; import com.sap.cloud.sdk.cloudplatform.connectivity.DefaultHttpDestination; import com.sap.cloud.sdk.cloudplatform.connectivity.HttpDestination; import com.sap.cloud.sdk.cloudplatform.security.BasicCredentials; (...) public DefaultHttpDestination getDestination() throws IllegalArgumentException { if (destination == null) { if (this instanceof BasicAuthentication) { destination = DefaultHttpDestination.builder(tenant.getURL()) .authenticationType(AuthenticationType.BASIC_AUTHENTICATION) .basicCredentials(new BasicCredentials(((BasicAuthentication)this).getUser(), ((BasicAuthentication)this).getPassword())) .keyStore(keystore) .build(); } } return destination; }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>(On your tenant you can use the&nbsp;<EM>DestinationService)</EM></P><P>With the destination described above we can request all packages and artifacts. As for now the request is sent by&nbsp;<EM>getAllIntegrationRuntimeArtifacts(). This includes iFlows but also Rest-APIs and more. </EM></P><P><EM>Unfortunately</EM></P><UL><LI><EM>runtime-artifacts do not point to any package</EM></LI><LI><EM>designtime-artifacts are called from a package-perspective but do not include some types like Rest-APIs.&nbsp;</EM></LI></UL><P><EM>(Status on 2024-05-24 is a response of HTTP 501 - not yet implemented. the dev is seems still working on putting everything in place)</EM></P><P><EM>Hence we have a gap of links between packages and artifacts, in case they are not iFlows (e.g. Rest-Api).&nbsp;</EM>The following code puts "everything" together as complete as possible and attaches the artifacts without a link to a package into a virtual package named "&lt;unknown&gt;"</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-java"><code>//create Hashtable for storing our version of packages designPackages = new Hashtable&lt;String, DesignPackage&gt;(); if (authentication != null) { //get url String tenantURL = authentication.getTenant().getRuntimeURL(); //create destination DefaultHttpDestination destination = authentication.getDestination(); //create the services generated in the vdm IntegrationContentService iCS = new DefaultIntegrationContentService().withServicePath("/api/v1/"); //create Hashtable for storing our version of runtime artifacts Hashtable&lt;String, IntegrationRuntimeArtifact&gt; ira_table = new Hashtable&lt;String, IntegrationRuntimeArtifact&gt;(); //retrieve all packages, execute the network-request try { final List&lt;IntegrationPackage&gt; ip = iCS.getAllIntegrationPackages() .executeRequest(destination); //retrieve all runtime artifacts final List&lt;IntegrationRuntimeArtifact&gt; ira = iCS.getAllIntegrationRuntimeArtifacts() .executeRequest(destination); //and put them in the table for (IntegrationRuntimeArtifact ira_iter : ira) ira_table.put(ira_iter.getId(), ira_iter); //iterate over all packages for (IntegrationPackage ip_iter : ip) { //store it in our Hashtable DesignPackage dp = new DesignPackage(ip_iter); designPackages.put(dp.getName(), dp); //get artifacts for this package final List&lt;IntegrationDesigntimeArtifact&gt; ida = ip_iter.getIntegrationDesigntimeArtifactsOrFetch(); //set artifacts as child to the package for (IntegrationDesigntimeArtifact ida_iter : ida) { String url = tenantURL + "/http/" + ida_iter.getId(); Artifact a = new Artifact(ida_iter, url); dp.addArtifact(a); //remove from the list of runtime artifacts ira_table.remove(a.getId()); } } //add remaining artifacts not linked to any package if (ira_table.size() &gt; 0) { //default package IntegrationPackage integrationPackage = new IntegrationPackage(); integrationPackage.setName("&lt;unknown&gt;"); defaultDesignPackage = new DesignPackage(integrationPackage); designPackages.put(defaultDesignPackage.getName(), defaultDesignPackage); Enumeration&lt;String&gt; t = ira_table.keys(); while (t.hasMoreElements()) { String iraId = t.nextElement(); Artifact a = new Artifact((IntegrationRuntimeArtifact)ira_table.get(iraId), tenantURL + "/http/" + iraId + "/*"); defaultDesignPackage.addArtifact(a); } } } catch (com.sap.cloud.sdk.datamodel.odata.client.exception.ODataConnectionException e) { } catch (ODataException e) { } catch (Exception e) { } }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>Having all packages and artifacts in place, we can get a (filtered) set of log-entries:</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-java"><code>/** * Returns an ArrayList of LogEntries. * The list is based on the filtering. * &lt;p&gt; * This methods processing-time depends on the amount of data requested from BTP. * The status should be set on the GUI for user-information. * In future releases this method will work in a background-task. * * authentication object relevant for login and serving a destination based on this creds * logListFilter the object for filtering the requested logs, i.e. datetime and number of entries * @return ArrayList of LogEntries. */ public ArrayList&lt;LogEntry&gt; updateMessageProcessingLog(Authentication authentication, LogListFilter logListFilter) { ArrayList&lt;LogEntry&gt; logEntries = new ArrayList&lt;LogEntry&gt;(); if (authentication != null) { MessageProcessingLogFluentHelper mPLFH = mPLS.getAllMessageProcessingLogs(); //logs should be filtered always by artifact-id (which is unique) if (logListFilter.getArtifact() != null) mPLFH = mPLFH.filter(MessageProcessingLog.INTEGRATION_FLOW_NAME.eq(logListFilter.getArtifact().getId())); //number of results limited by number? if (logListFilter.getCountFilterEnabled()) { mPLFH = mPLFH .skip(logListFilter.getCountFilterFrom() - 1) .top(logListFilter.getCountFilterTo()); } //filtered by date? if (logListFilter.getDateFilterEnabled()) { //set start and end, logListFilter returns a @LocalDateTime mPLFH = mPLFH.filter(MessageProcessingLog.LOG_START.gt(logListFilter.getDateTimeFilterStart())); mPLFH = mPLFH.filter(MessageProcessingLog.LOG_END.lt(logListFilter.getDateTimeFilterEnd())); } //the result is always ordered ascending by the LogEnd mPLFH = mPLFH.orderBy(MessageProcessingLog.LOG_END, Order.ASC); final List&lt;MessageProcessingLog&gt; mpl = mPLFH.executeRequest(authentication.getDestination()); for (MessageProcessingLog mpl_iter : mpl) { logEntries.add(new LogEntry(mpl_iter)); try { List&lt;MessageStoreEntry&gt; messageStoreEntries = mpl_iter.fetchMessageStoreEntries(); if (messageStoreEntries != null) for (MessageStoreEntry mse : messageStoreEntries) { List&lt;MessageStoreEntryAttachment&gt; mSEAs = mse.fetchAttachments(); //in future releases &lt;do_something&gt; with the MessageStoreEntries and their attachments } } catch(com.sap.cloud.sdk.datamodel.odata.client.exception.ODataResponseException e) { System.out.println("com.sap.cloud.sdk.datamodel.odata.client.exception.ODataResponseException"); } } } return logEntries; }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>The result, shown as a Java-GUI is as following:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="BTPcl_1.jpg" style="width: 932px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/111014iC71D40AF1B8A522E/image-size/large?v=v2&amp;px=999" role="button" title="BTPcl_1.jpg" alt="BTPcl_1.jpg" /></span></P><P>The java-object MessageProcessingLog and corresponding ..Attachment is based on the classes automatically created within the generator-plugin:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MPLAttachment.jpg" style="width: 461px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/110314i73328775844145E0/image-dimensions/461x138?v=v2" width="461" height="138" role="button" title="MPLAttachment.jpg" alt="MPLAttachment.jpg" /></span>&nbsp;</P><P>With that code we can retrieve the payload on any message starting from object MessageProcessingLog retrieve a MessageProcessingLogAttachment with the following code:</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-java"><code>import com.sap.cloud.sdk.datamodel.namespaces.messageprocessinglogs.MessageProcessingLog; import com.sap.cloud.sdk.datamodel.namespaces.messageprocessinglogs.MessageProcessingLogAttachment; (...) //the messageprocessinglog returns a java-List of attachments List&lt;MessageProcessingLogAttachment&gt; mplAttachments = null; try { mplAttachments = messageProcessingLog.fetchAttachments(); //create a Hashtable which we use to store a local object version of attachment, keys derived from the attachment-name attachments = new Hashtable&lt;String, LogAttachment&gt;(); for (MessageProcessingLogAttachment mpla_iter : mplAttachments) { LogAttachment logAttachment = new LogAttachment(mpla_iter); //use the name as key and put the attachment in the hashtable attachments.put(mpla_iter.getName(), logAttachment); //this logEntry has an attachment hasAttachment = true; } isPrepared = true; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>Different to the previous approaches, the attachment itself (payload) is not provided as a java-object, but by an InputStream. It will be stored in a String and returned by a getter:</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-java"><code>//the constructor gets the 'mpla' when instantiated public LogAttachment(MessageProcessingLogAttachment mpla) { this.mpla = mpla; } //prepare the payload seperate from the getter (for caching purpose) public void preparePayload() { InputStream is; try { is = mpla.fetchMediaStream(); if ( is instanceof ByteArrayInputStream) { int n; try { n = is.available(); byte[] bytes = new byte[n]; is.read(bytes, 0, n); payload = new String(bytes, StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } } } catch (ODataException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //getter for returning the payload as a String //Todo for a future release: what happens if a payload is 'big'? Let's say &gt; 10mb. //We don't want to store that in memory in a String!? public String getPayload() { if (payload == null) preparePayload(); return payload; }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>Based on the code shown in this blog any app can download, show and also re-send the payload to it's origin:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JoergHopmann_0-1715688559247.png" style="width: 457px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/110185i69D124D0222BF189/image-dimensions/457x297?v=v2" width="457" height="297" role="button" title="JoergHopmann_0-1715688559247.png" alt="JoergHopmann_0-1715688559247.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="resend.jpg" style="width: 501px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/110333i1576C9A01B5CFD57/image-dimensions/501x287?v=v2" width="501" height="287" role="button" title="resend.jpg" alt="resend.jpg" /></span></P><P>&nbsp;</P><P>Stay tuned for further blogs describing details. Don't hesitate to request details in which you are interested.</P><P>Best regards Jörg Hopmann</P><P>&nbsp;</P> 2024-05-16T09:36:10.757000+02:00 https://community.sap.com/t5/technology-blogs-by-members/syniti-rdg-provides-a-simplified-design-to-create-multi-value-validation/ba-p/13675776 Syniti RDG provides a simplified design to create Multi Value Validation and Derivation Rules 2024-05-17T12:35:22.385000+02:00 UmaArjunan https://community.sap.com/t5/user/viewprofilepage/user-id/1096 <P style=" text-align : justify; "><A href="https://www.sapappcenter.com/apps/59234" target="_blank" rel="noopener nofollow noreferrer">Syniti RDG</A>&nbsp;is an SAP-endorsed application on the Business Technology Platform (SAP BTP) to facilitate MDG<BR />implementation with intuitive UI and process automation. RDG automates many of the technical configuration<BR />steps that are required to implement SAP MDG and it offers a user-friendly interface to be more relatable<BR />to business users.</P><UL><LI>A multi-value check rule is for validating multiple attribute values against a logical condition.</LI><LI>A multi value derivation rule is to derive multiple attributes values based on a logical condition.</LI></UL><P>The below example is used to create Multi value validation to be triggered for a specific Change Request Type<BR />to validate attribute values of Entity&nbsp;‘BP_CENTRL’ of data model ‘BP’.</P><P>Step 1: Create <STRONG>Multi Validation Rule</STRONG> in Syniti RDG&nbsp;</P><P>In the main menu, select "Manage Business Rules".</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="pic1.png" style="width: 754px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108593i543DCD1C97325410/image-dimensions/754x166?v=v2" width="754" height="166" role="button" title="pic1.png" alt="pic1.png" /></span></P><P>In the business Rules Page, define a New Rule: Start by creating a new rule, select the type of rule as "Multivalue Check Rule" to create.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="fin_pic12.png" style="width: 929px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108596iA44AC91EC25F4D6E/image-size/large?v=v2&amp;px=999" role="button" title="fin_pic12.png" alt="fin_pic12.png" /></span></P><P>In the following steps, the user can choose a Change request type from the list and select the entity for which<BR />the rule must be created. The user then needs to select the type of Business Rule that he/she wants to create,<BR />Mutli Value Check Rule to create Validation Rule in BRFPlus and Derivation Rule to create Derivation Rule in<BR />BRFPlus.</P><P>Select Data model as ‘BP’, ‘ZBP1P1V1’ CR Type (select relevant CR type as required) , Entity as ‘BP_CENTRL’,<BR />Rule type: Multi Value Validation and then click on an option like "Rule1” to start defining a new validation rule.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="fin_pic1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108611i155E061221F1806D/image-size/large?v=v2&amp;px=999" role="button" title="fin_pic1.png" alt="fin_pic1.png" /></span></P><P>Business Scenario: Only Green business partners are allowed to create. Choose the attributes<BR />BP_CENTRL~NAME_ORG1 that needs to be validated. If BP_CENTRL~NAME_ORG1 = ‘RED’, send a warning message ‘Enter name1 as Green’</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="fin_pic2.png" style="width: 746px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108615i2EF3FE33E5D34B80/image-dimensions/746x302?v=v2" width="746" height="302" role="button" title="fin_pic2.png" alt="fin_pic2.png" /></span></P><P>Click’+’ to create "Rule2” validation rule. If BP_CENTRL~NAME_ORG1 = ‘YELLOW’, send a warning message ‘Enter name1 as Green’</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="fin_pic3.png" style="width: 734px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108617i3C5E9E714B9B7E4F/image-dimensions/734x300?v=v2" width="734" height="300" role="button" title="fin_pic3.png" alt="fin_pic3.png" /></span></P><P>Click’+’ to create "Rule3” validation rule. Define a new condition&nbsp;</P><P>If BP_CENTRL~NAME_ORG1 = ‘GREEN’ and BP_CENTRL~NAME_ORG2 != ‘CORP’ , When the conditions are not met,&nbsp;send error message ‘Enter name2 as CORP’</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="fin_pic4.png" style="width: 742px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108620iE7E2DCC99E01F9D8/image-dimensions/742x286?v=v2" width="742" height="286" role="button" title="fin_pic4.png" alt="fin_pic4.png" /></span></P><P>Multi value validation BADI implementation has bee created in the back end automatically to check the multi value validation.</P><P>Step 2: Trigger the rule in nwbc application.&nbsp;</P><UL><LI>The rules created in the previous step are triggered when creating a Change Request of the type for which&nbsp;the rules are created in RDG (ZBP1P1V1).</LI></UL><P>Validation Rule1 :</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mv_nwbc_pic1.png" style="width: 731px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108629i178072F76875D494/image-dimensions/731x344?v=v2" width="731" height="344" role="button" title="mv_nwbc_pic1.png" alt="mv_nwbc_pic1.png" /></span></P><P>Now name1 is entered as GREEN, Error message appears for name 2</P><P>Validation Rule3:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mv_nwbc_pic2.png" style="width: 737px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108634iB2DEA78722B234D6/image-size/large?v=v2&amp;px=999" role="button" title="mv_nwbc_pic2.png" alt="mv_nwbc_pic2.png" /></span></P><P>After successful verification of Validation Rule1 &amp; Rule 3 , ‘No Errors found’<span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mv_nwbc_pic3.png" style="width: 739px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108633iED4E117BC6D209DF/image-size/large?v=v2&amp;px=999" role="button" title="mv_nwbc_pic3.png" alt="mv_nwbc_pic3.png" /></span></P><P>Below is the Decision table that got automatically generated in BRFPlus through Syniti RDG.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="fin_pic7_mv.png" style="width: 750px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108635iE712BA4A3B370436/image-dimensions/750x354?v=v2" width="750" height="354" role="button" title="fin_pic7_mv.png" alt="fin_pic7_mv.png" /></span></P><P>Validation Rules created in FMDM Catalog automatically in decision table format</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="fin_pic6_mv.png" style="width: 765px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108637i92E0477F9A9C61C8/image-dimensions/765x360?v=v2" width="765" height="360" role="button" title="fin_pic6_mv.png" alt="fin_pic6_mv.png" /></span></P><P><STRONG>Multi Derivation Rule:</STRONG> Most of the steps are similar to Multi Validation rules, except here we have to mention<BR />the multiple deriving attributes which is derived based on satisfying certain condition</P><P>In the business Rules Page, define a New Rule: Start by creating a new rule, select the type of rule as "Multi Value Derivation Rule" to create.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="MD_NEW_PIC.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108719i2752A91543C98B95/image-size/large?v=v2&amp;px=999" role="button" title="MD_NEW_PIC.png" alt="MD_NEW_PIC.png" /></span></P><P><STRONG>Step 1 :</STRONG> Select Data model as ‘BP’, ‘ZBP1P1V1’ CR Type (select relevant CR type as required) , Entity as ‘BP_CENTRL’,<BR />Rule type: Multi Derivation and then click on an option like "Rule1” to start defining a new derivation rule.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="md_fin_pic11.png" style="width: 939px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108653i10A98D57F0ECC35A/image-size/large?v=v2&amp;px=999" role="button" title="md_fin_pic11.png" alt="md_fin_pic11.png" /></span></P><P>Business Scenario: For all Green business partners, derive multiple attributes like Salutation, Title, BU search term1,<BR />BU search term2 through multi value validation rules, for the ease of understanding, simple business derivations rules are taken and<BR />explained here, there is no restriction to create multiple rules with multiple condition.</P><P>If BP_CENTRL~NAME_ORG1 = ‘GREEN’, following attributes will be derived automatically upon successful validation rules&nbsp;</P><P>BP_CENTRL~BU_SORT1,&nbsp;BP_CENTRL~BU_SORT2,&nbsp;BP_CENTRL~TITLE_LET,&nbsp;BP_CENTRL~TITLE_BP</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="md_fin_pic4(derived attributes.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108664iE083D6CC526932F3/image-size/large?v=v2&amp;px=999" role="button" title="md_fin_pic4(derived attributes.png" alt="md_fin_pic4(derived attributes.png" /></span></P><P>After saving the Mutli value derivation business rule thru RDG,&nbsp;Multi value derivation BADI implementation has been<BR />created / updated in the back end automatically to derive multiple attributes&nbsp;&nbsp;</P><P>Step 2: Trigger the rule in NWBC application.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="md_fin_pic3(derived values).png" style="width: 757px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108665i19E9ED2C1B60CED2/image-dimensions/757x356?v=v2" width="757" height="356" role="button" title="md_fin_pic3(derived values).png" alt="md_fin_pic3(derived values).png" /></span></P><P>Multi Value Derivation Rules created in FMDM Catalog automatically in decision table format</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="md_fin_pic7_brf_plus_decision table.png" style="width: 755px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108666i3FA86DDEC6EE0871/image-dimensions/755x355?v=v2" width="755" height="355" role="button" title="md_fin_pic7_brf_plus_decision table.png" alt="md_fin_pic7_brf_plus_decision table.png" /></span></P><P>With the help of Syniti RDG, you can now create multi value validation / derivation rules without the effort of creating<BR />Custom BADI implementation in the backend and it simplifies the way of creating decision tables automatically&nbsp;in BRFPlus.</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="SAP Endorsed logo.png" style="width: 403px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/108716iAD11FBE668E11017/image-dimensions/403x76?v=v2" width="403" height="76" role="button" title="SAP Endorsed logo.png" alt="SAP Endorsed logo.png" /></span></P><P>&nbsp;</P><P>&nbsp;</P><P><A href="https://store.sap.com/dcp/en/product/display-2001014736_live_v1/syniti-rapid-data-governance" target="_blank" rel="noopener noreferrer"><SPAN>Syniti RDG</SPAN></A><SPAN> is a certified SAP BTP solution and is available on </SPAN><A href="https://store.sap.com/dcp/en/" target="_blank" rel="noopener noreferrer"><SPAN>SAP App Store</SPAN></A><SPAN>.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>&nbsp;</SPAN><SPAN>To know more details about the product, check the blog </SPAN><A href="https://blogs.sap.com/2021/02/05/how-partner-add-on-solutions-enhance-saps-master-data-governance/" target="_blank" rel="noopener noreferrer"><SPAN>Partner Add-on Solutions</SPAN></A><SPAN>.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Your opinions and feedback are highly appreciated and feel free to post them in the comment section.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Please follow and read more interesting blogs on </SPAN><A href="https://blogs.sap.com/tags/67837800100800004488/" target="_blank" rel="noopener noreferrer"><SPAN>SAP Master Data Governance | SAP | SAP Blogs</SPAN></A><SPAN>&nbsp;</SPAN></P><P><SPAN>You can also find and post questions about the product here: </SPAN><A href="https://answers.sap.com/tags/67837800100800004488" target="_blank" rel="noopener noreferrer"><SPAN>SAP Master Data Governance Community</SPAN></A><SPAN>&nbsp;</SPAN><SPAN>&nbsp;</SPAN></P> 2024-05-17T12:35:22.385000+02:00