発送可能な注文の集まりを取得するにはどうすればよいですか?


8

まだ発送されていない、または一部発送されている注文が必要です。以下のコードを使用して、出荷可能な注文を取得しています。

foreach ($orderIds as $orderId) {
    $order = Mage::getModel('sales/order')->load($orderId);
    if ($order->canShip()) {
        echo "Shipping Pending";
    }
}

しかし、私はforeachを使いたくありません。以下のようなものが必要です。

Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('status','can_ship');

回答:


9

canShipメソッドを調べて、計算方法を見てみましょう。

/**
 * Retrieve order shipment availability
 *
 * @return bool
 */
public function canShip()
{
    if ($this->canUnhold() || $this->isPaymentReview()) {
        return false;
    }

    if ($this->getIsVirtual() || $this->isCanceled()) {
        return false;
    }

    if ($this->getActionFlag(self::ACTION_FLAG_SHIP) === false) {
        return false;
    }

    foreach ($this->getAllItems() as $item) {
        if ($item->getQtyToShip()>0 && !$item->getIsVirtual()
            && !$item->getLockedDoShip())
        {
            return true;
        }
    }
    return false;
}

注文方法は次のように置き換えることができます

  1. canUnhold()

    order->state === 'holded'
  2. isPaymentReview()

    order->state === 'payment_review'
  3. getIsVirtual()

    order->is_virtual === 1
  4. isCanceled()

    order->state === 'canceled'
  5. getActionFlag()

    アクションフラグは販売プロセス中に設定され、データベースからの注文の取得には関係ありません。

  6. getAllItems()

    ここでは、注文アイテムを結合する必要があります。is_virtualそして、locked_do_shipの列ですsale_flat_order_itemテーブル。

    1. getQtyToShip()

      これも他の属性に基づいて計算されます

      /**
       * Retrieve item qty available for ship
       *
       * @return float|integer
       */
      public function getQtyToShip()
      {
          if ($this->isDummy(true)) {
              return 0;
          }
      
          return $this->getSimpleQtyToShip();
      }
      

      isDummyparent_id === null製品に「別個に出荷」オプションがある場合parent_id !== null、または製品に「別個に出荷」オプションがない場合、returnsはtrueです。

      getSimpleQtyToShipを返しますqty_ordered - qty_shipped - qty_refunded - qty_canceled。

コード

この情報を使用して、コレクションを準備できます。

$collection = Mage::getModel('sales/order')->getCollection();

まず、各注文に属するアイテムを結合します。

$collection->getSelect()
    ->joinLeft(
        array('order_item' => $collection->getTable('sales/order_item')),
        'main_table.entity_id=order_item.order_id', array('qty_ordered', 'qty_shipped', 'qty_refunded', 'qty_canceled', 'is_virtual', 'locked_do_ship'))
    ->group('main_table.entity_id');

次に、発送できない注文ステータスをフィルタリングします( "nin" = "not in"):

$collection
    ->addFieldToFilter('status', array('nin' => array(
        'holded', 'payment_review', 'canceled'
    )))
    ->addFieldToFilter('main_table.is_virtual', '0');

次に、出荷できるアイテム数のSQL式を作成します。

  • 注文商品の出荷可能数量を合計します
  • 仮想アイテムの場合、結果は0です
  • 「ロックされた」アイテムの場合、結果は0です。
  • 他のすべての場合、結果は qty_ordered - qty_shipped - qty_refunded - qty_canceled

TODO:「個別に出荷する」という製品オプションを考慮に入れてください。このクエリでは、すべての親アイテムと子アイテムがカウントされるため、誤検知が発生isDummy()します。SQLの結果も計算するための演習として残しておきます。

合計はエイリアス「shippable_items」で利用可能になります

$collection->addExpressionFieldToSelect(
    'shippable_items',
    'SUM(({{qty_ordered}} - {{qty_shipped}} - {{qty_refunded}} - {{qty_canceled}}) * !{{is_virtual}} * {{locked_do_ship}} IS NOT NULL)',
    array(
        'qty_ordered' => 'order_item.qty_ordered',
        'qty_shipped' => 'order_item.qty_shipped',
        'qty_refunded' => 'order_item.qty_refunded',
        'qty_canceled' => 'order_item.qty_canceled',
        'is_virtual' => 'order_item.is_virtual',
        'locked_do_ship' => 'order_item.locked_do_ship'));

最後に、出荷可能なアイテムの数が正の注文のみをフィルタリングします。列は集計関数で計算されるため、「WHERE」ではなく「HAVING」を使用する必要があります。

$collection->getSelect()->having('shippable_items > 0'));

良い説明。確認します。+ 1
— アミットベラ

2

because of lot of conditionsチェックすることはできませんし、いつでもwe use canShip()機能することはできません。

それはあるnot only depend one /two order fields dependように

  1. order status hold or not.
  2. order status cancel or not。
  3. order virtual or not.
  4. Order item is capable to do ship order

等

したがって、次のような複雑なロジック/条件に依存します。

Mage_Sales_Model_Orderクラスのビューを見ると、それが理解できます。

 public function canShip()
    {
        if ($this->canUnhold() || $this->isPaymentReview()) {
            return false;
        }

        if ($this->getIsVirtual() || $this->isCanceled()) {
            return false;
        }

        if ($this->getActionFlag(self::ACTION_FLAG_SHIP) === false) {
            return false;
        }

        foreach ($this->getAllItems() as $item) {
            if ($item->getQtyToShip()>0 && !$item->getIsVirtual()
                && !$item->getLockedDoShip())
            {
                return true;
            }
        }
        return false;
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.