Lassen Sie uns die canShipMethode untersuchen , um zu sehen, wie sie berechnet wird:
/**
* 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;
}
Die Bestellmethoden können wie folgt ersetzt werden
canUnhold ()
order->state === 'holded'
isPaymentReview ()
order->state === 'payment_review'
getIsVirtual ()
order->is_virtual === 1
ist storniert()
order->state === 'canceled'
getActionFlag ()
Aktionsflags werden während der Verkaufsprozesse gesetzt und sind für das Abrufen von Bestellungen aus der Datenbank nicht relevant
getAllItems ()
Hier müssen wir einen Join über die Bestellpositionen durchführen. is_virtualund locked_do_shipsind Spalten der sale_flat_order_itemTabelle.
getQtyToShip ()
Dies wird wiederum basierend auf anderen Attributen berechnet
/**
* Retrieve item qty available for ship
*
* @return float|integer
*/
public function getQtyToShip()
{
if ($this->isDummy(true)) {
return 0;
}
return $this->getSimpleQtyToShip();
}
isDummyRückgabe ist wahr, wenn parent_id === nullund das Produkt die Option "Separat versenden" hat ODER wenn parent_id !== nullund das Produkt nicht die Option "Separat versenden" hat.
getSimpleQtyToShipkehrt zurück qty_ordered - qty_shipped - qty_refunded - qty_canceled.
Der Code
Mit diesen Informationen können wir eine Sammlung vorbereiten:
$collection = Mage::getModel('sales/order')->getCollection();
Zuerst verbinden wir die Artikel, die zu jeder Bestellung gehören:
$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');
Dann filtern wir Auftragsstatus, die nicht versendet werden können ("nin" = "not in"):
$collection
->addFieldToFilter('status', array('nin' => array(
'holded', 'payment_review', 'canceled'
)))
->addFieldToFilter('main_table.is_virtual', '0');
Anschließend erstellen wir einen SQL-Ausdruck für die Anzahl der Artikel, die versendet werden können:
- Wir summieren die Versandmenge über die Bestellpositionen
- Für virtuelle Objekte ist das Ergebnis 0
- für "gesperrte" Elemente ist das Ergebnis 0
- für alle anderen ist das Ergebnis gleich
qty_ordered - qty_shipped - qty_refunded - qty_canceled
TODO: Produktoption "Versand separat berücksichtigen" berücksichtigen. Diese Abfrage zählt alle übergeordneten und untergeordneten Elemente, sodass es zu Fehlalarmen kommt. Ich überlasse es dem Leser, auch das Ergebnis von isDummy()in SQL zu berechnen .
Die Summe wird mit dem Alias "shippable_items" verfügbar sein.
$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'));
Schließlich filtern wir nur Bestellungen mit einer positiven Anzahl versandfähiger Artikel. Wir müssen "HAVING" anstelle von "WHERE" verwenden, da die Spalte mit einer Aggregatfunktion berechnet wird:
$collection->getSelect()->having('shippable_items > 0'));