Mari kita periksa canShip
metode 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_virtual
dan locked_do_ship
kolom dari sale_flat_order_item
tabel.
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();
}
isDummy
pengembalian adalah benar jika parent_id === null
dan produk memiliki opsi "kirim terpisah" ATAU jika parent_id !== null
dan produk tidak memiliki opsi "kirim terpisah".
getSimpleQtyToShip
kembali 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'));