😁

Google Apps Scriptを利用したシフト管理

2024/04/21に公開1

【導入】
今回はGoogle Apps Script(GAS)を活用して業務プロセスの効率化に取り組みました。
Google formで休みを申請し自動でGoogle calendarに反映し、毎朝チャットに通知されるシステムを構築しました。

【問題の説明】
私たちはホワイトボードを使用してスタッフのスケジュールと休暇を管理していました。しかし、以下の問題が頻繁に発生していました。

・事務所にこれないスタッフはシフトを把握できず、リモートでの情報共有が困難。
・休日にチャットを送ってしまいコミュニケーションが発生し、スタッフの休息を妨げる。
・外部の問い合わせに対し、どのスタッフがいつ戻るかを正確に伝えることができない。
・休みを取ったタイミングが不明で管理者が把握できていない。

【解決策の提示】
これらの課題を解決するため、Google Calendarを利用してスタッフの不在情報(休み)を自動的に抽出し、Google Chatを通じてリアルタイムで通知するシステムを開発しました。
このシステムにより、すべての関係者がいつでもスタッフの状況を正確に把握できるようになりました。
Google formから休みを入力することで自動的に反映されつつ、管理職に通知がいくようになっています。

フォームで申請するとカレンダーに反映されます。カレンダーに直接不在の予定を入れてもOKです。

// 休暇の種類を抽出する関数
function extractVacationType(summary) {
  // イベントのサマリーが未指定の場合は '不在' と返す
  if (!summary) {
    return '不在';
  }

  // サマリーをスペースで分割
  var parts = summary.split(' '); 
  if (parts.length > 1) {
    // 名前を除いた残りの部分を結合して返す
    return parts.slice(1).join(' '); 
  } else if (summary.includes('不在')) {
    // サマリーに '不在' が含まれている場合はそのまま '不在' を返す
    return '不在'; 
  }
  // それ以外の場合も '不在' を返す
  return "不在";
}

// 本日の不在スタッフ情報をGoogle Chatに送信する関数
function sendTodaysAbsencesToChat() {
  // スタッフごとのカレンダーID
  var staffCalendarIds = {
    'テスト': 'example.email@domain.com',
    'テスト': 'example.email@domain.com',
    // その他スタッフも同様に追加
  };

  // 今日の日付を00:00に設定
  var today = new Date();
  today.setHours(0, 0, 0, 0);
  // 明日の日付を設定
  var tomorrow = new Date(today);
  tomorrow.setDate(today.getDate() + 1);

  // 本日が土日かを判定し、土日の場合は処理を中断
  var dayOfWeek = today.getDay();
  if (dayOfWeek === 0 || dayOfWeek === 6) {
    console.log('本日は土日です。');
    return;
  }

  // 祝日かどうかを判定し、祝日の場合は処理を中断
  var holidays = Calendar.Events.list('ja.japanese#holiday@group.v.calendar.google.com', {
    timeMin: today.toISOString(),
    timeMax: tomorrow.toISOString(),
    singleEvents: true,
    orderBy: 'startTime'
  }).items;
  if (holidays.length > 0) {
    console.log('本日は祝日です。');
    return;
  }

  // メッセージ初期設定
  var formattedDate = Utilities.formatDate(today, Session.getScriptTimeZone(), "yyyy/MM/dd");
  var message = formattedDate + '\n';

  // 各スタッフのカレンダーから不在情報を取得
  Object.keys(staffCalendarIds).forEach(function(staffName) {
    var calendarId = staffCalendarIds[staffName];
    var events = Calendar.Events.list(calendarId, {
      timeMin: today.toISOString(),
      timeMax: tomorrow.toISOString(),
      singleEvents: true,
      orderBy: 'startTime'
    }).items;

    events.forEach(function(event) {
      var eventSummary = event.summary || "";
      var eventStart = new Date(event.start.dateTime || event.start.date);
      var eventEnd = new Date(event.end.dateTime || event.end.date);

      // 終日イベントの判定
      var isAllDayEvent = !event.start.dateTime && eventEnd - eventStart > 0 && eventEnd.getHours() === 0 && eventEnd.getMinutes() === 0;

      // 休憩時間や勤務記録はスキップ
      if (eventSummary.toLowerCase().includes("休憩") || eventSummary.includes("勤務")) {
        return; // このイベントを無視
      }

      // 不在とマークされたイベント情報をメッセージに追加
      if (event.eventType === 'outOfOffice' && eventStart <= tomorrow && eventEnd > today) {
        var eventTypeText = extractVacationType(eventSummary);
        if (isAllDayEvent) {
          // 終日イベントの場合、時間は表示しない
          message += `${staffName} ${eventTypeText}\n`;
        } else {
          // 終日でない場合、時間を含めた情報を表示
          var timeString = `${Utilities.formatDate(eventStart, Session.getScriptTimeZone(), "HH:mm")}~${Utilities.formatDate(eventEnd, Session.getScriptTimeZone(), "HH:mm")}`;
          message += `${staffName} ${eventTypeText} ${timeString}\n`;
        }
      }
    });
  });

  // 送信メッセージが初期設定と異なる場合、Google Chatに送信
  if (message !== formattedDate + '\n') {
    message += 'さんが、お休みです';
    sendNotificationToGoogleChat(message);
  } else {
    console.log('本日は休みを取っている人がいません。');
  }
}

// Google Chatに通知を送信する関数
function sendNotificationTo GoogleChat(message) {
  // Webhook URL(ダミー)
  var webhookUrl = 'https://chat.googleapis.com/v1/spaces/EXAMPLE/messages';
  // 通知メッセージをJSON形式でパッケージング
  var payload = JSON.stringify({text: message});
  var options = {
    method: 'post',
    contentType: 'application/json',
    payload: payload
  };
  // HTTP POSTリクエストを送信
  UrlFetchApp.fetch(webhookUrl, options);
}

【具体的なコードサンプルと解説】
上記で示したコードは、以下のような機能を持ちます。
・スタッフのカレンダーからその日の不在情報を取得し、Google Chatに自動で通知します。
・土日や祝日には通知を行わないようにすることで、不要なアラートを避けます。
・終日イベントや休憩といった特定のイベントは除外して処理を行います。
chatの画面です。出力形式はそれぞれ変えてください。

【実装手順】

Google Apps Scriptで新しいプロジェクトを開始します。
提供されたスクリプトをコピーしてスクリプトエディタに貼り付けます。
スクリプトのカレンダーIDやWebhook URLを適宜に調整し、スクリプトエディタのトリガー設定で毎日実行されるように設定します。
【結果と利点】
この自動化システムの導入により、スタッフの不在情報が迅速に共有されるようになり、情報の透明性が向上しました。結果として、「〇〇さんって今日出社してる?」というやりとりは無くなりました。

【まとめ】
この記事で紹介した方法で日々の業務が迅速かつ正確な情報共有を可能にします。
Google Apps Scriptのポテンシャルを最大限に活用し、訪問看護ステーションの運営をより効果的なものにしましょう。

この記事が、同じような課題に直面している他の医療介護関連の事業所にも役立つと幸いです。

Discussion

MASAMASA

追記
新しいApps Scriptプロジェクトの画面で、左側のメニューから「サービス」セクションを選択します。
「+ サービスを追加」をクリックし、リストから「Google Calendar API」を見つけて追加します。これにより、スクリプトからGoogle Calendarへのアクセスが可能になります。