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


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.