Power Automateでプリザンターのレコードを自動更新する

この記事は、[OSSのノーコード・ローコード開発ツール「プリザンター」 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/pleasanter) の３日目の記事です。

# はじめに
今回は、プリザンターのレコードを自動更新するPower Automateフローを作成してみたいと思います。

Power Automateは、Microsoftが提供する業務自動化のためのサービスです。

https://powerautomate.microsoft.com/ja-jp/

この記事で作成するPower Automateのフローは、プレミアムコネクタであるHTTPコネクタを使用します。
プレミアムコネクタの使用が可能なPower Automateのライセンスが必要となります。
（とりあえず試してみたい、という場合は試用版のライセンスが使えます）

https://learn.microsoft.com/ja-jp/power-platform/admin/power-automate-licensing/types

# 作るもの

下記のような仕様で作成します。
1. プリザンターに下の画像のような、自動引き落としの支払日を管理するテーブル（期限付きテーブル）を用意します
1. 毎日朝8:00に各レコードをチェックします
1. 状況が「実行中」かつチェックした時点で「完了日」を過ぎているレコードの状況を「完了」にします
1. 実行結果をTeamsの特定のチャンネルへ投稿します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/f6dae600-78f1-42ec-001e-7a186c6225c1.png)

# フローの作成
Power AutomateのWebページにログインし、左側の「＋作成」ボタン押します。

https://make.powerautomate.com/

「スケジュール済みクラウドフロー」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/fcbaa1f3-2232-2d13-cfd5-904aab61724a.png)

フロー名と開始日、繰り返し間隔を入力して「作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/ce0d93c1-b04b-d552-1933-603e19477f8a.png)

作成後、フローエディタ画面に切り替わります。この時点では「Recurrence」のブロックのみが表示されていると思います。このブロックをクリックして開き、実行日時を再確認します。
開いた時点では、UTC時間での8時に動作してしまうので、下記の様に設定し直します。
（開示時刻の末尾にZが付いていると、タイムゾーンを選択してもUTCの時間で動作してしまうので、末尾のZは削除します）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/378f3224-fde3-9deb-bc18-80c1da18b03b.png)

## 変数の初期化を行う

まず最初に、フロー内で使用する変数を定義しておきます。
- baseUrl: pleasanter.netのURL
- サイトID: 処理対象のサイト（支払い（自動引き落とし））のサイトID
- ApiKey: Pleasanter APIを実行するためのAPIキー
- Message: Teamsに通知するメッセージを保持するための変数

「＋新しいステップ」をクリックし、検索枠に「変数」と入力。出てきた一覧から「変数を初期化する」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/3f8f3ff4-8fd8-5c77-095b-2e2e4f66dc82.png)

「変数を初期化する」のブロックに、変数名と値を入力します。種類は文字列とします。
（Messageの初期値は空のままで良いです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/344fcd85-d44c-715c-3517-ca401b5913d2.png)

### APIで対象レコードを取得する
Pleasanterのレコード取得APIを使って処理対象のレコードを取得します。

- 状況が「実施中」で完了が「今日よりも前」のレコードを取得

APIの実行には、HTTPアクションを使用します。
「＋新しいステップ」をクリックし、検索枠に「http」と入力。「プレミアム」タブをクリックして出てきた一覧から「HTTP」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/6effbed2-9783-6025-1665-c66d356cfa43.png)

追加されたHTTPのブロックを開き、方法（HTTP Mothod）とURIを入力します。
URIには、変数に格納したbaseURlとサイトIDを「動的なコンテンツ」から選択して挿入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/0265acb1-cabb-577b-5f39-fab9fadfc53f.png)


- ヘッダに Content-Type: application/json を設定し、BodyにAPIリクエスト用のJSONを入力します。
- ApiKeyは変数値を挿入します。
- ColumnFilterHashで、更新対象のレコードを下記の条件で絞り込みます。
  - Statusが200(実施中)
  - CompletionTime（完了）が前日以前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/d4521b1c-231b-120a-c09a-193b1259d17c.png)

※ CompletionTimeの(addHoours(...))ところには、「動的なコンテンツの追加」ダイアログの「式」の入力欄に下記のコードを入力して設定します

```
addHours(addDays(utcNow(),-1),9,'yyyy/MM/dd')
```
- 前日の年月日を取得するコード
  1. 現在日時をUTCで取得(utcNow())
  2. 1日引いて前日にする(addDays(...,-1))
  3. 9時間足して日本時間にして、yyyy/MM/ddの文字列として出力 (addHours(...,9,'yyyy/MM/dd'))

### テスト実行してHTTPリクエストの結果を確認する

ここで一旦テスト実行します。
メニューバーの「テスト」をクリックして、ここまでのフローを手動実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/2595a06f-8cc6-8a87-f599-8ff29fe772a9.png)

実行後の画面で「フロー実行ページ」のリンクをクリックして実行結果のページへ移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/3e2eb3a2-2e73-7604-5ed0-c3bee5523016.png)

実行結果で「HTTP」の「出力」を確認します。対象のレコードが取得出来ていれば、取得結果のJSONが本文欄に記載されていると思います。
本文の内容は、次のフロー「JSONの解析」で使用しますので、コピーしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/757fea53-30b4-4c52-46de-96f7c461a429.png)

### リクエスト結果のJSONを解析する

「＋新しいステップ」をクリックし、検索枠に「json」と入力。出てきた一覧から「JSONの解析」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/792bdd04-8a85-60cf-4e2b-ded8a5cb2e23.png)

「コンテンツ」に動的なコンテンツからHTTPの「本文」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/a7e7b6d3-8349-0a46-7908-373e7d80010f.png)

「スキーマ」は先ほどコピーした実行結果のJSONから自動生成します。「サンプルから生成」ボタンをクリックし、実行結果のJSONを貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/6aef6c89-b17e-cdcd-c11d-96688d8edc90.png)

### 処理対象のレコードの状況をAPIで更新する

こちらの処理もHTTPアクションを使います。
「＋新しいステップ」でHTTPのブロックを追加したら、下図のように入力します。この時、URLの "items/" と　"/update" の間には更新対象のレコードのIDが入ります。

更新対象のレコードIDは最初のHTTPのリクエスト結果のJSONから取得します。
JSONは下記のような構造になっていて、"IssueId" にレコードのIDが格納されています。
```json
{
    ....
    "Response": {
        ....,
        Data: [
            {
                "IssueId":12345,
                ...
            },
            {
                "IssueId":12345,
                ...
           },
           ....
        ]
    }
}
```
HTTPの結果のJSONは「JSONの解析」によりデシリアライズされていますので、「動的なコンテンツ」からアクセスできるようになっています。
動的なコンテンツのダイアログで、"IssueId"を選択して"items/" と　"/update" の間に挿入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/3835b56c-aa5b-656b-47d9-fea602312acf.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/ed49e34e-62b1-350f-6a27-419feada5df8.png)

"IssueId"を設定すると、２つ目のHTTP（「HTTP 2」レコード更新用）の外側に「Apply to each」のブロックが自動で生成されます。
「Apply to each」は最初のHTTPで取得した処理対象のレコードを格納している"Data"配列をループ（繰り返し）処理するためのブロックです。

配列に含まれる要素（ここでは"IssueId"）を使うと自動でループ処理を作ってくれるんですね。素敵。

後はリクエストの本文にApiKeyと更新内容 `"Status":900` (状況を完了に設定) を設定すればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/ee7536a6-59c1-ea48-ead9-2cf32d6c9c2e.png)

レコード取得のHTTPの場合と同様にテスト実行して結果の本文からスキーマを作成して、JSONの解析を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/2d2a6040-d678-4a0d-90ab-9ebdd6e75d0a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/6ff6728f-92d5-0049-d13b-4583bc43a572.png)

### レコードの更新結果のメッセージを変数に格納する

レコード更新用のHTTPのレスポンスから、実行結果のメッセージを取得してMessage変数へ追加します。

「Apply to each」内の「アクションの追加」をクリック、「変数」で検索して「文字列変数に追加」を選びます。

「名前」欄で変数名「Message」を選択。
「値」欄には、「動的なコンテンツ」ダイアログから「Jsonの解析 2」のMessageを選んで追加します。対象レコード数分、複数のメッセージが入るので`<br>`で改行を入れつつ追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/adcda2de-6e2b-9463-0763-a0644828f732.png)

## 実行結果をTeamsのチャネルに投稿する

Message変数に入れたレコード更新の結果をTeamsのチャネルへ投稿します。

「Aplly to each」の外側の「＋新しいステップ」をクリックし、「Teams」で検索。出てきた一覧から「チャットまたはチャネルでメッセージを投稿する」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/fcc98eab-0779-068e-7c38-197b5d53c164.png)

投稿先のチーム、チャネルを選択して投稿するメッセージを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/ba5ae383-adeb-201b-c29a-ad90dd2e521d.png)

メッセージの`if(...)`の部分は、「動的なコンテンツ」ダイアログの「式」に下記の様に設定します。
- メッセージが空の場合は、"対象のレコードはありません。"を設定
- それ以外は、Message変数の値を設定。（式の中で変数の値を使用したい場合は`variables(変数名)`と記述します)

```
if(empty(variables('Message')), '対象のレコードはありません。', variables('Message'))
```

これでフローは完成です。「保存」ボタンをクリックして保存しておきましょう。

# 動作確認

動作確認のため、手動実行してみましょう。

実行前のテーブルの状態です。実行日は12/1とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/f6dae600-78f1-42ec-001e-7a186c6225c1.png)

実行後、下記の様に更新されたら成功です。
- 状況が「実施中」かつ「完了」が12/1の前日以前のレコード「電気代」と「ラーメンサブスク」のみの状況が「完了」となる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/62abc39f-e4d6-f600-90a8-6c14a81d3724.png)

さらに、指定したTeamsのチャネルを確認します。
下記の様に出力されたらOKです。連続で実行すると既に実行済みのため、２つ目のメッセージの様に「対象のレコードはありません」と出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28805/90b4eab6-029c-b89f-de7b-4b262801004c.png)


# おわりに

今回、Power Automateを使ってプリザンターのレコードを自動更新するシステムを作ってみました。Power Automateは直観的に操作できる部分が多く、割とすんなり実装を進めることができました。
作成したフローはクラウド上に保存され、開発後即運用できるもの大きな魅力だと思います。

プリザンターと別のシステムとを連携するなど、工夫次第で様々な用途に活躍できそうですね。