Mari kita periksa canShipmetode untuk melihat bagaimana cara menghitungnya:
/**
* 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;
}
Metode pemesanan dapat diganti sebagai berikut
canUnhold ()
order->state === 'holded'
isPaymentReview ()
order->state === 'payment_review'
getIsVirtual ()
order->is_virtual === 1
dibatalkan()
order->state === 'canceled'
getActionFlag ()
Bendera tindakan ditetapkan selama proses penjualan, tidak relevan untuk mengambil pesanan dari database
getAllItems ()
Di sini kita perlu melakukan join atas item-item pesanan. is_virtualdan locked_do_shipkolom dari sale_flat_order_itemtabel.
getQtyToShip ()
Ini lagi dihitung berdasarkan atribut lainnya
/**
* Retrieve item qty available for ship
*
* @return float|integer
*/
public function getQtyToShip()
{
if ($this->isDummy(true)) {
return 0;
}
return $this->getSimpleQtyToShip();
}
isDummypengembalian adalah benar jika parent_id === nulldan produk memiliki opsi "kirim terpisah" ATAU jika parent_id !== nulldan produk tidak memiliki opsi "kirim terpisah".
getSimpleQtyToShipkembali qty_ordered - qty_shipped - qty_refunded - qty_canceled.
Kode
Dengan informasi ini kami dapat menyiapkan koleksi:
$collection = Mage::getModel('sales/order')->getCollection();
Pertama, kami bergabung dengan barang-barang milik setiap pesanan:
$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');
Kemudian, kami memfilter status pesanan yang tidak dapat dikirim ("nin" = "not in"):
$collection
->addFieldToFilter('status', array('nin' => array(
'holded', 'payment_review', 'canceled'
)))
->addFieldToFilter('main_table.is_virtual', '0');
Kemudian, kami membuat ekspresi SQL untuk jumlah item yang dapat dikirimkan:
- kami menjumlahkan qty shippable atas item pesanan
- untuk item virtual hasilnya adalah 0
- untuk item "terkunci" hasilnya adalah 0
- untuk yang lainnya, hasilnya sama
qty_ordered - qty_shipped - qty_refunded - qty_canceled
TODO: ambil opsi produk "kirim secara terpisah ke dalam akun. Permintaan ini akan menghitung semua item induk dan anak, jadi akan ada positif palsu. Saya akan menyerahkannya sebagai latihan kepada pembaca untuk juga menghitung hasil isDummy()dalam SQL.
Jumlahnya akan tersedia dengan alias "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'));
Akhirnya kami hanya memfilter pesanan dengan jumlah positif barang yang dapat dikirim. Kita harus menggunakan "HAVING" alih-alih "WHERE" karena kolom dihitung dengan fungsi agregat:
$collection->getSelect()->having('shippable_items > 0'));