導入

仕入先から送られてくる請求書は、PDFや紙媒体で送られてくることが多いことが現状としてあります。その上、請求書のデータ入力は時に退屈な仕事で時間がかかり、誤入力の原因にもなっています。
その一連の作業を自動化してみませんか?

本ブログでは、SAP AppGyver、SAP AI Business Services、SAP BTP Kyma、SAP S/4HANA Cloudを使って、調達から支払いまでを自動化するプロセスを構築した方法を紹介します。

では本アプリケーションの概要から見ていきましょう。

 

プロセスの概要

Key%20Capabilities

Image1: ユーザーのアプリ使用のフロー

Image1のように、ユーザーが本アプリケーションを扱う部分は、写真撮影/pdfや画像文書のアップロード部分とボタンを押すというフローのみです。使い方はシンプルで、どなたでも1~2分の間でSAP S/4HANA Cloudに仕入先請求書を作成できます。

初期フローのステップ

では実際にどのようにユーザーがアップロードから請求書を作成するかを4ステップに分けて説明します。

  1. まず本アプリにログインします
  2. 請求書の写真を撮る、またはスマートフォンのフォルダからドキュメントをインポートします
  3. ボタン操作 – SAP AI Business Servicesにそのドキュメントをアップロードします
  4. ボタン操作 – SAP S/4HANA Cloudで請求書を自動で作成します

ステップは以上で、手作業で打ち込む過程を排除することができ、作業時間短縮が望めます。

アーキテクチャ

フロントエンドではSAP BTPのプロダクトである SAP AppGyverという Low-Code / No-Code のサービスを使用します。ミドルウェアとしては Go言語のDockerのコンテイナーを走らせる為にSAP BTP Kyma というクラウドネイティブでフルマネージドな Kubernetes ベースのランタイムを用います。このランタイムにより、ユーザーはSAP AppGyverを通してREST APIを用い、Document Information Extraction へ請求書のアップロードを行います。 そして自動的にODataを用いて Supplier Invoice Creation of S/4HANA Cloud で仕入先請求書の作成を行います。

ソリューションアーキテクチャは以下です。

Application%20Architecture

Image2: Application Architecture

DockerのGoのコンテイナーに関してはPDFドキュメントの操作も可能にするため、gccコンパイラーとして “git gcc musl-dev”を用います。以下が本アプリのDockerファイルの一部です:

FROM golang:1.18-alpine3.14 as builder

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

それではシンプルな2つのインテグレーションに関して説明します。

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

1: SAP AppGyver とミドルウェアのコミュニケーションに関しては合計で8つのリクエストを持ちます。この際使用したGoのWebフレームワークは 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()
}

Document Information Extractionに対するPOST リクエストでは, API は認証の為のトークンが必要なため、各リクエストのタイミングで同時にGETリクエストでそのトークンを取得する使用になっています。

そして仕入先請求書の作成においては、CSRFトークンとCookieの設定が必要です。その為、まず以下の様にGETリクエストを送り、tokenとCookieを取得します:

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
	}

それ故リクエストは以下のような形になります。

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")

更にSAP S/4HANA Cloudにアップロードしたドキュメントを添付するために、Attachmentsというビジネスオブジェクトに対してAttachmentを管理できるSAP S/4HANA CloudのODataサービスを用います。このPOSTリクエストにはLinkedSAPObjectKeyが必要であり、それはSupplier Invoiceを作成した際の返り値から抽出できます:

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

それ故リクエストは以下のような形になります。

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")

SAP AppGyverと稼働中のSAP BTP Kymaの接続は、SAP BTP KymaのエンドポイントをSAP AppGyverに追加することで可能になります。Image3をご覧ください。

AppGyver%20with%20Kyma

Image3: AppGyverとKyma

2:文書情報抽出と仕入先請求書作成の連携は、文書情報抽出の結果のデータを前処理として、仕入先請求書に適したJSONフォームを作成します。もし、総合計額や国コードなどの情報が抽出されていない場合は、そのデータの前処理で純額や税額などから計算することができる使用になっています。以下に計算例を示します。

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)
	}

またJSONのフォーマットの前処理はGo言語によって以下のように変換されます。Image4をご覧ください。

Data%20Preprocessing

Image4: データ前処理

アプリケーションのデモンストレーション

最後にアプリケーションのデモのビデオを見ます。どのように実際に動くのか確認してみてください。

まとめ

SAP AppGyverがS/4HANA Cloudで仕様請求書を作成するためにどのように機能するのか、その仕組みを見てきました。SAP AppGyverを使用し、他のSAPサービスを統合することで、ビジネスプロセスに大きな影響を与えることができます。また文書情報抽出の機能に関しては、あと3種類の文書が抽出可能です。

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

また自分自身でAIの学習をさせたりチューニングして自分の欲しいドキュメントの情報抽出用にモデルを組み替えることも可能です。
以上のアーキテクチャや上記のプロセスのパターンを用いれば、品質チェックシートや納品書、見積書などを電子化するためのモバイルアプリを簡単に作成することができます。

他のソリューションが思いついた方やこのアプリケーションにご興味のある方は気兼ねなくご連絡下さい。

参考文献

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