Hãy xem xét canShip
phương pháp để xem cách tính toán:
/**
* 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;
}
Các phương thức đặt hàng có thể được thay thế như sau
có thể ()
order->state === 'holded'
isPaymentReview ()
order->state === 'payment_review'
getIsVirtual ()
order->is_virtual === 1
bị hủy ()
order->state === 'canceled'
getActionFlag ()
Cờ hành động được đặt trong quá trình bán hàng, không liên quan để lấy đơn đặt hàng từ cơ sở dữ liệu
get ALLItems ()
Ở đây chúng ta cần phải tham gia vào các mục đặt hàng. is_virtual
và locked_do_ship
là các cột của sale_flat_order_item
bảng.
getQtyToShip ()
Điều này một lần nữa được tính toán dựa trên các thuộc tính khác
/**
* Retrieve item qty available for ship
*
* @return float|integer
*/
public function getQtyToShip()
{
if ($this->isDummy(true)) {
return 0;
}
return $this->getSimpleQtyToShip();
}
isDummy
trả về là đúng nếu parent_id === null
và sản phẩm có tùy chọn "ship riêng biệt" HOẶC nếu parent_id !== null
và sản phẩm không có tùy chọn "ship riêng biệt".
getSimpleQtyToShip
trả lại qty_ordered - qty_shipped - qty_refunded - qty_canceled
.
Mật mã
Với thông tin này, chúng tôi có thể chuẩn bị một bộ sưu tập:
$collection = Mage::getModel('sales/order')->getCollection();
Đầu tiên, chúng tôi tham gia các mục thuộc về mỗi đơn hàng:
$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');
Sau đó, chúng tôi lọc các trạng thái đơn hàng không thể được vận chuyển ("nin" = "không trong"):
$collection
->addFieldToFilter('status', array('nin' => array(
'holded', 'payment_review', 'canceled'
)))
->addFieldToFilter('main_table.is_virtual', '0');
Sau đó, chúng tôi tạo một biểu thức SQL cho số lượng các mặt hàng có thể được vận chuyển:
- chúng tôi tổng hợp số lượng shippable trên các mục đặt hàng
- đối với các mục ảo kết quả là 0
- đối với các mục "bị khóa", kết quả là 0
- đối với tất cả những người khác, kết quả bằng
qty_ordered - qty_shipped - qty_refunded - qty_canceled
TODO: đưa tùy chọn sản phẩm "gửi riêng vào tài khoản. Truy vấn này sẽ tính tất cả các mục cha mẹ và con, do đó sẽ có kết quả dương tính giả. Tôi sẽ để nó như một bài tập cho người đọc để tính kết quả của isDummy()
SQL.
Tổng số sẽ có sẵn với bí danh "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'));
Cuối cùng, chúng tôi chỉ lọc các đơn hàng có số lượng mặt hàng có thể chuyển đổi tích cực. Chúng tôi phải sử dụng "HAVING" thay vì "WHERE" vì cột được tính bằng hàm tổng hợp:
$collection->getSelect()->having('shippable_items > 0'));