2
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.

7
  • it request please focus on answer instead of edit suggestion
    – HaFiz Umer
    Commented Mar 14, 2019 at 7:44
  • 1
    Your code is from the Invoice model. That collection comes from sales_order_invoice_item. If your code would be in the Order model it would work. Do you want to filter the invoice item collection?
    – HelgeB
    Commented Mar 14, 2019 at 8:37
  • no am not filter invoice item collection. as my knowledge in the New invoice page when click on invoice tap in order view page a Section "Invoice to item" contain orders items that comes from sales_order_item . am right ? this collection comes from sales_order_item /
    – HaFiz Umer
    Commented Mar 14, 2019 at 10:04
  • 1
    Yes, that items come from order items collection. I've tried to explain you the situation in that context and showed you also an alternative option in my answer below.
    – HelgeB
    Commented Mar 14, 2019 at 14:13
  • 1
    @HaFizUmer Yes as HelgeB mentioned what you've mentioned is invoice class that doesn't have your sales_order_item attribute so below I've given answer for sales_order_item collection to filter by custom attribute, hope that helps you or else do clarify on what you required from this class Commented Mar 15, 2019 at 4:41

3 Answers 3

1

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.

13
  • HelgeB and @Prathap Gunasekaran Thanks for answering me ! my requirement was that i want to filter collection in the new invoice page. I apply condition on the custom attribute (current_seller_id) that is in sales_order_item . . I did this and share with both of you in answer please wait. Thanks for response me ASA
    – HaFiz Umer
    Commented Mar 15, 2019 at 9:58
  • ! yes it absolute Answer . others thing also manage from your solution,for example total,grantotal and current login user entities insert in database. from my filter getAllItems() it insert all items of invoice and total etc are also count wrong. Thanks
    – HaFiz Umer
    Commented Mar 20, 2019 at 7:32
  • HelgeB ! 1 thing more need to correct. In New Invoice page those items which is not for current user is present in Items to invoice Section with qty,grandtotal,rowtotal etc all thing value are 0. How can we exclude these items which is not belong to current user ? I want that not to shown also in New Invoice page. how remove those items ? it should look like this i.sstatic.net/B2HZw.png
    – HaFiz Umer
    Commented Mar 20, 2019 at 7:39
  • I would not remove them from the collection (because of complications in the calculation process, e.g. for totals) but either not render them in the template (skip the row with qty = 0 or better current_seller_id does not match) or using css class to just hide the row. Just look for the template and see what's the best for you - I guess the template is somewehere in the sales module in adminhtml templates: order/invoice/create/items/renderer/default.phtml could be the location
    – HelgeB
    Commented Mar 20, 2019 at 7:47
  • okay HelgeB ! i try to hide these row from template or css
    – HaFiz Umer
    Commented Mar 20, 2019 at 8:04
1

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

3
  • Dear in my requirement i don't make controller . I have to extend this same method getAllItems of this class Magento\Sales\Model\Order\Invoice.php have any other way to apply filter on same class ?
    – HaFiz Umer
    Commented Mar 14, 2019 at 7:54
  • Updated and you can use anywhere to apply filter in this method whether it is block or controller etc.., @HaFizUmer Commented Mar 14, 2019 at 8:07
  • @HaFizUmer make sure addFieldToFilter() is for non-EAV collection and for EAV collection you gotta go with addAttributeToFilter() and the arguments remains same. Commented Mar 14, 2019 at 9:55
0

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.