SlackとGASを使って会社のお弁当発注を自動化した話

  • 521
    いいね
  • 5
    コメント

こちらの内容は第一回 MAMORIO Meetupで発表した内容をまとめたものです。

背景

弊社ではお弁当が必要な人は前日に注文しておけば、会社が無料で提供してくれる福利厚生があります。(素晴らしいですね :thumbsup:)

ちょうど会社の近くに安くて美味しいお弁当屋さんがあり、配達もしてくれるのですが、この注文先のお弁当屋さんは電話かFAXでしか注文を受け付けておらず、誰かが毎日集計して朝お弁当屋さんに注文する必要がありかなり面倒です。

具体的には以下のような作業が毎日必要になります。

  • 集計
    • 呼びかけ: 明日誰がお弁当が必要か聞く
    • リマインド: 集計時に忙しくてすぐ答えてくれない人もいるので未回答の人に対してリマインドする
    • キャンセル: 集計したもののやっぱりキャンセルとなった場合はその分を差し引く
  • 確定&発注: 集計した個数を電話あるいはFaxで発注する

この作業を毎日人がやっているようでは、弊社の様に少ない人数ではやっていけませんし、極限まで自動化するというポリシーにも反します。

そこでこの問題を解決するためにお弁当の発注をSlackとGoogleAppScriptを使って自動化しました。今回はそれについてお話します。

まずは完成したものを御覧ください

呼びかけ

これが
mask_yobikake copy.png

こうなりました(ノで自動集計)
order.gif

リマインド

これが
mask_remind copy.png

こうなりました(決まった時間にリマインド)
Screenshot 2017-04-26 00.01.48.png

キャンセル

これが
mask_cancel copy.png

こうなりました(_で自動キャンセル)
cancel.gif

個数確定&発注

これが
call_phone.gif

こうなりました(決まった時間に自動個数確定 & FAX送信)
Screenshot 2017-04-26 00.05.23.png

良い感じに全てが自動化されましたね :thumbsup_tone1:

仕組みの説明に入る前に今回大活躍のGAS(Google App Script)についてとても便利なので簡単にご紹介します。

GoogleAppScriptについて

GoogleAppScript(略してGAS)はGmailやSpreadSheetなどGoogleの様々なシステムと連携するシンプルなWebアプリをjavascriptで簡単に書けるサービスです。

メリットとしては

  • サーバーレス
  • なのに無料(神)
  • Googleの他のサービスと連携するAPIが多数用意されている。

デメリットは

  • エディターがブラウザで編集しづらい、補完とかもない。
  • APIを複数書いたり、ファイルを分けたり出来ないので複雑なことをやろうとするとかなり辛い。
  • タイマー処理の時間とかが1時間とかのレベルでずれる。かなり適当。

といったように今回の様にさくっと何か単純なものを作りたいときにはサーバーレス&無料でとっても良いサービスなわけです。(といっても今回のお弁当botの複雑さくらいで限界でこれ以上の場合はなんかフレームワーク使った方がいいと思います。)

仕組み

集計されるまで

Screenshot 2017-04-26 01.18.25.png

集計処理は全体としては上図のような構成になっています。

呼びかけとリマインド

まず、明日「お弁当いる方〜?」と呼びかけるのはGASのタイマー処理でSlackのIncomingWebhookを叩いています。リマインドについても同様のタイマー処理で実装しています。

  function setCallTrigger() {
    for (var i = 0; i < Const.triggers.triggerDays.length; i++) {
      ScriptApp.newTrigger("triggerCall")
        .timeBased()
        .onWeekDay(Const.triggers.triggerDays[i])
        .atHour(Const.triggers.callTrigger.hour)
        .nearMinute(Const.triggers.callTrigger.minute)
        .create();
    }
  }
...
  function triggerCall() {
    loadSlackModule().send_slack('<!channel> 明日お弁当いる方〜?');
  }

注文、キャンセルについては以下のように誰かが「ノ」「_」とメンションするとGASにPOSTリクエストが飛ぶようにOutgoingWebHookを設定しておき
hook.png

GAS側で来たリクエストによって処理を振り分けてメンションした人のSpreadSheetに注文数を加算or減算します。完了したらSlackで応答を返します。

function doPost(e) {
  var request = parse_request(e);
  var commandar = loadCommander();

  #処理を振り分ける
  switch (true) {
    case /^obento/.test(request.text):
      commandar.command_order(request);
      break;
    case /^ノ/.test(request.text):
      commandar.command_add(request);
      break;
    case /^_/.test(request.text):
      commandar.command_cancel(request);
      break;
    default:
      no_command(request);
  }
...
}
...
  # 注文
  Commandar.command_add = function(request) {
    var date = loadDateUtils().parseDateTime(request.text);
    SpreadSheet.write_sheet(request.user, date, 1);
    var amount = loadSummerizer().summerizeOrder().orderAmount;
    var slack_result = "<@" + request.user + "> \n" + (date.getMonth() + 1) + "月" + date.getDate() + "日分 注文で登録しました。 \n 現在合計" + amount + "個"
    loadSlackModule().send_slack(slack_result)
  }

  # キャンセル
  Commandar.command_cancel = function(request) {
    var date = loadDateUtils().parseDateTime(request.text);
    SpreadSheet.write_sheet(request.user, date, -1);
    var amount = loadSummerizer().summerizeOrder().orderAmount;
    var slack_result = "<@" + request.user + "> \n" + (date.getMonth() + 1) + "月" + date.getDate() + "日分 注文をキャンセルしました。 \n 現在合計" + amount + "個"
    loadSlackModule().send_slack(slack_result)
  }

個数の確定&発注

Screenshot 2017-04-26 01.35.58.png

個数の確定&発注は上図のようになっています。

注文数の確定

まずはおなじみのGASが注文する時間になったらSpreadSheetから値を取ってきて合算して、何個注文するかを確定します。

発注処理

発注処理ではFaxの送信のためにefaxというメールでfax送信できるサービスを使っています。APIもあるようなのですが、ちょっと扱いづらそうだったのでGASからGmailAPIを使ってefaxに対してメールを送信して間接的にfax送信を実行しています。

  Commandar.command_order = function (request) {
    // prod
    var fax_email_address = "xxxxxxxxx@efaxsend.com"
    var params = parse_order_text(request.text);
    var subject = "MAMORIO株式会社" + params.month + "月" + params.day + "日分注文"
    var body = "いつもお世話になっております。MAMORIO株式会社です。" + params.month + "月" + params.day + "日、お弁当" + params.amount + "個お願い致します。"

    // mailを送信
    MailApp.sendEmail(fax_email_address,
      subject,
      body);

    // 結果をslack通知
    var slack_result = "<@" + request.user + ">" + params.month + "月" + params.day + "日分" + params.amount + "個注文しました。(FAXが送信できたらここに通知されます。)"
    loadSlackModule().send_slack(slack_result)
  }

送信完了通知

最後にfaxが送信出来たときの完了通知はGmailを送信した送信元にメールで通知されるのでSlackのemail Appを使って完了した旨をお弁当チャンネルに通知しています。

まとめ

このようにGASを使えば簡単に業務を効率化できるのでぜひ試してみてください!!

どなたかの参考になればと思い今回のソースをgistにしておきました。
(もしうちの会社でもfaxでお弁当を毎日注文しているよという稀有な方がいればよければ使ってください笑)

MAMORIO社に興味のある方はGEEK GARAGEのイベントでもwantedlyからでも遊びに来てください!お待ちしています :smiling_imp: