Wie bekomme ich eine Sammlung von Bestellungen, die versendet werden können?

8

Ich benötige Bestellungen, die noch nicht oder teilweise versendet werden. Ich verwende den folgenden Code, um Bestellungen zu erhalten, die versendet werden können.

foreach ($orderIds as $orderId) {
    $order = Mage::getModel('sales/order')->load($orderId);
    if ($order->canShip()) {
        echo "Shipping Pending";
    }
}

Aber ich möchte nicht foreach verwenden. Ich brauche so etwas wie unten.

Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('status','can_ship');
piyush_systematix
quelle

Antworten:

8

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

  1. canUnhold ()

    order->state === 'holded'
  2. isPaymentReview ()

    order->state === 'payment_review'
  3. getIsVirtual ()

    order->is_virtual === 1
  4. ist storniert()

    order->state === 'canceled'
  5. getActionFlag ()

    Aktionsflags werden während der Verkaufsprozesse gesetzt und sind für das Abrufen von Bestellungen aus der Datenbank nicht relevant

  6. getAllItems ()

    Hier müssen wir einen Join über die Bestellpositionen durchführen. is_virtualund locked_do_shipsind Spalten der sale_flat_order_itemTabelle.

    1. 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'));
Fabian Schmengler
quelle
gute Erklärung. Ich werde überprüfen. + 1
Amit Bera
2

Es kann nicht möglich sein, zu because of lot of conditionsüberprüfen und wann immer we use canShip()Funktion. Es ist zu komplex, um das zu tun.

Es ist not only depend one /two order fields dependwie

  1. order status hold or not.
  2. order status cancel or not.
  3. order virtual or not.
  4. Order item is capable to do ship order

usw

Es hängt also von einer komplexen Logik / Bedingung ab, wie:

Sehen Sie sich eine Ansicht der Klasse Mage_Sales_Model_Order an , und Sie können das verstehen.

 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;
    }
Amit Bera
quelle