音楽とお酒とものづくりと

営業マンが元webエンジニアの経験を生かしてあれやこれやするやつ

【営業マンのための】google app scriptを使って、翌日に外出の予定があれば交通費精算のタスクをtrelloに自動で登録する【仕事効率化】

やりたいこと

google calendarにて翌日の予定を確認し、外出の予定があれば交通費精算のタスクをtrelloに追加する

つかうもの

google app acript / google calendar / trello

背景

基本的に自分のタスクは全てtrelloで管理しています。
カンバン方式のようにレーンを作り、それぞれ以下のようなレーンでタスクを分類しています。
緊急度は高くないがやらないといけないこと / 今週やること / 今日やること / 今やってること / Blocker / 完了


営業になって、外出の予定がすごく増え、ほぼ毎日外に出ています(?)
外出に伴う交通費の申請処理を月末に一気にやると時間がかかる & 漏れが出てくるので、基本的には日ごとに入力を行うようにしています。
毎日やるタスクを毎日trelloに登録するのもめんどくさいし、でも登録していないとたまに入力を忘れる日が出てくるので、なんとかしたいなあと思ったのが背景です。


ちなみに何か仕事が入ってきたらとりあえずtrelloに登録、緊急度を他のタスクと比較し、次にやるタスクの選定を行っています。
基本的に何かをずっと覚えておくのはつらいので、trelloに登録したらそのタスクのことは一旦忘れます。
覚えておかないといけないこと(タスクの詳細やメモなど)は説明欄やコメントに残し、目の前の仕事に集中できるようにします。
そんなやり方をやっていると、交通費申請なんてどうでもいいタスク(よくないけど)、忘れてしまうわけです。


trelloは必ず頻繁に確認するので、自動でタスク登録してくれたら毎日忘れずに処理できるかなと思ったわけです。

実装

trelloのAPIトークンを取得する

さて本題。
まずはAPIを叩くためのトークンの発行を行います。
trelloにログインした状態で以下のURLにアクセスします。
https://trello.com/1/appKey/generate


まずは開発者向けのキーが表示されるので、これをメモ。
次に「あなたは手動でTokenを作られます。」のTokenの部分がリンクになっているのでこれをクリック。
遷移後に認証を求められるので、READとWRITEの権限があることを確認し、認証します。
認証後、APIトークンが表示されるので、こちらもメモ。


この段階で、まずは認証が正しく完了したかを確認します。
以下のURLをブラウザに入力します。
https://trello.com/1/members/"USERNAME"/boards?key="KEY"&token="TOKEN"&fields=name


"USERNAME"にはtrelloのユーザIDを
"KEY"と"TOKEN"にはそれぞれ先ほどメモしておいた値を入力します。
正しく認証が済んでいると、自分のアカウントに登録しているボードの情報が表示されると思います。
ちなみに最後の「fields=name」を入れることで、そのボードに対する名前とIDだけを表示させることができます。


これでtrelloを操作する準備が整いました。

google calendarの予定を取得する

calendarの予定を取得するメソッドは既にあり、取得対象となるメールアドレスのみ指定すればOK。
```
CalendarApp.getCalendarById('自分のメールアドレス');
```
あとは検査対象となる日付を与え、予定を取得します。

なお、予定を入力する際にその予定のカテゴリ(外出、来客、会議など)をプレフィックスとしてつけているので、外出の予定かどうかはこのプレフィックスを用いて判別します。
最終的に出来上がったコードは以下の通り。

function myFunction() {
  var date = new Date();
  var day = date.getDate();
  if (!isExistedCard(day) && isOutOfOffice()) {
    addCard(day);
  }
}

function isOutOfOffice(){
  var cal = CalendarApp.getCalendarById('自分のメールアドレス');
  var date = new Date();
  var events = cal.getEventsForDay(date);
  for(var i in events){
    if(events[i].getTitle().match(/^外出/)){
      return true;
    }
  }
  return false;
}

function isExistedCard(day){ 
  var data;
  var url = 'https://api.trello.com/1/lists/"LIST_ID"/cards?key="KEY"&token="TOKEN"&fields=name';
  var options = {
    'method' : 'get',
    'muteHttpExceptions' : true,
  }
  data = UrlFetchApp.fetch(url, options);
  var tasks = JSON.parse(data);
  for(var i in tasks){
    var task_name = tasks[i]['name'];
    if(task_name == day + '日交通費処理'){
      return true;
    }
  }
  return false;
}

function addCard(day){
  var listId = 'LIST_ID;
  var trelloKey = 'KEY';
  var trelloToken = 'TOKEN';
  
  var url = 'https://api.trello.com/1/cards/?key=' + trelloKey + '&token=' + trelloToken;
  var options = {
    'method' : 'post',
    'muteHttpExceptions' : true,
    'payload' : {
      'name'      : day + '日交通費処理',
      'desc'      : 'This is test.',
      'due'       : '',
      'idList'    : listId,
      'urlSource' : ''
    }
  }
  UrlFetchApp.fetch(url, options);
}


正直ソースコードはすっちゃかめっちゃかです。いずれクラス化(ライブラリ化?)したりして最適化したいとは思いますが、今回は諦めました。
cronのように特定の時刻になればこのプログラムが起動されるように設定しております。
すでに同じタスクが登録されているかどうか、外出の予定があるかどうかを確認し、交通費申請タスクを「今日やるタスク」リストに追加しています。


ユニットテストを書かずにコードを書いたのは久々で、めんどくさいな〜と思いながらも手動テストでせこせこやってました。
コードの最適化もそうだし、テスト環境も入れたいと思ってはいますが、もうちょっと本格的に自動化を進める段階で検討します。

実際に導入してみて

交通費処理漏れがなくなりました。タスクはtrelloに入れる、trelloを見る習慣がこびりついているので、絶対に思い出せます。
今回得られる恩恵は小さいものですが、今後も自分の作業を自動化していきたいと思います。