理想の勤怠管理を求めて -入社3年目エンジニアの開発記-

# はじめに

こんにちは。
この4月で社会人3年目を迎えた@icchi_hです。

私事ではありますが、入社してから定期的にプライベート用の勤怠管理システムを作っています。主な目的はQOL向上のために仕事に費やしている時間を管理したい...とかだったんですが、正直作ること自体が楽しくて目的化してしまった感はあります。そのシステムも何度か作り直して今や3代目ver2になりました。

この記事では その勤怠管理システムの開発記録と現行版について書いています。IFTTT、Google Apps Script(GAS)、Google Spreadsheetを使ってこんなものができるといった参考になれば幸いです。

これまでの経験から現行版では、GPS情報をベースに**自動で出退勤タイムテーブルが生成される**仕様にしています。今回利用したサービスだと**ランニングコストは0円**です。


# これまでの取り組み

## 初代: CLI型

<img width="658" alt=" 2019-03-31 6.33.59.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/2173d968-ecc8-4ec3-d2ed-75da79325f33.jpeg">

当時ハマっていたGolangで実装した出退勤打刻CLIツール。
出退勤時に`$ams <start/finish>`みたいに実行すると、月ごとにTSVファイルが生成&打刻される非常にシンプルな仕組み。

打刻時には音声を再生するように改良しました。

- 開始時: 「今日も一日がんばるぞい」
- 終了時: Get Wild♫

このツールがあればGet Wildを流しながら職場に背を向けることができます。
止めて、引く！！

### 問題点
- 飽きて使わなくなる

### 教訓
- 出退勤イベントの自動化は必須


## 2代目: 顔認識型
![figure (2).png](https://qiita-image-store.s3.amazonaws.com/0/135313/59f1794a-5d66-c20a-a1cf-7babfefa0b9f.png)

当時開発を担当していた**「深層学習での顔検出&認識技術」**を利用して作ったものです。

検出&認識にあたり、Raspberry Pie3とWebカメラを職場の卓上に設置。ラズパイ上で走らせているプログラムが顔を検出して私だと認識すれば、その日の記録と照らし合わせて出退勤イベントを発生させています。あとはそのイベントをトリガーとして初代同様に打刻する仕様です。

プライバシーの取り扱いが厳しいこの時代に、快くカメラを設置&稼働させてくれた職場の方々には感謝です。

### 問題点
* 悪意はないにしてもカメラによるプライバシー的な問題
* ノイズによる誤認識問題
    * 職場環境だと光量や背景の物体などによる誤認識が多々あり
* ラズパイのパワー不足で処理が心もとない

### 教訓
* プライバシーを考慮したシステム (他人に影響を与えない)
* ハードがシステムに絡んでくると考慮すべき内容が飛躍的に増加

## 3代目 v1: GPS連動型
![figure.png](https://qiita-image-store.s3.amazonaws.com/0/135313/d487bf4b-22d2-f5b8-6dd8-da54d11f7142.png)

初代、2代目の教訓を生かし、**GPS(位置情報)**を利用する**出退勤自動記録システム**に改良。会社の住所を設定しておき、エリアに出入りした際に出退勤イベントを検知すると打刻します。

この構成で注目すべきところは、IFTTTの**「Locationトリガー」**と**「Webhooksアクション」**を組み合わせて、指定エリア(会社)に入った際にGASに向けてPOSTリクエストを投げるところです。あとはGASを中心にスプレッドシートに時刻を挿入します。

### 問題点

- 自分の環境(Android 8)だと稀に出退勤イベント(IFTTT)が発生しない  
  (恐らくアプリのバックグラウンド稼働不具合)
  - タイムカード上の時刻挿入位置がずれデータがぐちゃぐちゃに
- せっかく作ったタイムカードの情報が他のサービスで利用できない

### 教訓

- 出退勤イベントの発生漏れがあっても正常可動するよう補正する必要性
  - → 直接タイムテーブルに時刻を挿入せずに、一旦イベントログシートに挿入
  - → ログ情報をもとに補正を加えてタイムテーブルを生成
- REST APIでタイムカード情報を取得できるように


# 3代目ver2: 現行システム
![thumbnail](https://qiita-image-store.s3.amazonaws.com/0/135313/b897dfd5-2aef-99b1-1799-4e3bf2863d92.png)


3代目v1で採用したGPSベースな出退勤検知の仕組みはそのままに

* **タイムカードをイベントログから生成(補正目的)**
* GASでREST APIを実装し外部からのリクエストに対してタイムテーブル情報を返却

できるよう改良しました。

また、タイムテーブルAPIを利用するためのChromeの拡張機能も用意して、外部のスケジュールサービスと連携できるようにしています。


## 作成されたスプレッドシート
### イベントログ
<img width="677" alt="eventlog_edited.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/0887e4bf-aa7b-4e8f-6693-c29024924df8.jpeg">

### タイムカード
<img width="821" alt="timecard-edited.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/adbf61c7-7085-bc45-9a7b-e45ad2e556bf.jpeg">

テンプレート内のセルに予め関数をセットしておき、入力された値によりスタイルを変更するようにしています。一目瞭然で気に入っています。Google Spreadシートの関数に少し詳しくなりました。

13~15日は出張で会社に行っていない為、ログが入力されていません。当たり前の話ですが、GPSをベースに出退勤を検知するとイレギュラーな勤務場所に対応できないのが難点です。


### まとめ
<img width="433" alt="summary_edited.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/135313/3793da94-b76b-456d-56e7-ee9d18c57184.jpeg">




# 感想

## IFTTTのLocationトリガーによる指定エリアへの出入り検知までの時間
1年以上利用してみて、検知までの時間にばらつきがあるように感じました。おおよそ実際の出入り後10分から30分以内に検知します。

ただ、先週は10分以内に検知していたのに、今週は30分ほどかかるなんてことも。IFTTTアプリに若干の癖がある模様。

### そもそも出退勤時刻は厳密な勤務開始・終了時刻ではない
上司の一言。
「それって本当の勤務開始・終了時間じゃないよね?」

これに尽きます。
参考程度には使えますが、もし正確な時刻を知りたい場合はIFTTTのLocationトリガー以外の方法を考える必要があります。


## 出退勤検出の代替手段
初代の教訓からやはり**全自動**でイベントを検知したい。

- ビーコン
- NFC
- 椅子に設置した圧力センサ

ただ、インフラに手を出しすぎると保守に労力がかかってしまうのも悩みどころ。


# おわりに
- 俺たちの戦いはこれからだ
- いい仕組み、アイデアがあれば教えてください

作り方は少し書いたんですが、全て書ききる前に疲れて諦めました書いている途中で疲れて書くのを諦めてしまいました。もし興味がある方がいらっしゃるようでしたら検討します。