Zoho CRMで他モジュールの項目を自動連携する方法【Deluge実装手順】


はじめに
Zoho CRMを運用していると、「商談モジュールの項目を更新したら、関連する仕入先モジュールの項目にも自動で反映させたい」というニーズが出てきます。 たとえば、商談で「仕入金額」を入力したら、その仕入先の管理レコードにも金額を転記したい、といったケースです。 この記事では、カスタム関数(Deluge)とワークフロールールを使って、モジュール間のフィールド値を自動連携する手順を、実装中にハマったポイントも含めて解説します。
やりたいこと

- 商談の「仕入金額」を入力/更新したら、対応する仕入先レコードの「仕入金額」に自動で転記する
- 仕入先は「仕入先名」のテキスト値を使って特定する
シンプルなクロスモジュール同期ですが、Zoho特有の落とし穴がいくつかあるので、最後まで読んでから実装することをおすすめします。
全体の流れ
を作成する_4.-ワー-941790.png)
1. 連携元・連携先のフィールドを準備する
2. 各フィールドのAPI名を確認する
3. カスタム関数(Deluge)を作成する
4. ワークフロールールを作成する
5. 引数マッピングを設定する
6. 動作確認
ステップ1: フィールドの準備
連携元と連携先の両方に、対応するフィールドを用意します。
今回の例では以下を準備しました。
- 商談モジュールに「仕入金額」フィールド(数値型)
- 仕入先モジュールに「仕入金額」フィールド(数値型)
- 商談モジュールに「仕入先名」フィールド(1行テキスト、連携先を特定するためのキー)
ポイント: 両モジュールのフィールドは同じデータ型に揃えてください。型が違うと更新時にエラーになります。
ステップ2: API名の確認
設定 → 開発者向け情報 → APIとSDK → API名 から、フィルター基準を切り替えて該当モジュールのフィールドのAPI名を確認します。
今回の例だと以下のような構成でした。
- 商談(Deals)
- 仕入先名:
Vender_syodan - 仕入金額:
Purchase_Amount - 仕入先(Vendors)
- 仕入先名:
Vendor_Name - 仕入金額:
Purchase_Amount
注意: 日本語ラベルから自動生成されるAPI名は、入力者の英語スペル次第で Vender のような綴りで作られていることがあります。必ず実物を確認しましょう。
ステップ3: カスタム関数の作成
設定 → 開発者向け情報 → 関数 → 新規作成
基本情報を入力します。
- 表示名: 仕入金額同期
- 関数名:
sync_purchase_amount - カテゴリー: automation
コード本体は以下のとおりです。
void automation.sync_purchase_amount(String dealId)
{
// 1. 商談レコードを取得
query_data = Collection();
query_data.insert("fields":"Vender_syodan,Purchase_Amount");
sourceDeal = zoho.crm.v8.getRecordById("Deals", dealId.toLong(), query_data);
vendorName = sourceDeal.get("Vender_syodan");
purchaseAmount = sourceDeal.get("Purchase_Amount");
// 2. 値の存在チェック
if(isnull(vendorName) || isnull(purchaseAmount))
{
info "値が不足。終了。";
return;
}
// 3. 仕入先モジュールから全レコードを取得
page_num = 1;
per_page_num = 200;
options = Collection();
options.insert("fields":"Vendor_Name");
allVendors = zoho.crm.v8.getRecords("Vendors", page_num, per_page_num, options);
// 4. ループで一致する仕入先を探す
vendorId = "";
for each vendor in allVendors.get("data")
{
if(vendor.get("Vendor_Name") == vendorName)
{
vendorId = vendor.get("id");
break;
}
}
if(vendorId == "")
{
info "一致する仕入先なし。終了。";
return;
}
// 5. 仕入先の仕入金額を更新
updateData = Collection();
updateData.insert("Purchase_Amount":purchaseAmount);
response = zoho.crm.v8.updateRecord("Vendors", vendorId.toLong(), updateData);
info response;
}
ステップ4: ワークフロールールの作成
設定 → 自動化 → ワークフロールール → ルールを作成する
以下のように設定します。
- モジュール: 商談
- ルール名: 仕入金額同期
- 実行条件: データの操作 → 作成または編集
- 対象項目: 「特定の項目が更新されたとき」で「仕入金額」を選択
- 適用範囲: すべての商談
ステップ5: アクションと引数マッピング
「すぐに実行する処理」→「+処理」→「関数」を選び、ステップ3で作成した関数を選択します。
ここで一番ハマりやすいのが引数マッピングです。
| 名前 | 値 |
|---|---|
| dealId | # を入力 → 商談モジュール → 「商談ID」を選択 |
値欄が空欄のままだと、関数に null が渡されて何も処理されません。設定後に必ず ${Deals.商談ID} のような表示が入っていることを確認してください。
完了する → 保存する → ワークフロー全体も保存。
ステップ6: 動作確認
- 商談を開いて「仕入金額」を変更して保存
- 対応する仕入先レコードを開く
- 「仕入金額」に同じ値が転記されていればOK
うまく動かないときは、設定 → 自動化 → アクションログ → 関数タブ から、該当関数の実行履歴を確認できます。info の出力内容を見れば、どこで止まっているかわかります。
ハマりポイントと解決策
実装中に何度か詰まったポイントを共有します。同じ落とし穴を避けるために、参考にしてください。
1. searchRecords がインデックス遅延で動かない
最初は仕入先を特定するのに zoho.crm.v8.searchRecords を使っていましたが、新規作成直後の仕入先レコードが見つからない問題に当たりました。
これはZoho公式の仕様で、「レコードを作成・編集してすぐに検索すると、インデックスの遅延により取得できないことがある(30〜60秒待つ必要がある)」とドキュメントに明記されています。
解決策として、getRecords で全件取得してループで一致を探す方法に切り替えました。レコード数が数百件程度ならパフォーマンス的にも問題ありません。
2. V8 API の構文ミス
V7と V8 で API の挙動が変わっている部分があります。特に注意すべきは以下です。
// ❌ V7のクセで書きがち(V8では動かない)
dealResponse.get("data").get(0).get("Test_1")
// ✅ V8では直接アクセス
dealResponse.get("Test_1")
V8の getRecordById は単一レコードを返すため、data でラップされていません。
3. getRecords の引数の型エラー
getRecords の引数を Map で渡そうとするとエラーになります。
// ❌ エラーになる
params = Map();
params.put("fields", "Vendor_Name");
params.put("per_page", 200);
allVendors = zoho.crm.v8.getRecords("Vendors", params);
// ✅ 正しい構文
options = Collection();
options.insert("fields":"Vendor_Name");
allVendors = zoho.crm.v8.getRecords("Vendors", 1, 200, options);
V8 の getRecords は (モジュール名, ページ番号, 件数, オプション) の4引数構造です。
また、page と per_page を数値リテラルで直接書くと型エラーになることがあるので、変数経由で渡すのが安全です。
4. 引数マッピングの値が空になっている
ワークフロー側で関数を呼び出すときの引数マッピングは、保存途中で値だけ消えてしまうことがあります。「成功してるのに動かない」という現象が出たら、まず引数マッピング画面を再確認してください。
info dealId; を関数の冒頭に入れて、ログで null になっていないか見るのが一番確実です。
5. API名のタイプミス
「ラベルが日本語だから大丈夫」と思いきや、自動生成されるAPI名が予期せぬ綴りになっていることがあります。
今回も Vendor のつもりが Vender になっていたフィールドがあり、コードと一致せずに値が取れない事態が発生しました。
API名6. 無限ループの心配は不要
「商談を更新 → 仕入先を更新 → そのトリガーでまた商談を更新」のような無限ループを心配する人もいますが、Zoho公式仕様で「Delugeから更新したレコードはデフォルトではワークフローを再発火させない」ことになっています。
なので、双方向の同期を組んでも基本的にループは発生しません。は必ず「設定 → APIとSDK」で実物を確認するクセをつけましょう。
6. 無限ループの心配は不要
「商談を更新 → 仕入先を更新 → そのトリガーでまた商談を更新」のような無限ループを心配する人もいますが、Zoho公式仕様で「Delugeから更新したレコードはデフォルトではワークフローを再発火させない」ことになっています。
なので、双方向の同期を組んでも基本的にループは発生しません。
まとめ
Zoho CRMでモジュール間のフィールド連携を実装する流れは、以下の通りでした。
- 連携元と連携先のフィールドを揃える
- API名を正確に把握する
- カスタム関数で「取得 → 検索 → 更新」のロジックを書く
- ワークフロールールでトリガーを設定する
- 引数マッピングを丁寧に行う
特に重要なのは、searchRecords のインデックス遅延と引数マッピングの空欄問題です。この2つさえ押さえておけば、大抵のクロスモジュール連携は実装できるはずです。
同じような連携を組みたい方の参考になれば幸いです。