Bagaimana cara mendapatkan koleksi pesanan yang bisa dikirim?

8

Saya membutuhkan pesanan yang belum dikirim atau sebagian dikirim. Saya menggunakan kode di bawah ini untuk mendapatkan pesanan yang dapat dikirim.

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

Tapi saya tidak ingin menggunakan foreach. Saya butuh sesuatu seperti di bawah ini.

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

Jawaban:

9

Mari kita periksa canShipmetode untuk melihat bagaimana cara menghitungnya:

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

Metode pemesanan dapat diganti sebagai berikut

  1. canUnhold ()

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

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

    order->is_virtual === 1
  4. dibatalkan()

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

    Bendera tindakan ditetapkan selama proses penjualan, tidak relevan untuk mengambil pesanan dari database

  6. getAllItems ()

    Di sini kita perlu melakukan join atas item-item pesanan. is_virtualdan locked_do_shipkolom dari sale_flat_order_itemtabel.

    1. getQtyToShip ()

      Ini lagi dihitung berdasarkan atribut lainnya

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

      isDummypengembalian adalah benar jika parent_id === nulldan produk memiliki opsi "kirim terpisah" ATAU jika parent_id !== nulldan produk tidak memiliki opsi "kirim terpisah".

      getSimpleQtyToShipkembali qty_ordered - qty_shipped - qty_refunded - qty_canceled.

Kode

Dengan informasi ini kami dapat menyiapkan koleksi:

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

Pertama, kami bergabung dengan barang-barang milik setiap pesanan:

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

Kemudian, kami memfilter status pesanan yang tidak dapat dikirim ("nin" = "not in"):

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

Kemudian, kami membuat ekspresi SQL untuk jumlah item yang dapat dikirimkan:

  • kami menjumlahkan qty shippable atas item pesanan
  • untuk item virtual hasilnya adalah 0
  • untuk item "terkunci" hasilnya adalah 0
  • untuk yang lainnya, hasilnya sama qty_ordered - qty_shipped - qty_refunded - qty_canceled

TODO: ambil opsi produk "kirim secara terpisah ke dalam akun. Permintaan ini akan menghitung semua item induk dan anak, jadi akan ada positif palsu. Saya akan menyerahkannya sebagai latihan kepada pembaca untuk juga menghitung hasil isDummy()dalam SQL.

Jumlahnya akan tersedia dengan 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'));

Akhirnya kami hanya memfilter pesanan dengan jumlah positif barang yang dapat dikirim. Kita harus menggunakan "HAVING" alih-alih "WHERE" karena kolom dihitung dengan fungsi agregat:

$collection->getSelect()->having('shippable_items > 0'));
Fabian Schmengler
sumber
penjelasan yang bagus. Saya akan periksa. + 1
Amit Bera
2

Itu tidak mungkin dilakukan because of lot of conditionsdan kapan saja we use canShip()berfungsi. Terlalu rumit untuk melakukan itu.

Itu not only depend one /two order fields dependseperti

  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

dll

Jadi, itu tergantung pada beberapa logika / kondisi kompleks seperti:

Lihat tampilan di kelas Mage_Sales_Model_Order , dan Anda bisa memahaminya.

 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
sumber