予約の状況を、人が見に行くのをやめました。GASとLINE公式アカウント(Messaging API)で、毎日10時半に翌日の予約一覧が関係者のLINEへ自動で届くようにしたからです。生産計画は、届いた通知を元にそのまま立てられます。
さらに、HP予約の受付メールと予約DB(スプレッドシート)をGASで毎日照合し、登録漏れがあったときだけ警告が飛ぶ「見張り」も作りました。この記事では、その考え方とそのまま動かせるサンプルコードを公開します。
通知を作る前は、生産計画のたびに「見に行く」作業をしていた
私は人口5万人未満の地方都市で弁当・惣菜店を2店舗やっています。注文はGASで1枚のスプレッドシートに集約し、5つある予約経路も1か所の予約DBに集約しました。データは1か所に揃っています。
それでも、残っていた作業があります。生産計画を立てるたびに、翌日・翌々日の状況はどうなっているかを、カレンダーと予約DBへ自分から確認しに行くことです。
データが1か所にあるのは大きな前進でした。でも「人が見に行く」構造のままだと、見に行くという手間と、見忘れるというリスクが残ります。次にやるべきことは明確でした。人が見に行くのではなく、データの方から人に届くようにする。それがこの記事の仕組みです。
設計の考え方:「見に行く」を「向こうから届く」に変える
作ったのは、通知専用のLINE公式アカウントを軸にした3つの動きです。お客さま向けの公式LINE(この記事)とは別に、関係者だけが友だち追加した通知専用アカウントをもうひとつ用意しています。
| 動き | タイミング | 内容 |
|---|---|---|
| 予約一覧の通知 | 毎日10時半(自動) | 翌日の予約全件をLINEへpush配信 |
| 登録漏れの見張り | 毎日(自動) | Gmailの受付メールと予約DBを照合し、漏れがあれば警告 |
| リッチメニュー | 欲しいとき(手動) | タップすれば予約状況などを自分のタイミングで取得 |
基本は「向こうから届く」push型ですが、通知を待たずに知りたい場面もあるので、リッチメニューをタップすればある程度の情報を取りに行けるようにもしてあります。push(受け取る)とpull(取りに行く)の両方を用意しておくと、運用が窮屈になりません。
仕組み①:毎日10時半、翌日の予約一覧がLINEに届く
GASの時間主導型トリガーで、毎日10時半に関数を実行します。予約DBから受取日が「明日」の予約を抜き出し、1通のメッセージに整形して、LINE公式アカウントのMessaging APIでpush配信する——それだけの仕組みです。
// 毎日10時半に実行:翌日の予約一覧をLINEへ通知する
function sendTomorrowReservations() {
const ss = SpreadsheetApp.openById(SS_ID);
const rows = ss.getSheetByName(SHEET_RESERVE).getDataRange().getValues().slice(1); // 見出し除く
const tz = Session.getScriptTimeZone();
const target = Utilities.formatDate(new Date(Date.now() + 86400000), tz, 'yyyy-MM-dd');
// 受取日が「明日」の予約だけ抜き出す
const list = rows.filter(function (r) {
return Utilities.formatDate(new Date(r[1]), tz, 'yyyy-MM-dd') === target;
});
// 通知メッセージを組み立てる(情報は削らず全部載せる)
let text = '【明日の予約】' + target + '(' + list.length + '件)\n';
if (list.length === 0) {
text += '予約はありません';
} else {
list.forEach(function (r) {
// 列の並び:[受付日時, 受取日, 受取時間, 商品, 数量, 名前, 経路, 備考]
text += '\n' + r[2] + ' ' + r[5] + '様\n'
+ ' ' + r[3] + ' × ' + r[4] + '\n'
+ ' 経路:' + r[6] + (r[7] ? '/備考:' + r[7] : '');
});
}
pushToLine_(text);
}
// LINE公式アカウント(Messaging API)へ配信する共通関数
function pushToLine_(text) {
const token = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
UrlFetchApp.fetch('https://api.line.me/v2/bot/message/broadcast', {
method: 'post',
contentType: 'application/json',
headers: { Authorization: 'Bearer ' + token },
payload: JSON.stringify({ messages: [{ type: 'text', text: text }] })
});
}
実際に動かしているコードから、店固有の処理を除いて簡略化したサンプルです。SS_ID(スプレッドシートID)とシート名は自分の環境に合わせて定義し、チャネルアクセストークンはスクリプトプロパティ「LINE_TOKEN」に保存してから実行してください。
予約が0件の日も「予約はありません」と送る作りにしています。通知が来ないのか、予約がないのかを受け取る側が区別できるようにするためです。毎日決まった時刻に必ず届くからこそ、「今日は来ていない=仕組みが止まっている」に気づけます。
通知には「全部」載せる——煩雑になるかと思ったら、逆だった
設計時に迷ったのが、通知に載せる情報量です。受取時間・品名・数量・お客さまの名前・予約経路・備考——全部載せると長くなるので、作る前は「煩雑になるかもしれない」と思っていました。
結果は逆でした。全部載せて正解でした。通知の中で一つ一つの予約を確認できるので、結局スプレッドシートを開きに行かずに済みます。情報を絞った通知は一見スマートですが、「詳細はDBを見に行く」が残るなら、見に行く作業をなくすという当初の目的が達成できません。
仕組み②:Gmail照合の「見張り」——きっかけは、記憶の違和感だった
もうひとつの仕組みは、通知の元データそのものを疑う「見張り」です。これを作ったきっかけは、ある日の違和感でした。
「あれ? この日に注文が入っていたような……?」
記憶を頼りに予約DBを確認すると、載っていない。次にメールを確認すると、受付メールはちゃんと届いている。DBにデータが抜けていたのです。HPから予約が入るとGASがスプレッドシートに書き込む仕組みですが、その書き込みが漏れていました。
このときは記憶のおかげで拾えました。でも、記憶は仕組みではありません。「このチェックを毎日、人がやるのか……?」と考えて、無理だと即答できたので、チェックそのものをシステムに落とすことにしました。
// 毎日実行:HP予約の受付メールと予約DBを照合して「登録漏れ」を探す
function auditReservations() {
const ss = SpreadsheetApp.openById(SS_ID);
const rows = ss.getSheetByName(SHEET_RESERVE).getDataRange().getValues().slice(1);
// DB側にある受付番号を控える(HPの受付メールに必ず記載される番号)
const known = {};
rows.forEach(function (r) { known[String(r[8])] = true; });
// 直近3日分の受付メールをGmailから検索する
const threads = GmailApp.search('subject:(ご予約を受け付けました) newer_than:3d');
const missing = [];
threads.forEach(function (th) {
th.getMessages().forEach(function (msg) {
const m = msg.getPlainBody().match(/受付番号[::]\s*([A-Z0-9-]+)/);
if (m && !known[m[1]]) missing.push(m[1]);
});
});
// 漏れが見つかったときだけLINEへ警告する
if (missing.length) {
pushToLine_('【要確認】予約DBに登録が見つからない受付番号があります\n' + missing.join('\n'));
}
}
メールの件名・受付番号の形式は自分の環境に合わせて書き換えてください。「漏れゼロなら何も送らない」作りなので、普段この見張りは沈黙しています。
考え方はシンプルです。HPからの予約は、受付メールと予約DBの2か所に必ず痕跡が残る。だから2つを突き合わせれば、片方の漏れを機械的に検出できる。自動化した仕組みも失敗することがある——だからこそ、自動化の上にもう1枚「自動の見張り」を重ねています。
つまずいた点・注意したこと
- 無料プランの配信上限:LINE公式アカウントの無料プランは月200通までで、「メッセージ数×受信者数」で数えられます。関係者数人に1日1通なら収まりますが、通知の種類や人数を増やすと超えます。設計時に計算しておくべきポイントです。
- トークンの管理:チャネルアクセストークンはコードに直書きせず、GASのスクリプトプロパティに保存します。コードを公開・共有する前提なら特に必須です。
- 「見張りの見張り」問題:照合の仕組み自体が止まったら気づけません。私は「予約0件でも毎日必ず届く通知」を生存確認代わりにしています。決まった時刻に来ないことが、そのまま異常のサインになります。
試験運用中:勤怠の提出とフォローもLINEに寄せている
同じ構成の応用として、勤怠管理のLINE化も試験運用中です。別の公式LINEアカウントで勤怠の提出を受け付け、未提出の人へのフォローを自動化し、月ごとの出勤回数と勤務時間を自分のタイミングでPDFとしてダウンロードできるようにしています。
まだ結論が出ている段階ではないので、運用が固まったら別の記事として書く予定です。「提出を受け取る」「未提出を追いかける」「集計して出力する」——通知と同じ道具立てで、意外なところまで届くというのが現時点の手応えです。
まとめ:データを1か所に集めたら、次は「届く」ようにする
注文と予約を1枚のスプレッドシートに集約した時点で、転記の手間とミスは消えました。今回の仕組みはその次の一歩で、「人がデータを見に行く」構造を「データが人に届く」構造に変えるものです。毎日10時半に翌日の予約一覧が届き、生産計画はそれを元に立てる。予約DBを開きに行く回数はゼロになりました。
そしてもうひとつ。自動化は完璧ではないので、自動化を見張る自動化を重ねました。記憶の違和感で登録漏れに気づいた日、「このチェックを毎日人がやるのは無理だ」と思えたことが、結果的にいちばんの収穫だったと思います。
手を付ける順番としては、まずデータを1か所に集める(注文管理の記事)、次に届くようにする(この記事)、が私のおすすめです。
よくある質問FAQ
GASからLINEに通知を送るには何が必要ですか?
LINE公式アカウント(無料で作成できます)とMessaging APIのチャネルアクセストークン、そして通知を受け取る人にそのアカウントを友だち追加してもらうことの3つです。GAS側はUrlFetchAppでMessaging APIを呼ぶだけなので、コード自体は数十行で済みます。
LINE Notifyでも同じことができますか?
LINE Notifyは2025年3月にサービスを終了しています。これから作るならLINE公式アカウント+Messaging APIの構成をすすめます。私の仕組みもこの構成で、関係者だけが友だち追加した通知専用の公式アカウントに配信しています。
LINE公式アカウントの無料プランで通知は足りますか?
私は足りています。無料プランで送れるのは月200通までで、配信数は「メッセージ数×受信者数」で数えられます。関係者数人に1日1通なら月150通前後に収まる計算です。通知先の人数や通知の種類が増えると超えるので、設計の段階で計算しておくべきポイントです。
通知に載せる情報は絞ったほうがいいですか?
私は全部載せる方を選び、正解だったと思っています。作る前は煩雑になるかと心配でしたが、受取時間・品名・数量・経路・備考まで載っていると通知だけで一つ一つ確認ができ、結局スプレッドシートを開かずに済みます。絞るより「通知だけで完結する」ことを優先しました。
Gmailとの照合はどういう仕組みですか?
HPから予約が入ると店側にも受付メールが届くので、GASでGmailを検索してメール側の受付番号を取り出し、予約DB(スプレッドシート)に同じ番号が存在するかを毎日照合しています。DBに見つからない番号があったときだけ、LINEに警告が飛ぶ仕組みです。