Como obter a coleta de pedidos que podem ser enviados?

8

Preciso de pedidos que ainda não foram enviados ou parcialmente enviados. Estou usando o código abaixo para obter pedidos que podem ser enviados.

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

Mas não quero usar foreach. Eu preciso de algo como abaixo.

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

Respostas:

9

Vamos examinar o canShipmétodo para ver como é calculado:

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

Os métodos de pedido podem ser substituídos da seguinte maneira

  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 ()

    Os sinalizadores de ação são definidos durante os processos de vendas, não relevantes para recuperar pedidos do banco de dados

  6. getAllItems ()

    Aqui precisamos fazer uma junção sobre os itens do pedido. is_virtuale locked_do_shipsão colunas da sale_flat_order_itemtabela.

    1. getQtyToShip ()

      Isso novamente é calculado com base em outros atributos

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

      isDummyretorna é verdadeiro se parent_id === nulle o produto tiver a opção "enviar separadamente" OU se parent_id !== nulle o produto não tiver a opção "enviar separadamente".

      getSimpleQtyToShipretorna qty_ordered - qty_shipped - qty_refunded - qty_canceled.

O código

Com essas informações, podemos preparar uma coleção:

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

Primeiro, juntamos os itens que pertencem 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');

Em seguida, filtramos os status dos pedidos que não podem ser enviados ("nin" = "not in"):

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

Em seguida, criamos uma expressão SQL para o número de itens que podem ser enviados:

  • somamos o qty entregável sobre os itens do pedido
  • para itens virtuais, o resultado é 0
  • para itens "bloqueados", o resultado é 0
  • para todos os outros, o resultado é igual a qty_ordered - qty_shipped - qty_refunded - qty_canceled

TODO: leve a opção do produto "em consideração separadamente. Essa consulta contará todos os itens pai e filho, portanto haverá falsos positivos. Vou deixar como um exercício para o leitor também calcular o resultado do isDummy()SQL.

A soma estará disponível com o 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'));

Por fim, filtramos apenas pedidos com um número positivo de itens que podem ser entregues. Temos que usar "HAVING" em vez de "WHERE" porque a coluna é calculada com uma função agregada:

$collection->getSelect()->having('shippable_items > 0'));
Fabian Schmengler
fonte
boa explicação .Eu vou verificar. + 1
Amit Bera
2

Não pode ser possível because of lot of conditionsverificar e sempre quewe use canShip() funcionar. É muito complexo fazer isso.

É 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

Portanto, depende de uma lógica / condição complexa como:

Veja uma exibição na classe Mage_Sales_Model_Order e você pode entender isso.

 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
fonte