有給・産休・育休・介護休暇の申請をLINEで受け付ける仕組みの作り方

LINE公式アカウント × エルメ
有給・産休・育休・介護休暇の申請をLINEで受け付ける仕組みの作り方

紙の休暇届と口頭申請を卒業。申請から台帳化・承認・期日アラートまで、手を動かせば同じ仕組みが作れる設計ガイドです。

Before:紙とLINEの個人チャットで回している総務

  • ×休暇届は紙。机の上に積まれ、誰の分が未処理か分からない
  • ×「今日休みます」が個人LINEやメールでバラバラに届く
  • ×有給の年5日取得義務、誰が未達か手集計でヒヤヒヤ
  • ×産休・育休の社会保険手続きの期日を、うっかり逃しそうになる

After:申請はLINE、台帳と期日は自動で見える

  • ◎休暇の種類を選んでLINEで申請。内容がそのまま台帳に並ぶ
  • ◎申請が来た瞬間、総務のスマホ(エルメのアプリ)に通知が届く
  • ◎有給5日未達の社員を、期限が近づくと自動でお知らせ
  • ◎産休・育休の開始/終了予定日が近づくと手続きリマインド

この記事でつくる仕組みの全体像

受付・入力・タグ付け・本人への返信は「エルメ」、台帳への転記と期日の見張りは「GAS(プログラム)」。役割を分けて共存させます。

社員 LINEで申請 エルメ 申請フォーム受付 タグ付け・自動応答 スプレッドシート 連携シート→申請台帳/有給マスタ GAS(読む・知らせる) 転記・期日アラート(メール) 総務
  • ◯4種類の休暇(有給・産休・育休・介護休暇)を、LINEのメニューから申請できる
  • ◯申請内容がスプレッドシートに自動記録され、総務のスマホに即通知
  • ◯承認・差戻しをタグで管理し、結果を本人のLINEに自動返信
  • ◯有給の年5日取得義務・産休育休の予定日・未処理の申請を、毎朝チェックして総務にメールでアラート

1. 全体設計とスプレッドシート2枚の準備

最初に、この仕組み全体の「土台」を決めます。ここを先に固めておかないと、あとでフォームの項目やプログラムの参照先がズレて動かなくなります。まずスプレッドシートの列(スキーマ)を確定させましょう。

アーキテクチャの大原則(ここだけは外さない)

LINE公式アカウントは、外部システムからの通知の受け取り口(Webhook=ウェブフック)を1つしか設定できません。エルメを使うと、その1枠はエルメが使います。
そのため GAS(プログラム)に「受信」はさせません。GASは毎朝きまった時刻に動いて、シートを読んで台帳に転記し、総務にメールするだけの「読む・知らせる専用」にします。受付・入力・社員への返信はすべてエルメ側に任せる——これが破綻しない設計の起点です。
もう1つの前提として、エルメの回答フォームはスプレッドシートにリアルタイムで自動記録されます(フォームごとに「連携シート」が作られる)。一方、ボタンのタップやタグの付け外しはシートに残りません。だから「記録はフォーム、状態はタグ」で役割を分けます。

手順:シートを2枚つくる

操作場所:Googleドライブ > 新規 > Googleスプレッドシート

  1. 新しいスプレッドシートを1つ作り、名前を「休暇管理」とする(エルメが作る連携シートとは別の、総務が見る「台帳」です)
  2. 下のタブを2枚用意し、シート名を「申請台帳」と「有給マスタ」にする(名前は1文字も変えないこと。あとでGASが名前で探します)
  3. それぞれ1行目に、下の表のとおり見出しを入れる

シート①「申請台帳」の列(この並びで固定)

列見出し入るもの
A申請ID受付ごとの通し番号
B申請日時申請が届いた日時
C社員番号社員を一意に特定する番号
D氏名申請者の名前
E休暇種類有給/産休/育休/介護 のいずれか
F開始日休暇の初日
G終了日休暇の最終日
H日数取得日数
I連絡事項理由・引き継ぎメモなど
Jステータス申請中/承認/差戻し/取消
K承認者承認した上長の名前

シート②「有給マスタ」の列(この並びで固定)

列見出し入るもの
A社員番号申請台帳のC列と同じ番号
B氏名社員の名前
C付与基準日有給を付与した起算日
D付与日数その年に付与した日数
E取得済み日数※GASが申請台帳から自動集計(付与基準日からの1年間に承認された有給)
F残日数※GASが自動計算(付与+繰越−取得)
G年5日充足※GASが自動判定(済/未/対象外=付与10日未満)
H繰越日数前年度から繰り越した残日数(手入力)
つまずきポイント:列の順番を後から入れ替えると、6章のGASが参照する列がズレて誤作動します。E列=休暇種類、H列=日数、J列=ステータス——この対応は記事の最後まで変えません。列を足したくなったら、A〜Kの右(L列以降)に追加してください。なお、連携シート(エルメが自動で作るファイル)は見出しも行も編集しないでください。GASが新しい回答をこの台帳へ転記します。
◆ ◆ ◆

2. LINEに「休暇を申請する」メニューを置く

社員がまず触れる入口をつくります。会社のLINE公式アカウントを社員に友だち追加してもらい、リッチメニュー(トーク画面の下に出る大きなボタン群)から申請へ進めるようにします。

手順①:リッチメニューに「休暇を申請する」を作る

操作場所:エルメ管理画面 > リッチメニュー > 新規作成

  1. テンプレートから、ボタンを配置できるレイアウトを選ぶ
  2. 1つのボタンに「🏖 休暇を申請する」とラベルを付ける
  3. そのボタンのアクションを「メッセージ送信」にし、送信内容を 休暇申請 にする(このキーワードで次の自動応答が動きます)
  4. 公開して、社員のトーク画面下にメニューが出ることを確認する

手順②:キーワードで種類選択を出す

操作場所:エルメ管理画面 > 自動応答 > 新規作成

  1. 「反応するキーワード」に 休暇申請 を設定
  2. 返信内容に、下のテンプレのボタン付きメッセージを設定する(4つのボタンのアクションは「URLを開く」にし、3章で作る各フォームのURLを入れる)

コピペ用テンプレ(種類選択メッセージ)

お疲れさまです。休暇の申請ですね。 下のボタンから、申請する休暇の種類を選んでください。 ▶ 有給休暇 ▶ 産前産後休業(産休) ▶ 育児休業(育休) ▶ 介護休暇 ※選び直したいときは、もう一度メニューの「休暇を申請する」を押してください。
🏖 休暇を申請する
お疲れさまです。休暇の申請ですね。下のボタンから種類を選んでください。
▶ 有給 / ▶ 産休 / ▶ 育休 / ▶ 介護
リッチメニューのタップに対する自動応答は「Reply」扱いで配信数にカウントされません。一方、フォーム送信後の自動返信やタグ追加時の返信は「Push」扱いでカウントされます(費用の章参照)。
つまずきポイント:キーワードの表記ゆれに注意。ボタンの送信内容とキーワードはまったく同じ文字列(ここでは「休暇申請」)にします。「休暇の申請」など1文字でも違うと自動応答が反応しません。
◆ ◆ ◆

3. 休暇の種類ごとに申請フォームを分ける

休暇の種類によって、聞くべきことが少しずつ違います。エルメのフォーム(回答フォーム)機能で、種類ごとに入力フォームを用意し、選ばれた種類に応じてタグを1つ付けます。このタグが、あとの通知・承認・集計の基準になります。

タグの名前は最初にこう決める(全編で統一)

タグ名は途中で揺らすと絞り込みが壊れます。「休暇_(種類)」という形にそろえます。

選ばれた種類付けるタグフォームで追加で聞くこと
有給休暇休暇_有給取得日(開始・終了)/日数/連絡事項
産前産後休業休暇_産休出産予定日/開始・終了予定/連絡事項
育児休業休暇_育休子の生年月日(予定)/開始・終了予定
介護休暇休暇_介護対象家族との続柄/取得日/日数(年5日・対象家族2人以上は10日まで)

※あわせて、状態を表すタグ「休暇_申請中」「休暇_承認済」「休暇_差戻し」も使います(5章で登場)。すべて「休暇_」で始めるのがこの記事のルールです。

手順:種類ごとにフォームを作る(有給を例に)

操作場所:エルメ管理画面 > フォーム > 新規作成

  1. フォーム名を「有給休暇の申請」にする
  2. 質問項目を「社員番号/氏名/開始日/終了日/日数/連絡事項」の順で作る(日付項目はカレンダー入力を選ぶ。質問文はそのまま連携シートの見出しになり6章のGASが参照するので、この文言で固定)。社員番号と氏名は友だち情報に保存しておけば自動入力にできます
  3. フォームの「回答後アクション」で、タグ 休暇_有給 と 休暇_申請中 を付与し、前回の 休暇_承認済/休暇_差戻し を外すよう設定。あわせて「受け付けました。総務で確認してご連絡します」の自動返信を設定
  4. フォーム一覧の「スプレッドシート」からGoogleアカウントを連携し、連携シートを作る(回答がリアルタイムで記録される)
  5. 2章の種類選択メッセージの「▶ 有給休暇」ボタンから、このフォームが開くようリンクする
  6. 同じ要領で「産休」「育休」「介護」のフォームも作り、それぞれ 休暇_産休 / 休暇_育休 / 休暇_介護 と 休暇_申請中 を付け、スプレッドシート連携も有効にする(産休は「出産予定日」、育休は「子の生年月日」、介護は「続柄」の質問を追加)

コピペ用テンプレ(有給フォームの案内文)

【有給休暇の申請】 下の項目を入力して送信してください。 ・社員番号(例:1023) ・氏名 ・取得の開始日 ・取得の終了日 ・日数(半休の場合は 0.5 と入力。時間単位の有給は年5日の義務には数えません) ・連絡事項(引き継ぎ・緊急連絡先など任意) 送信後、総務で確認しご連絡します。
つまずきポイント:フォームの回答後アクションでタグを付け忘れるのが最頻ミスです。タグが付かないと、4章の通知も6章の集計も対象から漏れます。フォームを1つ作るたびに「タグ設定は入れたか」を必ず確認してください。
◆ ◆ ◆

4. 申請を台帳に集め、総務のスマホに通知する

申請が届いたら、2つのことを起こします。(1) 内容を連携シートに自動記録し、GASが「申請台帳」に1行として転記する。(2) 総務の担当者のスマホにすぐ知らせる。(1)の記録と(2)の通知はエルメ側の設定で完結し、台帳への転記だけ6章のGASが担当します。

手順①:フォーム回答をスプレッドシートに集める

操作場所:エルメ管理画面 > フォーム > 一覧の「スプレッドシート」

  1. 3章で有効にしたスプレッドシート連携により、各フォームの回答は連携シート(フォームごとに1ファイル)にリアルタイムで1行ずつ記録される
  2. 連携シートのURLの /d/ と /edit の間の文字列(ファイルID)を4本分控えておく(6章でGASに登録)
  3. 6章のGASが毎朝、4枚の連携シートから台帳にない回答だけを「申請台帳」に転記する(申請ID採番・ステータス「申請中」)。すぐ台帳に反映したいときはGASエディタで dailyLeaveCheck を手動実行
連携シートは「受け口」なので、見出しも行も編集しません。総務が見る・直すのは「申請台帳」だけです。GASは連携シートを質問文(見出し名)で読むので、3章のフォームの質問文と、6章のコード冒頭の見出し設定を一致させます。

手順②:申請が来たら総務のスマホに通知する

操作場所:エルメのスマホアプリ > 顧客対応 > 通知設定

  1. 総務担当者のスマホにエルメのアプリを入れ、スタッフとしてログインする
  2. 通知設定で「フォーム回答」をリアルタイム通知にする(担当者が複数いれば全員のスマホで設定)
  3. 通知を開くと回答内容がそのまま見られるので、下のテンプレのような「誰が・どの休暇を・いつ」が分かる質問構成にしておく

コピペ用テンプレ(総務への通知文)

【休暇申請が届きました】 申請者:{氏名}(社員番号 {社員番号}) 種類 :{休暇種類} 期間 :{開始日} 〜 {終了日}({日数}日) 連絡 :{連絡事項} 台帳を確認し、承認または差戻しをお願いします。

※ 上は通知で確認する項目のイメージです。アプリ通知に文面の差し込みはなく、回答内容がそのまま表示されます。メールでも受け取りたい場合は、6章のGASの朝のメールに「未処理の申請」として載る仕組みで補います。

【休暇申請が届きました】
申請者:山田はな(社員番号 1042)
種類:産休 / 期間:2026/09/01 〜 2027/01/10
つまずきポイント:総務担当者のスマホでエルメアプリの通知設定がオフのままだと、申請が来ても気づけません。担当者全員のスマホで設定し、テスト申請で着信を確認してください。
◆ ◆ ◆

5. 承認・差戻しのフローと本人への自動返信

総務や上長が内容を確認したら、結果を本人に返します。承認フローはタグの付け替えで管理します。フォーム申請時に付いた「休暇_申請中」を外し、「休暇_承認済」または「休暇_差戻し」に切り替える——その切り替えをきっかけに、本人へ自動返信を送ります。

手順①:承認したときの動き

操作場所:エルメ管理画面 > 友だちリスト > (申請者)> タグ

  1. 申請台帳のJ列(ステータス)を「承認」に更新し、K列に承認者名を入れる
  2. エルメで対象者のタグを 休暇_申請中 → 休暇_承認済 に付け替える
  3. 「休暇_承認済」が付いたら本人に自動返信が飛ぶよう、タグ追加時アクションを設定しておく(同じアクションで「休暇_申請中」を外す)

手順②:差し戻すときの動き

  1. 申請台帳のJ列を「差戻し」に更新する
  2. タグを 休暇_申請中 → 休暇_差戻し に付け替える
  3. 差戻しの自動返信で「どこを直せばよいか」を必ず伝える(日付の記入漏れ等)

コピペ用テンプレ(承認/差戻しの自動返信)

《承認された場合》 {氏名}さん、休暇申請が承認されました。 種類:{休暇種類} / 期間:{開始日}〜{終了日} 当日はゆっくりお休みください。 《差し戻された場合》 {氏名}さん、申請内容に確認したい点があります。 お手数ですが、もう一度メニューから申請し直してください。 (不明点は総務まで)

※ {種類}{開始日} などを返信に差し込むには、フォームの回答を友だち情報(休暇種類・開始日・終了日)にも保存する設定にしておき、タグ追加時アクションの文面で友だち情報を差し込みます。難しければ「休暇申請が承認されました。内容は申請どおりです」の固定文でも運用できます。

山田さん、休暇申請が承認されました。
種類:産休 / 期間:2026/09/01〜2027/01/10
つまずきポイント:タグの「外す」設定を忘れると、「休暇_申請中」と「休暇_承認済」が両方付いたままになり、未処理の絞り込みが正しくできません。付け替えは「承認済を付ける+申請中を外す」を必ずセットで設定します(タグ追加時アクションに「申請中を解除」を入れておけば、管理者は承認済を付けるだけで済みます)。
◆ ◆ ◆

6. GASで期日アラートを自動化する(有給5日・産休育休)

ここが社労士的な要です。人の記憶に頼ると必ず抜ける「有給の年5日取得義務」と「産休・育休の予定日」を、プログラム(GAS)に毎朝見張らせて、期限が近づいたら総務にメールで知らせます。このGASは受信しませんし、社員のLINEにも送りません。決まった時刻に動いて連携シートと台帳を読み、総務に知らせるだけです(だからエルメと共存できます)。

このGASがやること(5つ)

処理内容
転記4枚の連携シートから、台帳にない回答だけを「申請台帳」に追記(申請ID採番・ステータス「申請中」)
集計申請台帳の「有給×承認」を、付与基準日からの1年間について社員ごとに合計し、有給マスタのE・F・G列を更新
有給5日アラート付与10日以上の社員で、付与基準日から10か月が過ぎても取得が5日未満の人を通知
産休・育休アラート開始2週間前/終了1か月前に、保険料免除の申出・給付の案内・復帰面談の準備を通知
未処理アラート「申請中」のまま3日以上たっている申請を通知

手順:GASを貼り付けてトリガーを設定する

操作場所:スプレッドシート > 拡張機能 > Apps Script

  1. スプレッドシートのメニュー「拡張機能 > Apps Script」を開く
  2. 下のコードを丸ごと貼り付けて保存する
  3. プロジェクトの設定 > スクリプト プロパティ で、ADMIN_EMAIL(総務のメールアドレス)と、4本のフォームの連携シートのファイルID FORM_YUKYU_ID/FORM_SANKYU_ID/FORM_IKUKYU_ID/FORM_KAIGO_ID を登録する(コードに直接書かないこと)
  4. 時計マーク(トリガー)>「トリガーを追加」で、dailyLeaveCheck を「日付ベースのタイマー/午前8時〜9時」に設定
  5. 初回実行時に権限の承認画面が出るので、許可する

GASコード(読む・知らせる専用・そのままコピペで動きます)

/** 休暇管理 毎朝チェック(読む・知らせる専用・時刻トリガー起動) **/
// このGASは「受信」しない。LINEのWebhookはエルメが占有しているため、
// GASは毎朝の時刻トリガーで起動し、連携シートと台帳を読んでメールするだけ。

// シート名(1章で決めた名前と1文字も変えない)
var SHEET_APPLY = '申請台帳';   // A申請ID B申請日時 C社員番号 D氏名 E休暇種類 F開始日 G終了日 H日数 I連絡事項 Jステータス K承認者
var SHEET_YUKYU = '有給マスタ'; // A社員番号 B氏名 C付与基準日 D付与日数 E取得済み日数 F残日数 G年5日充足 H繰越日数

// 連携シート(フォームの「スプレッドシート」連携で自動生成されるファイル)のIDは
// スクリプト プロパティに保存:FORM_YUKYU_ID / FORM_SANKYU_ID / FORM_IKUKYU_ID / FORM_KAIGO_ID
var FORMS = [
  { prop: 'FORM_YUKYU_ID',  type: '有給' },
  { prop: 'FORM_SANKYU_ID', type: '産休' },
  { prop: 'FORM_IKUKYU_ID', type: '育休' },
  { prop: 'FORM_KAIGO_ID',  type: '介護' }
];
// 連携シートの見出し(フォームの質問文に合わせて変更)
var H = { time: '回答日時', emp: '社員番号', name: '氏名', start: '開始日', end: '終了日',
          days: '日数', note: '連絡事項', due: '出産予定日', birth: '子の生年月日', rel: '続柄' };

function dailyLeaveCheck() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  importApplications_(ss);                       // 連携シート → 申請台帳(新しい回答だけ)
  aggregateYukyu_(ss);                           // 有給の取得済み日数を集計
  var msgs = [];
  msgs = msgs.concat(checkYukyu5days_(ss));      // 有給の年5日義務アラート
  msgs = msgs.concat(checkLeaveSchedule_(ss));   // 産休・育休の予定日アラート
  msgs = msgs.concat(checkPending_(ss));         // 未処理の申請
  if (msgs.length) notifyAdmin_(msgs.join('\n\n'));
}

// 4本のフォームの連携シートを読み、台帳にない回答を「申請中」で追記する
function importApplications_(ss) {
  var sheet = ss.getSheetByName(SHEET_APPLY);
  var rows = sheet.getDataRange().getValues();
  var known = {};
  var maxId = 0;
  for (var i = 1; i < rows.length; i++) {
    known[key_(rows[i][1], rows[i][2])] = true;   // B申請日時 + C社員番号 で同じ回答か判定
    maxId = Math.max(maxId, Number(rows[i][0]) || 0);
  }
  var props = PropertiesService.getScriptProperties();
  FORMS.forEach(function (f) {
    var id = props.getProperty(f.prop);
    if (!id) return;
    readSheet_(id).forEach(function (a) {
      var k = key_(a[H.time], a[H.emp]);
      if (!a[H.time] || known[k]) return;
      var note = String(a[H.note] || '');
      if (a[H.due])   note = '出産予定日 ' + fmt_(new Date(a[H.due])) + '/' + note;
      if (a[H.birth]) note = '子の生年月日 ' + fmt_(new Date(a[H.birth])) + '/' + note;
      if (a[H.rel])   note = '続柄 ' + a[H.rel] + '/' + note;
      maxId += 1;
      sheet.appendRow([maxId, a[H.time], a[H.emp], a[H.name], f.type,
                       a[H.start] || '', a[H.end] || '', Number(a[H.days]) || '', note, '申請中', '']);
      known[k] = true;
    });
  });
}

// 連携シートを見出し名で読み、1行=1オブジェクトにする
function readSheet_(id) {
  var v = SpreadsheetApp.openById(id).getSheets()[0].getDataRange().getValues();
  if (v.length < 2) return [];
  var head = v[0].map(String);
  return v.slice(1).map(function (row) {
    var o = {};
    head.forEach(function (k, i) { o[k] = row[i]; });
    return o;
  });
}
function key_(time, emp) {
  var t = time instanceof Date ? time.getTime() : String(time);
  return t + '|' + String(emp);
}

// 申請台帳の「有給×承認」を、付与基準日からの1年間について社員ごとに合計し、有給マスタのE/F/G列を更新
function aggregateYukyu_(ss) {
  var apply = ss.getSheetByName(SHEET_APPLY).getDataRange().getValues();
  var ymSheet = ss.getSheetByName(SHEET_YUKYU);
  var ym = ymSheet.getDataRange().getValues();
  for (var r = 1; r < ym.length; r++) {
    var e       = ym[r][0];                 // A列=社員番号
    var base    = ym[r][2];                 // C列=付与基準日
    var granted = Number(ym[r][3]) || 0;    // D列=付与日数
    var carried = Number(ym[r][7]) || 0;    // H列=繰越日数(前年度の残)
    if (!(base instanceof Date)) continue;
    var limit = new Date(base); limit.setFullYear(limit.getFullYear() + 1);
    var taken = 0;
    for (var i = 1; i < apply.length; i++) {
      if (String(apply[i][2]) !== String(e)) continue;        // C列=社員番号
      if (apply[i][4] !== '有給' || apply[i][9] !== '承認') continue; // E列・J列
      var start = apply[i][5];                                // F列=開始日
      if (!(start instanceof Date) || start < base || start >= limit) continue;
      taken += Number(apply[i][7]) || 0;                      // H列=日数(半休は0.5)
    }
    ymSheet.getRange(r + 1, 5).setValue(taken);                        // E列=取得済み日数(当年度)
    ymSheet.getRange(r + 1, 6).setValue(granted + carried - taken);    // F列=残日数(繰越込み)
    ymSheet.getRange(r + 1, 7).setValue(granted < 10 ? '対象外' : (taken >= 5 ? '済' : '未')); // G列
  }
}

// 付与10日以上の社員で、基準日から10か月を過ぎても取得5日未満の人を洗い出す
function checkYukyu5days_(ss) {
  var ym = ss.getSheetByName(SHEET_YUKYU).getDataRange().getValues();
  var today = new Date();
  var out = [];
  for (var r = 1; r < ym.length; r++) {
    var name    = ym[r][1];                 // B列=氏名
    var base    = ym[r][2];                 // C列=付与基準日
    var granted = Number(ym[r][3]) || 0;    // D列=付与日数
    var taken   = Number(ym[r][4]) || 0;    // E列=取得済み日数
    if (!(base instanceof Date) || granted < 10) continue;  // 年5日義務は付与10日以上の人だけ
    var limit = new Date(base); limit.setFullYear(limit.getFullYear() + 1);
    var alertDay = new Date(base); alertDay.setMonth(alertDay.getMonth() + 10); // 10か月で督促開始
    if (today >= alertDay && today < limit && taken < 5) {
      out.push('【有給5日】' + name + ' さん:取得' + taken + '日(あと' + (5 - taken) + '日)。' +
               '期限 ' + fmt_(limit) + ' までに本人の時季指定か会社の時季指定で5日に。');
    }
  }
  return out;
}

// 産休・育休の開始2週間前/終了1か月前に手続きリマインド
function checkLeaveSchedule_(ss) {
  var apply = ss.getSheetByName(SHEET_APPLY).getDataRange().getValues();
  var today = new Date();
  var out = [];
  for (var i = 1; i < apply.length; i++) {
    var name   = apply[i][3];   // D列=氏名
    var type   = apply[i][4];   // E列=休暇種類
    var start  = apply[i][5];   // F列=開始日
    var end    = apply[i][6];   // G列=終了日
    var status = apply[i][9];   // J列=ステータス
    if ((type === '産休' || type === '育休') && status === '承認') {
      if (start instanceof Date && daysBetween_(today, start) === 14) {
        out.push('【' + type + '開始】' + name + ' さん:開始(' + fmt_(start) + ')まで2週間。' +
                 (type === '産休' ? '産前産後休業の保険料免除の申出・出産手当金の案内を準備。'
                                   : '育児休業の保険料免除の申出・育児休業給付の受給資格確認を準備。'));
      }
      if (end instanceof Date && daysBetween_(today, end) === 30) {
        out.push('【' + type + '終了】' + name + ' さん:終了(' + fmt_(end) + ')まで1か月。' +
                 '復帰面談・延長希望の確認(育休の延長申出は終了2週間前まで)を。');
      }
    }
  }
  return out;
}

// 「申請中」のまま3日以上たっている申請を知らせる
function checkPending_(ss) {
  var apply = ss.getSheetByName(SHEET_APPLY).getDataRange().getValues();
  var today = new Date();
  var out = [];
  for (var i = 1; i < apply.length; i++) {
    var at = apply[i][1];
    if (apply[i][9] === '申請中' && at instanceof Date && daysBetween_(at, today) >= 3) {
      out.push('【未処理】' + apply[i][3] + ' さんの' + apply[i][4] + '(' + fmt_(at) + ' 申請)が未処理です。');
    }
  }
  return out;
}

function daysBetween_(a, b) {
  var A = new Date(a.getFullYear(), a.getMonth(), a.getDate());
  var B = new Date(b.getFullYear(), b.getMonth(), b.getDate());
  return Math.round((B - A) / 86400000);
}
function fmt_(d) { return Utilities.formatDate(d, 'JST', 'yyyy/MM/dd'); }

// 総務へメールで通知(宛先はスクリプト プロパティ ADMIN_EMAIL)
function notifyAdmin_(body) {
  var to = PropertiesService.getScriptProperties().getProperty('ADMIN_EMAIL');
  if (!to) return;
  MailApp.sendEmail(to, '【休暇管理】本日の要確認リスト', body);
}
通知はメールで動かします。GASから社員や総務のLINEへ直接送る(push)ことはしません——エルメを使う構成ではGASがLINEのユーザーIDを受け取れず、通数もかかるためです。総務への即時連絡はエルメのアプリ通知(4章)、まとめての確認は朝のメール、と使い分けます。
つまずきポイント:アラートが飛ぶのは、産休・育休のステータスが「承認」で、開始/終了日が正しく日付として入っているときだけです。J列が「申請中」のままだったり、日付が文字列で入っていると発火しません。台帳の日付はセル書式を「日付」にそろえてください。有給5日のアラートは条件を満たす間、毎朝のメールに載り続けます(取得して5日に達すると消えます)。
◆ ◆ ◆

費用と無料枠の目安

この仕組みは、社内利用(従業員数十名規模)なら基本的に無料の範囲で運用できます。配信の中心が「申請への受付返信」「承認・差戻しの返信」で、一斉配信を使わないためです。

使うもの費用補足
LINE公式アカウント(無料プラン)月0円執筆時点で月200通まで。超過分は配信不可(追加購入もできない)。社内の申請通知が中心なら通常は収まる
エルメプランによる無料プランと有料プランがある。フォーム数・タグ数の上限は最新の公式料金で確認を
Googleスプレッドシート/GAS月0円Googleアカウントがあれば無料
通数の考え方:フォーム送信後の自動返信とタグ追加時の返信は「Push」でカウントされ、申請1件につき受付返信1通+結果返信1通=2通です。社員30名が月に2件ずつ申請すると120通で、無料枠200通に収まります。リッチメニューのタップに対する自動応答はカウントされません。一斉配信(制度変更のお知らせなど)を足す場合は「1回×社員数」が加わるので、最新の公式料金ページで試算してください。

運用開始前のチェックリスト

確認項目OKの状態
シート名「申請台帳」「有給マスタ」が1文字も違わず作られている
列の並び申請台帳がA〜K、有給マスタがA〜Hの順で見出しが入っている
タグ名「休暇_有給/産休/育休/介護」「休暇_申請中/承認済/差戻し」で統一されている
フォームのタグ付与4種すべてのフォームで、種類タグ+「休暇_申請中」が付き、スプレッドシート連携が有効になっている
総務への通知担当者のエルメアプリで通知設定を済ませ、テスト申請の通知が届いた
GASの設定値スクリプト プロパティに ADMIN_EMAIL と4本の連携シートIDを登録した
トリガーdailyLeaveCheck が毎朝動くよう設定し、権限承認を済ませた
テストダミー社員で1件申請→承認→台帳反映→翌朝アラートまで通した

よくある質問

Q. 同じLINEアカウントで、勤怠の打刻もGASで受け付けられますか?
A. できません。LINEの受信口(Webhook)は1つで、それをエルメが使っているためです。打刻のように「GASがLINEを受信する」仕組みを併用したい場合は、打刻用に別のLINE公式アカウントを用意してください。この記事のGASは受信せず送るだけなので共存できます。
Q. この仕組みで、休暇届の「書類」そのものは作れますか?
A. この記事の範囲では、申請内容を台帳に残すところまでです。押印付きの正式な休暇届が必要な場合は、台帳から別途書類を起こす運用を足してください(応用アレンジ参照)。
Q. 有給の付与日数や基準日は自動で計算されますか?
A. 付与日数・付与基準日は「有給マスタ」に手入力する前提です。GASが自動で行うのは「取得済み日数の集計」と「5日未達の検知」までです。付与ルール(勤続年数による日数)は会社ごとに異なるため、あえて自動化していません。
Q. 産休・育休のアラートは何日前に飛びますか?
A. 開始の2週間前と、終了の1か月前に一度ずつ飛びます。日数はGASコードの「14」「30」の数字を変えれば調整できます。
Q. 介護休暇ではなく、長期の介護休業も受け付けられますか?
A. 受け付けられます。産休・育休と同じく「開始予定・終了予定」を聞くフォームを1本足し、タグ「休暇_介護休業」と、GASの FORMS に1行追加してください。介護休業は対象家族1人につき通算93日・3回まで、介護休業給付の手続きもあるので、産休育休と同じ期日アラートの対象にすると安心です。
Q. 申請を取り消したいときは?
A. 申請台帳のJ列(ステータス)を「取消」にし、エルメ側のタグを外してください。集計は「承認」のものだけを数えるので、取消は自動的に対象外になります。GASは台帳にある回答を二重に転記しないので、取消にした行が翌朝また「申請中」に戻ることはありません。

応用アレンジ(同じ骨格でできること)

  1. 残業・遅刻・早退の事前申請:休暇種類の選択肢に項目を足すだけで、同じフォーム+台帳の形で受けられます
  2. 有給取得率の月次レポート:GASに集計関数を1つ足し、月初に「部署別の取得率」を総務へ自動送信
  3. 休暇届のPDF自動生成:台帳の1行からGoogleドキュメントのひな型に差し込み、PDFを書き出して保存
  4. 復帰前アンケート:育休終了1か月前のアラートに合わせ、復帰意向を聞くフォームを自動案内

まとめ

受付・入力・タグ付け・本人への返信は「エルメ」、台帳への転記と期日の見張りは「読む・知らせる専用のGAS」——この役割分担で、有給・産休・育休・介護休暇の申請を、紙とバラバラのチャットから1本の台帳に集約できます。まず取りかかるなら、1章の「申請台帳」「有給マスタ」の2枚を作るところから。土台の列を固めれば、あとは順番に載せていくだけです。

※ 本記事は架空の製造業の会社(北山製作所)を想定したサンプルの構築例です。掲載コードはサンプルであり、ご利用は自己責任でお願いします。実際の運用にあたっては、有給休暇・産前産後休業・育児休業・介護休暇に関する最新の法令および自社の就業規則をご確認ください。Lメッセージ(エルメ)の機能名・画面構成、LINE公式アカウントの通数の上限やプラン内容は変更される場合があります。