UiPath Document Understanding Process日本向けテンプレートの作り方（#3 InvoicesJapan対応ビジネスルール）

# はじめに
[UiPath Document Understanding Process日本向けテンプレートの作り方（#1 初期設定）](https://qiita.com/Jun96427231/items/0ab0c0c7d47b834714aa)の「6.7 InvoicesJapan対応ビジネスルール」の詳細を解説した記事です。

UiPath Document Understanding Processでは、人による検証をスキップしても良いかのビジネスルールを入れることができます。
Document Understanding Processには、Invoices (請求書)用のビジネスルールがサンプルで入っており、これは英語のカルチャ情報（EN-USカルチャ）を利用したもので実装されています。これをInvoicesJapan (請求書 - 日本) に対応したものにカスタマイズします。

::: note warn
Document Understanding Processの注意書きにありますが、これはあくまでもサンプルです。これをそのまま使用しないでください。実際の実装では、後処理と検証をビジネスプロセスの詳細に合わせて調整する必要があります。
:::

# 既存の英語請求書のビジネスルールサンプル概要

Configファイルで定義されたフィールドや、信頼しきい値に基づき、下記のルールが適用されます。

* 定義された全ての必須フィールドと列が抽出されていること。
* すべてのテーブル行が数量 * 単価 = 明細金額のルールで計算が一致していること。
* すべての明細金額の合計 = 正味金額であること。
* すべての明細金額の合計に追加項目の金額（例：税額、送料、割引）を加算した金額が総額であること。
* 定義された各フィールドの抽出信頼度が個々の信頼しきい値と比較してクリアしていること。
* 定義されたその他フィールドの抽出信頼度が、共通の信頼しきい値と比較してクリアしていること。

# 日本請求書のビジネスルールサンプルへ変更するポイント

* 英語の文化情報に基づく処理から変更します。（金額に小数点は扱わない）
* InvoicesJapan(請求書-日本)で抽出されないフィールドはConfigファイルの定義から除外します。


# ビジネスルールを入れる場所

55_ExtractionBusinessRuleValidationに入れます。Document Understanding Processの全体構成から見た場所は下記の赤枠の部分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/429d1b30-bf1d-3576-a161-e3de7ab224ac.png)

# 日本の請求書のビジネスルールの追加箇所
文書の種類が日本の請求書「Semi-StructuredDocuments.Financial.InvoiceJapan」であった場合は、InvoicesJapan対応ビジネスルールを読み出す様に構築します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/245cb81e-3f11-b51b-784b-f826ec8057a6.png)


:::note info

***補足***
文書の種類は、io_ExtractionResults.ResultsDocument.DocumentTypeIdで識別でき、判定する値はタクソノミーマネージャから取得できます。

***タクソノミーマネージャでの取得場所***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/623052da-cc0d-b695-5c6b-d9e456609394.png)

:::

# 日本請求書ビジネスルールワークフローの作成
「\Framework\ReusableWorkflows」に格納されている「InvoicePostProcessing.xaml」コピーして「InvoiceJapanPostProcessing.xaml」を作成します。

**＜ 日本請求書ビジネスルールワークフローの呼び出し ＞**
これを前述の「55_ExtractionBusinessRuleValidation.xaml」から呼び出す形にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/eee25fc0-8d97-618b-e368-adc16df4edc2.png)


# Configファイルの設定

(1)「InvoicePostProcessing」からコピーしてシートを追加します。
(2) Nameを変更します。（InvoicePostProcessingとName重複による上書きを回避）
(3) ログメッセージを日本語に変更します。
(4) InvoicesJapan(請求書-日本)で抽出されないフィールドを除外します。
（除外：Billing VAT Number, Vendor VAT Number, Currency）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/f855df32-2e43-c1c3-6559-2b2dc353bf92.png)

(5) Mainワークフローから呼び出している「00_ReadConfigFile.xaml」の引数に"InvoiceJapanPostProcessing"を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/32b818d1-48cf-b28b-f3ee-039618239663.png)

# InvoiceJapanPostProcessing.xamlの処理と変更点

## 1.Configのキーの名前を変更
処理の変更に入る前にでディクショナリConfigのキーの名前を「InvoiceJapanPostProcessing」シートのNameに合わせて全て変更しておきます。

**＜ SubTotalAdditionsをSubTotalAdditionsJPに変更した例　＞**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/faefd7ed-e4c5-6185-6221-e36649c4da0c.png)


## 2.必須の抽出値を確認する（処理変更なし）
Configファイルでは、MandatoryFields および MandatoryColumns の下に必須としていくつかのフィールドを設定しました。ここでは、日付から始めて、それらが存在するかどうかを確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/60397d11-3cc2-db4f-ebd3-a5fa29fa63e3.png)

- 日付が存在しない場合、または解析できない場合、プロセスは失敗し、手動による検証が必要になります。
- MandatoryFields または itemTable (MandatoryColumns を含む) のフィールドのいずれかが欠落している場合は、手動検証が必要になります。



**＜ConfigファイルのMandatoryFieldsおよびMandatoryColumns＞**
|Name        |Value　※既定値       |
|:-----------|:-----------|
|MandatoryFieldsJP|Date,Invoice Number,PO Number,Total|
|MandatoryColumnFieldsJP|Quantity,Unit Price,Line Amount|

:::note warn

サンプル帳票に、この必須フィールドがない場合は、検証スキップは機能されなくなります。例えば注文書番号がない帳票をサンプルにする場合は、Configファイルに定義しているPO Numberを除いてください。

:::


## 3.値のクリーンアップ（処理変更あり）
抽出されたフィールドから空のフィールド、記号、余分なテキスト (OCR エラー)、および数値ではないすべてのものを削除します。これにより、値を使用して数学的演算を実行できるようになります。

***＜変更点＞***

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/d7d5ebf2-c3c4-ec98-748c-cc4238ab60cf.png)

① 数字以外を削除し、数字のみにする。
```ruby:RegexText の割り当ての変更
（変更前）
"[^0-9\.]+"

（変更後）
"[^0-9]+"
```
② 空フィールドは0とし、数字のみにする。
```ruby:例）Tax Amountの部分の変更
（変更前）
If(String.IsNullOrEmpty(documentFields("Tax Amount")) orElse (documentFields("Tax Amount").Equals("0") orElse documentFields("Tax Amount").Equals("0.0")), "0.00", Regex.Replace(documentFields("Tax Amount"), regexText, "").Replace(" ",""))

（変更後）
If(String.IsNullOrEmpty(documentFields("Tax Amount")), "0", Regex.Replace(documentFields("Tax Amount"), regexText, "").Replace(" ",""))
```
## 4.明細の検証（処理変更あり）
ここでは、数量、単価、明細金額に対して計算し、抽出された対応するものと一致することを確認します。計算が一致しない場合は、手動検証に進みます。

***＜変更点＞***

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/02ef8158-d724-023d-867f-35b7112ebb00.png)


① 少数点を扱わない前提に、通貨記号を削除し、空フィールドは0とし、数字のみにします。

```ruby:例）Unit Priceの部分の変更
（変更前）
If(String.IsNullOrEmpty(CurrentRow("Unit Price").ToString) OrElse (CurrentRow("Unit Price").Equals("0") OrElse CurrentRow("Unit Price").Equals("0.0")), "0.00", Regex.Replace(CurrentRow("Unit Price").ToString, regexText, "").Replace(" ",""))

（変更後）
If(String.IsNullOrEmpty(CurrentRow("Unit Price").ToString) , "0", Regex.Replace(CurrentRow("Unit Price").ToString, regexText, "").Replace(" ",""))```
```

② シーケンス「小数点以下の桁数」は不要なので削除します。

③ 少数点は扱わないため、明細行の金額計算比較はシンプルにする。
```ruby:条件式の変更
（変更前）
Math.Round(CDec(CurrentRow("Unit Price")) * CDec(CurrentRow("Quantity")),Cint(decimalPoints)) = CDec(CurrentRow("Line Amount"))

（変更後）
CDec(CurrentRow("Unit Price")) * CDec(CurrentRow("Quantity")) = CDec(CurrentRow("Line Amount"))
```

## 5.抽出結果の確認（処理変更なし）
このステップで問題が見つかった場合はout_AutoExtractionSuccessをFalseに設定し、Mainワークフローで手動による検証が行われます。問題が見つからなかった場合は、out_AutoExtractionSuccessをTrueに設定し、手動による検証はスキップされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/efd24c65-489d-8685-4948-4c9a692a919d.png)

① これまでのプロセスで問題が見つかったかどうかを確認します。

② 明細行の金額の合計が、抽出された正味金額(Net Amount)と一致するかどうかを確認します。

③ 抽出されたSubTotalAdditionsに定義されたフィールドの金額と小計への加算の合計が、抽出された合計金額(Total)と一致するかどうかを確認します。
|Name        |Value|
|:-----------|:-----------|
|SubTotalAdditionsJP|Tax Amount,Shipping Charges,Discount|

④ ConfidenceFieldsに定義されたフィールドにおいて、"フィールド名-ConfidenceJP"の名前で定義された個々の信頼度しきい値を下回っていないか確認します。
|Name        |Value|
|:-----------|:-----------|
|ConfidenceFieldsJP|Date,Shipping Address,Invoice Number,PO Number|

|Name        |Value|
|:-----------|:-----------|
|Date-ConfidenceJP|85|
|Shipping Address-ConfidenceJP|50|
|Invoice Number-ConfidenceJP|85|
|PO Number-ConfidenceJP|85|

⑤ OtherConfidenceFieldsJPに定義されたフィールドにおいて、"other-ConfidenceJP"に定義された信頼度しきい値を下回っていないか確認します。
|Name        |Value|
|:-----------|:-----------|
|OtherConfidenceFieldsJP|Tax Amount,Net Amount,Discount,Shipping Charges,Billing Name,Total,Name,Vendor Address,Billing Address,Payment Address,DueDate,Payment Terms,Discount|

|Name        |Value|
|:-----------|:-----------|
|other-ConfidenceJP|50|

:::note warn

サンプル帳票に、ここで定義されているフィールドがない、そして、その項目も活用しない場合は、調整しましょう。例えば注文書番号がない帳票をサンプルにし、注文書番号をデータとして活用しない場合は、Configファイルに定義しているPO Numberを除いてください。

:::


# おわりに

既存のInvoices対応ビジネスルールをベースに同等のInvoicesJapan対応ビジネスルールを追加して見ました。ただし、請求書を読み取り、その後、利用する項目によってもビジネスルールが変わりますし、更に、追加したいロジックをもあると思いますが、ビジネスルールのひな形としては参考になります。実稼働ユースケースに基づき、特定のニーズに合わせてワークフローを調整するためのサンプルとして活用しましょう。