Notionデータベースの関数プロパティを使って更新日を自動更新する

はじめに

グッドパッチで情報システム担当の@enpipiと申します。

2023年9月にNotionの関数に使える数式が大幅にアップデートされ今までできなかった表現ができるようになりました。 本記事では、数式2.0から登場した数式を用いて更新日の自動更新を実現します。

www.notion.so

注意

関数はオートメーショントリガーに使えず、Zapierでも関数は拾えません。 リマインド通知やカレンダーに予定として入れたい場合はNotionのdatabase APIを使う必要があります。

概要

サービスの契約更新日などを把握しておきたいが、更新日を毎回入力するのが手間だったのでデータベースの関数を使って更新日を自動更新しました。

できたもの

今日の日付が契約日を過ぎていた場合に年次は一年後、月次は一ヶ月後を算出する。

notion-database-renwal-date

できること

  • 今日を起算日として次回更新日を自動で算出する
  • 年次・月次を判定する

躓いたところ

例えば契約日が11/01だった場合、 day(prop"契約日")とすると、dd(01)ではなくd (1)で抽出されてしまうので、1/11と11/1が判別できません。そのため、formatDate を使って dd に整形する必要がありました。

手順

1. 適当なデータベースを用意して、プロパティに契約日を用意する

更新日の基準値としてなんでも良いので日付を用意します。ここではプロパティ名を契約日とします。

2. プロパティに年次・月次を追加

セレクトを使って年次・月次を追加。ここではプロパティ名は契約期間とします。

3. 関数を使って次回更新日を算出

関数として以下を入力。プロパティ名は更新日とします。

if(
    prop("契約期間") == "年次",
    if(
        0 > toNumber(formatDate(prop("契約日"), "MMDD")) - toNumber(formatDate(now(), "MMDD")),
        (year(now()) + 1 + "-" + formatDate(prop("契約日"), "MM-DD")).replaceAll("-", "").parseDate(),
        (year(now()) + "-" + formatDate(prop("契約日"), "MM-DD")).replaceAll("-", "").parseDate()
    ),
    if(
        0 > toNumber(formatDate(prop("契約日"), "DD")) - toNumber(formatDate(now(), "DD")),
        dateAdd(
            (year(now()) + "-" + month(now()) + "-" + formatDate(prop("契約日"), "DD")).replaceAll("-", "").parseDate(),
            1,
            "months"
        ),
        (year(now()) + "-" + month(now()) + "-" + formatDate(prop("契約日"), "DD")).replaceAll("-", "").parseDate()
    )
)

ロジック

上のロジックは次のとおりです。 chatGPT に言語化してもらいました。

  1. 最初に、if 関数で「契約期間」が「年次」かどうかを判断します。
  2. 「契約期間」が「年次」の場合:

    • 契約日と現在の日付を比較し、結果が0より大きい(契約日が本日より前)なら、現在の年と契約日を結合して更新日を設定します。
    • 結果が0より小さい(契約日が本日より後)場合、現在の年に1足したものと契約日を結合して更新日を設定します。
  3. 「契約期間」が「年次」以外(たとえば「月次」)の場合:

    • 契約日と現在の日付を比較し、結果が0より大きい(契約日が本日より前)なら、現在の年と月、契約日を結合して更新日を設定します。
    • 結果が0より小さい(契約日が本日より後)場合、現在の年と月、契約日を結合した日付に1か月を足して更新日を設定します。

この関数中の replaceAll("-","").parseDate() は、日付形式を整形し、正常な日付として Notion に認識させるために使用しています。また、formatDate() 関数は、日付を特定のフォーマットに変換するために使用されています

[ オプション1 ] フィルター、ソートをかける

notion-filter-example

最後に表示するサービスを直近のものだけに絞る、更新日順にソートなどして完成です。

[ オプション2 ] Notion APIを使って通知する

Notion APIを使うことで特定のデータベースに対してフィルターやソートをかけて値を取得することができます。Zapierでは関数で生成した値は取得できませんがAPI なら取得できます。 ここでは、GASを使います。

Notion APIを利用するための準備

  1. 私のインテグレーション | Notion開発者へアクセスし、新しいインテグレーションを作成します。ここでは名前を「YearlyServiceRenewalAlert」としました。
    • コンテンツ機能は「コンテンツを読み取る」、ユーザー機能は「ユーザー情報なし」とします。
  2. 「内部インテグレーションシークレット」を取得して保管しておきます。GASで利用します。
  3. データベースのIDを取得します。対象のデータベースのURLからデータベースIDを確認しましょう。
    • https://www.notion.so/<データベースID>?v=<ビューID>のようになっています。
  4. インテグレーションからデータベースを参照できるようにします。
    1. データベースページの右上の︙をクリック
    2. Add Connections
    3. YearlyServiceRenewalAlertを選択しましょう。

インテグレーションからデータベースを参照できるようにする

Notion APIを使って望む値を取得する

Query a databaseを使います。

このAPIはインテグレーションされたデータベースのレコードをフィルターして取得することができます。

const NOTION_API_KEY =
  PropertiesService.getScriptProperties().getProperty("NOTION_API_KEY");
const DATABASE_ID = PropertiesService.getScriptProperties().getProperty("DATABASE_ID");
const url = 'https://api.notion.com/v1/databases/' + DATABASE_ID + '/query';

function main() {
  let today = new Date();
  let dateThreeMonthsLater = new Date();

  dateThreeMonthsLater.setMonth(today.getMonth() + 3);
}


function getServicesWithinRenewalDate(startDate, endDate) {
  const payload = {

"filter": {
      "and": [
        {
          "property": "契約期間",
          "select": {
            "equals": "年次"
          }
        },
        {
          "and": [
            {
              "property": "更新日",
              "formula": {
                "date": {
                  "on_or_before": endDate
                }
              }
            },
            {
              "property": "更新日",
              "formula": {
                "date": {
                  "on_or_after": startDate
                }
              }
            }
          ]
        }
      ]
    },
    "sorts": [
      {
        "property": "更新日",
        "direction": "ascending"
      },
      {
        "property": "名前",
        "direction": "ascending"
      }
    ]
 };
 const options = {
    'method': 'POST',
    'headers': {
      'Notion-Version': '2022-06-28',
      'Authorization': 'Bearer ' + NOTION_API_KEY,
      'Content-Type': 'application/json'
    },
    'payload': JSON.stringify(payload),
  };
  let result = JSON.parse(UrlFetchApp.fetch(url, options));

  return result;
}

通知

取得後は、加工してSlackなどに通知しましょう。 通知を整形したい場合は、Block Kit Builderを使うと便利です。

GASからSlackに通知

おわりに

関数酷使は大変ですね。 手段が目的にならないように自制しつつも、notion 芸人するのは楽しいです。

Goodpatchではデザイン好きなエンジニアの仲間を募集しています。 少しでもご興味を持たれた方は、ぜひ一度カジュアルにお話ししましょう!

goodpatch.com