地方の中小企業のIT導入・活用コンサルティングを提供する株式会社etika(エティカ)CRMサポートセンターです。
「商談のメモ欄に会議の議事録を貼ったら、金額や次回アクションが自動で項目に入ってほしい」——Zoho CRMを使い込むほど出てくる要望です。この記事では、商談にメモ(議事録)を追加すると、ワークフローがDelugeカスタム関数を呼び出し、商談の5項目を自動更新する仕組みを、実際に動かしたコードそのままで解説します。
結論(先に要点)
- メモ本文を「■ラベル:値」の決まった形式で書く
- 商談のメモ作成をトリガーにワークフローで関数を発火させる
- 関数はメモを解析し、
Amount(総額)・Closing_Date(完了予定日)・Stage(ステージ)・次回アクション・要約の5項目をupdateRecordでまとめて更新する
何ができるようになるか
営業担当者が商談画面のメモに、次のような議事録を貼り付けます。
■総額:1,200万円
■完了予定日:2026/09/30
■ステージ:交渉
■次回アクション:見積の再提示と決裁者同席の打ち合わせ設定
■要約:
・現行の運用課題を確認
・価格は概ね合意、残るは決裁プロセス
・9月内の契約を目標に合意
保存すると数秒後、商談の「総額」「完了予定日」「ステージ」「次回アクション」「商談要約」が自動で埋まります。手入力の転記作業がゼロになり、入力漏れも防げます。

全体の構成
- カスタム項目の準備:商談モジュールに「次回アクション(1行テキスト)」「商談要約(複数行テキスト)」を用意します(総額・完了予定日・ステージは標準項目)。
- ワークフロールール:モジュール「商談」、実行タイミング「メモを追加したとき」で発火するルールを作成します。
- カスタム関数:ルールのアクションに、下記のDeluge関数を紐づけます。引数
dealIdに「商談 - 商談ID」をマッピングします。
Delugeカスタム関数(全文)
// 種別: ワークフローカスタム関数(モジュール: 商談)
// 引数: dealId (String) … WFの「引数を編集」で「商談 - 商談ID」をマッピング
try
{
// 1) 商談に紐づくメモから議事録メモを取得
notes = zoho.crm.getRelatedRecords("Notes", "Deals", dealId.toLong(), 1, 50);
content = "";
for each n in notes
{
t = ifnull(n.get("Note_Title"), "");
c = ifnull(n.get("Note_Content"), "");
if(t.contains("商談議事録") || c.contains("■総額"))
{
content = c;
break;
}
}
if(content == "")
{
return;
}
// 1.5) リッチテキスト対策: HTMLで保存されている場合はタグを除去
// 改行文字リテラルはDeluge非対応のためbase64で生成("Cg==" = \n)
nl = zoho.encryption.base64Decode("Cg==");
if(content.contains("<"))
{
content = content.replaceAll("<br>", nl);
content = content.replaceAll("<br/>", nl);
content = content.replaceAll("<br />", nl);
content = content.replaceAll("<[^>]*>", "");
content = content.replaceAll(" ", " ");
content = content.replaceAll("&", "&");
}
// 2) 「■ラベル:値」を ■ 区切りでパース
updateMap = Map();
segments = content.toList("■");
for each seg in segments
{
s = seg.trim();
if(s == "") { s = "-"; }
sep = ":";
if(s.contains(":")) { sep = ":"; }
label = ifnull(s.getPrefix(sep), "").trim();
value = ifnull(s.getSuffix(sep), "").trim();
if(label == "総額")
{
mult = 1;
numText = value;
if(value.contains("億")) { numText = ifnull(value.getPrefix("億"), ""); mult = 100000000; }
else if(value.contains("万")) { numText = ifnull(value.getPrefix("万"), ""); mult = 10000; }
num = numText.replaceAll("[^0-9.]", "");
if(num != "" && num.length() < 12)
{
updateMap.put("Amount", num.toDecimal() * mult);
}
}
else if(label == "完了予定日")
{
d = value.replaceAll("/", "-");
if(d.contains(nl)) { d = ifnull(d.getPrefix(nl), d).trim(); }
if(d.matches("[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}"))
{
updateMap.put("Closing_Date", d);
}
}
else if(label == "ステージ")
{
if(value.contains(nl)) { value = ifnull(value.getPrefix(nl), value).trim(); }
// ★jp orgではStageは「表示名」で渡す("受注" 等)
stageMap = Map();
stageMap.put("提案", "提案");
stageMap.put("交渉", "交渉");
stageMap.put("受注", "受注");
if(stageMap.containKey(value))
{
updateMap.put("Stage", stageMap.get(value));
}
}
else if(label == "次回アクション")
{
// 1行テキスト項目のため先頭行のみ
if(value.contains(nl)) { value = ifnull(value.getPrefix(nl), value).trim(); }
updateMap.put("Next_Action", value); // ← 実際のAPI名に置き換える
}
else if(label == "要約")
{
if(value != "")
{
updateMap.put("Meeting_Summary", value); // ← 実際のAPI名に置き換える
}
}
}
// 3) 1項目でも取れたら商談を更新(失敗してもthrowせずログのみ)
if(updateMap.size() > 0)
{
resp = zoho.crm.updateRecord("Deals", dealId.toLong(), updateMap);
info resp;
return;
}
return;
}
catch (e)
{
info e;
return;
}
Next_Action Meeting_Summary の部分は、ご自身の環境で作成したカスタム項目のAPI名に置き換えてください(API名は「設定 > APIとSDK > API名」で確認できます)。
実装でつまずきやすい3つのポイント
この関数には、公式ドキュメントには載っていない実測ベースの工夫が3つ入っています。

1. 改行での分割はできない → 「■」区切りにする
Delugeでメモをパースするときにありがちなのがcontent.toList("\n")で行分割する方法ですが、Delugeでは改行での分割が期待通りに動きません。そこで本関数は各項目の頭に「■」を付けたフォーマットにして、toList("■")で分割しています。改行に依存しないので、要約のような複数行テキストもそのまま1つの値として扱えます。
2. 改行文字は base64 で生成する
Delugeは"\n"のような改行文字リテラルを書けません。そこでzoho.encryption.base64Decode("Cg==")(Cg==はLFのbase64)で改行文字を生成し、変数nlとして使い回しています。
3. ステージは「表示名」で更新する
日本語環境(jp DC)のZoho CRMでは、APIでステージ(Stage)を更新するとき、内部値の"Closed Won"ではなく**表示名の"受注"**を渡す必要があります。ここは別記事で詳しく扱います。
まとめ
議事録メモから商談を自動更新する仕組みは、「決まったフォーマットで書く」「メモ追加で発火」「まとめてupdateRecord」という3点さえ押さえれば、標準機能とDelugeだけで実現できます。AI議事録ツールの出力をこのフォーマットに整えれば、そのままCRM入力の自動化まで一気通貫でつながります。



