TEXTBOOK SECTION / AI LEARNING

配送管理を作る

Square API × Next.js 実践EC開発|自社ECを低コストで作る、決済・在庫・注文管理の設計と実装の「管理画面を作る」より、配送管理を作るを解説。生成AI、AI活用、DX、業務改善を実践しながら学べるオンライン教材です。

3管理画面を作るEC

OVERVIEW

この節で学べること

概要を表示する
項目内容
教材名Square API × Next.js 実践EC開発|自社ECを低コストで作る、決済・在庫・注文管理の設計と実装
管理画面を作る
配送管理を作る
カテゴリEC
学習内容生成AI、AI活用、DX、業務改善を実践しながら理解するための教材です。

TABLE OF CONTENTS

目次

CONTENT

ここから

第16章では、商品登録、価格変更、在庫変更、公開・非公開など、商品管理機能を整理しました。

この章では、注文された商品を購入者へ届けるための配送管理を作ります。

ECでは、決済が完了しても、まだゴールではありません。

商品を正しく準備し、発送し、購入者へ案内するところまで含めて、ひとつの購入体験です。

注文
  ↓
決済完了
  ↓
配送準備
  ↓
発送
  ↓
購入者へ到着

配送管理が弱いと、次のようなトラブルが起きます。

・発送したかどうか分からない
・追跡番号を送り忘れる
・キャンセル注文を発送してしまう
・店頭受け取りの商品を配送してしまう
・送料の計算がズレる
・配送トラブル時に状況を追えない

攻略本風に言えば、第17章は**「売れた商品を無事に届けるステージ」**です。


17.1 配送ステータスの設計

まず、配送ステータスを設計します。

注文ステータスと配送ステータスは似ていますが、役割が違います。

注文ステータス:
決済や注文全体の状態を表す

配送ステータス:
商品を届ける作業の状態を表す

たとえば、注文ステータスがpaidでも、配送はまだ始まっていないことがあります。

注文ステータス:決済完了
配送ステータス:未発送

そのため、注文ステータスとは別に配送ステータスを持たせると分かりやすくなります。

基本の配送ステータスは、次の通りです。

not_required    配送不要
unshipped       未発送
preparing       配送準備中
shipped         発送済み
delivered       配達完了
cancelled       配送キャンセル
trouble         配送トラブル

日本語ラベルにすると、次のようになります。

not_required    配送不要
unshipped       未発送
preparing       配送準備中
shipped         発送済み
delivered       配達完了
cancelled       配送キャンセル
trouble         配送トラブル

小規模ECで最初に必要なのは、次の4つで十分です。

未発送
配送準備中
発送済み
配送トラブル

配送ステータスの流れは、次のようになります。

unshipped
  ↓
preparing
  ↓
shipped
  ↓
delivered

ただし、すべてのECでdeliveredまで管理する必要はありません。

配送会社の追跡情報と連携しない場合、配達完了を自動で取得できないからです。

最初は、shippedまで管理できれば実務上は十分です。

最小構成:
未発送
配送準備中
発送済み

配送管理では、今どこまで進んでいるかを店舗側がすぐに分かることが重要です。


17.2 未発送・発送済み・キャンセル

配送管理で最初に扱うべき状態は、次の3つです。

未発送
発送済み
キャンセル

この3つを正しく管理できるだけでも、配送ミスはかなり減ります。

それぞれの意味を整理します。

未発送:
まだ商品を送っていない状態

発送済み:
商品を配送会社へ渡した、または発送手続きが完了した状態

キャンセル:
配送しないことが決まった状態

ここで注意したいのは、注文キャンセルと配送キャンセルを分けることです。

注文キャンセル:
注文そのものを取り消す

配送キャンセル:
配送作業を止める

たとえば、決済後に購入者からキャンセル依頼が来た場合、注文ステータスと配送ステータスの両方を確認します。

注文ステータス:paid
配送ステータス:unshipped

この場合:
まだ発送していなければキャンセル対応できる可能性がある

一方で、すでに発送済みの場合は、対応が変わります。

注文ステータス:paid
配送ステータス:shipped

この場合:
配送停止できるか確認が必要
返品・返金ルールに従って対応する

発送済みへの変更は、慎重に行います。

一度発送済みにすると、購入者へ発送完了メールが送られることが多いからです。

発送済みにする
  ↓
追跡番号を保存
  ↓
発送完了メールを送る

管理画面では、発送済みにする前に確認を入れます。

この注文を発送済みにしますか?
追跡番号と配送会社が正しいか確認してください。

キャンセルも同じです。

この注文の配送をキャンセルしますか?
キャンセル理由を入力してください。

配送管理では、ボタンひとつで大きな処理が動きます。

そのため、確認画面と履歴を必ず残す設計にします。


17.3 追跡番号の登録

発送後、購入者が最も知りたい情報のひとつが追跡番号です。

追跡番号があると、購入者は自分で配送状況を確認できます。

発送しました
  ↓
追跡番号はこちらです
  ↓
購入者が配送状況を確認できる

管理画面では、発送済みにする前に追跡番号を登録できるようにします。

必要な項目は、次の通りです。

・配送会社
・追跡番号
・発送日
・追跡URL
・配送メモ

画面イメージです。

配送情報

配送会社:
[ ヤマト運輸 ▼ ]

追跡番号:
[ 1234-5678-9012 ]

発送日:
[ 2026-07-06 ]

配送メモ:
[ 午前中指定 ]

[ 発送済みにする ]

TypeScriptで型を作ると、次のようになります。

type ShippingCarrier =
  | 'yamato'
  | 'sagawa'
  | 'japan_post'
  | 'other';

type RegisterTrackingInput = {
  orderId: string;
  carrier: ShippingCarrier;
  trackingNumber: string;
  shippedAt: string;
  trackingUrl?: string;
};

/**
 * 役割: 注文に配送会社と追跡番号を登録する
 * 入力: 注文ID、配送会社、追跡番号、発送日時、追跡URL
 * 出力: 登録が成功したかどうか
 */
async function registerTrackingNumber(
  input: RegisterTrackingInput
): Promise<boolean> {
  // 実際の実装では、注文が発送可能な状態か確認してから保存する
  // 追跡番号の入力ミスを防ぐため、空文字は保存しない

  return true;
}

追跡番号で注意したいのは、入力ミスです。

1文字でも違うと、購入者が配送状況を確認できません。

そのため、発送済みにする前に確認画面を出します。

配送会社:ヤマト運輸
追跡番号:1234-5678-9012

この内容で発送完了メールを送信しますか?

追跡番号がない配送方法もあります。

たとえば、店頭受け取りや手渡しの場合です。

その場合は、配送ステータスではなく受け取りステータスで管理します。

配送あり:
追跡番号を登録する

店頭受け取り:
受け取り予定日を管理する

催事受け取り:
受け取り会場を管理する

追跡番号は、購入者の不安を減らすための大切な情報です。


17.4 発送完了メール

発送完了メールは、商品を発送したことを購入者へ伝えるメールです。

注文完了メールとは役割が違います。

注文完了メール:
注文を受け付けたことを伝える

発送完了メール:
商品を発送したことを伝える

発送完了メールに入れるべき内容は、次の通りです。

・購入のお礼
・注文番号
・発送したこと
・配送会社
・追跡番号
・追跡URL
・到着目安
・問い合わせ先

テンプレート例です。

件名:
商品を発送しました|注文番号:ORDER-0001

本文:
山田 太郎 様

このたびはご注文いただき、誠にありがとうございます。

ご注文の商品を発送いたしました。
到着まで今しばらくお待ちください。

【配送情報】
注文番号:ORDER-0001
配送会社:ヤマト運輸
追跡番号:1234-5678-9012
追跡URL:https://example.com/tracking

配送状況は、上記の追跡番号よりご確認いただけます。

ご不明な点がございましたら、下記までお問い合わせください。

株式会社〇〇
メール:support@example.com
電話:052-000-0000

発送完了メールは、発送済みにしたタイミングで送ります。

追跡番号を登録
  ↓
発送済みにする
  ↓
発送完了メールを送る

ただし、発送完了メールの送信に失敗しても、配送ステータスはshippedのままです。

メール送信失敗と配送失敗を混同してはいけません。

配送ステータス:発送済み
発送メールステータス:送信失敗

この場合は、管理画面から再送できるようにします。

[発送完了メールを再送する]

発送完了メールも、送信履歴を残します。

2026-07-06 16:10
発送完了メール送信
送信結果:sent

購入者にとって、発送完了メールは安心材料です。

発送したら、できるだけ早く送る設計にしましょう。


17.5 配送料の計算

ECでは、商品代金とは別に配送料が必要になることがあります。

配送料の計算方法を曖昧にすると、決済金額がズレます。

まず、配送料の考え方を整理します。

商品小計
  +
配送料
  ー
割引
  =
合計金額

たとえば、商品が5,400円、送料が800円の場合です。

商品小計:5,400円
送料:800円
合計:6,200円

配送料の計算方法には、いくつかあります。

・全国一律送料
・地域別送料
・購入金額に応じた送料無料
・商品ごとの送料
・配送温度帯ごとの送料
・店頭受け取りは送料無料

最初の小規模ECでは、全国一律送料が一番分かりやすいです。

全国一律送料:
送料 800円

TypeScriptで送料計算の型を作ると、次のようになります。

type ShippingFeeInput = {
  subtotalAmount: number;
  shippingMethod: 'delivery' | 'store_pickup' | 'event_pickup';
};

/**
 * 役割: 注文小計と配送方法から配送料を計算する
 * 入力: 商品小計、配送方法
 * 出力: 配送料
 */
function calculateShippingFee(input: ShippingFeeInput): number {
  if (input.shippingMethod === 'store_pickup') {
    return 0;
  }

  if (input.shippingMethod === 'event_pickup') {
    return 0;
  }

  return 800;
}

送料計算で重要なのは、サーバー側で計算することです。

ブラウザから送られてきた送料をそのまま信用してはいけません。

危険な設計:
ブラウザから送料0円で送られてきたので、そのまま決済する

安全な設計:
配送方法と配送先をもとに、サーバー側で送料を計算する

最終的な合計金額は、必ずサーバー側で決めます。

商品小計
送料
割引
合計金額

これらはサーバー側で計算する

送料は、購入者が不満を感じやすいポイントでもあります。

商品ページやカート画面で、できるだけ早めに送料の目安を表示すると親切です。


17.6 地域別送料

全国一律送料で対応できない場合は、地域別送料を使います。

地域別送料とは、配送先の地域によって送料を変える方法です。

関東:800円
中部:700円
関西:800円
九州:1,000円
北海道:1,300円
沖縄:1,500円

地域別送料が必要になるのは、次のようなケースです。

・遠方への配送費が高い
・冷蔵・冷凍配送がある
・大きい商品を送る
・離島配送がある
・利益率が低く送料を吸収できない

地域別送料を計算するには、配送先住所が必要です。

特に使うのは、都道府県です。

配送先:
愛知県

送料グループ:
中部

送料:
700円

送料グループを作ると管理しやすくなります。

type ShippingRegion =
  | 'hokkaido'
  | 'tohoku'
  | 'kanto'
  | 'chubu'
  | 'kansai'
  | 'chugoku'
  | 'shikoku'
  | 'kyushu'
  | 'okinawa';

type RegionalShippingFee = {
  region: ShippingRegion;
  fee: number;
};

都道府県から地域を判定します。

type Prefecture = '愛知県' | '東京都' | '大阪府' | '北海道' | '沖縄県';

function getShippingRegion(prefecture: Prefecture): ShippingRegion {
  if (prefecture === '北海道') {
    return 'hokkaido';
  }

  if (prefecture === '沖縄県') {
    return 'okinawa';
  }

  if (prefecture === '愛知県') {
    return 'chubu';
  }

  if (prefecture === '大阪府') {
    return 'kansai';
  }

  return 'kanto';
}

実際の実装では、47都道府県すべてを定義します。

送料テーブルの例です。

const REGIONAL_SHIPPING_FEES: Record<ShippingRegion, number> = {
  hokkaido: 1300,
  tohoku: 1000,
  kanto: 800,
  chubu: 700,
  kansai: 800,
  chugoku: 900,
  shikoku: 900,
  kyushu: 1000,
  okinawa: 1500,
};

地域別送料では、購入者に分かりやすく表示することが大切です。

配送先を入力すると、送料が自動で計算されます。

送料が最後に急に増えると、離脱の原因になります。

そのため、早い段階で送料の目安を見せる設計にします。


17.7 送料無料条件

送料無料条件は、購入単価を上げるためによく使われます。

たとえば、次のような条件です。

税込5,000円以上で送料無料
税込10,000円以上で送料無料
ギフトセットは送料無料
店頭受け取りは送料無料

送料無料は強い導線ですが、利益を圧迫することもあります。

そのため、なんとなく設定するのではなく、利益と送料を見て決めます。

商品粗利
  ー
送料負担
  =
残る利益

送料無料条件を作る場合、システムでは次のように判定します。

商品小計が10,000円以上
  ↓
送料0円

商品小計が10,000円未満
  ↓
通常送料

TypeScriptで考えると、次のようになります。

const FREE_SHIPPING_THRESHOLD = 10000;

/**
 * 役割: 送料無料条件を満たしているか判定する
 * 入力: 商品小計
 * 出力: 送料無料かどうか
 */
function isFreeShipping(subtotalAmount: number): boolean {
  return subtotalAmount >= FREE_SHIPPING_THRESHOLD;
}

送料計算に組み込むと、次のようになります。

type CalculateShippingFeeInput = {
  subtotalAmount: number;
  baseShippingFee: number;
  shippingMethod: 'delivery' | 'store_pickup' | 'event_pickup';
};

function calculateFinalShippingFee(
  input: CalculateShippingFeeInput
): number {
  if (input.shippingMethod !== 'delivery') {
    return 0;
  }

  if (input.subtotalAmount >= FREE_SHIPPING_THRESHOLD) {
    return 0;
  }

  return input.baseShippingFee;
}

購入者には、あといくらで送料無料になるかを表示すると効果的です。

あと2,000円で送料無料です。

ただし、表示だけでなく、決済時にもサーバー側で再計算します。

画面表示:
あと2,000円で送料無料

決済前:
サーバー側で商品小計を再計算
送料無料条件を再判定

送料無料条件は、売上を伸ばす導線にもなります。

しかし、利益を削りすぎないように注意が必要です。


17.8 店頭受け取り

実店舗があるECでは、店頭受け取りを選べると便利です。

店頭受け取りとは、購入者がオンラインで注文し、店舗で商品を受け取る方法です。

オンラインで注文
  ↓
決済
  ↓
店舗で準備
  ↓
購入者が来店して受け取り

店頭受け取りのメリットは、次の通りです。

・送料がかからない
・実店舗への来店につながる
・商品説明を直接できる
・追加購入につながる可能性がある

店頭受け取りでは、通常配送とは別の情報が必要です。

・受け取り店舗
・受け取り希望日
・受け取り希望時間
・受け取り期限
・本人確認方法

管理画面では、配送ステータスとは別に受け取りステータスを持たせてもよいです。

pickup_pending     受け取り待ち
pickup_ready       受け取り準備完了
picked_up          受け取り済み
pickup_cancelled   受け取りキャンセル

小規模ECでは、最初はシンプルに次の流れで十分です。

注文完了
  ↓
店舗が商品を準備
  ↓
受け取り準備完了メール
  ↓
購入者が来店
  ↓
受け取り済みに変更

店頭受け取り用のメール例です。

件名:
商品のお受け取り準備ができました|注文番号:ORDER-0001

本文:
山田 太郎 様

ご注文商品の準備が整いました。
下記店舗にてお受け取りいただけます。

受け取り店舗:〇〇本店
住所:愛知県名古屋市〇〇区〇〇
受け取り可能時間:10:00〜18:00
注文番号:ORDER-0001

ご来店時に、注文番号をスタッフへお伝えください。

店頭受け取りでは、発送完了メールではなく、受け取り準備完了メールを送ります。

配送:
発送完了メール

店頭受け取り:
受け取り準備完了メール

ここを間違えないようにします。


17.9 催事受け取り

催事受け取りは、ポップアップ販売、展示会、イベント会場などで商品を受け取る方法です。

小規模事業者やD2Cでは、かなり相性が良い販売方法です。

ECで事前注文
  ↓
オンライン決済
  ↓
催事会場で受け取り

催事受け取りのメリットは、次の通りです。

・事前に販売数を把握できる
・現地での会計を減らせる
・在庫を持って行きすぎなくてよい
・購入者との接点を作れる
・限定販売と相性が良い

催事受け取りでは、通常配送とは違う情報が必要です。

・催事名
・会場名
・受け取り日
・受け取り時間
・受け取り場所
・注文番号
・本人確認方法

注文時には、受け取り方法として「催事受け取り」を選べるようにします。

受け取り方法:
[ 配送 ]
[ 店頭受け取り ]
[ 催事受け取り ]

催事受け取りのデータ例です。

type PickupMethod = 'delivery' | 'store_pickup' | 'event_pickup';

type EventPickupInfo = {
  eventName: string;
  venueName: string;
  pickupDate: string;
  pickupTimeRange: string;
  pickupLocationNote: string;
};

催事受け取りメールの例です。

件名:
催事受け取りのご案内|注文番号:ORDER-0001

本文:
山田 太郎 様

このたびはご注文いただき、誠にありがとうございます。

ご注文商品は、下記の催事会場にてお受け取りいただけます。

【受け取り情報】
催事名:〇〇百貨店 特別販売会
会場:〇〇百貨店 3階 特設会場
受け取り日:2026年7月20日
受け取り時間:10:00〜17:00
注文番号:ORDER-0001

当日は、注文番号をスタッフへお伝えください。

催事受け取りでは、未受け取りの管理が重要です。

受け取り予定
  ↓
受け取り済み
  ↓
未受け取り

催事終了後に未受け取りの商品がある場合、次の対応を決めておきます。

・後日配送する
・店舗受け取りに変更する
・キャンセル対応する
・個別連絡する

催事受け取りは、便利ですが、現場で混乱しやすい方法でもあります。

そのため、管理画面では催事受け取り注文だけを一覧で出せるようにしておくと便利です。

催事受け取り一覧

ORDER-0001 山田 太郎 受け取り予定
ORDER-0002 佐藤 花子 受け取り済み
ORDER-0003 鈴木 一郎 未受け取り

17.10 配送トラブル時の管理

ECでは、配送トラブルが起きることがあります。

たとえば、次のようなケースです。

・商品が届かない
・追跡番号が間違っている
・配送先住所が間違っている
・商品が破損して届いた
・別の商品を送ってしまった
・長期不在で返送された
・催事で未受け取りになった

配送トラブルで大切なのは、感覚で対応しないことです。

管理画面に記録を残しながら対応します。

まず、配送ステータスにtroubleを用意します。

配送ステータス:
配送トラブル

トラブル種別も記録します。

・未着
・破損
・住所不備
・誤配送
・返送
・追跡番号誤り
・未受け取り
・その他

トラブル管理用の型を作ると、次のようになります。

type ShippingTroubleType =
  | 'not_delivered'
  | 'damaged'
  | 'address_error'
  | 'wrong_item'
  | 'returned'
  | 'tracking_error'
  | 'not_picked_up'
  | 'other';

type ShippingTroubleRecord = {
  orderId: string;
  troubleType: ShippingTroubleType;
  memo: string;
  reportedAt: string;
  resolvedAt: string | null;
};

管理画面では、トラブル対応メモを残せるようにします。

配送トラブルメモ:

2026-07-06 16:30
購入者より商品未着の問い合わせ。
配送会社の追跡では配達中。
明日再確認予定。

トラブル対応の流れは、次のようにします。

問い合わせ発生
  ↓
注文詳細を確認
  ↓
配送ステータスをtroubleに変更
  ↓
対応メモを残す
  ↓
配送会社または購入者へ確認
  ↓
対応完了
  ↓
ステータスを更新

配送トラブルでは、購入者への返信も重要です。

最初の返信では、すぐに断定しない方が安全です。

ご連絡ありがとうございます。
配送状況を確認のうえ、改めてご案内いたします。
恐れ入りますが、確認まで今しばらくお待ちください。

破損の場合は、写真を送ってもらうことがあります。

お手数をおかけしますが、
商品の状態と外箱の状態が分かるお写真をお送りいただけますでしょうか。
確認のうえ、対応方法をご案内いたします。

配送トラブルは、完全に防ぐことはできません。

しかし、記録と対応フローがあれば、慌てずに対応できます。


第17章のまとめ

配送管理は、商品を購入者へ届けるための実務機能です。

決済が完了しても、商品が届くまでは購入体験は終わっていません。

この章で覚えておきたいポイントは、次の通りです。

1. 注文ステータスと配送ステータスは分けて考える
2. 最初は未発送、配送準備中、発送済みを管理できればよい
3. 追跡番号は購入者の不安を減らす重要な情報である
4. 発送完了メールは、注文完了メールとは役割が違う
5. 送料は必ずサーバー側で計算する
6. 地域別送料は都道府県や地域グループで管理する
7. 送料無料条件は売上導線になるが、利益も確認する
8. 店頭受け取りでは、発送ではなく受け取り管理を行う
9. 催事受け取りでは、未受け取り対応を決めておく
10. 配送トラブルは記録と対応履歴を残す

最初から配送会社とのAPI連携まで作る必要はありません。

小規模ECでは、まず次の機能があれば十分です。

・配送ステータス管理
・追跡番号登録
・発送完了メール
・送料計算
・店頭受け取り
・配送トラブルメモ

配送管理が整うと、店舗側は注文後の作業を迷わず進められます。

購入者にとっても、注文後の不安が減り、安心して商品を待てるようになります。

第18章では、ここまで作ってきたECをさらに売れやすくするために、Next.jsで高速ECを実現する方法を学んでいきます。

FAQ

よくある質問

配送管理を作るは医療関係者向けだけの内容ですか。
医療分野の例が含まれる場合もありますが、医療関係者だけに限定した内容ではありません。生成AI、AI活用、DX、業務改善、プロトタイプ開発など、一般的なAI学習の事例として読める内容です。
AI初心者でも読めますか。
はい。AIをこれから学ぶ方、数学が苦手な方、仕事でAIを使いたい方にも読み進めやすいように、教材の章と節の流れに沿って整理しています。
サムネイル画像は必ず表示されますか。
はい。教材にcoverUrlが設定されている場合はその画像を表示し、未設定の場合は代替サムネイル画像を表示します。
Square API × Next.js 実践EC開発|自社ECを低コストで作る、決済・在庫・注文管理の設計と実装のほかの章も読めますか。
はい。教材トップから章立てを確認でき、前後の節へもページ下部のナビゲーションから移動できます。