繰り返し注文する取引先の次の注文時期を購買履歴から見込んで、声をかける先と文面を用意する
定期的に同じ品目を買う取引先について、受注履歴から次の注文が来るはずの日を計算し、いつもより遅れている先だけを抜き出します。抜き出した先には、営業メモから事情を読み取ったうえで連絡文の下書きを用意します。
- 生成AI
- ChatGPT/Claude/Gemini
- 連携・自動化
- Google Apps Script/Power Automate/Python
- 対象業界
- 商社/小売
- 対象部門
- カスタマーサポート/営業
- 対象業務
- 書類作成/集計・分析
- 主な課題
- データ分析に時間がかかる/営業フォローが追いつかない/期限・対応漏れが起きる
- AIで行う処理
- 予測
- 主な効果
- 判断支援/工数削減/機会損失防止
- 導入難易度
- ★★☆☆☆
- 実装レベル
- 半自動化
- 費用感
- API連携(中)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 月初に内勤営業が販売管理システムから直近1年の受注履歴をCSVで出し、スプレッドシートに貼る
- 取引先ごとに並べ替え、主な品目の前回注文日を目で追う
- 「いつもならもう注文が来ている」と感じた先に印を付ける
- 印を付けた先の営業メモを開き、最近の訪問や電話の記録を読む
- 連絡すべきと判断した先について、メールの文面を1通ずつ書くか、電話の要点をメモする
- 連絡の結果を営業メモに書き足す
- 人週に1回、販売管理システムから受注履歴のCSVを出し、指定のシートに貼る(連携できる環境なら自動で取り込む)
- 自動決まった時刻に Apps Script が動き、取引先×品目ごとに注文間隔の中央値とばらつきを計算する
- 自動前回注文日と間隔から次回見込み日と遅れ日数を出し、遅れがばらつきを超えた先だけを抜き出す
- 自動注文回数が少ない先、季節で波のある品目、切り替えの兆しのある先を、それぞれ別の扱いに振り分ける
- 自動抜き出した先の営業メモを Gemini API に渡し、事情の分類と根拠の文を返させる
- 自動事情に合わせて、連絡文の下書きを作らせる
- 自動結果を「フォロー候補」シートに書き出す
- 人担当者が候補の一覧を見て、連絡するか・どの手段で連絡するかを決め、下書きを直して送る
- 人連絡の結果を候補シートに記録する
各工程の詳しい説明を読む
- 月初に内勤営業が販売管理システムから直近1年の受注履歴をCSVで出し、スプレッドシートに貼る
- 取引先ごとに並べ替え、主な品目の前回注文日を目で追う
- 「いつもならもう注文が来ている」と感じた先に印を付ける
- 印を付けた先の営業メモを開き、最近の訪問や電話の記録を読む
- 連絡すべきと判断した先について、メールの文面を1通ずつ書くか、電話の要点をメモする
- 連絡の結果を営業メモに書き足す
(a)「いつもなら」の基準が人の記憶にある。 3番目の判断は担当者が取引先の癖を覚えているかどうかで決まり、担当替えのあとは、止まった注文に数か月気づかないことがあります。
(b)遅れの大きさを比べられない。 毎月注文する先の2週間の遅れと、隔月の先の2週間の遅れは重さが違いますが、目で追う一覧では同じに見えます。結局、注文額の大きい先から見ることになり、小口の先の離脱は拾えません。
(c)300社を毎月見る時間が無い。 締めや繁忙期が重なる月から順に省かれ、省いた月に限って、他社へ切り替えた先が出ます。
- 【人】 週に1回、販売管理システムから受注履歴のCSVを出し、指定のシートに貼る(連携できる環境なら自動で取り込む)
- 【自動】 決まった時刻に Apps Script が動き、取引先×品目ごとに注文間隔の中央値とばらつきを計算する
- 【自動】 前回注文日と間隔から次回見込み日と遅れ日数を出し、遅れがばらつきを超えた先だけを抜き出す
- 【自動】 注文回数が少ない先、季節で波のある品目、切り替えの兆しのある先を、それぞれ別の扱いに振り分ける
- 【自動】 抜き出した先の営業メモを Gemini API に渡し、事情の分類と根拠の文を返させる
- 【自動】 事情に合わせて、連絡文の下書きを作らせる
- 【自動】 結果を「フォロー候補」シートに書き出す
- 【人】 担当者が候補の一覧を見て、連絡するか・どの手段で連絡するかを決め、下書きを直して送る
- 【人】 連絡の結果を候補シートに記録する
3番目がこの設計の要です。 遅れているかどうかを計算の規則で決めているので、同じ履歴からはいつも同じ候補が出ます。 担当者が替わっても、候補の選び方は変わりません。
8番目で、人は送るかどうかを決めます。 下書きが出ても、取引先との関係を知っているのは担当者です。送信は人が行い、この構成からは自動で送りません。
02今回想定するシステム構成
販売管理システム │ 受注履歴をCSVで出力(週1回) ▼ Googleスプレッドシート「受注履歴」シート ▼【トリガー】時間主導型トリガー(毎週月曜 7時台) Google Apps Script ├── 取引先×品目ごとに注文間隔の中央値・ばらつきを計算 ├── 次回見込み日・遅れ日数を計算し、許容幅を超えた先を抽出 └── 回数不足/季節品目/切り替えの兆し を振り分け ▼ │ UrlFetchApp で呼び出し(抽出した先の営業メモと計算結果) Gemini API │ ① 営業メモから事情を分類(根拠の文つき) │ ② 事情に合わせた連絡文の下書き ▼ JSONで返す Google Apps Script ── 値の検査(分類が決められた語か、日付が計算結果と同じか) ▼ 「フォロー候補」シート ▼ 【人が確認】連絡する先と手段を決め、下書きを直して Gmail で送る
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Google Apps Script | Python、Power Automate |
| 生成AI | Gemini API | OpenAI API、Claude API |
スプレッドシートとGmailは、新しく足すものではありません。 受注履歴の置き場、候補の一覧、連絡の記録はすべてスプレッドシートに置き、送信は担当者がふだんのGmailで行います。販売管理システムには書き込みません。
実行環境を Apps Script にしたのは、データがすでにスプレッドシートにあるからです。 計算も呼び出しも同じ場所で書け、別のサーバーを用意する必要がありません。時間主導型トリガーは、毎分、数時間ごと、毎日の指定時刻、毎週の指定曜日、毎月、特定の日時で動かせます。ただし時刻は少しずらされ、9時のトリガーなら9時から10時のあいだのどこかで動き、その時刻は日ごとに保たれるとされています。朝の始業前に一覧をそろえたいなら、1時間早めに設定します。
インストール型のトリガーは、作成した人のアカウントで動きます。 担当者の個人アカウントで作ると、その人が異動したときに止まります。部署で管理するアカウントで作ることを最初に決めます。トリガーが失敗したときは、Apps Script から通知のメールが届きます。
外部との通信は UrlFetchApp で行います。 HTTPとHTTPSで外部のホストと通信するための仕組みで、method、contentType、headers、payload を指定して呼びます。muteHttpExceptions を true にすると、失敗の応答でも例外で止まらず応答が返るので、応答コードを見て再試行するかを決められます。
制限は、1回の実行が6分までという点がいちばん効きます。 トリガーの合計実行時間は一般アカウントで1日90分、Google Workspace のアカウントで1日6時間、トリガーはスクリプトごと・ユーザーごとに20個まで、URL Fetch の呼び出しは一般アカウントで1日20,000回、Workspace で1日100,000回とされています。これらは予告なく変わりうるとも書かれています。300社の計算は数秒で終わりますが、Gemini API を1社ずつ呼ぶと6分に届くことがあるため、呼び出しは分けて行います(第7章)。
Gemini API は構造化出力を使います。 JSONスキーマを渡して、決めた形のJSONで返させる機能で、用途として「テキストをあらかじめ決めたカテゴリに分類する」「名前や日付などの情報を取り出す」が挙げられています。構文として正しいJSONは返るが、値はアプリケーション側で検査することとされています。
03どうやって実装するのか
処理の起点を決める
時間主導型トリガーで、毎週月曜の朝に動かします。 注文は日々来ますが、フォローの判断は週に1回まとめて行えば足ります。毎日動かすと、同じ先が連日候補に出て、担当者が一覧を見なくなります。
トリガーは2本に分けます。1本目が計算と抽出(月曜6時台)、2本目が Gemini API の呼び出し(月曜7時台、以降は未処理が残っていれば15分ごと)です。1回の実行は6分までなので、計算と呼び出しを1本にまとめると、候補の多い週に途中で止まります。2本目は候補シートの「未処理」の行だけを取り、処理した行に印を付けて、次の実行は続きから始めます。
受注履歴のCSVが今週分に貼り替わっていなければ、1本目は計算をせずに担当者へ知らせて終わります。古い履歴で計算すると、先週注文した先が「遅れ」として出ます。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 受注履歴 | 受注日、取引先コード、品目コード、数量 | 販売管理システムのCSV(直近2年分) |
| 品目の区分 | 品目コード、季節品目かどうか、フォローの対象外とする品目か | 自社で用意する品目の表 |
| 取引先の情報 | 取引先コード、名称、担当者、フォローを止めている理由(休業・取引停止など) | 取引先の表 |
| 営業メモ | 取引先コード、日付、記録者、本文 | 営業メモのシート(直近90日分だけ) |
| 過去の連絡結果 | 取引先コード、連絡日、結果 | フォロー候補シートの記録 |
計算の質を決めるのは受注履歴の粒度です。 1回の注文に複数の品目があるときは、品目ごとに1行になっている必要があります。受注番号の単位で1行のCSVしか出せない場合は、品目で行を分けるところから準備します。
営業メモを直近90日に絞るのは、古い事情で今の遅れを説明させないためです。 1年前の「担当者交代」を根拠に、今月の遅れを説明する下書きが出るのを防ぎます。
データの取得方法を決める
| 取るもの | どこから | どう取るか |
|---|---|---|
| 受注履歴 | 「受注履歴」シート | 週1回CSVを貼る。販売管理システムがファイルを出力できるなら、指定フォルダのCSVを読み込む処理を足す |
| 品目の区分・取引先の情報 | 同じスプレッドシート内の表 | Apps Script で読む |
| 営業メモ | 営業メモのシート | 抽出した先の取引先コードで絞って読む |
| 事情の分類と下書き | Gemini API | UrlFetchApp で呼び出し、JSONで受け取る |
販売管理システムからの取り込みは、最初は手作業で構いません。 週に1回CSVを貼る作業は数分です。自動化するのは、計算の結果が営業に使われると確かめてからです。
Gemini API の呼び出しは、UrlFetchApp.fetch に送信先、method: 'post'、contentType: 'application/json'、APIキーを入れたヘッダー、本文を渡します。APIキーはスクリプトの本文に書かず、スクリプトの設定側に置きます。
AIへ渡す前に整形する
ここがこの記事の中心です。計算はすべて Apps Script で行い、AIには渡しません。
| 記号 | 意味 | 計算のしかた |
|---|---|---|
| n | 注文回数 | 取引先×品目ごとの、直近2年の注文の数 |
| 間隔 | 注文と注文のあいだの日数 | 受注日を古い順に並べ、隣どうしの差を取る |
| M | 間隔の中央値 | 間隔を並べた真ん中の値 |
| S | 間隔のばらつき | 各間隔と M の差の絶対値を並べた真ん中の値 |
| W | 許容幅 | S × 2 と 7日 の大きいほう |
| 補正 | 前回の数量による調整 | 前回数量を数量の中央値で割った値。0.5〜2.0の範囲に収める |
| E | 次回見込み日 | 前回注文日 + M × 補正 |
| L | 遅れ日数 | 基準日 - E |
抽出の条件は「L が W を超えている」ことです。 平均ではなく中央値を使うのは、1回だけの長い空白(年末年始の休業など)に引きずられないためです。ばらつきにも同じ理由で中央値からの差を使います。W の下限を7日にしているのは、毎回きっちり同じ間隔で注文する先で S が0になり、1日の遅れで候補に出てしまうのを防ぐためです。
数量の補正は、まとめ買いへの対策です。 前回いつもの2倍を買った先は、次の注文もいつもより遅くなるのが普通です。補正を掛けずに計算すると、まとめ買いをしてくれた上客ほど「遅れ」として出てきます。
振り分けは次の順で行います。
- フォロー停止中の取引先 … 取引先の表に停止理由がある先は、計算せずに除きます
- 注文回数が3回未満 … 間隔が1つしか取れず、ばらつきを出せません。候補にはせず、「履歴不足」として件数だけ数えます
- 季節品目 … 品目の表で季節品目とした品目は、M と W による判定を使いません。前年の同じ月の前後1か月に注文があり、今年の同じ期間に無いときだけ候補にします
- 切り替えの兆し … 直近3回の数量がいずれも数量の中央値の半分以下で、L が W を超えている先は、「減少」として別の区分にします
- 長期停止 … L が M の3倍を超えている先も、「長期停止」として別の区分にします
- 残りのうち L が W を超えた先 … 「遅れ」として候補にします
4番目と5番目を「遅れ」と分けるのは、声のかけ方が違うからです。 数か月注文が無い先や、少しずつ量を減らしている先に「そろそろ在庫はいかがですか」と送ると、事情を分かっていない会社だと受け取られます。この2つの区分は下書きを作らず、担当者の判断に回します。
1社で複数の品目が候補になったときは、取引先ごとに1行にまとめます。 同じ週に同じ先へ品目ごとの連絡が3通届くのを防ぎます。
中央値と判定の部分は、次のように書けます。
function median(values) {
const a = values.slice().sort((p, q) => p - q);
const mid = Math.floor(a.length / 2);
return a.length % 2 ? a[mid] : (a[mid - 1] + a[mid]) / 2;
}
// dates: 同じ取引先・同じ品目の受注日(Date)を古い順に並べたもの
function judge(dates, baseDate, correctedIntervalDays) {
if (dates.length < 3) return { status: 'insufficient_history' };
const day = 86400000;
const gaps = [];
for (let i = 1; i < dates.length; i++) {
gaps.push(Math.round((dates[i] - dates[i - 1]) / day));
}
const m = median(gaps);
const s = median(gaps.map(g => Math.abs(g - m)));
const w = Math.max(s + s, 7);
// correctedIntervalDays は M に数量の補正を掛けた日数(別の関数で計算)
const expected = new Date(dates[dates.length - 1].getTime());
expected.setDate(expected.getDate() + Math.round(correctedIntervalDays));
const lateDays = Math.round((baseDate - expected) / day);
return { median_interval: m, spread: s, tolerance: w,
expected_date: expected, late_days: lateDays,
is_late: lateDays > w };
} AIに処理させる
Gemini API に渡すのは、候補になった先の計算結果と、直近90日の営業メモだけです。 受注履歴そのものは渡しません。
| させること | 中身 |
|---|---|
| 事情の分類 | 営業メモから、遅れの理由になりうる事情を決めた語から選ぶ |
| 根拠の抜き出し | 分類の根拠にしたメモの文を、そのまま写す |
| 連絡文の下書き | 「遅れ」区分の先について、事情に合わせたメールの下書きを作る |
事情の分類は、在庫過多(まとめ買いした、在庫が余っている)、担当者交代、他社検討(相見積もり、他社の名前が出ている)、休業・改装、需要減(店舗の閉鎖、生産の縮小)、不満あり(納期・品質の苦情)、記載なし の7つです。
| させないこと | 理由 |
|---|---|
| 次回見込み日や遅れ日数の計算・修正 | 計算の結果をそのまま使う。AIが日付を書き換えると、なぜ候補になったかを説明できない |
| 連絡するかどうかの判断 | 取引先との関係を知っているのは担当者 |
| 値引きや特別条件の提案 | 価格は営業の権限で決める |
| メモに無い事情の推測 | 「たぶん在庫がある」と書かせない。無ければ 記載なし |
減少・長期停止 区分の下書き | 担当者が事情を確かめてから連絡する |
他社検討 と 不満あり が出た先も、下書きは作りますが担当者に先に知らせます。 定型の文面で済ませてよい先ではありません。
指示内容を固定する
system_instruction に次を置きます。
あなたは業務用消耗品の商社で、既存取引先へのフォローを手伝う内勤営業です。
渡された「計算結果」と「営業メモ」だけを使ってください。
【してほしいこと】
1. 営業メモから、注文が遅れている理由になりうる事情を、次の7つから1つ選ぶ。
在庫過多/担当者交代/他社検討/休業・改装/需要減/不満あり/記載なし
2. 選んだ根拠となるメモの文を、一字一句そのまま evidence に写す。
3. category が「遅れ」の先について、取引先の担当者あてのメール下書きを作る。
【厳守事項】
- 次回見込み日、遅れ日数、品目名は、計算結果の値をそのまま使う。
書き換えたり、別の日付を計算したりしない。
- メモに書かれていない事情を推測しない。当てはまる記載が無ければ「記載なし」とし、
evidence は空にする。
- 事情が2つ以上あるときは、日付の新しいメモのほうを選ぶ。
- 下書きでは、注文が遅れていることを責める書き方をしない。
「前回のご注文から○週ほど経ちましたので、在庫のご状況を伺えればと思います」の調子にする。
- 値引き、特別価格、納期の約束を書かない。
- 他社の名前がメモにあっても、下書きには書かない。
- 在庫過多のときは、次の注文を促さず、状況の確認だけにとどめる。
- 担当者交代のときは、新しいご担当者へのあいさつを先に書く。
- category が「減少」または「長期停止」のときは、draft を空にする。
- 下書きは本文だけ。署名は付けない。300字以内。
本文には、取引先ごとに次を入れます。
【取引先】{customer_name}(担当:{contact_name})
【計算結果】category: {category} / 品目: {items} / 前回注文日: {last_date}
次回見込み日: {expected_date} / 遅れ日数: {late_days}
【営業メモ(直近90日、新しい順)】{memos}
「計算結果の値をそのまま使う」を最初に書くのは、下書きの中で日付が変わるのを防ぐためです。 何も言わないと、メモの日付と見込み日を混ぜて「3週間ほど」を「1か月ほど」に言い換えることがあります。
「在庫過多のときは注文を促さない」を明記するのは、下書きの失敗がいちばん目立つ型だからです。 在庫を持ちすぎたと言った先に注文を勧めると、メモを読んでいないことが相手に伝わります。
出力形式を固定する
構造化出力で、次のスキーマを渡します。 送信先は https://generativelanguage.googleapis.com/v1beta/interactions、ヘッダーは x-goog-api-key、本文の response_format に mime_type: "application/json" とスキーマを入れます。
{
"type": "object",
"properties": {
"customer_code": { "type": "string" },
"reason": {
"type": "string",
"enum": ["在庫過多", "担当者交代", "他社検討", "休業・改装", "需要減", "不満あり", "記載なし"]
},
"evidence": { "type": "string" },
"evidence_date": { "type": "string", "format": "date" },
"expected_date": { "type": "string", "format": "date" },
"late_days": { "type": "integer" },
"draft": { "type": "string" },
"notify_first": { "type": "boolean" }
},
"required": ["customer_code", "reason", "evidence", "expected_date", "late_days", "draft", "notify_first"]
}
JSONにする1つ目の理由は、reason を決めた語に固定できることです。 enum で7つに絞るので、「在庫がだぶついている」のような言い換えが入らず、事情ごとの件数を毎週数えられます。
2つ目は、戻ってきた値を検査できることです。 構文として正しいJSONが返っても値の正しさは保証されないので、Apps Script で次を確かめます。
| 検査 | 合わないとき |
|---|---|
expected_date と late_days が計算結果と同じか | 下書きを捨て、要確認 にする |
evidence がメモの本文にそのまま含まれるか | reason を 記載なし に戻し、要確認 にする |
reason が 記載なし なのに evidence が入っていないか | evidence を空にする |
区分が 減少・長期停止 なのに draft が入っていないか | draft を空にする |
2行目が効きます。 根拠の文がメモに無ければ、それはAIが作った事情です。文字列の一致で機械的に見分けられるので、人が読む前に落とせます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 受注履歴シート | Apps Script で読む | 取引先×品目ごとの受注日と数量 |
| 品目・取引先の表 | Apps Script で読む | 季節品目、フォロー停止の理由 |
| 営業メモのシート | Apps Script で読む | 候補の先の直近90日分だけ |
| Gemini API | UrlFetchApp | 事情の分類と下書きをJSONで受け取る |
| フォロー候補シート | Apps Script で書く | 1社1行。区分、見込み日、遅れ日数、事情、根拠、下書き、担当者 |
フォロー候補シートは、担当者の列で絞って見られるようにします。 1行ごとに「連絡した/見送った/次回に回す」の選択欄と、結果を書く欄を置きます。
Gmail への送信は、この構成に入れません。 下書きを候補シートからコピーして、担当者がふだんのGmailから送ります。送信まで自動にすると、在庫過多の先に注文を促す1通が、止める人のいないまま出ていきます。
人が確認する
人が見るのは、候補シートに出た先だけです。 300社を毎月見る作業は、計算が肩代わりします。
notify_firstが付いた先を先に見る …他社検討と不満あり。メールより電話か訪問がよいかを先に決めます減少・長期停止の先を見る … 下書きはありません。取引の状況を知っている担当者が、連絡するかを決めます遅れの先の下書きを直して送る … 事情と根拠の文を読み、下書きがそれに合っているかを確かめます- 結果を記録する … 「在庫があった」「他社に替えていた」「注文をもらえた」を選択欄で残します
4番目を省かないでください。 「在庫があった」が多い先は、数量の補正が足りていないか、間隔の中央値が実態より短く出ています。記録が無いと、計算の規則を直す材料がありません。
例外に対処する
| 起きること | 対応 |
|---|---|
| 注文回数が3回未満 | 候補にしない。「履歴不足」として件数だけ数え、月1回担当者に一覧を渡す |
| 季節で波のある品目 | 品目の表で季節品目にしたものは、前年同期との比較で判定する |
| 他社へ切り替えた兆し(数量の減少、長期停止) | 下書きを作らず、担当者に回す |
| 受注履歴が今週分に貼り替わっていない | 計算をせずに担当者へ知らせて終わる |
| 取引先コードが営業メモと合わない | 事情は 記載なし として扱い、候補シートに「メモ未照合」と印を付ける |
| 1回の実行が6分に近づく | 処理した行に印を付けて止め、次のトリガーで続きから |
| Gemini API が失敗の応答を返す | muteHttpExceptions で応答コードを見て、その行を未処理のまま残す。3回続けば担当者に知らせる |
| 返ったJSONの値が検査に通らない | 下書きを捨て、要確認 として計算結果だけを候補シートに出す |
| 長期休業・年末年始 | 取引先の表の停止理由と、基準日から除く期間の表で除く |
上の3行が、計算の規則だけでは決めきれない部分です。 どれも「遅れ」として一律に扱うと、連絡してはいけない先に定型の文面が届きます。区分を分け、人に回す先をはっきりさせておくことが、この構成の例外処理の中心です。
記録を残す
- 実行日時と、使った受注履歴のCSVの出力日
- 取引先×品目ごとの n、M、S、W、補正、E、L と、振り分けた区分
- Gemini API に渡した本文と、返ったJSONの全文
- 値の検査の結果(通った/
要確認にした理由) - 担当者の対応(連絡した/見送った/次回に回す)と、連絡の結果
2つ目を毎週残すのは、後から「なぜこの先が候補になったのか」を説明するためです。 候補から漏れた先で注文が止まったときも、その週の計算の値を見れば、W が広すぎたのか、履歴不足で外れたのかが分かります。
04実装レベルの3段階
本記事の想定は半自動化です。 CSVを週1回貼る数分の手作業は残りますが、1件6分の作業のうち、履歴を追う・遅れを判断する・メモを読む・文面を書くの大部分が置き換わります。 本格構成は、半自動化で2〜3か月の連絡結果がたまってから進めてください。 「在庫があった」の記録が無いうちに許容幅を自動で調整すると、何を根拠に広げたのか分からなくなります。販売管理システムの出力の仕組みも、会社ごとに違います。
05工数削減シミュレーション
導入後 300件 × 1.5分 ÷ 60 = 7.5 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 包装資材・清掃用品・事務用品・飲食店向け食材など、同じ取引先が同じ品目を周期的に注文してくる商社や小売の法人営業。受注履歴を販売管理システムからCSVで出せ、Googleスプレッドシートで扱える場合。取引先が数百社以上あり、営業が「そろそろ注文が来るはず」の先を記憶に頼って追っている場合。
- 注文が案件ごとの一品物で、同じ品目の繰り返しがほとんど無い場合。取引先が数十社で、営業が全社の注文の波を把握できている場合。定期便・自動補充の契約で注文の時期がすでに決まっている場合。なお、取引を続けるか、値引きで引き留めるかといった判断は、この構成では代替できません。
07最小構成で試す方法
- 受注履歴から、過去1年に3回以上注文のある取引先を20社選ぶ(うち数社は、実際に注文が止まった先を入れる)
- スプレッドシートで取引先×品目ごとに受注日を並べ、隣どうしの差を関数で出す
- 間隔の中央値と、中央値との差の中央値を関数で出し、第7章の表のとおりに見込み日と遅れ日数を計算する
- 遅れが許容幅を超えた先について、営業メモを手元の Gemini の画面に貼り、「この営業メモから、注文が遅れている理由を7つの分類から選び、根拠の文をそのまま写してください。書かれていなければ記載なしとしてください」と指示する
- 候補になった先と、担当者の記憶で「気になっていた先」を突き合わせる
AIを使う前に、計算だけで候補が妥当かを確かめてください。 この構成の価値の大半は計算の側にあります。
| 出てきた内容 | 判断 |
|---|---|
| 実際に止まった先が候補に出た | Apps Script で自動化に進む |
| まとめ買いの先ばかりが出た | 数量の補正を入れる。構成は有効 |
| 季節品目の先が毎回出る | 品目の表に季節品目の列を作るのが先 |
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 次回見込み日をAIに出させてしまう | 計算は Apps Script で行う。 AIには計算結果を渡すだけにする |
| まとめ買いした上客が「遅れ」に出る | 前回数量による補正を入れ、0.5〜2.0に収める |
| 毎回きっちり注文する先が1日の遅れで出る | 許容幅に7日の下限を置く |
| 年末年始の空白で中央値が伸びる | 平均でなく中央値を使い、除く期間の表を持つ |
| 季節品目が毎年同じ時期に候補に出る | 品目の表で季節品目を分け、前年同期と比べる |
| 受注番号単位のCSVで品目ごとに計算できない | 品目で行を分けて出力できるか、先に確かめる |
| 実行が6分で途中で止まる | 計算と呼び出しのトリガーを分け、処理した行に印を付けて続きから |
| トリガーが担当者の異動で止まる | 作成者のアカウントで動く。 部署で管理するアカウントで作る |
| 下書きの日付や期間がずれる | 計算結果と照合し、合わなければ下書きを捨てる |
| メモに無い事情が書かれる | 根拠の文がメモに含まれるかを文字列で照合する |
| 在庫過多の先に注文を促す文面が出る | 指示で禁じ、事情ごとの書き方を決めておく |
| 同じ先へ品目ごとに何通も届く | 取引先ごとに1行にまとめる |
上の3行は、AIではなく計算の問題です。 候補の選び方が営業の感覚とずれると、下書きがよくても一覧が見られなくなります。最小構成で20社を試す段階で、ここを先に合わせてください。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 取引先の名称と担当者名、品目ごとの注文の時期と数量、そして営業メモに書かれた取引先の内部事情(担当者の異動、店舗の閉鎖、他社との比較)です。
- 外部へ渡すのは候補の先の直近90日のメモだけ … 受注履歴や取引先の一覧は Gemini API に渡しません。計算はスプレッドシートの中で終わらせます
- 営業メモの個人に関する記述に気をつける … 「担当の○○さんが体調を崩して」のような記述は、下書きの材料にしません。メモの書き方のルールを、あわせて営業部で決めてください
- 連絡するかどうかは人が決める … 送信は担当者が行います。他社検討や不満ありの先に定型の文面が届くと、取引そのものに響きます
- 価格の話を下書きに入れない … 値引きや特別条件は営業の権限です。AIが書いた条件が取引先に届くと、約束として受け取られます
- APIキーと実行アカウントを部署で管理する … キーはスクリプトの本文に書かず、トリガーは部署で管理するアカウントで作ります
- 利用する契約の条件を確かめる … 外部のAIへ取引先の情報を送るため、入力したデータの扱いが自社の取り決めに合う契約・設定かを、情報システム担当と確かめてから本番のデータを流します
誤りが起きた場合のリスクは、連絡すべき先を見落とすことと、連絡すべきでない先に定型の文面を送ることの2つです。 前者は許容幅と振り分けの規則で、後者は区分ごとの下書きの扱いと人の確認で防ぎます。
10まず何から始めるか
1週目:受注履歴の形を確かめる
販売管理システムから直近2年の受注履歴をCSVで出し、品目ごとに1行になっているか、取引先コードが営業メモと同じかを確かめます。あわせて、主な品目に季節品目の印を付けます。
2週目:20社で計算だけを試す
第8章の手順で20社の見込み日と遅れ日数を出し、担当者の記憶と突き合わせます。まとめ買いと季節品目で外れた先を数え、補正と振り分けの規則を決めます。
3週目:Apps Script で計算を自動にする
第7章の計算を Apps Script に移し、時間主導型トリガーで毎週の候補シートを出します。この時点ではAIを呼ばず、候補の一覧だけを1週間使ってもらいます。
4週目以降: Gemini API での事情の分類と下書きを足し、連絡の結果を記録します。「在庫があった」の件数を毎週見て、許容幅の規則を直していった時点で、この構成は運用に乗ります。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
| 時間主導型トリガーの間隔(毎分〜特定日時)、時刻が1時間の範囲でずらされ日ごとに保たれること、作成者のアカウントで動くこと、失敗時に通知メールが届くこと | Google for Developers: Installable Triggers | 2026-09-28 |
UrlFetchApp の fetch/fetchAll、method・contentType・headers・payload、muteHttpExceptions が true なら失敗時も応答を返すこと | Google for Developers: Class UrlFetchApp | 2026-09-28 |
| 1回の実行6分、トリガーの合計実行時間(一般90分/Workspace 6時間)、トリガー20個、URL Fetch 1日20,000回/100,000回、予告なく変わりうること | Google for Developers: Quotas for Google Services | 2026-09-28 |
response_format に mime_type とスキーマを渡すこと、enum・required・format が使えること、分類と抽出が用途に挙がること、値はアプリ側で検査すべきこと | Google AI for Developers: Structured outputs | 2026-09-28 |
interactions の送信先、x-goog-api-key ヘッダー、system_instruction、generation_config | Google AI for Developers: Text generation | 2026-09-28 |
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-0263)についてのご相談はこちらから。
