フルリモートになったのでVimで出勤する

この記事は[freee APIで業務を楽しく便利にハックしよう！ 【PR】 freee Advent Calendar 2020](https://qiita.com/advent-calendar/2020/freee-api)の6日目の記事です。空いていたので代打投稿させていただきました。

## フルリモート時代の出勤はVimでする

![demo_taikin.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142791/6cbc636f-1cae-1a4e-d6b2-6c8ae168f191.gif)
[人事労務freee API](https://developer.freee.co.jp/docs/hr/reference)を使って勤怠を取得し、NeoVimのFloatingWindowでカレンダーを作成して表示しています。
ご覧の通りVimとfreeeAPIの相性は抜群。**お互いが手を取り合って同じ呼吸**をしていますね。
![screenshot_ 2020-12-27 22.59.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142791/7700efbb-ad1b-02e3-fb82-5640dbf0f518.png)
![screenshot_ 2020-12-27 22.58.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142791/d03b96ed-564f-55c0-4b4e-98b1aec9f799.png)

## Vim × freeeAPI

新型コロナウィルスによって、フルリモートになった会社も多いのではないでしょうか。

フルリモートにおける出退勤の方法は、freeeやKING OF TIMEなどの勤怠管理システムを利用することがデフォルトだと思います。
![screenshot_ 2020-12-27 22.32.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142791/7c2f9459-d5d6-a9e8-f951-b0fe1a57f36f.png)
ただ、毎朝出勤するためにブラウザを開いて出勤ボタンをポチッとするのは非常に面倒くさい。**いち早くVimを起動して仕事に取り掛かりたい**のに、なぜボタンを押すためだけにブラウザを開く必要があるのか。

ということで**Vimから出勤できるようにしました**。

## Vimでカレンダーを表現する

愚直に各日付ごとにNeoVimのFloatingWindow(以後FW)で作成しています。カレンダーなので各日付ごとに線で区切って表示したいところですが、FWには枠線をつけるオプションが存在しません。

そのため枠線用のウィンドウを作成し、同じ位置に日付表示用のウィンドウを設置しています。2つで1つのウィンドウとして見せているという感じですね。

```vim
" 日付用ウィンドウの作成
function! s:create_contents_window(config, field) abort
  let config = {'relative': 'editor', 'row': a:config.row + 1, 'col': a:config.col + 2, 'width': a:config.width - 4, 'height': a:config.height - 2, 'style': 'minimal'}
  let buffer = nvim_create_buf(v:false, v:true)
  call nvim_buf_set_lines(buffer, 0, -1, v:true, a:field)
  return nvim_open_win(buffer, v:true, config)
endfunction

" 枠線用ウィンドウの作成
function! s:create_border_window(config) abort
  let width = a:config.width
  let height = a:config.height
  let top = "╭" . repeat("─", width - 2) . "╮"
  let mid = "│" . repeat(" ", width - 2) . "│"
  let bot = "╰" . repeat("─", width - 2) . "╯"
  let lines = [top] + repeat([mid], height - 2) + [bot]
  let buffer = nvim_create_buf(v:false, v:true)
  call nvim_buf_set_lines(buffer, 0, -1, v:true, lines)
  return nvim_open_win(buffer, v:true, a:config)
endfunction

" 2つで1つのウィンドウとしてみせる
function! s:new_window(config, field) abort
  call s:create_border_window(a:config)
  call s:create_contents_window(a:config, a:field)
endfunction
```
参考: [Feature: optional floating window borders](https://github.com/neovim/neovim/issues/9718)

## Vimからfreee APIを叩く

シンプルに`system()`関数でcurlを実行しています。

```vim
" 2020年12月の勤怠情報を取得
function! s:get_work_record_summaries() abort
  let cmd = 'curl -s -X GET "https://api.freee.co.jp/hr/api/v1/employees/'.g:EMP_ID.'/work_record_summaries/2021/1?company_id='.g:COMPANY_ID.'&work_records=true" -H "accept: application/json" -H "Authorization: Bearer '.g:TOKEN.'"'
  let json = json_decode(system(cmd))
endfunction
```
freeeのAPIドキュメントからcurlコマンドがコピーできてそのまま使えるのでめちゃ楽です。Swagger万歳ですね。

## ENTERでAPIを実行する

今回は「出勤する」もしくは「退勤する」の文字列の上でENTERを押したらfreee APIを実行するようにしています。

ENTERの判定はシンプルにvimスクリプト上に`nnoremap <CR>`を書くだけですね。

```vim
" ENTERで関数を呼ぶ
nnoremap <silent> <CR> :call PostWork()<CR>

" 打刻APIを実行
function! PostWork() abort
  let line = getline('.')
  let action = line == '出勤する' ?
    \ {'type': 'clock_in', 'msg': '出勤しました'} :
    \ {'type': 'clock_out', 'msg': '退勤しました'}
  let cmd = 'curl -s -X POST "https://api.freee.co.jp/hr/api/v1/employees/'.g:EMP_ID.'/time_clocks" -H "accept: application/json" -H "Authorization: Bearer '.g:TOKEN.'" -H "Content-Type: application/json" -d "{ \"company_id\": '.g:COMPANY_ID.', \"type\": \"'.action['type'].'\"}"'
  let json = json_decode(system(cmd))
endfunction
```

## タイムレコーダーの入力は削除できない

人事労務freeeには[出勤ボタンをポチッとするAPI](https://developer.freee.co.jp/docs/hr/reference#operations-tag-%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%80%E3%83%BC(%E6%89%93%E5%88%BB))は存在するが、入力を削除できない。
一度ポチってしまうとその日は出勤ボタンが押せなくなってしまうため、テストがしずらかった。
回避策は従業員を新たに追加して、その従業員でAPIを実行した。めちゃくちゃ面倒臭い上に、これまた1回しか猶予がないが今回はこれで乗り切った。

## 終わり

freee APIとVimをコラボさせることで、出勤さえVimで出来るようになりました。
普段触らない技術も間にVimを挟むことで楽しく開発できますね。