導入
仕入先から送られてくる請求書は、PDFや紙媒体で送られてくることが多いことが現状としてあります。その上、請求書のデータ入力は時に退屈な仕事で時間がかかり、誤入力の原因にもなっています。
その一連の作業を自動化してみませんか?
本ブログでは、SAP AppGyver、SAP AI Business Services、SAP BTP Kyma、SAP S/4HANA Cloudを使って、調達から支払いまでを自動化するプロセスを構築した方法を紹介します。
では本アプリケーションの概要から見ていきましょう。
プロセスの概要
Image1のように、ユーザーが本アプリケーションを扱う部分は、写真撮影/pdfや画像文書のアップロード部分とボタンを押すというフローのみです。使い方はシンプルで、どなたでも1~2分の間でSAP S/4HANA Cloudに仕入先請求書を作成できます。
初期フローのステップ
では実際にどのようにユーザーがアップロードから請求書を作成するかを4ステップに分けて説明します。
- まず本アプリにログインします
- 請求書の写真を撮る、またはスマートフォンのフォルダからドキュメントをインポートします
- ボタン操作 – SAP AI Business Servicesにそのドキュメントをアップロードします
- ボタン操作 – 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 で仕入先請求書の作成を行います。
ソリューションアーキテクチャは以下です。
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つのインテグレーションに関して説明します。
- SAP AppGyver と SAP BTP Kyma
- 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をご覧ください。
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をご覧ください。
アプリケーションのデモンストレーション
最後にアプリケーションのデモのビデオを見ます。どのように実際に動くのか確認してみてください。
まとめ
SAP AppGyverがS/4HANA Cloudで仕様請求書を作成するためにどのように機能するのか、その仕組みを見てきました。SAP AppGyverを使用し、他のSAPサービスを統合することで、ビジネスプロセスに大きな影響を与えることができます。また文書情報抽出の機能に関しては、あと3種類の文書が抽出可能です。
- Payment Advice
- Purchase Order
- Business Card
また自分自身でAIの学習をさせたりチューニングして自分の欲しいドキュメントの情報抽出用にモデルを組み替えることも可能です。
以上のアーキテクチャや上記のプロセスのパターンを用いれば、品質チェックシートや納品書、見積書などを電子化するためのモバイルアプリを簡単に作成することができます。
他のソリューションが思いついた方やこのアプリケーションにご興味のある方は気兼ねなくご連絡下さい。
参考文献
- 本ブログの英語訳
- SAP AppGyver – No-Codeのビジュアルプログラミング
- SAP AI Business services – 文書情報抽出
- SAP S/4HANA Cloud – Cloud ERPのソリューション
- SAP BTP Kyma / SAP Kyma – SAPにおけるBTPのKubernetesランタイム
- SAP Developer tutorials – チュートリアル
Credits
Gunter Albrecht, Sumin Lee, Mohini Verma, Sam Yu Puay
I sincerely appreciate your support.