¿Cómo obtener la recogida de pedidos que se pueden enviar?

8

Necesito pedidos que aún no se envían o que se envían parcialmente. Estoy usando el siguiente código para obtener pedidos que se pueden enviar.

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

Pero no quiero usar foreach. Necesito algo como a continuación.

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

Respuestas:

9

Examinemos el canShipmétodo para ver cómo se calcula:

/**
 * 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;
}

Los métodos de pedido se pueden sustituir de la siguiente manera

  1. canUnhold ()

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

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

    order->is_virtual === 1
  4. está cancelado()

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

    Las marcas de acción se establecen durante los procesos de venta, no son relevantes para recuperar pedidos de la base de datos

  6. getAllItems ()

    Aquí necesitamos unirnos sobre los artículos del pedido. is_virtualy locked_do_shipson columnas de la sale_flat_order_itemtabla.

    1. getQtyToShip ()

      Esto nuevamente se calcula en base a otros atributos

      /**
       * Retrieve item qty available for ship
       *
       * @return float|integer
       */
      public function getQtyToShip()
      {
          if ($this->isDummy(true)) {
              return 0;
          }
      
          return $this->getSimpleQtyToShip();
      }

      isDummylas devoluciones son verdaderas si parent_id === nully el producto tiene la opción "enviar por separado" O si parent_id !== nully el producto no tiene la opción "enviar por separado".

      getSimpleQtyToShipvuelve qty_ordered - qty_shipped - qty_refunded - qty_canceled.

El código

Con esta información podemos preparar una colección:

$collection = Mage::getModel('sales/order')->getCollection();

Primero, unimos los artículos que pertenecen a cada pedido:

$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');

Luego, filtramos los estados de los pedidos que no se pueden enviar ("nin" = "not in"):

$collection
    ->addFieldToFilter('status', array('nin' => array(
        'holded', 'payment_review', 'canceled'
    )))
    ->addFieldToFilter('main_table.is_virtual', '0');

Luego, creamos una expresión SQL para la cantidad de artículos que se pueden enviar:

  • Sumamos la cantidad de envío sobre los artículos de pedido
  • para elementos virtuales el resultado es 0
  • para los elementos "bloqueados" el resultado es 0
  • para todos los demás, el resultado es igual qty_ordered - qty_shipped - qty_refunded - qty_canceled

TODO: tenga en cuenta que la opción de producto "se envía por separado. Esta consulta contará todos los elementos primarios y secundarios, por lo que habrá falsos positivos. Lo dejaré como un ejercicio para que el lector también calcule el resultado isDummy()en SQL.

La suma estará disponible con el 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'));

Finalmente, filtramos solo los pedidos con un número positivo de artículos enviables. Tenemos que usar "TENER" en lugar de "DONDE" porque la columna se calcula con una función agregada:

$collection->getSelect()->having('shippable_items > 0'));
Fabian Schmengler
fuente
buena explicación. Comprobaré. + 1
Amit Bera
2

No es posible que because of lot of conditionsse comprueben y siempre que we use canShip()funcionen. Es demasiado complejo para hacerlo.

Es not only depend one /two order fields dependcomo

  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

etc.

Entonces, depende de alguna lógica / condición compleja como:

Vea una vista en la clase Mage_Sales_Model_Order , y puede entender eso.

 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
fuente