如何收集可以发货的订单?


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');

Answers:


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_virtuallocked_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();
      }

      isDummy如果parent_id === null并且产品具有“单独运输”选项,或者如果parent_id !== null并且产品不具有“单独运输”选项,则返回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:将产品选项“ ship”单独考虑在内。此查询将计算所有父项和子项,因此会出现误报。我将其作为练习让读者也可以计算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'));

最终,我们仅过滤可发货项目为正数的订单。我们必须使用“ HAVING”而不是“ WHERE”,因为该列是使用聚合函数计算的:

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

好的解释。我会检查。+ 1
阿米特·贝拉

2

这不可能because of lot of conditions是检查和每当we use canShip()function.Tt太复杂而无法做到这一点。

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;
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.