Lassen Sie uns die canShip
Methode 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_virtual
und locked_do_ship
sind Spalten der sale_flat_order_item
Tabelle.
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();
}
isDummy
Rückgabe ist wahr, wenn parent_id === null
und das Produkt die Option "Separat versenden" hat ODER wenn parent_id !== null
und das Produkt nicht die Option "Separat versenden" hat.
getSimpleQtyToShip
kehrt 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'));