Introduction

Tons of invoices have been sent from suppliers with PDF document or even paper style. On top of that doing data entry of invoices is grunt work and time-comsuming that causes mistypings as well.
Fancy doing it automatically?

This blog introduces you how we built the automated procure to pay process using SAP AppGyver, SAP AI Business Services, SAP BTP Kyma and SAP S/4HANA Cloud.

Let’s dive into this application.

Process Steps

Key%20Capabilities

Image1: Key Capabilities

As image1 shows, the part of where users have to handle this application is only the first flow which is taking picture/uploading pdf or image document part and button-pressing. It is easy to use.

Steps of the first flow

Let’s break the first flow down into 4 steps.

  1. Log in to the application
  2. Take a picture/Import a pdf or image of invoice
  3. Press button – upload the document to SAP AI Business Services
  4. Press button – Create Supplier Invoice in S/4HANA Cloud

Altogether it takes you around 1 to 2 minutes from scratch to the creation of supplier invoice. That absolutely cuts off the fiddly process!

Architecture

For the front end, we use SAP AppGyver which is Low-Code / No-Code service on SAP BTP.  As the middleware, we introduce Go container runnning upon SAP BTP Kyma that is a cloud-native application runtime that combines Kubernetes. This runtime gets the request from users to communicate with Document Information Extraction with REST API connection and Supplier Invoice Creation of S/4HANA Cloud using OData.

Application%20Architecture

Image2: Application Architecture

For Docker Go container that enables you to handle pdf document, we use “git gcc musl-dev”. see the top of this application’s Docker file below:

FROM golang:1.18-alpine3.14 as builder

RUN apk add --no-cache build-base 
    git gcc musl-dev

Now Let’s look into 2 simple integrations.

  1. SAP AppGyver and SAP BTP Kyma
  2. Document Infomation Extraction and Supplier Invoice Creation

1: The communicaton between SAP AppGyver and middlewere has got altogether 8 REST requests using Go web framework called gin.

func main() {
	gin.SetMode(gin.ReleaseMode)
	r := gin.Default()
	r.Use(CORSMiddleware())
	r.GET("/get_stored_result", handleIdToInfo)
	r.GET("/get_item_result", handleItemData)
	r.GET("/data/show_data", dbhandle.HandleShowData)
	r.POST("/data/user_login", dbhandle.HandleLogIn)
	r.POST("/create_supplier_invoice", handleSupplierInvoiceCreation)
	r.POST("/get_extracted_info", handleExtractDocInfo)
	r.DELETE("/data/delete_data", dbhandle.HandleDeleteData)
	r.DELETE("/delete_data", handleDeleteData)
	s := &http.Server{
		Addr:           ":8000",
		Handler:        r,
	}
	s.ListenAndServe()
}

For the POST request to Document Information Extraction, API needs auth token, hence it calls GET request to get token in every POST inside of middleware. And for Supplier Invoice Creation, CSRF tokens is to be called and Cookie needs to be set. To do this, you firstly need to implement GET request. The way you can get a token and Cookie is below:

req.Header.Add("Accept", "application/json")
req.Header.Add("X-CSRF-Token", "Fetch")
req.Header.Add("Authorization", auth)
res, err := client.Do(req)
if err != nil {
	fmt.Println(err)
	return
        }
defer res.Body.Close()
cke := ""
for _, cookie := range res.Cookies() {
	cke = cookie.Value
        }
token := res.Header.Get("x-csrf-token")
if err != nil {
	fmt.Println(err)
	return
	}

This consideration sums up the Header below:

req.Header.Add("Accept", "application/json")
req.Header.Add("X-CSRF-Token", token)
req.Header.Add("Authorization", auth)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Cookie", "SAP_SESSIONID_E5Z_100="+cookie+"; sap-usercontext=sap-client=100")

On top of that, in order to create the attachment to check the document you uploaded in SAP S/4HANA Cloud, you can send POST request to Attachments that allows you to manage attachments and attachment URLs for business objects with LinkedSAPObjectKey. You can extract it from the returned json from Supplier Invoice Creation:

messageLabel:
for k, v := range resJson {
	if k == "d" {
		message = "Success"
		for k1, v1 := range v.(map[string]interface{}) {
			if k1 == "SupplierInvoice" {
				linkedSAPObjectNum = v1.(string)
			} else if k1 == "FiscalYear" {
				linkedSAPObjectYear = v1.(string)
			}
		}
		break messageLabel
	} else if k == "error" {
		for eKey, eVal := range v.(map[string]interface{}) {
			if eKey == "message" {
				for mKey, mVal := range eVal.(map[string]interface{}) {
					if mKey == "value" {
					message = "Error in Supplier Invoice Creation: " + mVal.(string)
					break messageLabel
					}
				}
			}
		}
	}
}
linkedSAPObjectKey = linkedSAPObjectNum + linkedSAPObjectYear

Finally you can set the Header to create the attachment:

req.Header.Add("Accept", "application/json")
req.Header.Add("X-CSRF-Token", token)
req.Header.Add("Authorization", auth)
req.Header.Add("Slug", "Invoice #attachment.png")
req.Header.Add("BusinessObjectTypeName", "BUS2081")
req.Header.Add("LinkedSAPObjectKey", linkedSAPObjectKey)
req.Header.Add("Cookie", "SAP_SESSIONID_E5Z_100="+cookie+"; sap-usercontext=sap-client=100")
req.Header.Set("Content-Type", "application/png")

The connection between SAP AppGyver and SAP BTP Kyma, which is up and running, is to add SAP BTP Kyma endpoint to SAP AppGyver. See the Image3.

AppGyver%20with%20Kyma

Image3: AppGyver with Kyma

2: How we integrate Document Infomation Extraction and Supplier Invoice Creation is we straightforwardly preprocess the result of data from Document Infomation Extraction to make right JSON form for Supplier Invoice. If some of the contents such as gross amount, country code etc were not extracted, they can be possibly calculated in preprocessing using net amount and tax and so on. The calculation example is below:

if documentContent["taxAmount"] == "" {
		taxAmount := 0.0
		if (documentContent["netAmount"] != "") && (documentContent["grossAmount"] != "") {
			taxAmount = grossAmount - netAmount
		} else if (documentContent["netAmount"] != "") && (documentContent["taxRate"] != "") {
			taxAmount = (taxRate/100 + 1) * netAmount
		}
		documentContent["taxAmount"] = strconv.FormatFloat(taxAmount, 'f', -1, 64)
	}

Regarding the transformation JSON format, see Image 4.

Data%20Preprocessing

Image4: Data Preprocessing

Application Demo

Finally you will be looking into the demo video!

Wrap up

We have gone through how this SAP AppGyver application works to create Supplier Invoice in S/4HANA Cloud. Using SAP AppGyver and intergrating other SAP services have great impact on your business processes. Speaking of Document Information Extraction, there are 3 more document types that are available to be extracted

  1. Payment Advice
  2. Purchase Order
  3. Business Card

and also you can train and tune your own desirable types of documents.

Using the architecture and pattern outlined above, you can now quickly create mobile apps to digitize and interpret your quality check sheet results, your delivery documents at goods receipt, incoming quotations and many more!

Reference

Product references are below:

Credits

Gunter AlbrechtSumin LeeMohini VermaSam Yu Puay

I sincerely appreciate your support.

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x