こんにちは。カスタマーサクセス担当です。
前回の記事「在庫管理システムを自作し効率化|AI発注予測をn8nとスプレッドシートで実装」ではn8nと生成AIを用いてスプレッドシートの販売データから発注数を予測し、通知する仕組みを紹介しました。
今回はさらに一歩進め、「在庫数の更新」から「発注数の予測・通知」までを自動化します。これにより、「在庫を確認する→発注数を考える」という日々の作業を自動化する在庫管理システムを作成しました。
本記事は続編にあたるため、まずは前回の記事ご覧いただきますと理解がスムーズです。
【目次】
在庫管理システムの一連の流れ
前回の発注数予測のワークフローは大きく以下の流れでした。
- スプレッドシートから商品マスタ、直近30日間と直近7日間の販売履歴から平均販売数のデータの取得
- 生成AIによる需要量と発注数の予測
- 発注が必要な商品に対し、Slackに通知を行う
今回はこのワークフローの前に、在庫数を更新するワークフローを追加します。
在庫数の更新を自動化するワークフローの流れは以下の通りです。
- スプレッドシートから商品マスタ、販売履歴、発注履歴のデータを集計する
- 商品ごとに現在庫数、前日の販売数、本日の入荷数を整理する
- 在庫数を計算し、現在庫数を自動更新する
そして、自動更新を行った後、n8nにある「サブワークフロー」を用いて発注数予測のワークフローを実行します。その際、未入荷分の商品も考慮し、より適切な発注数の予測を行います。
最終的な一連のワークフローの全体像は以下になります。

- 発注数の予測

スプレッドシートのデータ構成
前回使用した「products」「sales_history」「purchase_recommendations」のシートに加えて、新たに以下のシートを使用します。
新たなシートのデータ構成は以下の通りです。
order_history(発注履歴)
列名 | 内容 |
order_id | 発注ID |
order_date | 発注日 |
product_id | 商品ID |
product_name | 商品名 |
quantity | 発注量 |
lead_time_days | リードタイム (発注から入荷までの日数) |
arrival_date | 入荷日 |
その他のシートの構成は前回の記事をご参照ください。
在庫管理システムの各手順の詳細
在庫数を自動更新するワークフロー
在庫数の自動更新を行うワークフローの全体像は以下の通りです。

各手順について解説します。重複する設定に関しましては、前回の記事で詳しく解説していますので、割愛いたします。
データの集計と整理

ここでは、商品マスタに加え、販売履歴と発注履歴のデータを取得します。その後、販売履歴に関しては前日のデータ、発注履歴に関しては入荷日が当日のデータのみ抽出し、各商品ごとに総数を計算して整理を行います。
- 「Schedule Trigger」:指定した時刻をトリガーにワークフローを開始します。
- 「Get row(s) in sheet」:それぞれ商品マスタ、販売履歴、発注履歴のデータを取得します。
- 「Filter」:販売履歴は前日、発注履歴は当日のデータのみを以下の条件で抽出します。
条件設定
販売履歴:{{ $json.date }} is equal to {{ $now.minus({days:1}).toFormat('yyyy-MM-dd') }}
発注履歴:{{ $json.arrival_date }} is equal to {{ $now.toFormat('yyyy-MM-dd') }}
- 「Summarize_sum」:販売履歴と発注履歴それぞれproduct_idごとに合計を計算します。
- 「Edit_Fields」:product_id以外のキー名も統一されてしまっているため、重複を避けるためにproduct_id以外のキー名を変更します。
設定例:
取得元 | 名前 | 形式 | 値 |
両方 | product_id | String | {{ $json.product_id }} |
sales_history | quantity_sales | Number | {{ $json.sum_quantity }} |
order_history | quantity_order | Number | {{ $json.sum_quantity }} |
データの結合と在庫数の更新

それぞれ整理したデータを商品IDを基準に「Merge」ノードを用いて結合します。その後、スプレッドシートの商品マスタにある現在庫数を更新します。
- 「Merge」:product_id をキーに販売履歴と発注履歴、それらと商品マスタの順にデータを結合します。
- 「Update row in sheet」:商品マスタのシートの現在庫数を商品IDを基準に更新します。販売履歴や発注履歴は商品によって存在しない場合があるため、「?? 0」を加えることでエラー回避を行います。
設定例:
項目 | 設定値 | 値 |
Mapping Column Mode | Map Each Column Manually | ー |
Column to match on | product_id | ー |
Values to Update | product_id | {{ $json.product_id }} |
Values to Update | current_stock | {{ $json.current_stock + ($json.quantity_order ?? 0) - ($json.quantity_sales ?? 0)}} |
サブワークフローを用いたワークフローの連携
在庫数の自動更新と生成AIによる発注数の予測について、ワークフローをそれぞれ作成することができました。しかし、現時点ではそれぞれ独立して動いています。この場合、在庫数が更新される前に発注数の予測が始まってしまうケースなどが発生し、本来行いたい「在庫数が更新されたのをもとに必要な発注数を予測してほしい」という目的が達成できません。また、この2つのワークフローを一つのワークフローとしてつなげようとすると、複雑になりすぎてしまいどこで何の処理を行っているのか分からなくなってしまいます。
そこで、n8nにある「サブワークフロー」を用い、2つのワークフローを連携させることで今までのワークフローの形式をある程度保ったまま「在庫数の更新→発注数の予測」といった一連の流れを実行することができます。
サブワークフローでは「Execute Sub-Workflow」ノードと「Execute Sub-Workflow Trigger」ノードの2つのノードを組み合わせて、ワークフロー同士を接続します。
ワークフローの接続方法
在庫数の自動更新を行うワークフローの最後に、「Execute Sub-Workflow」ノードを配置します。

このノードで呼び出すワークフローを指定すると、実行時にそのワークフローへ処理を引き継ぐことができます。ワークフローの指定はリスト、もしくはIDを用いて発注数を予測するワークフローを指定します。IDはURLの「/workflow/」の後に含まれています。(/workflow/abc1De2fG34hの場合、IDはabc1De2fG34h)このノードの出力はサブワークフローにおいて最後に実行されたノードの出力を返します。
呼び出される側である発注数予測のワークフローには、「Schedule Trigger」ノードから新たなトリガーとして「Execute Sub-Workflow Trigger」にあたる「When Executed by Another Workflow」ノードに置き換えます。

これにより発注数予測のワークフローは単体では実行されず、在庫数の更新が完了した後にのみ実行されます。
データの受け渡し方法
「When Executed by Another Workflow」では受け取るデータの形式を選ぶことができます。今回は「Define using fields below」を使用し、商品マスタを参考に以下のデータ名と形式を定義しました。
設定例:
名前 | 形式 |
|---|---|
product_id | String |
product_name | String |
current_stock | Number |
safety_stock | Number |
lead_time_days | Number |
supplier | String |
「Execute Sub-Workflow」では呼び出すワークフローに対してどのデータを渡すか設定できます。先ほど定義したデータに以下のように必要なデータを渡しています。
設定例:
名前 | 値 |
|---|---|
product_id | {{ $json.product_id }} |
product_name | {{ $('Merge|products+quantity').item.json.product_name }} |
current_stock | {{ $json.current_stock }} |
safety_stock | {{ $('Merge|products+quantity').item.json.safety_stock }} |
lead_time_days | {{ $('Merge|products+quantity').item.json.lead_time_days }} |
supplier | {{ $('Merge|products+quantity').item.json.supplier }} |
サブワークフローの実行モード
サブワークフローの実行には以下の2つのモードがあります。
「Run once with all items」:すべての入力アイテムをまとめ、ワークフローを1回のみ実行します。
「Run once for each item」:入力アイテムの数だけ、ワークフローを1回ずつ実行します。
今回の発注数予測は1回の実行ですべての商品を予測しているため、「Run once with all items」を選択し発注数予測のワークフローは1回のみ実行します。
ただし、1回の実行はあくまでもワークフローの起動回数であり、ワークフロー内の各ノードは渡されたアイテム数だけ処理を繰り返すことに注意してください。特に、今回はスプレッドシートからデータを取得する際にすべてのデータを1回で取得しています。何も設定をしなければ商品数の数だけすべてのデータを取得してしまい、過剰なデータを取得してしまうだけでなく後続の処理に影響が発生してしまいます。
そこで、発注数予測のワークフローにおいて、スプレッドシートからデータを取得する際は以下の画像のように「Execute Once」のトグルをONにすることで複数アイテムが入力にきてもノードの実行回数は最初の1回のみとなります。

生成AIを用いた発注数予測フローの変更点
前回記事のワークフローにおいて、サブワークフローによる連携に伴い、一部変更を行いました。ここからさらに在庫数の更新、および実行時点で未入荷分の数量を考慮した発注数の予測を行うため以下の変更を行います。
商品マスタの取得の削除と翌日以降に入荷予定のデータ整理を追加

サブワークフローのトリガーで商品マスタをもとにデータを既に受け取っているため商品マスタを取得するノードは不要となります。また、販売履歴だけでなく、赤丸で囲まれている発注履歴から未入荷の分だけ抽出・整理を加えることで、未入荷分の数量を発注数の予測に含めることができます。詳細は以下の通りです。
- 「Get row(s) in sheet|order_history」:発注履歴のシートからデータを取得します。このノードも「Execute Once」のトグルをONにし複数回の実行を避けるようにします。
- 「Filter|arrival_date」:以下の条件から入荷日が翌日以降の商品のみ抽出します。
条件設定:{{ $json.arrival_date }} is after {{ $now.toFormat('yyyy-MM-dd') }}
- 「Summarize|quantity and arrival_date」:product_idごとに数量の合計と一番早い入荷日を整理します。これらは生成AIの発注数の予測の際に使用します。
設定例:
Aggregation | Field |
|---|---|
Sum | quantity |
Min | arrival_date |
- 「Edit Fields|order」:商品ID以外のキー名が他と重複しないようデータを整理します。
設定例:
名前 | 形式 | 値 |
|---|---|---|
product_id | String | {{ $json.product_id }} |
incoming_quantity | Number | {{ $json.sum_quantity }} |
arrival_date | String | {{ $json.min_arrival_date }} |
- 「Merge|+ order」:他のMergeノードと同様にproduct_id をキーに平均販売数と商品マスタに未入荷分の情報を結合します。
生成AIのプロンプトに未入荷分を考慮する
プロンプト内に未入荷分を考慮するため、入力データとして以下を追加します。
翌日以降入荷予定数の合計(発注済み未入荷分): {{ $json.incoming_quantity ?? 0 }}
最速入荷日:{{ $json.arrival_date ?? "入荷予定なし" }}
また、入荷予定を考慮する際の方針として以下の方針を明示しています。
- 翌日以降の入荷予定数は、現在発注済みで今後入荷予定の合計量であり、将来の供給として確保される
- 推奨発注数を考える際は、既存の入荷予定を無視せず、リードタイム期間に入荷する予定数量を、将来の供給として考慮すること
- 今回の推奨発注数を決める際、リードタイム期間より後は考慮しないこと
- 予測需要数をもとに現在庫数が最速入荷日まで持つか確認すること
- 現在庫数が最速入荷日まで持つ場合は、最速入荷日までに入荷する予定数量も含め、リードタイム期間中の需要数と安全在庫数から必要な発注数を推測すること
- 既存の入荷予定数と現在庫数によって将来の需要数と安全在庫数を十分に確保できると判断する場合は推奨発注数を0としてよい
- 現在庫数が最速入荷日まで持たない場合、リードタイム期間に想定される需要数、現在庫数、最速入荷日以降に発生する既存の入荷予定数、安全在庫数を考慮し最低限必要な発注数を算出すること。しかしこれはあくまでも最低限であり、販売増加の傾向や予測需要数が大きい場合など在庫数の確保をさらにした方がよい場合は適切な数を上乗せをすること
ここでは予測需要数から最速入荷日より前に現在庫数が尽きてしまうのか判断し、尽きない場合は今後入荷予定の数量も考慮に加えて発注数を予測すること、もし尽きてしまう場合は、予測需要数と安全在庫数から考えられる必要数と、現在庫数や入荷予定数などの供給数を考慮しながら最低限の必要数を算出しつつ、販売傾向や予測需要数をもとに発注数を予測するようにしています。
なお、今回使用したプロンプトの全文はこちらからダウンロードいただけます。
実際の使用結果例
在庫数の自動更新と未入荷分を考慮した場合どのような違いが得られたのか確認します。
2026年9月10日に本ワークフローを実行した際に、前日の購入履歴と発注履歴が以下のようにあったとします。
- 購入履歴

- 発注履歴

商品マスタに関しては、前回の記事の例と同じものを使用しています。
ワークフロー実行後、現在庫数に関しては以下のように適切に更新されました。

また、発注数の予測に関して、入荷予定があるP003と、入荷により在庫数が増えさらに入荷予定があるP008を、前回の発注数の予測のみ行った場合と比較した結果が以下の通りです。それぞれ上が在庫更新や未入荷考慮を行っていない結果、下が在庫数の更新と未入荷分を考慮した予測結果です。

この結果を見ると、予測需要数が同じ場合において、P003では現在庫数が減少したにもかかわらず、翌日に20個の入荷が見込まれているため推奨発注数は前回と比較し減少しています。P008では現在庫数が増加し、さらに15個の入荷が見込まれているため推奨発注数が大きく減少していることが確認できました。
ワークフロー使用時の注意点
今回のワークフローでは現在庫数の自動更新と発注数の予測を自動化することができました。一方で以下の点には注意が必要です。
発注後の記録は自動化されない
本ワークフローでは、在庫数の更新と発注数の予測・通知までであり、その予測をもとに発注した後の記録は自動化していません。発注した担当者がその内容をorder_historyへ記録する運用が前提となります。
例外的なケースは考慮していない
以下のようなイレギュラーな状況には対応していません。実運用では別途ルールや処理を追加することを検討してください。
- 発注したものがリードタイム通りの予定日に届かない場合
- 入荷した数量が発注数量と異なる場合
- 返品などで現在庫数が増加する場合
まとめ
本記事では、前日の販売実績と当日の入荷予定をもとに在庫数を自動更新するワークフローを作成し、前回の発注予測ワークフローとサブワークフローとして連携させることで、在庫数の更新から発注数の予測・通知までをつなげた一連の在庫管理システムを自作しました。
これにより、前回の時点で残っていた「在庫数を手動で反映する必要がある」「発注済み・未入荷分が考慮されていない」という2つの課題を解消し、より実運用に近い形で在庫管理を自動化できたのではないでしょうか。
まずは今回のような基本構成から自社の在庫管理に取り入れてみて、運用しながら必要な範囲を広げていってみてください。
出典一覧
n8n Docs「Execute Sub-workflow」 ,https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflow,2026年9月16日閲覧
n8n Docs「Execute Sub-workflow Trigger」,https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.executeworkflowtrigger,2026年9月16日閲覧
