毎週末にチームの勤務場所を確認しあうTeamsテクニック

# はじめに
**出社とテレワーク、せめてどちらかはわかりあいたい・・・！！** そんなニーズはありませんか！？
職場によりけりだと思いますが、ハイブリッドワークであれば出社する日を合わせたり、当番制にしたり様々な事情があると思います。

そんな日常のお困りごとを解決するものが正に`Power Automate`の出番だと思います！
本日は上記のような状況を解決する`Tips`、`Power Automate`フローをシェアしたいと思います！

::: note
関連するテクニックは
 - Teams タグメンバーを取得する
 - Teams タグメンションを取得するTips
 - `選択`、`JSON`といったデータ操作テクニック

です！
:::

# フローの全体像
まずはフローのキャプチャです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/f228dc99-7d25-272c-dea0-63d3b898f83d.png)

エラーハンドリングや条件分岐は全くない状態。
ブラッシュアップの余地はありますが、一旦稼働するものを紹介しています。

```mermaid
flowchart TD
    A[フローチケット取得] --> C[Compose 曜日]
    C --> D[Map 来週のweekday]
    D --> E[Map 系のProcess]
    E --> F[Map items]
    F --> G[Compose body]
    G --> H[For each]
    
    subgraph Loop[For each スコープ]
        I[アダプティブ カードを投稿して応答を待機する] --> J[選択]
        J --> K[HTML テーブルの作成]
        K --> L[チャットまたはチャネルでメッセージを投稿する]
    end
    
    H --> Loop
```


::: note info
繰り返し処理にしたり、トリガーは需要に合わせて自由に変更してください！
:::

## 1. メンバーを取得する
今回のシナリオは `Teamsの特定のタグでメンバーを管理する`手法を一旦想定します。
`Teams`コネクタの[タグのメンバーを一覧表示する](https://learn.microsoft.com/ja-jp/connectors/teams/#%E3%82%BF%E3%82%B0%E3%81%AE%E3%83%A1%E3%83%B3%E3%83%90%E3%83%BC%E3%82%92%E4%B8%80%E8%A6%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B)を使用しましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/d8774a9a-2a53-2d88-f90f-6a5c6afdcaa4.png)


https://learn.microsoft.com/ja-jp/connectors/teams/#%E3%82%BF%E3%82%B0%E3%81%AE%E3%83%A1%E3%83%B3%E3%83%90%E3%83%BC%E3%82%92%E4%B8%80%E8%A6%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B

戻り値で所属するメンバーの`Id`が取得できます。

```json: 参考スキーマ
{
    "statusCode": 200,
    "headers": {
        "Transfer-Encoding": "chunked",
        "Vary": "Accept-Encoding",
        "Strict-Transport-Security": "max-age=31536000",
        "request-id": "f9104446-5d0a-405d-b776-bec925c7c4cd",
        "client-request-id": "f9104446-5d0a-405d-b776-bec925c7c4cd",
        "x-ms-ags-diagnostic": "{\"ServerInfo\":{\"DataCenter\":\"Japan East\",\"Slice\":\"E\",\"Ring\":\"5\",\"ScaleUnit\":\"001\",\"RoleInstance\":\"TYO1EPF00001C9E\"}}",
        "OData-Version": "4.0",
        "x-ms-client-region": "japan",
        "x-ms-flavor": "Production",
        "X-Ms-Workflow-Resourcegroup-Name": "A5510967A68D45B8B128110263BF391F-2A9F4A58FB85E21FB72EF1240BA74EB0-ENV",
        "x-ms-workflow-subscription-id": "c642c65c-bdd8-4e8a-9881-4b38764afe3c",
        "x-ms-environment-id": "2a9f4a58-fb85-e21f-b72e-f1240ba74eb0",
        "x-ms-tenant-id": "guid__",
        "x-ms-dlp-re": "-|-",
        "x-ms-dlp-gu": "-|-",
        "Timing-Allow-Origin": "*",
        "x-ms-apihub-cached-response": "false",
        "x-ms-apihub-obo": "false",
        "Date": "Wed, 11 Dec 2024 15:40:53 GMT",
        "Content-Type": "application/json",
        "Content-Length": "577"
    },
    "body": {
        "@odata.context": "https://graph.microsoft.com/beta/$metadata#teams('hogehoge')/tags('hogehoge')/members",
        "@odata.count": 1,
        "value": [
            {
                "id": "hogehoge==",
                "displayName": "出戻り ガツオ",
                "tenantId": "guid__",
                "userId": "userid___"
            }
        ]
    }
}
```

このプロパティは`Teams`の`タグメンション`にも活用できます。

https://learn.microsoft.com/ja-jp/power-automate/trigger-flow-teams-message

::: note
今回のシナリオでは`タグメンション`は活用しませんが、この`ID`がつかえるのか！くらいに見ていただければ幸いです!!
:::

上記のアクションでは`Teams`の`タグ`で管理するメンバーを取得します。
~~手間なので~~ メンバーは私ひとりにしていますが、結果は複数人でも同じです。

`Teams`の`チーム`で管理している`タグ`を指定してください。
今回は`勤怠管理` という`チャネル`と`タグ`がある想定で指定をしてみましょう。

::: note
動的な指定は可能ですが、本記事では取り扱いません。
:::

## 2. 曜日の配列を作成する
勤怠の確認対象を`月` ~ `金`とします。祝日は考慮できていないフローです。
配列で下記のように日本の曜日を既定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/71a94edb-5ffc-54fd-41bd-c129c34176e2.png)

※ 作成アクションです

```yaml:input
createArray('月曜日', '火曜日', '水曜日', '木曜日', '金曜日')
```

[createArray 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#createArray)

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#createArray

ここで関数を使うかどうかは好みの問題ですね。
下記を直打ちしても動作します。

```json:input
[
  "月曜日",
  "火曜日",
  "水曜日",
  "木曜日",
  "金曜日"
]
```

## 3. 来週の月から金曜日を取得する
[選択](https://learn.microsoft.com/ja-jp/power-automate/data-operations)アクションで、`Power Automate`フローからみて、来週の月曜日から金曜日を取得します。

https://learn.microsoft.com/ja-jp/power-automate/data-operations

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/c4467adf-2f83-2af0-8ab7-7b54541f0b05.png)

```json:From
@{range(0, 5)}
```

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#createArray


```json:Map
{
  "date": @{convertTimeZone(
    addDays(
        utcNow(),
        add(
            sub(8, dayOfWeek(utcNow())),
            item()
        )
    ),
    'UTC',
    'Tokyo Standard Time',
    'MM/dd'
)},
  "weekday": @{outputs('Compose_曜日')?[item()]}
}
```

ややこしいところは、相対的に見た来週の月曜日から金曜日を取得する式です。

Power Automateの[dayOfWeek 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#dayOfWeek)は、日曜日であれば`0`、月曜日は`1`、火曜日`2`という値を返します。

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#dayOfWeek

`8` - 曜日を表す整数で、相対的に見た来週の月曜日を算出します。

関数がややこしいので順を追ってみていきます。
このような関数は**一番階層が深いところから見ていくことが肝心です。**

1. [sub 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#sub)で`8`から本日の曜日を表す整数を引く : こちらで来週の月曜日までの差分が判明します
1. [add 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#add)と曜日を表す整数を足す : 相対的に見た来週の`月曜日`から`金曜日`を算出
1. [addDays 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addDays)で差分となる日数を現在日時に対して足していきます
1. [convertTimeZone 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#convertTimeZone)で日本時間に日付を変えます。ついでにフォーマットを変えます。

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#sub

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#add

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#addDays

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#convertTimeZone

まさしく関数芸ですね。

## 4. アダプティブカードを組み立てる
アダプティブカードのラジオボタンとなる選択肢を構築します。

先にアダプティブカードのキャプチャです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/9d368217-3d0c-2d68-2977-daa5f5fb86d0.png)

この選択肢となる部分を[選択 アクション](https://learn.microsoft.com/ja-jp/power-automate/data-operations)で定義します。

https://learn.microsoft.com/ja-jp/power-automate/data-operations

アダプティブカードの`選択肢`の箇所が配列のため、[選択 (Map)](https://learn.microsoft.com/ja-jp/power-automate/data-operations)で定義をしています。
そのほかにも[選択](https://learn.microsoft.com/ja-jp/power-automate/data-operations)アクションは`データ操作`テクニックの中でも最強のアクションです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/be1bb7f7-16dd-ddb4-8b06-0cee77e39b25.png)

```javascript:From
@{body('Map_来週のweekday')}
```

```json:Map
{
  "type": "Input.ChoiceSet",
  "id": "@item()?['date']",
  "label": "@{item()?['date']} @{item()?['weekday']}",
  "choices": [
    {
      "title": "出社",
      "value": "office"
    },
    {
      "title": "リモート",
      "value": "remote"
    },
    {
      "title": "休暇",
      "value": "holiday"
    }
  ],
  "style": "expanded"
}

```

## 5. アダプティブカードを仕上げる
アダプティブカードのボディを組み立てます。
単純な見た目のため、内容は簡素です。
ラジオボタンの入力必須である制御はかけていません。

```json: 入力
{
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "type": "AdaptiveCard",
  "version": "1.4",
  "body": [
    {
      "type": "TextBlock",
      "text": "勤務形態を選択してください",
      "wrap": true,
      "weight": "Bolder",
      "size": "Medium"
    },
    {
      "type": "TextBlock",
      "text": "来週の予定を入力してください。",
      "wrap": true,
      "spacing": "None"
    },
    {
      "type": "FactSet",
      "facts": [
        {
          "title": "対象期間:",
          "value": "@{first(body('Map_来週のweekday'))?['date']}(月) ～ @{last(body('Map_来週のweekday'))?['date']}(金)"
        }
      ]
    },
    {
      "type": "TextBlock",
      "text": "日付ごとに出社またはリモートを選択してください。",
      "wrap": true
    },
    {
      "type": "Container",
      "items": @{body('Map_items')}
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "送信"
    }
  ]
}
```

ここからは各メンバーの勤務予定のヒアリング結果をまとめる工程に入ります。

## 6. メンバーにアダプティブカードを送信する🚀
### 6-1. アダプティブ カードを投稿して応答を待機する
繰り返し処理の`Concurrency control`の制限を`ON`にします。
`並列実行`でほかのメンバーの回答保留に対する待機を回避します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/462026c4-1956-3d0b-b802-30484df8575f.png)

`メンバーの抜け漏れを回避したい` というニーズがあると思います。
そのようなときは`メンション`が有効です。しかしアダプティブカードのアクションでは`IsAlert` プロパティがあるため、アナウンスを強調することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/246da695-f3ad-ad98-2bbc-3ad8f175a880.png)


こちらで代替しましょう。

### 6-2. 回答結果をマッピング
回答結果を日付と勤務予定でマッピングします。
こちらにより、配列で日付と勤務予定のペアに変換できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/44674f71-0acc-5c97-aac7-c89162fa532f.png)


### 6-3. HTML テーブルに変換
上記の結果を投稿用に`HTML テーブル`へ変換します。
**単純に見やすいです。**

https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-create-html-table-action

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/e3384b5a-20f3-0007-5034-727d14bc1412.png)


### 6-4. 結果を`Teams`に投稿する
テーブル形式で`Teams`に投稿しましょう。
来週の勤務予定が出そろいましたね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/a395cd9a-4b69-189e-fa17-03d732df116a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/6e53a3c9-60ef-a892-c5fd-2764f239a988.png)


# おわりに
**勤務予定のヒアリングといったスモールな業務こそ業務削減時間もとい定量的な効果が大きく、データ操作のテクニックが身につく絶好の機会だったりします。**

**データ操作の腕を磨く絶好のドリルだったりしますので、ぜひチャレンジしてみてくださいね！**

**今回のフローを是非使いたいという場合は、思う存分パクッて現場に活かしてください！**

**それでは良いPower Lifeを！**