Zoho CRMの日付ベースのワークフローとは、レコードの日付項目の値をもとに、作成や編集がなくても決まった日に処理を動かす仕組みです。たとえば「商談の完了予定日の1週間前にメールを送る」「契約更新日の30日前にタスクを作る」といった使い方をします。
便利な仕組みですが、当社が用意したテストレコードでは、ルールを有効にした時点で基準日がすでに過去になっているレコードは、実行予定に乗りませんでした。 公式ヘルプに明記がない挙動で、当社が確認した範囲での結果です。 新しく作るレコードでは問題なく動くため、移行データを入れてから初めて気づく、という形になりがちです。
本記事では、当社が支援している非営利の会員制団体のZoho CRMで、定期的な入金の予定を自動で延ばす仕組みを作ったときの検証結果と、日次のスケジュール関数に置き換えた設計をまとめます。
やりたかったこと:入金予定を、なくなる前に自動で延ばす
この団体では、毎月または年1回の定期的な入金を「継続課金」というカスタムモジュールで管理し、将来の入金予定を「入金予定」(商談にあたるモジュール)のレコードとして先に作っています。入金予定は2年分を一度に作り、最後の1件が近づいたら、次の2年分を自動で足します。
最初の設計は、次のような日付ベースのワークフローでした。
- 対象:入金予定(商談にあたるモジュール)
- 基準の日付:処理日(入金予定日)
- 実行日:処理日の30日前
- 条件:フェーズが「未納」
- 繰り返し:1回のみ
- 処理:関数を呼び、最後の1件なら2年分を追加する
検証1:発火予定の前に日付を編集すると、新しい値で組み直された
まず、テスト用のレコードで、発火予定の前に処理日を書き換えるとどうなるかを確かめました(2026年8月)。
結果は、書き換えた後の日付をもとに、実行予定が組み直されました。 入金予定日が変わっても、古い日付で動いてしまう心配はないことが分かりました。
公式ヘルプにも、日付と時刻の項目を基準にしたスケジュールアクションについて、「レコードを編集して日付と時刻の値を変えると、新しい値に合わせて予定が組み直される」という趣旨の記載があります。当社の日付ベースのルールでの検証も、同じ動きでした。
検証2:基準日がすでに過去のレコードは、実行予定に乗らなかった
次に、「処理日の30日前」がすでに過去になっているテストレコードを用意し、ルールを有効にしました。
結果、そのレコードの履歴タブにある「今後予定されている自動処理」は0件でした。ルールを有効にした後も、実行予定に一切乗りませんでした。
ここで困ったのが、別のCRMから移してくる既存データです。移行データには、処理日がすでに過去のものが多く含まれます。この方式のままでは、そうしたレコードで延長の処理がずっと動かないことになります。
公式ヘルプの記載との関係
当社が確認した時点の公式ヘルプ(Configuring Workflow Rules)では、日付ベースのルールについて次のことが書かれています。
- 日付項目の値をもとに動くため、レコードの作成や編集は発火の条件にならない
- 毎月・毎年の繰り返しを設定できる
- 1回に動くのは10分ごとに最大5,000件で、超えた分は次の10分に回る
一方で、基準日がすでに過去のレコードをどう扱うかは、日付ベースのルールの説明には書かれていませんでした。 同じページのスケジュールアクションの注意書きには「計算した実行時刻が過去なら、すぐに実行する」という記載がありますが、これはスケジュールアクションの説明です。当社の日付ベースのルールの検証では、過去のレコードはすぐに実行されることも、予定に乗ることもありませんでした。
仕様が明記されていない以上、「過去のレコードも拾われるはず」という前提で設計するのは危険です。必ず実機で、対象レコードの「今後予定されている自動処理」を確かめてください。
発火する予定かどうかは、どこで確かめる?
日付ベースのワークフローが動く予定かどうかは、次の手順で確かめられます。
- ルールの対象になるはずのレコードを開く
- 履歴タブ(予定されている自動処理の一覧)を開く
- 「今後予定されている自動処理」に、該当ルールの予定があるかを見る
- 予定が無ければ、そのレコードではルールが動かない
公式ヘルプでも、スケジュールされた処理はレコードの詳細画面に一覧で表示されると説明されています。移行データを入れる前後で、過去の日付のレコードと未来の日付のレコードを1件ずつ見比べておくと安心です。
置き換えた設計:日次のスケジュール関数で「今日」のレコードを探す

スケジュール関数とは、決まった日時に自動で動くDelugeの関数です(Delugeの基本は「はじめてのDeluge」をご覧ください)。
検証の結果を受けて、日付ベースのワークフローをやめ、毎日決まった時刻に動くスケジュール関数に置き換えました。考え方は次のとおりです。
- 毎日早朝に、処理日が今日の入金予定を検索する
- 継続課金に紐づいていない単発の入金は対象外にする
- その継続課金に紐づく入金予定の中で、処理日が一番新しい1件かを確かめる(後ろに予定が残っていれば対象外)
- 継続課金が解約済み(終了日が入っている)なら対象外にする
- 対象なら、最新の処理日を起点に次の2年分(毎月なら24件、年1回なら2件)を作る
あわせて、判定にフェーズ(未納・入金済み)を使わないようにしました。最後の1件が処理日までに入金済みになっていると、未納だけを対象にする条件では取りこぼすためです。
サンプルコード
項目名を一般的な名前に置き換えた例です。継続契約を「Subscriptions」モジュール、入金予定を「Deals」とし、Dealsに継続契約へのルックアップ項目「Subscription」がある前提です。
void schedule.ExtendPlannedDealsDaily()
{
todayStr = zoho.currentdate.toString("yyyy-MM-dd");
criteria = "(Closing_Date:equals:" + todayStr + ")";
targets = List();
pages = {1,2,3,4,5,6,7,8,9,10};
for each p in pages
{
found = zoho.crm.searchRecords("Deals",criteria,p,200);
if(found == null || found.size() == 0)
{
break;
}
targets.addAll(found);
if(found.size() < 200)
{
break;
}
}
info "処理日が今日の件数: " + targets.size();
for each deal in targets
{
sub = deal.get("Subscription");
if(sub == null)
{
continue;
}
subId = sub.get("id");
// 同じ継続契約の入金予定から、処理日が一番新しい1件を探す
related = zoho.crm.getRelatedRecords("Deals","Subscriptions",subId);
latest = null;
for each r in related
{
if(latest == null || r.get("Closing_Date").toDate("yyyy-MM-dd") > latest.get("Closing_Date").toDate("yyyy-MM-dd"))
{
latest = r;
}
}
if(latest == null || latest.get("id") != deal.get("id"))
{
continue;
}
subscription = zoho.crm.getRecordById("Subscriptions",subId.toLong());
if(subscription.get("End_Date") != null)
{
continue;
}
count = 2;
stepMonths = 12;
if(subscription.get("Frequency") == "毎月")
{
count = 24;
stepMonths = 1;
}
baseDate = latest.get("Closing_Date").toDate("yyyy-MM-dd");
for each i in {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}
{
if(i > count)
{
break;
}
nextDate = baseDate.addMonth(i * stepMonths);
newDeal = Map();
newDeal.put("Deal_Name",subscription.get("Name") + "-" + nextDate.toString("yyyy/MM/dd"));
newDeal.put("Closing_Date",nextDate.toString("yyyy-MM-dd"));
newDeal.put("Stage","未納");
newDeal.put("Amount",subscription.get("Amount"));
newDeal.put("Subscription",subId);
res = zoho.crm.createRecord("Deals",newDeal);
if(res.get("id") == null)
{
info "作成失敗: " + res;
}
}
}
}
実運用では、次の点を足してください。
- 作成に失敗したときの通知(ログだけでは誰も気づきません)
- 必須項目(パイプライン、レイアウトなど)の指定
- 関連リストの件数が多い場合のページ送り(
getRelatedRecordsは1回で取れる件数に上限があります) - ルックアップの値の渡し方は環境で確認(IDをそのまま渡す書き方で入らない場合は、
{"id": subId}の形で渡します)
スケジュールは、設定 → 自動化 → スケジュールから、毎日の実行時刻を決めて登録します。当社の事例では早朝に1日1回動かしています。スケジュール関数を本番で動かす前の確認項目は、「Zoho CRMで進級・年度切替を自動化する」のチェックリストも参考になります。
検証のしかた
置き換えた関数は、テストデータで次の6通りを用意し、関数のエディタから実行して結果を読み戻しました(2026年8月)。
| ケース | 期待する結果 |
|---|---|
| 年1回・最後の1件の処理日が今日 | 2件追加される |
| 毎月・最後の1件の処理日が今日 | 24件追加される |
| 解約済みの継続課金 | 追加されない |
| 今日の入金予定が最後の1件ではない | 追加されない |
| 最後の1件がすでに入金済み | フェーズに関係なく追加される |
| 継続課金に紐づかない単発の入金 | 何も起きず、エラーにもならない |
すべて期待どおりに動き、テストデータは検証後に全件削除しました。対象が0件の日にもう一度実行し、エラーなく終わることも確かめています。
実行前には「処理日が今日」の既存データが0件であることを確かめてから動かしました。本番環境で検証する場合、この確認を飛ばすと、実データに追加の予定が作られてしまいます。
移行時の注意:すでに日付を過ぎたレコードは、別に1回だけ補充する
スケジュール関数は「処理日が今日」のレコードを探す仕組みです。そのため、移行の時点ですでに最後の予定日を過ぎている継続課金(予定が尽きているもの)は、この関数でも拾えません。
移行の手順の中に、次のような1回だけの補充処理を入れておく必要があります。
- 解約されていない継続課金を一覧にする
- それぞれ、紐づく入金予定の一番新しい処理日を調べる
- その日付が今日より前なら、予定が尽きているものとして抜き出す
- 抜き出したものに、起点となる日付を決めて予定を作る(起点をどこに置くかは業務側と決める)
- 作ったあと、次回の延長が日次の関数で拾われることを確かめる
日付ベースのワークフローでも、スケジュール関数でも、「すでに過ぎた日付」は自動では拾われないと考えて、移行計画を立てるのが安全です。移行前に確認するデータ項目は「SalesforceからZoho CRMへ移行する前に確認すべきデータ項目」にまとめています。
日付ベースのワークフローとスケジュール関数は、どう使い分ける?
| 場面 | 向いている仕組み |
|---|---|
| 新しく作るレコードだけが対象で、決まった日の前後に通知・タスクを出したい | 日付ベースのワークフロー |
| 移行データなど、日付が過去のレコードが混ざる | スケジュール関数+1回だけの補充処理 |
| 判定が複雑(最後の1件か、解約済みかなど) | スケジュール関数 |
| 発火したかどうかを毎日のログで追いたい | スケジュール関数 |
日付ベースのワークフローは設定画面だけで作れる手軽さがあります。一方、どのレコードが対象になるかを毎日自分で決めるスケジュール関数は、動きが読みやすく、ログで追いやすいのが利点です。
まとめ
Zoho CRMの日付ベースのワークフローは、日付の編集には追随しますが、当社の検証では、基準日がすでに過去のレコードは実行予定に乗りませんでした。公式ヘルプにもこの場合の扱いは明記されていないため、設計の前提にしないことが大切です。
移行データを含めて確実に動かしたいなら、日次のスケジュール関数で「今日」のレコードを探す方式に置き換え、移行時には1回だけの補充処理を組み込みます。どちらの方式でも、対象レコードの「今後予定されている自動処理」やログを見て、実際に動く予定があるかを確かめてから本番に入れてください。
Zoho CRMのワークフローや関数の設計、データ移行の進め方でお困りの場合は、Zoho CRMカスタマイズ・設定代行サービスまでお気軽にご相談ください。
よくある質問
日付ベースのワークフローが発火するかどうかは、どこで確かめられますか?
対象レコードの詳細画面で、予定されている自動処理の一覧を見ます。当社が使った日本語画面では、履歴タブの「今後予定されている自動処理」に表示されました。ここに何も無ければ、そのレコードではルールが動く予定がありません。
基準日が過去のレコードは、公式にはどう扱われると書かれていますか?
当社が確認した時点では、日付ベースのルールで基準日がすでに過去のレコードをどう扱うかは、公式ヘルプに明記されていませんでした。スケジュールアクションについては「計算した実行時刻が過去なら即時に実行する」という記載がありますが、当社の日付ベースのルールの検証では、実行予定に乗りませんでした。
日付ベースのワークフローとスケジュール関数は、どう使い分ければよいですか?
新しく作るレコードだけを対象に、決まった日の前後に通知などを出すなら、日付ベースのワークフローで足ります。移行データのように日付が過去のレコードが混ざる場合や、毎日の判定を確実に行いたい場合は、スケジュール関数の方が動きを読みやすく、検証もしやすくなります。
スケジュール関数は画面から手動で動かせますか?
当社が使った環境では、関数のエディタから実行して動作を確かめました。業務担当者が画面のボタンで起動する仕組みではないため、手動実行が必要な運用なら、別途の仕組みを用意してください。




