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

ついカっとなって、本の購入申請ワークフローを作った話

この記事は、JSL (日本システム技研) Advent Calendar 2019 - Qiita の5日目の記事です

TL;DR

社内の書籍の購入申請の仕組みを紙から電子に切り替えようと試みた話です。
(SlackのワークフローとGASを使って)

ことの始まり

「Grid Systems in Graphic Design」の和訳版があった。

スクリーンショット 2019-12-05 10.29.24.png
Grid systems in graphic design|グリッドシステム グラフィックデザインのために | ボーンデジタル

社内Slackの分報にそんなポストが。欲しくてたまらなかったけど、試用期間中の僕の手元にそんなお金はなかった。

スクリーンショット 2019-12-05 10.29.36.png
「そうだ。本の購入申請の仕組みがあるじゃないか」

技術書や業務に関係のある書籍なら会社に購入してもらう仕組みが我が社にはある。
これを利用しない手はない。そう思って僕は手続きを確認した。

Google Driveから申請用紙を探しだし、それを紙を印刷して、必要事項を記入して、ハンコを押して上長承認、社長承認を得れば、購入可能、そんなよくある仕組みだ。

早速紙を印刷して必要事項を記入しハンコを押して、、これで上長承認さえもらえすれば、あとは買うだけ。

ただこれはだいぶ時間がかかりそうだ。。。上長に「業務で役に立つのか」「費用の回収計画を説明してくれ」
など購入理由を問い詰められ、書類を書き直し再度レビューしてもらい。。
2ヶ月はかかるな。。すぐに読みたいのに。。
まあ本自体もWEBだと軒並み在庫はないし。。高値をつけて転売されている。。ちょうど良いか。。
などと考えていた。

その日はすでに上長が客先で不在であったため、書類をもって総務のひとに相談した。
「はい。分かりました。あしたには買えますよ」
「!?><+L+L <POKL`*」

驚愕だ。早すぎる。
メンバーが隣の街の書店で本の在庫を見つけてくれて、さらに買いに走ってくれて、
スクリーンショット 2019-12-05 11.14.05.png

週明けには本を手に入れることができた。
IMG_6180.jpg

そんな最高な仕組みがあるにもかかわらず、社内ではあまり使われていないようだ。(去年度9冊、本年度7冊)
メンバにヒヤリングしてみたところ、

  • 申請書を探すのがだるい
  • 申請書を印刷して書くのがだるい
  • そもそもそんな仕組みがあったの??

ということで、Slackで簡単に申請できるように試みてみました。

技術

  • Slack
    • ワークフロー
    • InCommingWebhhok
    • OutGoingWebhook
  • GAS

実装の流れ

  1. チャンネルを作成し、Slackワークフローを登録する
  2. Botを作成し、IncomingWebhookを利用可能にする
  3. GAS
  4. GASをOutgoingWebhookに登録

以下にかいつまんで書きます。

チャンネルを作成し、Slackワークフローを登録する

本の購入申請用のSlackチャンネルを作成し、次にワークフロービルダーを選択します。
スクリーンショット 2019-12-05 10.38.02.png

作成ボタンをより、名前をつけて 次へ を押下。
スクリーンショット 2019-12-05 10.40.15.png

アクションメニューを選択し、適宜設定。
新規に追加したチャンネルを設定します。
スクリーンショット 2019-12-05 10.41.02.png

必要事項を記入するフォームを追加し、右上の公開するボタンを押下。
スクリーンショット 2019-12-05 22.19.13.png

すると、チャンネルの右上にかみなりのようなマークが追加されワークフローが利用可能になります。
workflow.gif

フォームに記入し、送信を押下すると、以下のような感じでSlackに投稿されます。
スクリーンショット 2019-12-05 22.31.12.png

Botを作成し、IncomingWebhookを利用可能にする

Slack API: Applications | Slack で「Create α Slack App」を選択。
App Name,Development Slack Workspace を設定。
スクリーンショット 2019-12-05 10.54.56.png

Activate Incoming Webhooks を有効にし、投稿したいチャンネルを設定。
スクリーンショット 2019-12-05 10.55.27.png

COPYボタンを押下しWebhook URLを取得しておきます。(これがGASからSlackへ投稿するときに必要)
スクリーンショット 2019-12-05 10.59.45-2.png

GAS

Google Driveにて任意のスプレッドシートを作成し整えます。
スクリーンショット 2019-12-05 22.26.24.png

スプレッドシートのメニューより「ツール->スクリプトエディタ」を選択。
スクリーンショット 2019-12-05 21.59.55.png

コードは以下のような感じ。

//Outgoing Webhook のTOKEN(後述)
var WEBHOOK_TOKEN = "xxx";
// SlackからのPostを受け取る
function doPost(e) {
  if (WEBHOOK_TOKEN != e.parameter.token) {
    postSlack("debug:tokenが不正なアクセスがあったらぼ〜" ); 
    throw new Error("invalid token.");
  }
  try{
    var data = e.parameter.text;
    record(data);
    postSlack("申請完了ラボ!\n承認をしばしまつラボ〜!"); 
  }
  catch (e) {
    postSlack("debug:失敗ラボ〜〜!\nたぶんフォーマットエラーらぼ〜 :tsurai: \n ```" +  e + "```" ); 
  }
}

// Slackへ投稿する
function postSlack(text){
  //incomingwebhookを設定する
  var url = "前述のWebhook URL";
  var options = {
    "method" : "POST",
    "headers": {"Content-type": "application/json"},
    "payload" : '{"text":"' + text + '"}'
  };
  UrlFetchApp.fetch(url, options);
}

// スプレッドシートへ記入する
function record (data) {
  var recordsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('購入申請'); 

  //入力する行のオブジェクトを取得
  var lastrow = recordsheet.getLastRow();
  var recordrow = lastrow + 1;

  //投稿日時を取得
  var formatdate = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss');
  //Slackのポストを整える
  var lists = data.split(/\*/)
  //ユーザ名を整える
  applicant_user = lists[2].split(/\<|\>/)
  auth_user = lists[12].split(/\<|\>/)
  //スプレッドシートを更新する
  recordsheet.getRange("A" + recordrow).setValue("=ROW()-1"); // No
  recordsheet.getRange("B" + recordrow).setValue(formatdate); // 申請日
  recordsheet.getRange("C" + recordrow).setValue('=VLOOKUP("' + applicant_user[1] + '",ID!A:B, 2,FALSE)'); // 申請者
  recordsheet.getRange("D" + recordrow).setValue(lists[4]); // 本のタイトル
  recordsheet.getRange("E" + recordrow).setValue(lists[6]); // 税込金額
  recordsheet.getRange("F" + recordrow).setValue(lists[8]); // URL
  recordsheet.getRange("G" + recordrow).setValue(lists[10]); // 購入希望理由
  recordsheet.getRange("H" + recordrow).setValue('=VLOOKUP("' + auth_user[1] + '",ID!A:B, 2,FALSE)'); // 承認者
}

SlackからPOSTされた本文は、e.parameter.textの中に全て入っており、今回はsplitし整えています。

また、IDは普段見ないほうのユニークなidが含まれているため、idと名前の紐付けをどこかでやってあげる必要がありました。
今回はスプレッドシートの別シートにidと名前の一覧を作成しています。
GASではそこを参照するような式をスプレッドシートに出力しています。

参考までにSlack全メンバのidは以下より取得可能。
users.list method | Slack

GASをOutgoingWebhookに登録

GASのメニューより「公開->ウェブアプリケーションとして導入...」を選択。
スクリーンショット 2019-12-05 22.56.54.png

適宜入力し、web app URL を取得。
(これをSlackのOutgoingWebhookに登録します。)
スクリーンショット 2019-12-05 22.58.43.png

Slackにて「Slackをカスタマイズ」を選択。
スクリーンショット 2019-12-05 23.01.43.png

「App 管理」を選択し
スクリーンショット 2019-12-05 23.02.04.png

App ディレクトリよりOutGoing Webhookを選択
スクリーンショット 2019-12-05 23.03.00.png

チャンネルや引き金となる言葉を入力し、URLにはGASのweb app URLを設定。
前後してしまいますが、ここで取得可能なトークンの値をGASのコードの先頭部分に貼ってください。(グレーの部分)
スクリーンショット 2019-12-06 9.15.44.png

これで完了です。

使ってみた

Slackでワークフローを使うと
スクリーンショット 2019-12-05 23.10.18.png

投稿されて、
スクリーンショット 2019-12-05 23.24.26.png

スプレッドシートも更新されました!
スクリーンショット 2019-12-05 23.25.17.png

これで承認されれば本を買ってもらますね!

作ってみて

本を購入できる制度があるのは素晴らしいですが、使われなけば意味がありません。
これを機にもっと社内でこの制度が使われれば良いなあと思います。

みなさんもご自身の会社で確認してみてはいかがでしょうか?

またGAS(+スプレッドシート)とSlackの連携によって、他の紙で管理している申請なども
どんどん電子化してしまいたい所存です。

謝辞(参考URL)

本記事の実装の多くは以下を参考にしています。感謝を。

Slack Bot、GASまわり
Slackとスプレッドシートを連携して筋トレ管理をする | GMOアドパートナーズグループ TECH BLOG byGMO

Slackワークフロー
Slack に便利機能 "ワークフロービルダー" が増えたので勇み足で使ってみた - Feedforce Developer Blog

jrfk
こんにちは!
jsl
株式会社日本システム技研は、1976年に設立した長野に本社を構えるIT企業です。主にPython/Djangoの使用したWebアプリケーションの受託開発とプロダクト開発を行なっています。エンジニア向けコミュニティGEEKLAB.NAGANO( http://geeklab-nagano.com ) の運営をしています。
https://jsl.co.jp
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