mcpField
O
order-management-system

order-management-system

github.com/finsilabsその他60144 回インストール5 日前に更新
リポジトリ

order-management-system について

EC プラットフォーム向けに注文管理システムの設計を支援するスキルです。マーチャントやプラットフォーム開発者を対象に、出荷先の振り分け、入荷待ち、分割出荷、監査記録を扱います。

主な機能

  1. 01複数拠点への注文振り分け
  2. 02分割出荷の処理
  3. 03入荷待ち注文のワークフロー
  4. 04注文変更の監査記録
  5. 05プラットフォーム別の設定ガイド

活用シーン

  1. 01倉庫や 3PL 間での注文振り分け
  2. 02在庫品を先に出荷し欠品分を管理
  3. 03独自の注文処理パイプラインの構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill order-management-system

インストール後、Claude Code で/order-management-systemを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

tile.json
evals/backorder-management-and-inventory-reple/
criteria.json
task.md
evals/multi-source-fulfillment-routing-and-pla/
criteria.json
task.md
evals/order-state-machine-and-audit-trail/
criteria.json
task.md

詳細

注文管理システム

概要

注文管理システム(OMS)は、注文の受付から配送までの全ライフサイクルを管理します。注文を適切なフルフィルメント拠点(自社倉庫、3PL、ドロップシップのサプライヤー)に振り分け、商品を複数の拠点から発送する必要がある場合は注文を分割し、入荷待ち注文に対応するとともに、完全な監査証跡を維持します。多くのマーチャントでは、プラットフォームに標準搭載されている機能と配送アプリを組み合わせれば、OMS のニーズの 80~90%を満たせます。複数のフルフィルメント拠点や複雑な振り分けルールがある場合、または他のブランド向けのプラットフォームを構築する場合は、カスタム OMS が適しています。

このスキルを使用するタイミング

  • 注文量が単一倉庫のワークフローで対応できる範囲を超え、複数拠点への振り分けが必要な場合
  • 在庫のある商品とない商品が混在する注文を、フルフィルメントを滞らせずに別々の配送で発送する必要がある場合
  • 自社倉庫、3PL、ドロップシップのサプライヤーなど、複数のフルフィルメント拠点を統合された振り分けエンジンに連携する場合
  • 大量の注文に対応する新しいプラットフォームの中核となる注文処理パイプラインを構築する場合
  • カスタマーサービスや財務処理のために、注文のあらゆる状態変更を完全な監査証跡として記録する必要がある場合

主な手順

ステップ 1:プラットフォームを確認し、適切な OMS の方法を選択する
シナリオ推奨する方法理由
単一倉庫、ShopifyShopify + ShipStationShipStation は注文管理、配送ラベルの作成、追跡に標準で対応しています
複数拠点、ShopifyShopify Locations + ShipStation または Shopify Fulfillment NetworkShopify は最大 10 拠点をサポートし、ShipStation はルールに基づいて適切な拠点に振り分けます
3PL 連携ShipBob、Whiplash、または Flexport + 利用中プラットフォームのアプリ各 3PL は Shopify、WooCommerce、BigCommerce 用の標準アプリを提供しています
複雑な振り分け + 入荷待ちSkubana (Extensiv)、Linnworks、または ShipHeroこれらの専用 OMS ツールは、複数倉庫への振り分け、入荷待ちキュー、分割配送に対応しています
カスタム/ヘッドレスOMS のステートマシンを構築し、配送ラベル用に Shippo/EasyPost を連携する振り分けルール、状態遷移、監査証跡を完全に制御できます
ステップ 2:複数拠点への注文振り分けを設定する
Shopify

Shopify Locations(通常プランでは最大 10 拠点):

  1. 倉庫またはフルフィルメントセンターごとに、Settings → Locations → Add location に移動します
  2. Settings → Shipping and delivery → Fulfill orders from で、フルフィルメントの優先順位を設定します。
    • Shopify は、在庫がある拠点の中から顧客に最も近い拠点に注文を自動的に振り分けます
  3. 商品バリエーションごとに、その商品を在庫する拠点を設定します。Products → [Product] → Inventory に移動し、各拠点の在庫数を確認します
  4. 注文が入ると、Shopify は優先順位ルールに基づいて最適なフルフィルメント拠点を自動的に選択します

3PL との連携:

  • 3PL の標準 Shopify アプリ(ShipBob、Whiplash、Flexport はすべて Shopify アプリを提供しています)をインストールします
  • アプリの設定で、3PL と自社倉庫のどちらから各商品をフルフィルメントするかを設定します
  • 3PL アプリは Shopify に追加の「location」を作成し、注文通知を自動的に受信します

分割配送:

  • 1 件の注文を複数拠点から発送する場合、Shopify はフルフィルメントを自動的に分割します
  • 各フルフィルメントには個別の追跡番号が付与され、顧客への配送通知もそれぞれ送信されます
WooCommerce

ATUM Inventory Management を使用する場合:

  1. ATUM Inventory Management(無料版/プレミアム版、WordPress.org)をインストールします
  2. ATUM により、WooCommerce に複数拠点の在庫追跡機能が追加されます
  3. ATUM → Settings → Multi-inventory で、フルフィルメントの優先順位を設定します
  4. 優先順位ルールに基づいて、在庫のある拠点に注文が振り分けられます

3PL との連携:

  • ShipBob には WooCommerce プラグインがあります。インストールして、ShipBob から発送する商品を設定します
  • ShipStation の WooCommerce プラグインは、複数の配送業者や倉庫に接続します。ShipStation → Automation → Rules で振り分けルールを設定します
BigCommerce
  1. Inventory → Locations に移動して、複数のフルフィルメント拠点を追加します(Plus 以上で利用可能です)
  2. 各商品の在庫数を拠点ごとに設定します
  3. BigCommerce は設定に基づき、顧客に最も近い、在庫のある拠点に注文を割り当てます
  4. 3PL との連携には、ShipBob、Whiplash、ShipStation のいずれも、App Marketplace 経由で BigCommerce のネイティブ連携を利用できます
ステップ 3:バックオーダーに対応する

バックオーダーとは、在庫切れの商品に注文が入ることです。顧客は引き続き商品を希望しているため、在庫が届いたら注文をフルフィルメントする必要があります。

Shopify

バックオーダーを有効にする:

  1. Products → [Product] → Variants → [Variant] に移動します
  2. 在庫追跡の設定で「在庫切れでも販売を続ける」にチェックを入れます。在庫が 0 でも注文を受け付けられるようになります
  3. 在庫が 0 の場合は、商品ページに「発送まで 2〜3 週間」と表示して、顧客に明確に伝えます

バックオーダーについて顧客に連絡する:

  • 商品がバックオーダーになっても、Shopify の標準の注文確認では自動的にその旨が表示されません
  • Klaviyo または Shopify Email を使ってトリガーを設定します。注文に、利用可能な在庫数を超える数量の明細項目が含まれている場合、再入荷予定日を記載した「バックオーダー」メールを送信します

バックオーダーの注文をフルフィルメントする:

  • 在庫が届いたら(入荷を受け取ったら)、Shopify → Orders でバックオーダーの注文を手動でフルフィルメントします。「Unfulfilled」で絞り込み、注文日順に並べ替えます
  • バックオーダーの注文を自動でフルフィルメントするには、Shopify Flow(Plus)または webhook を使い、在庫補充時にフルフィルメントをトリガーします
WooCommerce
  1. WooCommerce → Settings → Products → Inventory に移動します
  2. 全体設定で「バックオーダーを許可する」を有効にするか、商品ごとに設定します:Products → [Product] → Inventory → Allow Backorders
  3. オプション:「許可しない」「許可するが顧客に通知する」「通知せずに許可する」
  4. 「許可するが顧客に通知する」を推奨します。WooCommerce は「バックオーダー中」バッジを追加し、チェックアウト時に顧客へ通知します
  5. バックオーダーの注文は、支払いの処理方法に応じて、WooCommerce → Orders で「On Hold」または「Processing」のステータスで表示されます
BigCommerce
  1. Products → [Product] → Inventory に移動します
  2. 「Allow Purchasing Out of Stock」を有効にします。在庫が 0 になると、BigCommerce は商品を自動的に「予約注文可能」と表示します
  3. Store Setup → Store Settings → Product Settings で「Back Ordering」のメッセージを設定します
ステップ 4:注文の監査証跡を維持する

注文ステータスを変更するたびに、変更者と変更日時を記録する必要があります。これはカスタマーサービスと不正調査に不可欠です。

Shopify
  • Shopify は注文ステータスの変更をすべて Orders → [Order] → Timeline に自動で記録します
  • Timeline には、支払いの確認、フルフィルメントの作成、配送ラベルの購入、追跡情報の更新など、すべてのイベントが表示されます
  • 手動で行った操作は、Timeline に手動メモを追加します(スタッフのみ閲覧可能です)
WooCommerce
  • WooCommerce は各注文の Order Notes セクションに注文メモを記録します
  • ステータスの変更は自動で記録されます(「注文ステータスが Processing から Completed に変更されました」)
  • より包括的な監査ログを記録するには、WooCommerce Order Status Manager または Activity Log プラグインをインストールします
BigCommerce
  • BigCommerce は各注文の Order Activity セクションに注文ステータスの変更を記録します
  • アクティビティログには、すべてのステータス変更、追加されたメモ、システムの操作が表示されます
カスタム/ヘッドレス — イベントログ付き注文ステートマシン
// Order status state machine with full audit trail
type OrderStatus =
  | 'pending'
  | 'payment_processing'
  | 'paid'
  | 'awaiting_fulfillment'
  | 'partially_fulfilled'
  | 'fulfilled'
  | 'delivered'
  | 'cancelled'
  | 'refunded';

const VALID_TRANSITIONS: Partial<Record<OrderStatus, OrderStatus[]>> = {
  pending:              ['payment_processing', 'cancelled'],
  payment_processing:   ['paid', 'cancelled'],
  paid:                 ['awaiting_fulfillment', 'cancelled'],
  awaiting_fulfillment: ['partially_fulfilled', 'fulfilled', 'cancelled'],
  partially_fulfilled:  ['fulfilled'],
  fulfilled:            ['delivered', 'refunded'],
  delivered:            ['refunded'],
};

async function transitionOrder(params: {
  orderId: string;
  newStatus: OrderStatus;
  actorId: string;
  note?: string;
}): Promise<void> {
  const order = await db.orders.findById(params.orderId);
  const allowed = VALID_TRANSITIONS[order.status] ?? [];

  if (!allowed.includes(params.newStatus)) {
    throw new Error(`Invalid transition: ${order.status} → ${params.newStatus}`);
  }

  await db.transaction(async tx => {
    await tx.orders.update(params.orderId, { status: params.newStatus, updated_at: new Date() });
    // Every transition is recorded — this IS the audit trail
    await tx.orderEvents.insert({
      order_id: params.orderId,
      from_status: order.status,
      to_status: params.newStatus,
      actor_id: params.actorId,
      note: params.note ?? null,
      occurred_at: new Date(),
    });
  });
}

// Route an order to the right fulfillment source
async function routeOrder(orderId: string): Promise<void> {
  const order = await db.orders.findById(orderId);
  const lines = await db.orderLines.findByOrderId(orderId);

  for (const line of lines) {
    // Check own warehouse first
    const warehouseStock = await db.inventory.findAvailable(line.sku, line.quantity);
    if (warehouseStock) {
      await db.fulfillmentLines.insert({
        order_id: orderId,
        order_line_id: line.id,
        source: 'warehouse',
        source_id: warehouseStock.location_id,
        status: 'pending',
      });
      continue;
    }

    // Fall back to dropship supplier
    const supplier = await db.supplierProducts.findBestSupplier(line.product_id, line.quantity);
    if (supplier) {
      await db.fulfillmentLines.insert({
        order_id: orderId,
        order_line_id: line.id,
        source: 'dropship',
        source_id: supplier.supplier_id,
        status: 'pending',
      });
      continue;
    }

    // No source available — create a backorder
    await db.backorders.insert({
      order_id: orderId,
      order_line_id: line.id,
      product_id: line.product_id,
      quantity: line.quantity,
      status: 'pending',
    });
    // Notify customer about the backorder
  }
}

ベストプラクティス

  • カスタム開発の前に、専用のOMSを利用します — Skubana/Extensiv($500+/月)またはLinnworksを使えば、複数倉庫への振り分け、入荷待ち注文、分割発送を実績のある信頼性で処理できます。カスタム開発は、こうしたツールでは特定のニーズを満たせない場合にのみ始めてください。
  • 注文とフルフィルメントは別のエンティティとして扱います — 注文は顧客との金銭的な契約であり、フルフィルメントは物理的な発送です。1件の注文から複数のフルフィルメントが発生する場合があります。
  • フルフィルメントの計画は非同期でキューに登録します — チェックアウト中に注文を同期的に振り分けないでください。支払い確認後すぐに振り分けをキューに登録し、バックグラウンドワーカーで処理します。
  • 入荷待ちの商品を通知なしに取り下げないでください — 必ず顧客に通知し、待つかキャンセルするかを選べるようにします。通知なしの入荷待ちは、数週間後に顧客が気づいた際に信頼を損ないます。
  • 「フルフィルメント待ち」の状態が24時間以上続く注文にアラートを設定します — フルフィルメントに進んでいない注文について、毎日のアラートを設定します。通常、振り分けエラーまたはシステムの問題を示しています。

よくある落とし穴

問題解決策
注文が予期せず複数の発送に分割される複数の場所から発送される注文は、チェックアウト時に顧客へ事前に知らせます。発送ごとの配達予定日を個別に表示します
在庫が補充されても入荷待ち注文がフルフィルメントされない自動トリガーを設定します。在庫が入荷待ち数量を上回ったら、最も古い保留中の入荷待ち注文をフルフィルメントします(FIFO)
一部キャンセルにより注文が不整合な状態になる一部キャンセルを実装します。ピッキングされていない商品だけをキャンセルし、キャンセル分を返金して、注文合計を更新します
Shopifyで「一部フルフィルメント済み」と表示されているのに、顧客は全商品が発送されると思っている各発送時に、今回の発送に含まれる商品と後日発送される残りの商品を説明する明確なメールを送信します

関連スキル

  • @order-fulfillment-workflow
  • @returns-management
  • @multi-channel-selling
  • @dropshipping-integration
  • @demand-forecasting

コメント