How to setup file upload planning sequence from SAPUI5 – Part 1
Introduction
In our customer projects at Consetto, we are often faced with the requirement to provide a file upload for the plan data in BW-IP or BPC. The WebDynpro based file upload from Marc Bernard is a really good solution for this requirement. However, sometimes customers ask for changes in the user interface of the existing file upload solution or support for mobile devices, responsive design, etc. That is why we thought it is worth trying to have a solution which allows to call a planning sequence from SAPUI5 frontend.
In this blog post I will explain how we can use a SAPUI5 application to communicate with an OData service for the execution of a planning sequence in BW-Integrated Planning. I will also demonstrate how to upload file data to the OData service which will be used later in the second part of the blog series. The main goal of the blog series is to do a flat file upload into BW-Integrated Planning using Planning Sequence from SAPUI5.
ABAP Setup
Go to SE11 and create the following DD structure for planning function execution file upload.This will be used later in the gateway service.
Gateway Setup
Open the transaction SEGW and create a new project. Right click on the ‘Data Model’ and select Import -> ‘DDIC structure’. Enter name for the entity type and the name of the ABAP structure created in the previous step and click Next. Select all data source parameters and click next. In the next screen, check ‘is Key’ for all the parameters and click on Finish.
Click on ‘Generate Runtime Objects’ so that the DPC_EXT and MPC_EXT artifacts are generated for service implementation.
From the ‘Runtime Artifacts’ go to MPC_EXT class and redefine the method ‘DEFINE’. This is done to set the content type for the entity. We set the type to ‘Mimetype’ which is one of the properties for our entity. The code for MPC_EXT can be found here: MPC_EXT
Register your newly created service in the TCODE ‘/IWFND/MAINT_SERVICE’ and activate it. For testing it, you can use the TCODE ‘/IWFND/GW_CLIENT’
SAPUI5 Setup
XML code for creating an input field for planning sequence name and simple file uploader:
<mvc:View controllerName="bi_file_upload.main" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc" displayBlock="true"
xmlns="sap.m" xmlns:l="sap.ui.layout.form" xmlns:v="sap.ui.layout" xmlns:u="sap.ui.unified">
<App>
<pages>
<Page title="File Upload">
<content>
<MessageStrip
text=""
id="msg_strip"
showIcon="true"
showCloseButton="true"
class="sapUiMediumMarginBottom">
</MessageStrip>
<l:SimpleForm editable="true">
<l:content>
<Label text="Planning sequence name" required="true">
</Label>
<Input id="PlanningSequence" width="50%" placeholder="Enter the sequence name"></Input>
<Label text="File" required="true">
</Label>
<VBox>
<u:FileUploader id="FileUploader" width="50%"
sameFilenameAllowed="false" buttonText=""
placeholder="Choose a file" style="Emphasized">
</u:FileUploader>
<Button text="Upload" type="Accept" icon="sap-icon://upload" press="onUpload"></Button>
</VBox>
</l:content>
</l:SimpleForm>
</content>
</Page>
</pages>
</App>
</mvc:View>
The above code gives the following view for our application:
In the controller, we get the selected file and the sequence name:
Following is the code to convert the file contents to base64 and send it to the backend. Please note that we first need to fetch the CSRF token before making the file upload request.
// Create a File Reader object
var file_reader = new FileReader();
file_reader.onload = (function(e) {
return function(evt) {
// Find base64 data
var base_index = evt.target.result.indexOf(base64_marker) + base64_marker.length;
// Get base64 data
var base64_data = evt.target.result.substring(base_index);
var sUploadService = window.location.origin + "/sap/opu/odata/SAP/ZFILEUPLOAD_SRV/UPLOAD_MAPSet";
$.ajaxSetup({ cache: false });
// Fetch CSRF Token
jQuery.ajax({
url : sUploadService,
type : "GET",
async: false,
beforeSend : function(xhr) {
xhr.setRequestHeader("X-CSRF-Token", "Fetch");
},
success : function(data, textStatus, XMLHttpRequest) {
// Read the CSRF token value from header
token = XMLHttpRequest.getResponseHeader('X-CSRF-Token');
},
error : function(data, textStatus, XMLHttpRequest) {
}
});
$.ajaxSetup({ cache: false });
// Upload the file data to OData service
jQuery.ajax({
url : sUploadService,
async : false,
dataType : 'json',
cache : false,
data : base64_data,
type : "POST",
beforeSend : function(xhr) {
xhr.setRequestHeader("X-CSRF-Token", token);
xhr.setRequestHeader("Content-Type", file.type);
xhr.setRequestHeader("slug", sFileName);
xhr.setRequestHeader("ps-name", ps_name);
},
success : function(data, textStatus, XMLHttpRequest) {
// Get message from response header
var message = XMLHttpRequest.getResponseHeader("custom-message");
// Set the message in the MessageStrip
msg_strip.setText(message);
msg_strip.setVisible(true);
},
error : function(data, textStatus, XMLHttpRequest) {
// Set the error in the MessageStrip
msg_strip.setText("Planning sequence "+ ps_name +" could not be executed.");
msg_strip.setVisible(true);
}
});
};
})(file);
file_reader.readAsDataURL(file);
You can find the UI5 app code here: UI5 app
CREATE_STREAM redefinition
In the gateway service, from the ‘Runtime Artifacts’ go to the DPC_EXT class and redefine the ‘CREATE_STREAM’ method from the /IWBEP/IF_MGW_APPL_SRV_RUNTIME interface. Finally, in the create_stream method get the base64 data that we sent from the front end along with the planning sequence name. Call the ‘RSPLSSE_PLSEQ_EXECUTE’ function to execute the planning sequence.
The complete code for the DPC_EXT class can be seen here: DPC_EXT
Download
You can find the code in our consetto github repository: https://github.com/consetto/ui5-file-upload-planning
Remarks
I would like to thank Marc Bernard for How-to Load a File into BW-Integrated Planning which motivated me to try this solution using SAPUI5 instead of a WebDynpro application.
I would also like to mention this blog post which helped me to do file upload to the gateway service from SAPUI5 app.
The next part of the blog series will involve flat file upload into BW-Integrated Planning using a custom planning function type from SAPUI5.
Very good Waleed!