Slackで勤怠管理してみませんか?
私の職場ではSlackを使用しているのですが、「#greetings」というチャンネルに、出勤時と退勤時に挨拶(+勤務実績報告等)を書き込み、勤怠を管理しています。
しかし、各々の生活習慣から、毎日数分早く出社したり、また遅く帰ったり、ごく少数の時間ながら、残業時間が積み重なっていきがちです。
とはいえ、「昨日は10分残業したから、今日は10分早く帰ろう!」 などとするのは、いくら認められた権利とはいえ、何となく気まずいものです。そういった少しずつ積もった残業時間を正確に把握し、堂々と消化できるのが、こちらの勤怠管理システムになります。
同じような勤怠管理の形式をとっている職場にお勤めの際は、ぜひ使用してみてください!
作るシステムのイメージ
・勤怠報告専用のチャンネルがあり、いつも 「おはようございます」 や 「お疲れ様です」 といったワードが飛び交います。 スタンプで挨拶をする人もいます。
・時折、離席する人もいます。
・それぞれの投稿において、特定のキーワード(おはよう、お疲れ)やスタンプに反応し、現在時刻をスプレッドシートに打刻してくれるようにします。
・さらに、『退勤』の項目が打刻されたら、勤務時間と残業時間を算出してくれるようにします。(私の職場は勤務時間が7時間30分となっているので、図の例では、残業時間は0となります。)
・月ごとの累計残業時間も計算してくれます。(こちらはスプレッドシートのSUMIF関数で導出しています。)
Outgoing Webhookの設定
・Slack側の設定は、「Outgoing Webhook」 を使用します。
①左上のハンバーガーメニューをクリックし、ファイル>設定と管理>App管理>カスタムインテグレーション を選択します。
②Outgoing Webhook>Slackに追加>Outgoing Webhookインテグレーションの追加 を選択します。
③設定画面を開くことができました。最初に、「Outgoingペイロードとレスポンス」を確認しておきましょう。(「開く」をクリック)。
こちらに表記されているデータはPOST送信され、後ほど使用することになります。
特に「token」「user_id」「trigger_word」は実際に使用します。
④チャンネル名、引き金となる言葉を設定します。
・「:おはようございます:」という表記がありますが、これはスタンプを表します。ホバーで確認できます。
・URLは後ほど設定します。
・トークンは後ほど使用します。変更する必要はありません。
・「名前をカスタマイズ」「アイコンをカスタマイズする」をお好みで設定したら、いったんSlackの準備は終了しますが、まだ設定は保存しないでください。 Googleスプレッドシートの設定がまだ終わっていないためです。
Googleスプレッドシートの設定
次にGoogleスプレッドシートの設定を行います。
ここでは 「Gas」(Google Apps Script) という言語で記述していきます。
①まずは新規シートを作成してください。
・タイトルは好きなものを設定してください。
・シート名は、SlackのユーザーIDにしてください。Slackの個人プロフィールで確認できます。
③タイトル、ファイル名をお好みで設定してください。当記事では「勤怠管理」「attendance.gs」とします。
④プロジェクトの設定>「appsscript.json」マニフェスト ファイルをエディタで表示する を選択し、チェックマークをいれます。
⑤エディターでappsscript.jsonは次のように記載します。
{
"timeZone": "Asia/Tokyo",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"webapp": {
"executeAs": "USER_DEPLOYING",
"access": "ANYONE_ANONYMOUS"
}
}
⑥テストコードとして、下記のように記載してください。
※詳しい文法は、別途調べてみてください。
function doPost(e) {
// xxxxxxxxxxxxxxxxxxxxxxxはURLを入力してください。
const ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxx");
const sheet = ss.getSheetByName(e.parameter.user_id);
const datetime = new Date();
sheet.getRange(1,1).setValue(datetime);
sheet.getRange(2,1).setValue('Post送信成功!');
sheet.getRange(3,1).setValue(e.parameter.user_id);
sheet.getRange(4,1).setValue(e.parameter.trigger_word);
sheet.getRange(5,1).setValue(e.parameter.token);
return;
}
⑦プロジェクトを保存し、デプロイ>新しいデプロイ を選択します。
⑧アクセスできるユーザー「自分のみ」を選択し、「デプロイ」ボタンを押します。(「自分のみ」の権限は変更してもOKです。)
⑨自分のGoogleアカウントでログインした後、詳細を表示>(安全ではないページ)に移動>許可 を選択します。
このあたりはこちらのページでも詳しく解説されています。
Google Apps Scriptでデプロイしてウェブアプリとして公開する方法【2021年更新】
⑩下記の画面が出れば完了です。そのままURLをコピーします。
このURLをSlackの設定に使用します。
⑪再び、Slackの「Outgoing Webhook」の設定に戻ります。(まだ設定は保存しないでください。 と記載した場所になります。)
URLに、先ほどデプロイしたアプリのURLを貼り付け、設定を保存します。
POST送信テスト
さて、テストコードは次のようになっていました。
function doPost(e) {
// xxxxxxxxxxxxxxxxxxxxxxxはURLを入力してください。
const ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxx");
const sheet = ss.getSheetByName(e.parameter.user_id);
const datetime = new Date();
sheet.getRange(1,1).setValue(datetime);
sheet.getRange(2,1).setValue('Post送信成功!');
sheet.getRange(3,1).setValue(e.parameter.user_id);
sheet.getRange(4,1).setValue(e.parameter.trigger_word);
sheet.getRange(5,1).setValue(e.parameter.token);
return;
}
実際に、Slackでトリガーワードの1つである 「出勤」 を含む投稿をしてみましょう。
すると、このように、スプレッドシートの中身が変わっていることが分かります。
無事にPOST送信が成功しました。
また、 3~5行目の様子から、POSTデータが「e.parameter」の中に配列で格納されていることが分かります。
オリジナルの勤怠管理シートを作成
さて、残るは実際に使用するプログラムを記述するのみですが、会社によって、もちろん勤務制度は異なりますので、そのままコピーすることは難しいかと思います。
サンプルを記載しておきますので、良ければアレンジしてみてください。
【サンプルの仕様】
スプレッドシート(ご自由にコピーしてお使いください)
・勤務時間は7時間半とする
・4時間以上勤務する場合、1時間の休憩が認められる
・社員は3名と仮定(社員の分だけシート数を用意します。)
function doPost(e) {
const ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxx/edit#gid=0");
const sheet = ss.getSheetByName(e.parameter.user_id); // スプレッドシートのシート名もslackのuser_idにしておくこと
const token = 'xxxxxxxxxxxxxxxxxxxx';
if (token !== e.parameter.token) return; // token値が一致していない場合は打刻を行わない
let category = e.parameter.trigger_word;
const startArr = ['おはよう', ':おはようございます:']; // コロンで囲まれているものはSlackのスタンプを表す
const finishArr = ['お疲れ', ':おつです:', ':お疲れさまです:'];
if (startArr.indexOf(category) >= 0) category = '出勤';
if (finishArr.indexOf(category) >= 0) category = '退勤';
let lastRow = sheet.getLastRow();
let addRow = lastRow;
if (sheet.getRange(addRow, 7).isBlank() === false) addRow++; // 「退勤」に打刻されていれば、新しい行に追加する
const datetime = new Date();
let timeArr = {
'year': datetime.getFullYear(),
'month': datetime.getMonth() + 1,
'date': datetime.getDate(),
'出勤': sheet.getRange(addRow, 4).getValue(),
'離席': sheet.getRange(addRow, 5).getValue(),
'再開': sheet.getRange(addRow, 6).getValue(),
'退勤': sheet.getRange(addRow, 7).getValue(),
};
// 例:8時→08の後ろから2文字,17時→017の後ろから2文字
timeArr[category] = (('0' + datetime.getHours()).slice(-2) + ':' + ('0' + datetime.getMinutes()).slice(-2));
// 列番号を割り振らないと、シートに書き込みができないため。
array = [[timeArr['year'],timeArr['month'],timeArr['date'],timeArr['出勤'],timeArr['離席'],timeArr['再開'],timeArr['退勤']]];
sheet.getRange(addRow,1,1,7).setValues(array); // 行番号,列番号,行数,列数
// 「退勤」に打刻されていれば、勤務時間・残業時間を計算する
if (category === '退勤') {
let workingHours = (Number(timeArr['退勤'].slice(0,2)) - Number(timeArr['出勤'].slice(0,2)) + Number(timeArr['再開'].slice(0,2)) - Number(timeArr['離席'].slice(0,2)));
let workingMinutes = (Number(timeArr['退勤'].slice(-2))- Number(timeArr['出勤'].slice(-2))+ Number(timeArr['再開'].slice(-2))- Number(timeArr['離席'].slice(-2)));
if (workingHours >= 4) workingHours--; // 4時間以上勤務していれば、昼休み1時間を付与
if (workingMinutes < 0) {
workingHours--;
workingMinutes += 60;
};
timeArr['実勤務時間'] = ('0' + workingHours.toString()).slice(-2) + ':' + ('0' + workingMinutes.toString()).slice(-2);
timeArr['残業時間'] = workingHours * 60 + workingMinutes - 450; // 残業時間=実勤務時間ー7時間半(450分)
sheet.getRange(addRow,8,1,2).setValues([[timeArr['実勤務時間'], timeArr['残業時間']]]); // 行番号,列番号,行数,列数
}
return;
}
おわりに
以上で 「Slack Outgoing Webhookでスプレッドシートに打刻する」 の解説を終わります。
ぜひとも皆さんの職場でも導入し、勤務の手助けになれば幸いです。