It turns out the same error in the same place, that's why and how I fixed it.
Magento order fulfillment reports build a "list" from "sales_flat_order_item", then join the "catalog / product" for more product information (sku, type, options, attribute_set, etc.).
In my case, 3 products were removed from the store, when Magento built the list and joined the catalog / product, all the information above was NULL. When the Report module creates a collection, in the addItem method it tries to set the identifier as the key in the collection array, there is no identifier in this remote product, therefore NULL is set.
Imagine this set of elements for creating a report.
ID - Name: 1, 2, 3, REMOTE ITEM, 4
When "DELETE ITEM" is added to the collection, it will look like this:
Array( 1 => Object, 2 => Object, 3 => Object, 4 => Object (DELETED ITEM) )
This is due to the fact that in addItem, when there is no Magento ID, add a new position to the array with automatic addition:
if (!is_null($itemId)) { . . . } else { $this->_items[] = $item; }
Then, when the collection adds the following element (ID: 4), you will get the exception that you are looking at:
if (isset($this->_items[$itemId])) { throw new Exception('Item ('.get_class($item).') with the same id "'.$item->getId().'" already exist'); }
Changing the way addItem works is very dangerous! Collections are used throughout Magento by adding a trycatch block that will definitely affect how your store works in other places / modules. Here is how I fixed it:
You can either copy to local or ovewrite using a custom module, it is up to you:
Add a new method to "Reports_Product / Collection" to filter only "existing products"
Application / code / local / Mage / Reports / Model / mysql4 / product / Collection.php
public function addNotDeletedProductRestrition(){ $this->getSelect()->where('order_items.product_id is NOT NULL'); return $this; }
Call this method in the ORDERED collection.
Application / code / local / Mage / Reports / Model / mysql4 / Product / Ordered / Collection.php
protected function _joinFields($from = '', $to = '') { $this->addAttributeToSelect('*') ->addOrderedQty($from, $to) ->setOrder('ordered_qty', 'desc') ->addNotDeletedProductRestrition(); return $this; }
I placed inside _joinFields, but you can call wherever you want.
Sorry for my rusty English, I do not have much time to review, this error has already accepted me a lot.