見出し画像

Notionオートメーションのかなりマニアックな活用方法 〜繰り返しタスクの日付を、休祝日を回避して設定する〜

こんにちは!カウシェのJimと申します。
カウシェというECプラットフォームのスタートアップで、フルスタックコーポレートと名乗り情シスを担当しています。

情シスと言いつつ、「フルスタック」なので、労務、総務、オフィスマネジメントなど、守備範囲広く仕事をしています。その一環で、カウシェのNotion環境の管理・整備なども行なっており、今日はNotionオートメーションを利用したタスクの日付設定の(ほぼ)自動化についてお話ししたいと思います。

先に言いますが、かなーりマニアックな話になってしまったな…と自分でも思ってます。ただ、同じようなことを求めている方のヒントになればいいなと思ってますので、ぜひ最後までお付き合いいただけると嬉しいです。


カウシェではNotionをフル活用しており、Notionは我々が利用するSaaSの中でもかなり中核な存在です。過去にもスタートアップ組織におすすめなNotionの活用Noteを書いているので、ぜひご一読ください!

カウシェのコーポレート部門では、Notionプロジェクトを活用して日々の業務を行っています。少数精鋭組織であるがゆえに、プロジェクトを利用して同時進行で動く複数のプロジェクトを、メンバー間で共有しながら進めています。

実際のプロジェクト運用の話はカウシェのアドベントカレンダーで解説してますので、ぜひそちらも一読ください。

今回は、オートメーションを活用した繰り返しタスクの日付プロパティの自動設定についてお話しします。
例えば経理担当者は、毎月同じタイミングで仕訳、証憑回収、費用計上、などを行うことがあると思います。月初1営業日までにこれ、3営業日にあれ、など決まったタイミングで作業をする必要がある場合、これらを我々は毎月プロジェクトをオートメーションで作成し、その中に「月次タスク」を設定しています。

この「月次タスク」は「月次プロジェクト」のテンプレート内にボタンを仕込み、そのプロジェクトにリレーションされた状態でタスクページを作成する、という方法で行なっていました。ただ、今までのNotionだとここで日付の計算ができず、「月初からX営業日」を起源として設定する、みたいなことができませんでした。
これが2024年10月にリリースされた新しいオートメーション機能で出来るようになりました。今までが月次タスクが作成されたら、「あーこれはX営業日だからこの日付へ動かして…いや、祝日だからその次の日だ」みたいなことを半日ぐらいかけてやっていました。これが、新しいオートメーション機能によって全部自動的にできるようになりました。

どうやって行っているか

毎月の定常プロジェクトは、該当月の前月15日自動的にオートメーションから作成されるようになっています。つまり、「11月の労務」に関するプロジェクトは10月15日に作成されます。11月の労務について、10月の時点からタスクや共有事項を書く必要がたまにあるため、事前に作成されるようになっています。

月初にプロジェクトを開始したら、言いたいこと書き忘れちゃうじゃん?

ここで作成されるプロジェクトのテンプレートには、ボタンブロックが仕込まれています。このボタンブロックを押すと、そのプロジェクトにまつわる毎月行われるタスクがタスクデータベースに作成されるようになっています。

ここで注目していただきたいのが、タスクに設定する「期限」です。元々タスクには日付プロパティがありタスクの期限を設定できるのですが、今まではボタンオートメーションからは日付を固定日でしか設定できませんでした。これが関数で設定できるようになり、月初から換算してX営業日を期限として設定できるようになりました。

結果、すごい長いFormulaになっちゃいましたが、とりあえず全部載せちゃいます。

lets(
  days_to_add, 1, /* 追加したい営業日。1営業日を追加する場合は1を指定 */

  /* 開始日: 範囲プロパティのdateStartを取得 */
  start, {"global":"button_page","source":"global"}.prop("日付").dateStart(),

  /* 次の月の1日を計算 */
  first_of_next_month, dateAdd(
    dateSubtract(start, date(start) - 1, "days"),
    1,
    "month"
  ),

  /* 次の月の1日が土曜日または日曜日の場合、翌月曜日に調整 */
  first_weekday, first_of_next_month.formatDate("EEE"),
  adjusted_start, if(
    first_weekday == "Sat",
    first_of_next_month.dateAdd(2, "days"), /* 土曜日の場合は月曜日に移動 */
    if(
      first_weekday == "Sun",
      first_of_next_month.dateAdd(1, "days"), /* 日曜日の場合は月曜日に移動 */
      first_of_next_month /* 平日の場合はそのまま使用 */
    )
  ),

  /* 日本の祝日(YYYY-MM-DD形式、2025年) */
  japanese_holidays, [
    "2025-01-01", "2025-01-13", "2025-02-11", "2025-02-23", "2025-02-24", "2025-03-20", 
    "2025-04-29", "2025-05-03", "2025-05-04", "2025-05-05", "2025-05-06", "2025-07-21", 
    "2025-08-11", "2025-09-15", "2025-09-23", "2025-10-13", "2025-11-03", "2025-11-23", "2025-11-24"
  ],

  /* 祝日の場合、開始日を1日進める */
  start_date, if(
    japanese_holidays.includes(adjusted_start.formatDate("YYYY-MM-DD")),
    adjusted_start.dateAdd(1, "days"), /* 祝日の場合は翌日に移動 */
    adjusted_start
  ),

  /* 営業日計算のための日付を生成 */
  dates, "x".repeat(days_to_add * 3).split("").map( /* 必要な日数をカバーする十分な範囲を生成 */
    !index ? start_date : start_date.dateAdd(index, "days")
  ),

  /* 振替休日を計算 */
  substitutes, dates.filter(
    current.formatDate("EEE") == "Sun" && 
    japanese_holidays.includes(current.formatDate("YYYY-MM-DD"))
  ),
  substitutesLen, substitutes.length(),
  candidates, "x".repeat(5).split("").map(lets(
    add, index + 1,
    substitutes.map(current.dateAdd(add, "days")).filter(
      !["Sat", "Sun"].includes(current.formatDate("EEE")) &&
      !japanese_holidays.includes(current.formatDate("YYYY-MM-DD"))
    )
  )),
  substitutes, "x".repeat(substitutesLen).split("").map(lets(
    subIdx, index,
    candidates.map(current.at(subIdx)).filter(!empty(current)).first()
  )),

  /* 営業日をフィルタリング */
  businessDays, dates.filter(
    !["Sat", "Sun"].includes(current.formatDate("EEE")) &&
    !japanese_holidays.includes(current.formatDate("YYYY-MM-DD")) &&
    !substitutes.includes(current)
  ),

  /* 指定した営業日を返す */
  result, if(
    businessDays.length() < days_to_add,
    "1970-01-01", /* 十分な営業日が見つからない場合のフォールバック */
    businessDays.at(days_to_add - 1)
  ),

  parseDate(result.formatDate("YYYY-MM-DD"))
)

ものすごく長くなっちゃってますが、端折って解説すると…

  • 月初X営業日にしたいか指定(days_to_add)

  • プロジェクトの開始日を指定(start - ボタンが住んでいるプロジェクトのプロパティから取得。先述の通り、前月の15日)

  • プロジェクトの当月月初を指定(first_of_next_month - startをもとに計算)

  • 日本の祝日を設定(japanese_holidays - 2025年の祝日)

これらの関数をもとに、月初からX営業日を祝日と休日を回避しながら計算しています。
祝日と休日の計算は、Notionアンバサダーの熊倉さんの記事を大いに参考させていただきました…!

上の記事では指定日間の営業日を計算するためのもので、これを応用して指定日からX営業日の日付を計算するようにしました。

この関数は、各プロジェクトのテンプレートの、ボタンプロパティ内のすべてのタスクにコピペするだけです。あとは月初からX営業日に指定したいか設定するだけで、繰り返しのタスク設定が可能になります。

ボタンひとつで、月次タスクが設定できる

プロジェクトの「日付」プロパティの開始日から計算し、12月2日から順次タスクの期限が設定されています

上記は、実際に11月の月次プロジェクトでボタンを押した状態です。
ひとつ目のタスクは月初1営業日に設定していますが、12月1日が日曜日のため、1日ずれて12月2日開始になっていることがわかります。
それ以降のタスクも、月初が日曜日であることを考慮し1日ずつずれています。

月初が日曜日のため、タスクが1日ずつずれてくれます

これだけで(と言っていいのかわからないが…)毎月のタスクの日付を自動的に設定することができます。

タスク自体は日付を設定していなくてもカンバンビューでは活用できますが、タイムライン表示したい場合は日付は必須です。複数のビューで進行管理したい場合は、このような設定をしておけば安心です。

なるべく楽をして生きていきたい

実際の関数を作るのは私自身はそこまで大変ではないものの、一定レベルが高い作業だとは思います。
一方で、こういった課題認識があり、解決に向けてチャレンジすることがスキルアップにもつながるんじゃないかなと私は考えています。

この関数を作るための数時間を無駄と考えるかは人それぞれだと思いますが、私は機械に頼める仕事はとことん機械に頼むべき派なので、こう言ったオートメーションはどしどし活用したいと思います。

ぜひ皆さんもお試しください!

いいなと思ったら応援しよう!