【タスク管理】Toggl に作業時間管理をやらせてみた
弊社では作業管理ツールに Redmine を使用しています。
チケットと呼ばれる各タスクに作業時間を入力して↓みたいに退社時に Slackbot で1日の作業内容がわかるようになっています。
(ちなみに上記のSlackbotは弊社代表の自作です。)
ただ、これが少し手間です。
作業開始時の時刻を覚えておいて作業が完了したら終了時の時刻から逆引きして時間を出すっていう、算数の引き算でつまずいた人間からすると地獄です。冗談抜きに引き算だけで30分くらい取られます。
ということでめんどくさいことはプログラムにやらせよう!
事前準備
Toggl アカウントの作成
これがなきゃ始まりません。
Toggl 拡張機能のインストールと設定
https://chrome.google.com/webstore/detail/toggl-track-productivity/oejgccbfbmkkpaidnkphaiaecficdnfn
なくても成立はするんですが、Redmine 上でタイマーを打ちたいのでインストールします。
インストール後に、拡張機能の設定で Integrations メニューの中で Redmine のURLを有効にします。
(自社サーバーに Redmine を立ててる場合は Custom URLs for integrations にドメインを登録すればOK)
最終的にRedmine のチケットを見た時に Toggl のボタンが表示されてればOK
プログラムの作成
最低限必要な処理以外は省略してるので「リクエスト周りのエラーハンドリングどうすんの?」とか言う輩は帰ってください。
アーキテクチャ警察も帰ってください。
API Document は以下を参照しました
- https://github.com/toggl/toggl_api_docs/blob/master/toggl_api.md
- https://www.redmine.org/projects/redmine/wiki/Rest_TimeEntries
① 当日の作業記録を取得する
$togglUri = 'https://api.track.toggl.com/api/v8/time_entries';
$options = ['auth' => [$_ENV['TOGGL_API_TOKEN'], 'api_token']];
$dateTime = new DateTimeImmutable();
$query = http_build_query([
'start_date' => $dateTime->setTime(00, 00, 00)->format('c'),
'end_date' => $dateTime->setTime(23, 59, 59)->format('c'),
]);
$entryRequest = (new \GuzzleHttp\Client())->request('GET', "{$togglUri}?{$query}", $options);
$res = $entryRequest->getBody()->getContents();
$entries = json_decode($res, true);
② Toggl の作業内容から Redmine に登録する作業時間データを用意する
foreach ($entries as $entry) {
// 作業時間のコメント
$description = $entry['description'] ?? '';
// 作業時間の時間
// 開始・終了の差分
$start = new DateTimeImmutable($entry['start']);
$stop = new DateTimeImmutable($entry['stop']);
$diff = $stop->diff($start);
$min = round(($diff->i / 60), 3);
$diffHours = $diff->h + $min;
// Redmine でタイマーを打ったときのフォーマットに沿って` #1234 `の文字列をチケットIDとして検索
preg_match('/\ #([0-9]+)\ /', $description, $results);
// description にチケットIDがあればサブパターンマッチの文字列を使用する
// プロジェクトに紐付かない場合は任意のデフォルトのチケットIDを指定
$issueId = $results[1] ?? $_ENV['REDMINE_DEFAULT_ISSUE_ID'];
// 活動の選択肢
$activities = ['作業内容1' => 1, '作業内容2' => 2];
// タグの登録があれば1番目のタグを活動とする
// なければデフォルトの活動IDを指定
$activityId = $activities[$entry['tags'][0] ?? 1];
// xmlの生成
$xmlValues = [
'issue_id' => $issueId,
'spent_on' => $dateTime->format('Y-m-d'),
'hours' => $diffHours,
'activity_id' => $activityId,
'user_id' => $_ENV['REDMINE_USER_ID'],
'comments' => $description,
];
$xml = new SimpleXMLElement('<time_entry></time_entry>');
foreach ($xmlValues as $key => $value) {
$xml->addChild($key, $value);
}
}
Toggl の作業レコードごとに以下のようなXMLが生成されます。
<time_entry>
<issue_id>1234</issue_id>
<spent_on>2022-02-19</spent_on>
<hours>1.0</hours>
<activity_id>1</activity_id>
<comments>タスク #1234 テキストテキストテキストテキスト</comments>
<user_id>1</user_id>
</time_entry>
③ Redmine に作業時間を登録する
$redmineUri = "{$_ENV['REDMINE_URL']}time_entries.xml?key={$_ENV['REDMINE_API_KEY']}";
$request = (new \GuzzleHttp\Client())->request('POST', $redmineUri, [
'headers' => ['Content-Type' => 'text/xml',],
'body' => $xml->asXML()
]);
APIキーが発行されてない Redmine を使ってる場合は知りません!管理者に頼もう!
作業の登録
ここからがやりたかったことです
- 作業の前後で Redmine のチケット画面に表示されてる Toggl のタイマーをクリック
- 退勤前にプログラムを実行する
- Redmine に作業内容が登録されるのを確認する
((Wantedly動画貼れないじゃん...ブログ見てね))
ちなみにこのプログラムを作るまでは、下記サイトをiframeに埋め込んだものを拡張機能にして手動で計算してました!お世話になりました!2桁以上の引き算は苦手です!!
http://www.jalps.net/cgi-bin/timecal/time.cgi
最後に
弊社では各々が好きなツールを使用して開発・作業をしています。そんな中で改善できるものについては時には話し合いをしながら日々改善をしています。
今後も働きやすい作業環境を追求していきたいと思います!
[カバー画像]