弁護士ドットコムで働く人事部 労務チームの後沢です。
弊社には様々な部活があるのですが、私は某アイドル事務所を応援する部活に入り、大好きなアイドルグループ Kis-My-Ft2 を応援することに生きがいを見出しております。
しかし、昨年、事件が起きました。
生きがいであるアイドルグループKis-My-Ft2のメンバー北山宏光くんが2023年8月31日にグループを脱退し、事務所も退所することになったのです。
仕事の憂さは、推し活で晴らし、日々生きながらえているのですが、この事態だけはどうにも受け止めることができません。 忘れるために熱心に仕事をしていたら、推し活の憂さを仕事で晴らす結果となったので、せっかくだからブログにしたためました。
(エンジニアでもない私が、GASを書くきっかけは、こちらをお読みください。) creators.bengo4.com
これはなに?
2024年4月施行の裁量労働制導入にかかる法改正により、「専門業務型裁量労働制を適用させる前に本人から同意をとる」というプロセスを自動化できた話です。
(実際はこれから同意をとるので、「自動化できそう」になるのかな?)
異次元の働き方改革に関わる法改正が多いし、某アイドル事務所からは退所者が後を絶たないし、世の労務マンは、大変ですよね。。。
そんな労務マンの助けになればと思って公開を決意しました。
(裁量労働制に関するルール改正の解説は、弊社サービス BUSINESS LAWYERS の「裁量労働制が2024年4月変更!弁護士が対応を解説」記事もおすすめです。)
やりたいこと
法改正により、専門業務型裁量労働制を適用させるには、本人同意が必要となりました。 同意については、書面で交わすこととされていましたが、北山くんの退所日が迫る2023年8月2日に厚生労働省からQ&Aがリリースされ、その中で電磁的記録での保存にOKがでていたので、該当者から同意をとるプロセスをGAS(Google Apps Script)を使って自動化させることにしました。
https://www.mhlw.go.jp/content/001164350.pdf
Q8-1(A)保存方法は書面のみならず、電磁的記録による保存も可能である。 電磁的記録による保存を行う場合には、 平成17年3月31日付け基発第0331014号 「厚生労働省の所管する法令の規定に基づく民間事業者等が行う書面の保存等における情報通信の技術の利用に関する省令について」 において示した取扱いに準じること。
自動化に取り組んでみる
自動化させるためのプランを立てる
まず最初に、GASに書く前に、実行することをリストアップし、骨組みを考えました。
- アンケートフォームを作成する
- アンケートフォームの回答結果をスプレッドシート「回答シート」に転記させる
- 「回答シート」に転記されたと同時に「同意書シート」にも転記させる
- 転記された「同意書シート」をPDF化し、アンケート回答者へPDFをメールで送信する
- PDFはリネームしてフォルダへ保存する
次にリストアップしたことに肉付けをします。
アンケートフォームの質問内容
次に、アンケートフォームの内容は、今回の法改正で義務化された部分を漏らさず質問するように作成したかったので、1〜11までの問いを用意しました。
- 氏名を教えてください。
- あなたに適用されている裁量労働制の種別にチェックを入れてください。【ラジオボタン】専門業務型裁量労働制【ラジオボタン】企画業務型裁量労働制
- 専門業務型裁量労働制・企画業務型裁量労働制の制度の概要を確認してください。★専門業務型裁量労働制資料 ★企画業務型裁量労働制資料 【ラジオボタン】はい、制度の概要を確認しました。
- 当社の裁量労働制の運用ルールを読みましたか? ①専門業務型裁量労働制に関する労使協定書※リンク※ ②企画業務型裁量労働制決議書※リンク※ ③評価制度※リンク※ ④給与テーブル※リンク※ 【ラジオボタン】はい、ルールを読みました。
- 裁量労働制の適用についての同意は、撤回が可能です。撤回をしたい場合は、撤回届を作成し、人事へ提出してください。 【ラジオボタン】同意の撤回について、理解しました。
- 当社では、裁量労働制の適用について同意を撤回した従業員に対し、配置および処遇において不利益な取り扱いを行っていません。 【ラジオボタン】撤回したことにより、不利益な取り扱いを受けないことを理解しました。
- 苦情の申出先、人事部です。申出方法は、●●●です。 【ラジオボタン】はい、苦情の申出先を理解しました。
- 長時間労働が続く場合は適用を解除となります。※専門業務型裁量労働制に関する協定届のリンク※ 【ラジオボタン】はい、裁量労働制の適用解除について、理解いたしました。
- 当社では、裁量労働制の適用に同意しなかった従業員に対し、配置および処遇において不利益な取り扱いを行っていません。【ラジオボタン】理解しました。
- 2024年4月〜2025年3月末まで裁量労働制が適用されることについて同意しますか?【ラジオボタン】同意します。【ラジオボタン】同意しません。
- 同意しない方へ:新たに適用させる勤務形態は●●●です。給与テーブル、人事制度、配属については、現在と変わりません。【ラジオボタン】理解しました。※この設問は各社の規則を当てはめてください。
※各社の状況に応じてアンケートの設問を設計してください。
スプレッドシートとGAS
そして、アンケートフォームの回答内容が転記されるシートを作成しました。
回答内容に応じて、同意書を作るシートも作成しました。
同意書の様式は労政時報4067号「裁量労働制の法改正に伴う実務対応」を参考に作成しています。
私のプログラミングスキル不足部分については、スプレッドシートに関数を直接入力することで解決させました。(黄色のセル部分)
- B列15行目の関数=
"また、私に"&G14&"が適用されることについて、"&G15
- B列18行目の関数
=G14&"の制度の概要および"
- D列18行目の関数
=IF($B$18="専門業務型裁量労働制","労使協定","労使委員会決議")&"の内容"
A列のチェックを表示させるために関数
=IF(G18="はい、制度の概要を確認しました。","✔","")
をいれてあります。- ※IF関数の一致条件は、それぞれ変更してください。
コード
最後にGASのコードを作成しました。
(参考図書:「Google Apps Script実践プログラミング 著:今西航平」)
今回は、弊社のSlackにある「#非エンジニアを応援する」チャンネルで助けを求めることなく、参考図書を片手になんとか作ることができ、「完璧じゃーん」と自画自賛していたところ・・・
この記事の下書きを見たエンジニアさんからコードレビューが・・・
ぐぬぬっ........
記事にする前に #非エンジニアを応援するチャンネル でコードレビューをもらっとけばよかった…。 とはいえ、今もなぜforループの中に長大なコードが入っていることがよろしくないのか理解できていないし、そもそも、forループの中にあることを繰り返し処理させたいと思っているから、どこで区切ったら良いのか分からない....。
だから、きっと事前にチャンネルでレビューをお願いしても結局「そうなの?」スタンプしか押せなかっただろう.......
forループの課題は、宿題ですね...!!!
エンジニアのみなさんからしてみたら、違和感ありありのコードかもしれませんが、実際、動いちゃってるんで、公開します!!
//アンケートフォームの情報を取得 //GASを回す前にトリガーを設定してください。スプレッドシートから>フォーム送信時>今すぐ通知を受け取る function sendConsentForm(){ const ssForm = SpreadsheetApp.getActiveSpreadsheet(); const sheetForm = ssForm.getSheetByName('回答'); const lastRow = sheetForm.getLastRow(); Logger.log(lastRow); const sentCheck_list = sheetForm.getRange(2,14,lastRow).getValues(); //最終行までループ for (let i = 0; (sentCheck_list.length - 1) > i; i++){ //2次元配列から実データを抽出する const sentCheck = sentCheck_list[i][0]; if(sentCheck !== '送信済'){ //未送信の行(i)のみ処理する const email = sheetForm.getRange(i + 2,2).getValue(); const personName = sheetForm.getRange(i + 2,3).getValue(); const workStyle = sheetForm.getRange(i + 2,4).getValue(); const organization = sheetForm.getRange(i + 2,5).getValue(); const rules = sheetForm.getRange(i + 2,6).getValue(); const disadvantage = sheetForm.getRange(i + 2,8).getValue(); const complaint = sheetForm.getRange(i + 2,9).getValue(); const cancellation = sheetForm.getRange(i + 2,10).getValue(); const disadvantage2 = sheetForm.getRange(i + 2,11).getValue(); const agree = sheetForm.getRange(i + 2,12).getValue(); Logger.log(workStyle); //ちゃんと情報を取得できてるかな?? Logger.log(personName); //同意書のテンプレートを指定 const ssConsentForm = ssForm.getSheetByName('同意書'); const ssId = '***************'; //同意書シートのシートIDを入力 //テンプレートに書き込み ssConsentForm.getRange('A2').setValue(email); ssConsentForm.getRange('G14').setValue(workStyle); ssConsentForm.getRange('G15').setValue(agree); ssConsentForm.getRange('G18').setValue(organization); ssConsentForm.getRange('G20').setValue(rules); ssConsentForm.getRange('G22').setValue(disadvantage); ssConsentForm.getRange('G25').setValue(complaint); ssConsentForm.getRange('G27').setValue(disadvantage2); ssConsentForm.getRange('G30').setValue(cancellation); ssConsentForm.getRange('G32').setValue(agree); ssConsentForm.getRange('F34').setValue(personName); Utilities.sleep(1000); //一旦休止 SpreadsheetApp.flush(); //再描 //PDFに出力するシートを指定する const folder = DriveApp.getFolderById('************');//★格納するフォルダID const url = 'https://docs.google.com/spreadsheets/d/SSID/export?'.replace("SSID",ssId); const sheetId = '*********'; //★https://docs.google.com/spreadsheets/d/ スプレッドシートID/edit#gid=シートID const pdfRange = 'A3%3AF34'; //★PDF化する範囲を指定 //pdf化させる書式を指定する const pdfoptions = { format: 'pdf', size: 'A4', portrait: 'true', fitw: 'true', sheetnames: 'false', printtitle: 'false', pagenumbers: 'false', gridlines: 'false', // falseにしないと薄い罫線が入ってしまいます。 fzr: 'false', horizontal_alignment:'CENTER', vertical_alignment: 'MIDDLE', range: pdfRange, gid: sheetId }; let urlExt = []; for( optionName in pdfoptions){ urlExt.push(optionName + '=' + pdfoptions[optionName]); } const option = urlExt.join('&'); //APIを叩いてpdfフォルダに格納 const token = ScriptApp.getOAuthToken(); let today = new Date(); var blob = UrlFetchApp.fetch(url + option, {headers: {'Authorization': 'Bearer ' + token}}).getBlob().setName(Utilities.formatDate(today, 'JST', 'yyyy-MM-dd') + '_' + personName + '_' + "裁量労働制同意書"+".pdf"); //const blob = response.getBlob().setName('2023_'+ personName +'裁量労働制同意書'+'.pdf'); const file = folder.createFile(blob); //メールを送信する const subject = '裁量労働制に関する同意書の送付'; const body = personName + '様' +'\n' +'\n' + '人事部労務チームです。' +'\n' +'\n' +'裁量労働制適用にかかるアンケートフォームにご回答いただき、ありがとうございました。' +'\n' +'回答内容に基づいて作成された同意書を送付いたします。添付ファイルをご確認ください。' +'\n' +'なお、同意を撤回したい場合は、撤回届(撤回届のリンク)を作成し人事労務チームにご提出ください。' +'\n' +'不同意の方には、後日、労務チームより新たな勤務形態の労働条件通知書をお送りします。'; const options = { attachments:[file] }; GmailApp.sendEmail( email, subject, body, options, ); //未送信の行(i)のみ処理し、結果を入力 sheetForm.getRange(i + 2 ,14).setValue("送信済") }else{ Logger.log(sentCheck); } } }
自動化のトリガー設定
さらに効率化させるために、自動化のトリガーを設定すれば完了です。
これで、アンケートに回答してもらうだけで、同意書を作成しメールで送信され、さらにその同意書は、フォルダに格納されるようになりました!
このプログラムは、専門業務型裁量労働制を導入の企業だけでなく、企画業務型裁量労働制を導入の企業にも応用できるかと思います。
ただ!!正直にいうとまだ不安です。
これをお読みになられた労務マンの皆様、もし不備がありましたら、ご指摘いただけると幸いです。
終わりに
前回書いたブログがまさかのPVを稼ぎ、エンジニア部門の中で表彰され、副賞としてアマゾンギフト券1万円をいただきました。 (この記事を読んでいる労務マンならおわかりですね。これは労働の対価なので、給与に該当しますね。ちゃんと給与課税しました。)
私は、畑違いの非エンジニアで、しかも全く別の部門の人間です。 そんな私にまで、「コードを1行でも書いたらエンジニアです!ブログを書きませんか?」と声をかけてくれて、賞賛までも送ってくれるこの会社の風土を素直に素晴らしいと思っています。 しかも、これは特別なことではないのです。
Slackで従業員同士が「ありがとう!」「すごい!」といった感謝や賞賛の言葉を自然に贈りあっているのをよく見かけます。
こんなフラットな関係性がある弁護士ドットコムで働きませんか? 求人はこちら
(今回もいっぱい読まれて、アマゾンギフト券欲しいな!Kis-My-Ft2の新曲CDを追加で買いたいな!)