Garoon のワークフローから、Chatwork のチャットルームへメッセージを送信する

目次

はじめに

Garoon のワークフローから Chatwork へメッセージを送信するサンプルです。
Chatwork に「Garoon 連携用のユーザーアカウント」を作成し、個人ユーザーとコンタクトすることで、Garoon のワークフロー画面上から承認者宛てに催促メッセージを送ることができます。

概要

Garoon のワークフローから申請した後に、申請者から承認者へ「承認の催促」を行うボタンを表示します。
「催促」ボタンをクリックすると、直近の未処理の承認者あてに Chatwork のメッセージを送信します。

ワークフローの承認が完了したり、却下された場合は、催促ボタンが表示されなくなりますので、これ以上の催促が行えなくなります。

以下は紹介動画です。

カスタマイズの適用

  1. サンプルに使用するユーザアカウントを Garoon、Chatwork それぞれで作成します。
    (登場人物は実在の人物ではありません)

    組織イメージ

    以下の 1 名を Chatwork にアカウント作成します。

    • 連携用:外部連携さん(Garoon との連携用です)

    以下の 3 名を Chatwork、Garoon にアカウントを作成します。

    • 申請者:藤田一さん(開発部:一般職)
    • 承認者 1 :谷啓介さん(開発部:課長)
    • 承認者 2 :佐藤一二三さん(開発部:部長)

    以下の 2 名は、Garoon にアカウントを作成します。

    • 回覧 : 林原さん(経理部:課長)
    • 回覧 : 恋沼さん(経理部:部長)

    「外部連携」アカウントのコンタクト一覧に申請者、承認者のアカウントが追加されているか確認してください。
    表示されていない場合は、「コンタクト管理」からユーザーを追加してください。

  2. Garoon のユーザのプロフィール項目にカスタマイズ項目を追加します。

    項目名 項目コード タイプ 公開/非公開 ユーザーによる変更
    Chatworkアカウント ID cw_account_id 文字列(1行) 公開 許可

  3. Chatwork の各個人それぞれの「アカウント ID」を Garoon の各個人のカスタマイズ項目へ登録してください。

  4. Chatwork の「外部連携」ユーザの「API Token」を取得しておいてください。

  5. Garoon の「プロキシ API の設定」で、Chatwork の URL を登録します。
    プロキシ API の詳細については、プロキシ API の設定 クラウド版 (External link) パッケージ版 (External link) を参照してください。

    • メッセージの送信用

      • プロキシコード:AP0001
      • メソッド:POST
      • URL:https://api.chatwork.com/v2/room
      • ヘッダー
        • キー:X-ChatWorkToken
        • 値:上記 4. で取得した APIToken の値
    • コンタクト一覧の取得用

      • プロキシコード:AP0002
      • メソッド:GET
      • URL:https://api.chatwork.com/v2/
      • ヘッダー
        • キー:X-ChatWorkToken
        • 値:上記 4. で取得した APIToken の値

  6. Garoon の「ファイル管理」に今回の JavaScript を登録します。

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    
    /*
    * Garoon × Chatwork 連携 サンプルプログラム
    *
    * 「gr_post_ext_chat.js」ファイル
    *
    * Copyright (c) 2018 Cybozu
    *
    * Licensed under the MIT License
    */
    (function() {
      'use strict';
      const g_garoon_base_url = location.origin;
      const g_chatwork_base_url = 'https://api.chatwork.com';
      const g_garoon_proxy_id_CW_postmessage = 'AP0001';
      const g_garoon_proxy_id_CW_contasts = 'AP0002';
      const g_garoon_workflow_top_url = g_garoon_base_url + '/g/workflow/index.csp?';
      const g_garoon_custom_item_name = 'cw_account_id';
    
      // //////////////////////////////////////////////
      // ■(非同期3)Chatwork 承認者あてにメッセージを送信
      //    送信メッセージを編集してChatworkへ送信する
      //
      //    <非同期後の処理>
      //    ・成功/失敗のアラートを表示する
      // //////////////////////////////////////////////
    
      function postMessage(room_id, from_account_id, to_account_id, to_account_name, workflow_name, form_url) {
    
        // Chatwork room_id
        const cw_room_id = room_id;
    
        // Garoon Proxy code
        const garoon_proxy_code = g_garoon_proxy_id_CW_postmessage;
    
        // Chatwork url
        const posturl = g_chatwork_base_url + '/v2/rooms/' + cw_room_id + '/messages';
    
        // METHOD
        const post_method = 'POST';
    
        // body(送信するメッセージを編集)
        const msg = encodeURIComponent('[piconname:' + from_account_id + '] [hr] [To:' + to_account_id + ']  '
                    + to_account_name + 'さん [info][title](devil)承認をお願いします:' + workflow_name
                    + '[/title] ' + form_url + ' [/info]');
        const post_data = 'body=' + msg;
    
        // proxy経由で外部メソッドコール
        garoon.base.proxy.send(garoon_proxy_code, posturl, post_method, {}, post_data).then((args) => {
          /*  args[0] -> レスポンスボディ(文字列)
           *  args[1] -> ステータスコード(数値)
           *  args[2] -> レスポンスヘッダ(オブジェクト)
          */
          console.log(args[1], JSON.parse(args[0]), args[2]);
          if (args[1] === 200) {
            alert('成功しました');
          } else {
            alert('失敗しました "' + JSON.parse(args[0]).errors[0] + '"');
          }
        }, (error) => {
          console.log(error); // proxy APIのレスポンスボディ(文字列)を表示
          alert('Proxy送信が失敗しました');
        });
      }
    
      // //////////////////////////////////////////////
      // Garoonのアカウント情報から、カスタム項目の
      // 値を取得する
      // //////////////////////////////////////////////
      function getAccountCustomItem(acount_info, item_name) {
        let returnValue = '';
        for (let i = 0; i < acount_info.customItemValues.length; i++) {
          if (acount_info.customItemValues[i].code === item_name) {
            returnValue = acount_info.customItemValues[i].value;
          }
        }
        return returnValue;
      }
      // //////////////////////////////////////////////
      // Garoonのアカウント一覧から、指定したコードの
      // アカウント情報を取得する
      // //////////////////////////////////////////////
      function getAccount(acount_list, code) {
        for (let i = 0; i < acount_list.users.length; i++) {
          if (code === acount_list.users[i].code) {
            return acount_list.users[i];
          }
        }
        return null;
      }
    
      // //////////////////////////////////////////////
      // ■(非同期2)Chatwork 「外部連携」ユーザのコンタクト一覧を取得
      //
      //    <非同期後の処理>
      //     ・コンタクト一覧から催促したい承認者のルームIDを取得
      //     ・Chatwork チャットのメッセージを送信処理をコール
      // //////////////////////////////////////////////
      function getContactList(acount_list) {
    
        // Garoon Proxy code
        const garoon_proxy_code = g_garoon_proxy_id_CW_contasts;
    
        // Chatwork url
        const posturl = g_chatwork_base_url + '/v2/contacts';
    
        // METHOD
        const get_method = 'GET';
    
        // proxy経由で外部メソッドコール
        garoon.base.proxy.send(garoon_proxy_code, posturl, get_method, {}, '').then((args) => {
          /*  args[0] -> レスポンスボディ(文字列)
                *  args[1] -> ステータスコード(数値)
                *  args[2] -> レスポンスヘッダ(オブジェクト)
                */
          const contact_list = JSON.parse(args[0]);
    
          // /////////////////
          // コンタクト一覧から、承認者のアカウントIDがあるものを取得
          // /////////////////
          // ワークフローのリクエスト内容取得
          const req = window.garoon.workflow.data['workflow.request.detail.show'].request;
          let send_process_account_code;
    
          // "承認" 以外のステータスの承認者を探す
          for (let p = 0; p < req.steps[req.processingStepCode].processors.length; p++) {
            if (req.steps[req.processingStepCode].processors[p].result !== '承認') {
              send_process_account_code = req.steps[req.processingStepCode].processors[p].code;
              break;
            }
          }
    
          // Garoonの申請者のアカウント情報を探す
          const send_account_info = getAccount(acount_list, send_process_account_code);
          const my_account_info = getAccount(acount_list, req.applicant.code);
    
          // 催促した承認者のルームIDを取得する
          let send_account_id = getAccountCustomItem(send_account_info, g_garoon_custom_item_name);
          let send_account_name, send_room_id;
          for (let c = 0; c < contact_list.length; c++) {
            if (contact_list[c].account_id === Number(send_account_id)) {
              // 催促した承認者のルームIDが見つかった場合、
              // 承認者の「ChatworkアカウントID」「Garoonの表示名」「ルームID」を保存
              send_account_id = contact_list[c].account_id;
              send_account_name = send_account_info.name;
              send_room_id = contact_list[c].room_id;
            }
          }
    
          // /////////////////
          // Chatworkへメッセージ送信
          // /////////////////
          const room_id = send_room_id;
          const from_account_id = getAccountCustomItem(my_account_info, g_garoon_custom_item_name);
          const to_account_id = send_account_id;
          const to_account_name = send_account_name;
          const workflow_name = req.name;
          const form_url = g_garoon_workflow_top_url;
          postMessage(room_id, from_account_id, to_account_id, to_account_name, workflow_name, form_url);
    
        }, (error) => {
          console.log(error); // proxy APIのレスポンスボディ(文字列)を表示
        });
      }
    
      // //////////////////////////////////////////////
      // ■(非同期1)Garoon ユーザ一覧取得
      //
      // //////////////////////////////////////////////
      function getAllUsers(request) {
    
        const req = new XMLHttpRequest();
        const url = g_garoon_base_url + '/v1/users.json';
        req.open('GET', url, true);
        req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        req.onload = function() {
          const acount_list = JSON.parse(req.responseText);
    
          // /////////////////
          // Chatworkからコンタクト一覧を取得
          // /////////////////
          getContactList(acount_list);
    
        };
        req.send(null);
      }
    
      // //////////////////////////////////////////////
      // 外部連携メイン処理
      //
      // <処理順序>
      // ■この関数
      // ┗■(非同期1)ユーザ一覧取得
      //   ┗■(非同期2)Chatwork 「外部連携」ユーザのコンタクト一覧を取得
      //      ┗■(非同期3)Chatwork 承認者あてにメッセージを送信
      // //////////////////////////////////////////////
      function postChatWork(request) {
        // /////////////////
        // ユーザ一覧取得
        // /////////////////
        getAllUsers(request);
      }
    
      // //////////////////////////////////////////////
      // 画面表示時の処理
      // 催促ボタンを表示する
      // //////////////////////////////////////////////
      garoon.events.on('workflow.request.detail.show', (event) => {
    
        // 申請者本人の場合に「催促」ボタン表示
        if (event.request.applicant.code === garoon.base.user.getLoginUser().code) {
    
          // ワークフローの「進行中」の場合に「催促」ボタン表示
          if (event.request.status.type === 'UNPROCESSING' || event.request.status.type === 'IN_PROGRESS') {
    
            // 項目コードSaisokuButtonの要素を取得
            const el = garoon.workflow.request.getSpaceElement('JS01');
            const e = document.createElement('button');
            e.innerHTML = '催促';
            e.onclick = function() {
              postChatWork(event.request);
            };
            el.appendChild(e);
          }
        }
      });
    })();

    ここでアップした JavaScript ファイルのダウンロードリンクを、のちほど使うので控えておいてください。
    ファイルの詳細から右クリックし、「リンクのアドレスをコピー」でダウンロードリンクが生成できます。

  7. ワークフローの申請フォームで、「JavaScript カスタマイズ用項目の追加」を行います。

    申請フォームは Garoon にサンプルがいくつか用意されていますので、試す際はそちらを利用してください。
    今回の例では、サンプルフォーム > 経理関連 > 交際費申請を利用しています。

    続けて、「JavaScript/CSS によるカスタマイズ」で、(5)で追加した JavaScript ファイルのリンクを追加してください。

動作確認

  1. 藤田さんで Garoon にログインし、上記で JavaScript を組み込んであるワークフローを選択し、申請してください。

    経路の設定では、課長欄:谷さん、部長欄:佐藤さん、回覧の欄:恋沼さんと林原さんを設定してください。
    設定が済んだら、申請します。

  2. 申請後にホーム画面の「ワークフロー」から、先ほど申請したワークフローを開きます。

    「催促」ボタンは表示されているでしょうか?
    催促ボタンがある場合は、クリックしてみましょう。

    直近の承認者の「谷さん」へメッセージが送信されます。

おわりに

Chatwork と Garoon を連携することで、コミュニケーションがより手軽になります。
ぜひご活用ください。

information

この Tips は、2018 年 10 月版 Garoon で動作を確認しています。