freee勤怠登録画面からプロジェクト予実管理をハックする！

# はじめに
どんな仕事でもプロジェクトの予実管理というのは非常に重要です。
予算と実績を見ながら、戦略を立てたり軌道修正していくものなので、予実をしっかり取っていないと勘で意思決定するようなことになってしまいます。
そのためには、働いている人が「何に」「どれだけ」時間を使ったかを把握しないといけません。

# よくあるプロジェクト予実管理の悩み
まず人事労務freeeを使っていれば、勤務時間の実績は記録できます。

問題はその内訳です。

freeeさんが提供している<a href="https://www.freee.co.jp/project-management" target="_blank">プロジェクト管理freee</a>と人事労務freeeを両方使っていれば、内訳も管理できていると思います。ただ、多くの会社では、勤怠の管理とプロジェクト予実管理は別のツールなどで行われていて、二重管理になっているのではないかと思います。

社員数が少ないころはそんなに予実も気にしなかったけど、大きくなってきたからそろそろ詳細を把握したい・・・という流れはよくあるでしょうし、その結果、勤怠とプロジェクト予実管理が連携してないのは、仕方ない部分もあると思います。
また、勤怠とプロジェクト予実を統一して管理したくても、業務の影響範囲が大きいので簡単に変更できない・・・ということもあるでしょう。
ただ、最初に書いたとおり、戦略を立てたり意思決定をするために、プロジェクト予実管理は重要なので、そのまま捨て置くわけにはいきません。

そこで今回、現実的にプロジェクト予実管理をうまくやるためにどうするべきか、考えてみました。

# どうやって解決するか
たとえば、勤怠はfreee、内訳はExcelで、というような二重管理をしていると、

- 勤怠と工数の不整合（時間が合わない）
- 内訳を登録するのを忘れる
- 登録がめんどくさいというクレーム

という問題が起こりがちです。
これらの問題を１つずつ読み解いていくと

**勤怠と内訳の不整合（時間が合わない）**
→ 内訳登録時に勤怠の時間が分かれば間違えないのでは？

**内訳を登録するのを忘れる**
→ 勤怠登録するときに内訳登録できたらいいんじゃない？

**内訳登録がめんどくさいというクレーム**
→ これも勤怠登録と同時にできたら楽なんじゃない？

という解決へのアプローチが取れそうな気がしてきました。たぶん取れる。大丈夫。
つまりは、「勤怠登録」と「内訳登録」が同時にできれば良いわけです。
となると、freeeの勤怠登録画面で内訳登録ができるインターフェースを作ればよい。
さすがにfreeeの画面になにか項目を入れ込むのは無理なので、考えた結果・・・

####「よろしい、ならばchrome extentionだ」

# chrome extentionで解決を試みる
## 前提
- 専用のchrome extentionを作ってインストールする
- 自社システム（もしくはExcel）でプロジェクト予実管理をしている

chrome extentionの作成方法などは本筋からずれるので割愛しますが、
<a href="https://toranoana-lab.hatenablog.com/entry/2020/04/23/174421" target="_blank">このあたり</a>参考ください。

## 画面イメージ
さて早速ですが完成形から見せちゃいます。
![ezgif.com-gif-maker (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/4e1c9b41-6f68-c673-2e83-c94577a0fa15.gif)

chrome extentionをインストールすると、上記画像のように右サイドメニューが出てきて、
そこで工数の内訳を登録できるようにします。

## 処理の流れ
chrome extention上での処理フローは概ね下記のような形となります。

1. 内訳を登録する日付を選択
2. 人事労務freeeのAPIを使用して、選択日の労働時間を取得
3. 自社システムから登録されているプロジェクト情報や、内訳情報をAPIなどで取得（※）
4. 労働時間と内訳情報を表示
5. 入力完了すれば、自社システムへ内訳情報をAPIなどで登録（※）

ステップ３と５では自社システムと連携しており、ステップ３では表示のために、自社システムからプロジェクトマスタと当該日の実績情報を取得、ステップ５では、入力された内容を自社システムに登録しています。

## 入力画面
日付選択すると下記のように、内訳を入力する画面になります。

![イメージ-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/7e1f021b-0552-6e97-68ce-0c3f25926116.jpeg)

右ペインに労働時間と登録済みの時間、そして内訳が表示されています。
このうち、労働時間は下記のようにfreee APIから取得して計算しています。
freee APIのtokenの取得方法などは割愛しますが、<a href="https://developer.freee.co.jp/docs/hr" target="_blank">こちら</a>に詳しいです。

![イメージ-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/854d0e72-4e07-e268-52cf-0df9d8fc8b47.jpeg)

```javascript:freeeデータ取得処理
//従業員ID取得
let getEmployId = async () => {
  return await fetch("https://api.freee.co.jp/hr/api/v1/users/me", {
    method: 'GET',
    headers: {
      "Accept": "application/json",
      "Authorization": "Bearer ************************"
    },
  })
  .then((res)=>{return res.text();})
  .then((res)=>{
    console.log(res)
    return JSON.parse(res).companies[0].employee_id
  });
}
//特定日の勤怠データ取得
let getWorkrecord = async (emp_id,date) => {
  return await fetch(`https://api.freee.co.jp/hr/api/v1/employees/${emp_id}/work_records/${date}`, {
    method: 'GET',
    headers: {
      "Accept": "application/json",
      "Authorization": "Bearer ************************"
    },
  })
  .then((res)=>{return res.text();})
  .then((res)=>{
    console.log(res)
    return JSON.parse(res)
  });
}
//休憩を引いた稼働時間を算出
let calcWorktime = (data)=>{
  let _work_in = new Date(data.clock_in_at);
  let _work_out = new Date(data.clock_out_at);
  let _worktime = (_work_out-_work_in)/(60*1000);

  let _break_in;
  let _break_out;
  let _breaktime = 0;
  for(let i in data.break_records){
    _break_in = new Date(data.break_records[i].clock_in_at)
    _break_out = new Date(data.break_records[i].clock_out_at)
    _break_out = (_break_out-_break_in)/(60*1000)
  }
  return _worktime - _breaktime
}
//主処理
let exec = async (date) => {
  emp_id = await getEmployId()
  workrecord = await getWorkrecord(emp_id,date)
  console.log(workrecord)
}
```
労働時間より下にある情報は自社システムから取得して表示するものになっていて、今回、
下記のようなJSONでプロジェクト情報と内訳情報を返却するAPIを作成しました。
これらのJSONをAPIで取得し、画面表示しています。

```json:プロジェクトマスタ
{
  "PRJ-001":"改善プロジェクト",
  "PRJ-002":"機能A開発プロジェクト",
  "PRJ-003":"インフラ再構築プロジェクト",
  "PRJ-004":"GDPR対応",
  "PRJ-005":"OSアップデート対応"
}
```
```json:実績データ
{
    "PRJ-001":"180",
    "PRJ-003":"120",
    "PRJ-005":"240"
}
```


## より入力利便性を上げる
基本的にはこれで入力できるので要件は満たしているのですが、最初に問題としてあげていた「忘れる」とか「めんどくさい」については、できるだけクリアしておきたいところです。
なので、左ペインにある、freeeの勤怠登録と連動して動作するようにしておきましょう。

![イメージ-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/c6d147e9-ceb2-2722-6baf-44986c4896e0.jpeg)

ここは、少し無理矢理感はありますが、左ペインのDOMにイベントバインドしてあげれば、連動できます。

```javascript:日付ボックスイベント処理
//jquery使用の場合
//日付ボックスをclickしたときに発火
$(".week .day").on("click",function(){
  exec($(this).data("date"))
})
```

これで、左ペインの日付をクリックしたタイミングで、右ペインにその日の内訳が自動的に表示されるようになりました。
コードではよく分からないと思うので、GIFアニメにて確認ください。

![ezgif.com-gif-maker (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23578/647605cf-0ce4-9caf-f58d-349994db04ae.gif)

勤怠登録の流れと内訳登録がつながって操作できるので、より忘れづらくなったと思います！


# まとめ
いかがだったでしょうか。
理想として、１つのツールで勤怠もプロジェクト管理もすべて統一して管理するのがよいとは
思いますが、現実問題としてそれができない場合も多々あると思います。
理想ができないから諦める、ではなく、まずはできるところから改善を試みていって少しでも
前に進めていくことが重要ではないでしょうか。
その手法の１つとしてchrome extentionでの問題解決アプローチを検討してみました。

今回、そこまで細かく作り込む時間はなかったですが、下記のような機能があるともっと利便性があがるはずです。

- 全ての労働時間が内訳登録されていないときに赤文字にする
- 勤怠登録時に内訳登録不足をチェックしてアラートを出す
- 内訳登録画面からfreeeAPIを使って勤怠登録を行う
- 内訳未登録の日は、左ペインの日付のところが赤くなる

やや無理矢理感はありましたが、入力支援としては十分使うことができますし、
今はEdgeでもインストールできるので、企業でも使いやすいと思います。
問題解決手法の１つとして参考になれば幸いです。

それでは！