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
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.
- Log in to the application
- Take a picture/Import a pdf or image of invoice
- Press button – upload the document to SAP AI Business Services
- 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.
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.
- SAP AppGyver and SAP BTP Kyma
- 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.
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.
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
- Payment Advice
- Purchase Order
- 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:
- SAP AppGyver – No-Code visual programming
- SAP AI Business services – Document Information Extraction
- SAP S/4HANA Cloud – The Cloud ERP solution
- SAP BTP Kyma / SAP Kyma – SAP’s Kubernetes-based runtime on BTP
- SAP Developer tutorials – Find the tutorial suitable for your learning needs for free!
Credits
Gunter Albrecht, Sumin Lee, Mohini Verma, Sam Yu Puay
I sincerely appreciate your support.