Skip to Content

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.

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply