Salesforceフロー × Slack通知を柔軟に管理する設計パターン

## 背景と目的

Slackへの通知運用において、以下のような課題があった：

- 通知内容や投稿先チャンネルの変更要望が多く、フローの保守が煩雑
- 通知要件がオブジェクトや所有者などに応じて柔軟に変化する
- メンションを含むメッセージの構築も必要になってきた

これに対応するため、**通知設定をデータとして持たせ、条件に応じて柔軟に通知を切り替える構成**を構築することを検討した。


## フローの全体像
```mermaid
sequenceDiagram
    actor Client as クライアント
    participant Record as トリガーレコード（ケース／キャンペーンメンバーなど）
    participant Flow as 通知フロー
    participant Setting as Slack通知設定オブジェクト
    participant ChannelA as SlackチャンネルA
    participant ChannelB as SlackチャンネルB

    Client->>Record: フォーム送信などの操作によりレコード作成
    Record->>Flow: トリガーフローが起動

    Flow->>Setting: 通知条件に一致するSlack通知設定を検索
    alt 通知設定が見つかった場合
        Setting-->>Flow: 通知チャンネル・テンプレート・メンション先を返却
        Flow-->>Flow: トリガーレコードと設定をもとにメッセージ本文を構築

        loop 通知設定ごとに
            alt 通知先がチャンネルA
                Flow->>ChannelA: メッセージを投稿（メンション含む）
            else 通知先がチャンネルB
                Flow->>ChannelB: メッセージを投稿（メンション含む）
            end
        end
    else 通知設定が見つからなかった場合
        Flow-->>Flow: 通知対象なし、処理終了
    end

```
### 1. 構成要素

| オブジェクト | 役割 |
|--------------|------|
| トリガーレコード（例：CampaignMember） | 通知の発端になるオブジェクト |
| Slack通知設定オブジェクト（カスタム） | 通知の条件・チャンネル・追加メッセージ・メンション先を定義 |
| User（標準オブジェクト） | SlackユーザーIDを保持（Slackメンション用） |

### 2. 通知設定オブジェクトの主な項目

| 項目名 | 内容 |
|--------|------|
| TriggerObjectName | トリガー対象オブジェクト名（例：CampaignMember） |
| 条件1（例：CampaignId） | トリガーレコードの該当項目と一致する値 |
| 条件2（例：GroupName） | 同上 |
| 通知先チャンネル | Slackのチャンネル名またはID |
| メンション先ユーザー | ユーザー参照。SlackIDを保持しているUserレコード |
| 追加メッセージ | 現場ユーザーが任意に記載する補足文言 |


## オブジェクトの関係性
```mermaid
erDiagram
    SLACK_NOTIFICATION_SETTING }o--|| USER : mentions

    %% 疑似的な関係を表すために intermediary object を挟む
    TRIGGER_RECORD ||--|| EVALUATION : triggers
    SLACK_NOTIFICATION_SETTING ||--|| EVALUATION : matched_by

    SLACK_NOTIFICATION_SETTING {
        string Id
        string Name
        string TriggerObjectName
        string ConditionField1
        string ConditionField2
        string ChannelName
        string MessageTemplate
        boolean IsActive
        string MentionUserId
    }

    USER {
        string Id
        string Name
        string SlackId
    }

    TRIGGER_RECORD {
        string Id
        string ObjectType
        string Field1
        string Field2
    }

```

## フローの全体像
```mermaid
flowchart TD
    A[トリガーレコードの作成（例：キャンペーンメンバー）] --> B[レコードトリガーフロー起動]
    B --> C[Slack通知設定を取得
    TriggerObjectName = CampaignMember
    CampaignId = トリガー.CampaignId
    GroupName = トリガー.Contact.Owner.Group__c]
    C --> D{取得件数 > 0}
    D -- いいえ --> E[処理終了]
    D -- はい --> F[一致した通知設定ごとにループ]
    F --> G[チャンネル名、テンプレート、メンション先を取得]
    G --> H[メッセージを組み立てる（トリガーレコードの値を使用）]
    H --> I[Slackへ通知送信]
    I --> F
    F --> J[すべての通知設定に通知完了]


```

## 実装ポイント

条件評価はGet Recordsで完結
- TriggerObjectName などの完全一致で通知設定を事前に取得
- フロー内での条件分岐やループ中評価は不要

テンプレートは固定
- テンプレート本文はフロー側で固定定義
- Slack通知設定側では「追加メッセージ」のみ保持し、現場で編集可能

例）メッセージ構築：
"キャンペーンメンバーが登録されました。\n" + {!設定.追加メッセージ__c}

メンション対応
- Slack通知設定に「メンション先ユーザー」参照項目を持たせる
- そのユーザーのSlackID（User.SlackId__c）を取り出して、<@SlackId> 形式でメッセージに差し込み

---

## まとめ

- 通知条件・投稿先・補足文言を「設定データとして持たせる」ことで、運用負荷とフロー改修コストを大幅に削減
- 条件分岐ロジックはGet Recordsで完結させ、フロー構造もシンプルに
- メッセージ本文は固定テンプレ＋補足だけで構成。差し込み複雑化を避け、現場での補足投稿を柔軟に実現

---

## 今後の展開（案）

- 通知ログ保存（Slack送信結果を保持）
- 通知テンプレの多言語化対応
- メンション複数指定、時間帯による通知制御