Question

namespace Magento\Sales\Model\Order;
class Invoice {
 public function getAllItems()
    {
        $items = [];
             foreach ($this->getItemsCollection() as $item) {
            if (!$item->isDeleted()) {
                $items[] = $item;
            }
        }
}
  return $filter;
    }

This Magento 2 core method. But I want to apply filter in this collection. As my knowledge this collection from sales_order_item table.
I Save custom attribute(current_seller_id) in sales_order_item table but in this collection my custom attribute is missing and I need to filter collection on the condition of my custom attribute.

Can anyone please help me to tell why my custom attribute is not there and how can I add custom attribute in this collection.

I try

  public function getAllItems()
    {
        $items = [];
        $filter=[];
        foreach ($this->getItemsCollection()->addFieldToFilter('current_seller_id',array('eq'=>27)) as $item) {
            if (!$item->isDeleted()) {
                $items[] = $item;
            }

       }
return $items;
}

But not filter the collection.

Was it helpful?

Solution

First it needs to said that you cant apply any filter on getItemsCollection() in Order model because the collection is already loaded in that method and after loading filters can't be applied anymore to a collection.

But that shouldn't bother you. You can just iterate through the collection and remove non matching items. For example like this:

$filteredItems = $order->getItemsCollection();
foreach ($filteredItems as $key => $orderItem){
    if ($orderItem->getCurrentSellerId() != 27){
        $filteredItems->removeItemByKey($key);
    }
}
$order->setItems($filteredItems->getItems());

You could apply a code like above somewhere appropriate, for example before Magento\Sales\Model\Service\InvoiceService::prepareInvoice() is called. That's the method which creates new invoices. If you want to use that, you can change the method code below with that and you won't see non matching items. But you with that approach the totals calculation process may have some difficulties since it's not a good idea to manipulate the order collection in the invoice creation process.

I would suggest you a plugin before the mentioned method, but I would strongly recommend not to manipulate the order item collection but to work with invoiced quantities. That would be exactly the same procedute as you would set quantities into the invoice form and klick UpdateQty's, just automatically based on your current_seller_id. You will see all items in the form, but all non matching have qty 0. That would work as follows:

di.xml entry:

<type name="Magento\Sales\Model\Service\InvoiceService">
    <plugin name="Module_InvoiceService" type="Vendor\Module\Plugin\InvoiceService" sortOrder="10" disabled="false"  />
</type>

Vendor/Module/Plugin/InvoiceService.php

namespace Vendor\Module\Plugin;

class InvoiceService{

  public function beforePrepareInvoice(
        \Magento\Sales\Model\Service\InvoiceService $subject,
        \Magento\Sales\Model\Order $order,
        array $qtys = []
        )
    {
        foreach ($order->getItemsCollection() as $key => $orderItem){
            if ($orderItem->getCurrentSellerId() == 27){
               $qtys[$orderItem->getId()] = $orderItem->getQtyOrdered() - $orderItem->getQtyInvoiced();
            } else {
               $qtys[$orderItem->getId()] = 0;
            }
        }

        return [$order, $qtys];
    }

I hope that helps you understand the context and may be a solution for your requirement.

OTHER TIPS

Try this,

Inject this in your constructor

 \Magento\Sales\Model\Order\ItemFactory $itemFactory

and add this in your constructor

 $this->itemFactory = $itemFactory;

then you can apply filter like this anywhere in your function and in your case it would be like

public function getAllItems()
{
    $current_seller_id = 5;
    $order = $this->itemFactory->create()->getCollection()->addFieldToFilter('current_seller_id', $current_seller_id);
    foreach ($order as $items) {
      echo $itemId =  $items->getItemId();
    }
}

this is how you can add filter by your attribute.

Hope this helps :)

am Giving answer of my question after 2 days struggle, i don't want to spend time others also.

My Problem was that just display those Invoice Items in the New Invoice Page which is belong to current login admin(seller). 1 order may contain 5 products that is belong to different sellers. I already filter items in order view page on the condition on custom attribute(current_seller_id) in sales_order_item.Now want to also filter items to invoice in new Invoice page. i use plugin. make di.xml in the directory VendorName\ModuleName\etc Code

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
 <type name="Magento\Sales\Model\Order\Invoice">
        <plugin name="Invoice_collection_filterPlugin" type="VendorName\ModuleName\Plugin\Invoice" sortOrder="10" disabled="false"  />
    </type>
</config>

make file Invoice.php in VendorName\ModuleName\Plugin\Invoice.php

<?php

namespace VendorName\ModuleName\Plugin;

class Invoice{
protected $authSession;
public function __construct(\Magento\Backend\Model\Auth\Session $authSession)
{
$this->authSession=$authSession;
}
    public function afterGetAllItems(\Magento\Sales\Model\Order\Invoice $subject,$items)
    {
        $filter_InvoiceItems=[];
        $CurrentUserId=$this->authSession->getUser()->getUserId();
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $orderitemrepo = $objectManager->create('\Magento\Sales\Api\OrderItemRepositoryInterface');
        foreach ($items as $row)
        {
            $item_id=$row->getOrderItemId();
            $Item_recorde=$orderitemrepo->get($item_id);
            if($Item_recorde->getData('current_seller_id')==$CurrentUserId){
                $filter_InvoiceItems[]=$row;
            }
        }
        return $filter_InvoiceItems;
    }
}

See please enter image description here

In this order has 5 items But just display 2 because current seller has 2 product in this order.

Thank you

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top