クリエイターズネットワーク フリーナンス engineering

決裁書承認システムとSlackを連携させた後、承認フローの階層追加に対応した話

クリエイターズネットワーク フリーナンス engineering

こんにちは! GMO ペパボのグループ会社である GMO クリエイターズネットワークのよしだです。

今回は、社内で使われている 2 つの決裁書承認システムと Slack を連携させて効率化した話の続きとして、決裁書承認システムと Slack を連携させた後、承認フローの階層追加に対応した話をします。

前回のおさらい

さて、本題に入る前に前回の記事で掲載したフロー図をおさらいしておきましょう。 承認フローの階層追加の説明をさせていただくにあたって、重要な部分です。 現在のフロー

登場人物

登場人物は以下の通りです。

申請者

フリーナンス管理画面から決裁書を申請する弊社パートナーを指します。

フリーナンス

「フリーランスを、もっと自由に。」との想いからフリーランスのお客様向けに保険やファクタリングを提供する、弊社サービスです。 前回の記事で、フリーナンス管理画面から X-point 経由で決裁書を作成できるようにしました。

X-point

株式会社エイトレッドの提供する電子稟議システムX-point Cloudです。 前回の記事で、承認フローは X-point の責務として実装しました。

Slack

弊社業務で利用しているビジネスチャットツールです。 前回の記事で、決裁書の承認を Slack から実施できるようにしました。

決裁書提出の流れ

申請者が決裁書を提出するまでの流れは下記となります。

  1. 申請者はフリーナンス管理画面から「決裁書作成」ボタンを実行
  2. フリーナンスは X-point に決裁書を下書きで作成
  3. フリーナンスは決裁書の ID から X-point の決裁書編集画面の URL を返却
  4. 申請者は決裁書編集画面にリダイレクトし、決裁書を提出

決裁書提出後の流れ

決裁書提出後は X-point からフリーナンスが Webhook を受信し、フリーナンス経由で Slack や X-point と連携します。

  1. フリーナンスから Slack に承認依頼を送信
  2. Slack から承認操作を実施し、フリーナンスで受信
  3. フリーナンスから X-point へ決裁書の承認依頼を送信
  4. X-point からフリーナンスへ承認完了の Webhook を受信

今回のテーマ

ある日の午後、「来月から承認フローの階層を追加することになった」と連絡がありました。 決裁書の承認者として、フリーナンスで扱う全ての決裁書の承認フローに、1 部門増えるとのことでした。

来月までに承認フローの階層を増やさなければなりません。どこを変更すればよいでしょうか。

修正箇所

前回の記事で、承認フローは X-point の責務として実装しました。 そのため、承認フローの階層追加は X-point で実施できます。

しかし、フリーナンスでは X-point から送信される、承認フローの階層毎にそれぞれの Slack チャンネルに対して承認依頼を送信しています。 下記、修正箇所のフロー図部分は修正が必要です。

修正箇所

承認依頼を送信(変更前)

一部ぼかしていますが、フリーナンスで承認フロー毎の Slack チャンネルに承認依頼を送信しているのは下記部分です。

const MANAGER_APPROVAL = 1;
const EXECUTIVE_OFFICER_APPROVAL = 2;
const PRESIDENT_APPROVAL = 3;

/**
 * X-pointからのWebhook
 */
public function handleWebhook($documentStatusCode, $payload)
{
    // 決裁書のステータスから、次の承認者が存在する場合は次の承認者へSlack承認依頼送信
    if ($documentStatusCode == self::XPOINT_STATUS_APPROVING) {
        // 承認フローの階層とSlackチャンネルのマッピング
        $channelMap = [
            self::MANAGER_APPROVAL               => XPOINT_SLACK_CHANNEL_MANAGER,
            self::EXECUTIVE_OFFICER_APPROVAL     => XPOINT_SLACK_CHANNEL_DIRECTOR,
            self::PRESIDENT_APPROVAL             => XPOINT_SLACK_CHANNEL_PRESIDENT,
        ];
        // 現在の承認フロー
        $currentStep = $payload['document']['step']['current'] ?? null;
        // エラーチェック
        if (is_null($currentStep) || !isset($channelMap[$currentStep])) {
            $this->log('[XpointWebhook] パラメータが不正です。', 'error');
            return;
        }
        // Slackに送信する承認依頼の文言やボタンを生成
        $message = $this->makeSlackTemplateForApprovalRequest($channelMap[$currentStep], $payload);
        // Slackへ承認依頼送信
        $this->SlackNotification->postMessage($message);
    }
}
  • MANAGER_APPROVAL,EXECUTIVE_OFFICER_APPROVAL,PRESIDENT_APPROVALは承認フローの何階層目かを表すもののため、整数が入ります。
  • XPOINT_SLACK_CHANNEL_MANAGER,XPOINT_SLACK_CHANNEL_DIRECTOR,XPOINT_SLACK_CHANNEL_PRESIDENTは各 Slack チャンネル ID が文字列で入ります。

承認依頼を送信(変更後)

承認フローの階層と Slack チャンネルのマッピングが追加されれば良いため、$channelMapの内容を変更します。 また、併せて定数の追加と階層番号の修正を行います。

const DEPARTMENT_APPROVAL = 1; // ←今回追加
const MANAGER_APPROVAL = 2; // 番号変更
const EXECUTIVE_OFFICER_APPROVAL = 3; // 番号変更
const PRESIDENT_APPROVAL = 4; // 番号変更

/**
 * X-pointからのWebhook
 */
public function handleWebhook($documentStatusCode, $payload)
{
    // 決裁書のステータスから、次の承認者が存在する場合は次の承認者へSlack承認依頼送信
    if ($documentStatusCode == self::XPOINT_STATUS_APPROVING) {
        // 承認フローの階層とSlackチャンネルのマッピング
        $channelMap = [
            self::DEPARTMENT_APPROVAL => XPOINT_SLACK_CHANNEL_DEPARTMENT, // ←今回追加
            self::MANAGER_APPROVAL               => XPOINT_SLACK_CHANNEL_MANAGER,
            self::EXECUTIVE_OFFICER_APPROVAL     => XPOINT_SLACK_CHANNEL_DIRECTOR,
            self::PRESIDENT_APPROVAL             => XPOINT_SLACK_CHANNEL_PRESIDENT,
        ];
        // 現在の承認フロー
        $currentStep = $payload['document']['step']['current'] ?? null;
        // エラーチェック
        if (is_null($currentStep) || !isset($channelMap[$currentStep])) {
            $this->log('[XpointWebhook] パラメータが不正です。', 'error');
            return;
        }
        // Slackに送信する承認依頼の文言やボタンを生成
        $message = $this->makeSlackTemplateForApprovalRequest($channelMap[$currentStep], $payload);
        // Slackへ承認依頼送信
        $this->SlackNotification->postMessage($message);
    }
}

Slack チャンネル ID であるXPOINT_SLACK_CHANNEL_DEPARTMENT.envから取得しており、Secret Manager での設定が必要ですが、本筋からは外れますので割愛します。

切り替え作業

今回対象となる承認フローは動かなくなると業務が止まってしまいます。 そのため、確認をしながら慎重に移行する必要がありました。

切り替えの時間は下記の点から、夕方 17:00 以降としました。

  1. 承認フローが使われるのは平日 17:00 迄
  2. 動作確認を実施するため、関係者の業務時間外である夜間は避けたい

手順としては下記の通りです。

  • 検証環境での切り替え
  • 本番環境での切り替え後、戻す

検証環境での切り替え

本番とは別の検証用 X-point に新しい決裁書を作成します。 その後、修正したコードを反映し、決裁書作成 ~ 承認までの動作確認をします。

Slack への通知も検証用のチャンネルに対して行われます。

本番環境での切り替え後、戻す

決裁書作成が実行されない時間帯に、修正したコードを反映し、決裁書作成 ~ 承認までの動作確認をします。 動作確認は実際に業務を行う、申請者と承認者に実施してもらいました。

作成した決裁書はテストデータとして破棄し、コードを元の状態に戻します。

本番環境での切り替え

予行演習を実施した際に、申請者と承認者に対してテストでの確認点をうまく伝えられず、確認に時間がかかってしまっていました。 そのため、今回は以下の点をテスト観点として共有しました。

  • 決裁書作成時に新たに追加した Slack チャンネルへ承認依頼が送信されている
  • 新たに追加した Slack チャンネルで承認を実施した際に、X-point の承認状態も連動している
  • 新たに追加した Slack チャンネルで承認を実施した際に、次の承認者の Slack チャンネルへ承認依頼が送信されている
  • 最後の承認者の Slack チャンネルで承認を実施した際に、X-point の承認状態も承認完了になっている

修正したコードを反映し、テスト観点に沿って動作確認をしてもらいました。予行演習よりもスムーズに実施でき、トラブルなく完了できました。

全体を通して感じたこと

承認フローを X-point の責務にすることで、承認者や承認フローの階層変更にも柔軟に対応できました。

しかし、承認フローの階層と Slack チャンネルをマッピングしている部分はハードコーディングであったため、コードの修正は必要です。 今後はマッピング部分もデータベースで保持することにより、コードを修正することなく対応できるのではないかと思います。

また、切り替え時の予行演習をすることで、リリース時の課題を明確にできたのは良かった点です。 今後も継続して行っていきます!

GMO クリエイターズネットワークでは、プロダクト開発職種の採用をおこなっています!

フリーナンスでは今、プロダクト開発組織を立ち上げていこうとしている最中です。

ソフトウェアエンジニアとして面白い部分は、フロントエンド〜バックエンド〜インフラを横断的に触る開発スタイルで開発している点です。 Go のコードを書いたり、Terraform を書いたりしながら開発を進めていることが多いです。

現在は Go や React を中心としたシステムへのリアーキテクチャを検討しています。 バックエンドアーキテクチャの設計やフレームワークの選定、検証とやれることは非常に多いです。

そんな技術課題の解消やユーザに価値を提供出来る仕組みづくりを私達と一緒に進めていってくださる方々を募集中です!以下の職種を積極採用しています!

また、カジュアル面談も大歓迎ですのでお気軽に申し込んでいただけると嬉しいです!