Давайте рассмотрим 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;
}
Методы заказа могут быть заменены следующим образом
canUnhold ()
order->state === 'holded'
isPaymentReview ()
order->state === 'payment_review'
getIsVirtual ()
order->is_virtual === 1
isCanceled ()
order->state === 'canceled'
getActionFlag ()
Флаги действий устанавливаются в процессе продаж и не имеют отношения к получению заказов из базы данных.
getAllItems ()
Здесь нам нужно объединить элементы заказа. is_virtual
и locked_do_ship
являются столбцами sale_flat_order_item
таблицы.
getQtyToShip ()
Это снова рассчитывается на основе других атрибутов
/**
* Retrieve item qty available for ship
*
* @return float|integer
*/
public function getQtyToShip()
{
if ($this->isDummy(true)) {
return 0;
}
return $this->getSimpleQtyToShip();
}
isDummy
return is true, если parent_id === null
и у продукта есть опция «отправить отдельно» ИЛИ если parent_id !== null
у продукта нет опции «отправить отдельно».
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'));
Наконец, мы фильтруем только заказы с положительным количеством отправляемых товаров. Мы должны использовать «HAVING» вместо «WHERE», потому что столбец рассчитывается с помощью статистической функции:
$collection->getSelect()->having('shippable_items > 0'));
Это не может быть возможно
because of lot of conditions
проверить и всякий раз, когдаwe use canShip()
функция. Это слишком сложно, чтобы сделать это.Это
not only depend one /two order fields depend
какorder status hold or not.
order status cancel or not
,order virtual or not.
Order item is capable to do ship order
так далее
Итак, это зависит от некоторой сложной логики / условия, например:
Посмотрите на класс Mage_Sales_Model_Order , и вы можете это понять.
источник