Help us understand the problem. What is going on with this article?

Power Automate で稟議書を実装してみた5 (Power Automate 編3)

経緯

前回 は、承認ルートの階層分繰り返す処理に入り、承認ルートがなくなった時に抜ける処理まで説明しました

今回は少し長いですが、承認ルートがあった時に下記の処理を行うところを説明します

  1. 確認者にメールを送り
  2. 承認者に承認依頼を送り、承認されたときと否認された情報を登録し
  3. 承認数が設定を越えていたら、次の承認ルートに進み、越えていなかったら否認として処理する

グループマスタリストから、アイテムを取得

申請経路に設定されたグループの参照先を取得し、登録されている承認者と確認者を取得します

この処理を SharePoint コネクタの「項目の取得」 で行います

ID は下記のようになっています

@{body('作成されたアイテムに設定された承認ルートの取得')?[variables('動的列名用オブジェクト')['PathTitle']]?['Id']}

1 週目だと variables('動的列名用オブジェクト')['PathTitle']「Path1」という文字列になり、body('作成されたアイテムに設定された承認ルートの取得')?['Path1'] で参照列の値 「グループ1」 となり、グループ1?['Id'] で参照列の ID を取得しています
つまり、グループマスタのグループ名「グループ1」のアイテムを取得するという処理です

確認者分メールを送る

確認者として登録されたユーザーに確認メールを送ります
繰り返し処理を、コントロールコネクタの「Apply to each」で行います

Apply to each を使うことにより、設定された値(コレクション)の分処理を行いますが、値が空だと処理は行われません

以前の手順から出力を選択は、動的コンテンツから「グループマスタリストから、アイテムを取得」の「確認者」を選びます

続いて、右にある ・・・ をクリックして、設定をクリックします

コンカレンシー制御をオンにして、並列処理の次数を 20 としています
これにより、メール送信を待たずに確認者に登録されたユーザーへどんどんメールを送ることが可能となります

確認メールの送信

次に、Office 365 Outlook コネクタの「メールの送信(V2)」を使って、メールを送信します

  • 宛先は「確認者 Email」としています
  • 件名、本文、は適当に作成しています
    本文例
<p>@{triggerBody()?['Author']?['DisplayName']} さんからワークフローが届いています<br>
<br>
@{triggerBody()?['Title']}<br>
<br>
<a href="@{triggerBody()?['{Link}']}">申請文はこちら</a> </p>
  • 差出人は「登録者 Email」としています

承認者分メールとチャットを送る

続いて、承認者として登録されたユーザーに承認依頼(メール)と通知するためにチャットを送りますが、こちらは、コントロールコネクタの「Apply to each」 を並列分岐として追加します

以前の手順から出力を選択は、動的コンテンツから「グループマスタリストから、アイテムを取得」の「承認者」を選びます

こちらも先程と同様に、右にある ・・・ をクリックして、設定をクリックして、コンカレンシー制御をオンにして、並列処理の次数を 20 としています

この設定を行わないと、順次処理になってしまい、A さんが承認、または、否認をしたら B さんの承認依頼が作成されて、というように一人づつの処理になってしまいます

承認を作成

次に 承認コネクタの「承認を作成」 を使って、承認を作成します

  • Assigned to は「承認者 Email」としています
  • Title, Details は適当に作成しています
    Details 例
## @{triggerBody()?['Author']?['DisplayName']} さんからワークフローが届いています
* @{triggerBody()?['Title']}
  • Item link は「申請ワークフローリストにアイテムが追加されたとき」の「アイテムへのリンク」を使います

依頼のメールは次のように届き、メールで承認や拒否を行うことができます

メッセージをフローボットとしてユーザーに投稿する

承認依頼が届いていることを、チャットでも通知すると親切と思います
Microsoft Teams コネクタの「メッセージをフローボットとしてユーザーに投稿する」 を使います

  • Recipient は「承認者 Email」としています
  • Message は適当に作成しています Message 例
* タイトル  
  @{body('承認を作成')?['title']}

* [承認依頼はこちら](@{body('承認を作成')?['respondLink']})
* [申請文はこちら](@{body('承認を作成')?['itemLink']})
  • 詳細オプションを表示して、IsAlert を「はい」にしています

承認を待機する

承認を作成したら、ユーザーのアクションを待つ必要があるので、承認コネクタの「承認を待機」を使います

承認 ID は、「承認を作成」の Approval ID を使います

承認アクション時、登録されたアイテムの最新状態を取得

ユーザーからのアクションがあったとき、登録されたアイテムの最新状態から更新したいので、アイテムを取得します

承認結果を判定

ユーザーのアクションが承認だったかどうかの判定を行います

「承認を待機」の結果が「承認」、または、「Approve」かどうかを判定しています
「または」を使っているのは、言語設定の問題などを考慮したつもりです

また、今回試したフローでは、はいの場合といいえの場合の違いは、承認数に値を加えるかどうかだけですので、次の項目からは並行して説明します

現在の承認数に +1 、現在の否認数に +1

先程「承認アクション時、登録されたアイテムの最新状態を取得」で取得した承認数、または否認数をカウントアップする処理です

変数コネクタの「変数の設定」を使います

「現在の承認数に +1」の時

@{add(int(body('承認アクション時、登録されたアイテムの最新状態を取得')?[variables('動的列名用オブジェクト')['PathAcceptTitle']]),1)}

「現在の否認数に +1」の時

@{add(int(body('承認アクション時、登録されたアイテムの最新状態を取得')?[variables('動的列名用オブジェクト')['PathRejectTitle']]),1)}

動的列名用オブジェクトから、列名を取得している部分ですが、1 周目だと下記の文字列になります

  • variables('動的列名用オブジェクト')['PathAcceptTitle'] には「Path1Accept」
  • variables('動的列名用オブジェクト')['PathRejectTitle'] には「Path1Reject」

最新状態のアイテム情報から、その列名の値を取得して整数(int)に変換後、式 add を使って 1 足しています

承認ログと承認コメントの生成、否認ログと否認コメントの生成

応答はコレクションになっているため、コントロールコネクタの「Apply to each」 を使って値を取得します

以前の手順から出力を選択に、「承認を待機」の応答を設定します

承認ログの生成、否認ログの生成

だれが承認(or 否認)したというログを残したいので、ログの生成を行います

変数コネクタの「変数の設定」を使います

違いは、利用する動的コンテンツと文言が微妙に違うだけです

「承認ログの生成」の時

[@{convertFromUtc(utcNow(), 'Tokyo Standard Time', 'yyyy-MM-dd HH:mm:ss')}] @{items('承認ログと承認コメントの生成')?['responder']?['displayName']}さんが承認しました
@{body('承認アクション時、登録されたアイテムの最新状態を取得')?['Log']}

「否認ログの生成」の時

[@{convertFromUtc(utcNow(), 'Tokyo Standard Time', 'yyyy-MM-dd HH:mm:ss')}] @{items('否認ログと否認コメントの生成')?['responder']?['displayName']}さんが否認しました
@{body('承認アクション時、登録されたアイテムの最新状態を取得')?['Log']}

承認コメントの生成、否認コメントの生成

承認(or 否認)時のコメントを残したいので、コメントの生成を行います
こちらも、変数コネクタの「変数の設定」を使います

「承認コメントの生成」の時

[@{convertFromUtc(body('承認を待機')?['completionDate'], 'Tokyo Standard Time', 'yyyy-MM-dd HH:mm:ss')}]  @{items('承認ログと承認コメントの生成')?['responder']?['displayName']}さんが承認しました
@{items('承認ログと承認コメントの生成')?['comments']}

@{body('承認アクション時、登録されたアイテムの最新状態を取得')?[variables('動的列名用オブジェクト')['PathCommentTitle']]}

「否認コメントの生成」の時

[@{convertFromUtc(body('承認を待機')?['completionDate'], 'Tokyo Standard Time', 'yyyy-MM-dd HH:mm:ss')}] @{items('否認ログと否認コメントの生成')?['responder']?['displayName']}さんのコメント
@{items('否認ログと否認コメントの生成')?['comments']}

@{body('承認アクション時、登録されたアイテムの最新状態を取得')?[variables('動的列名用オブジェクト')['PathCommentTitle']]}

現在のコメントを取得している部分で、動的列名用オブジェクトから列名を取得している部分ですが、 1 周目だと下記の文字列になります

  • variables('動的列名用オブジェクト')['PathCommentTitle'] には「Path1Comment」

承認登録データ、否認登録データ

登録処理はまとめて行うので、登録データを生成しています

「承認登録データ生成」の時

{
  "Log": "@{variables('ログ')}",
  "CountResult": @{variables('承認数一時保持変数')},
  "CountResultTitle": "@{variables('動的列名用オブジェクト')['PathAcceptTitle']}",
  "Comment": "@{variables('コメント一時保持変数')}",
  "CommentResultTitle": "@{variables('動的列名用オブジェクト')['PathCommentTitle']}"
}

「否認登録データ生成」の時

{
  "Log": "@{variables('ログ')}",
  "CountResult": @{variables('承認数一時保持変数')},
  "CountResultTitle": "@{variables('動的列名用オブジェクト')['PathRejectTitle']}",
  "Comment": "@{variables('コメント一時保持変数')}",
  "CommentResultTitle": "@{variables('動的列名用オブジェクト')['PathCommentTitle']}"
}

オブジェクトのプロパティを説明すると次のようになります

  • Log には、生成されたログ
  • CountResult には、カウントアップ後の承認数(or 否認数)
  • CountResultTitle には、カウントアップ後の数値を更新する列名
  • Comment には、ユーザーが記入したコメント
  • CommentResultTitle には、コメントを更新する列名

承認・否認データの更新

更新は今まで同様に、SharePoint コネクタの「SharePoint に HTTP 要求を送信します」を使います

今までとの違いはボディだけですが、周回や条件(承認 or 否認)により、登録する列が違うため、更新する列名も動的に作られているのは今までと違います

ボディの例

{
    '__metadata': {'type': 'SP.Data.ApplyListItem'},
    'Log': '@{variables('登録用データ')['Log']}',
    '@{variables('登録用データ')['CountResultTitle']}': '@{variables('登録用データ')['CountResult']}',
    '@{variables('登録用データ')['CommentResultTitle']}': '@{variables('登録用データ')['Comment']}'
}

これで承認者分のメールとチャットを送る部分は終わりです

承認数が設定値以上の時、次の承認経路へ進む

最新の情報を取得

承認ルートに設定されたすべての承認者のアクションが終わった後、承認した人数が、必要承認数を越えているかの判定を行います

まずはその前に、今まで同様、最新のアイテムを取得する必要があります

承認数が設定値以上か

承認数が設定値以上か判定します

左辺は、最新のアイテムから、現在周回の承認数を取得しています

@body('最新の情報を取得')?[variables('動的列名用オブジェクト')['PathAcceptTitle']]

右辺は、承認ルートの設定から、必要承認数を取得しています

@body('作成されたアイテムに設定された承認ルートの取得')?[variables('動的列名用オブジェクト')['PathApprovalsTitle']]

はいの場合

ログを生成して、ログを更新しています

ログに設定している値の例

[@{convertFromUtc(utcNow(), 'Tokyo Standard Time', 'yyyy-MM-dd HH:mm:ss')}] 承認されたので次の承認経路に移ります
@{body('最新の情報を取得')?['Log']}

更新時のボディの例

{
    '__metadata': {'type': 'SP.Data.ApplyListItem'},
    'Log': '@{variables('ログ')}'
}

いいえの場合

いいえの場合は、否認とみなしてステータスとログを更新後、終了フラグに true を設定しています

ログに設定している値の例

[@{convertFromUtc(utcNow(), 'Tokyo Standard Time', 'yyyy-MM-dd HH:mm:ss')}] 承認数が足りないため否認されました
@{body('最新の情報を取得')?['Log']}

更新時のボディの例

{
    '__metadata': {'type': 'SP.Data.ApplyListItem'},
    'Log': '@{variables('ログ')}',
    'Status': '@{variables('ステータス用オブジェクト')['Rejected']}'
}

承認ルートのループカウンターを 1 プラス

「承認ルートの階層分繰り返す」処理の最後に、変数の承認ルートカウンターに 1 足します
変数コネクタの「変数の値を増やす」を使います

これで、承認されている時には次のループに移ることができます

考察

こういうように文章に起こしながら、改めて見直すと直したいところが多数ありますね...
次回は終了処理部分の説明を行います

関連記事

自分のためのメモに近い記事なのですが、長いのでインデックスつけます

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした