O item (Mage_Sales_Model_Order) com o mesmo ID "X" já existe

12

Após criar uma remessa na área administrativa do Magento, o seguinte erro aparece na var/reportpasta (após uma página de falha padrão do Magento) ao exibir a página da grade de pedidos do administrador:

Item (Mage_Sales_Model_Order) with the same id "1234" already exist

Eu posso me livrar desse erro adicionando uma cláusula DISTINCT ao seletor de objetos varien na app/code/core/Mage/Eav/Model/Entity/Collection/Abstact.phplinha 662. No entanto, eu realmente não quero fazer isso por vários motivos (consultas muito lentas, edição de arquivos principais, etc.).

Qual é a melhor maneira de resolver isso, mantendo a integridade dos dados. Devo excluir o pedido? Eu apreciaria qualquer contribuição construtiva, especialmente sobre o que causaria esse conflito em primeiro lugar. Obrigado.

- editar -

Aqui está o rastreamento completo da pilha para maior clareza / para apontar minha estupidez:

a:5:{i:0;s:67:"Item (Mage_Sales_Model_Order) with the same id "1234" already exist";i:1;s:4829:"#0 lib/Varien/Data/Collection/Db.php(576): Varien_Data_Collection->addItem(Object(Mage_Sales_Model_Order))
#1 app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(533): Varien_Data_Collection_Db->load()
#2 app/code/core/Mage/Adminhtml/Block/Sales/Order/Grid.php(61): Mage_Adminhtml_Block_Widget_Grid->_prepareCollection()
#3 app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(626): Mage_Adminhtml_Block_Sales_Order_Grid->_prepareCollection()
#4 app/code/core/Mage/Adminhtml/Block/Widget/Grid.php(632): Mage_Adminhtml_Block_Widget_Grid->_prepareGrid()
#5 app/code/core/Mage/Core/Block/Abstract.php(862): Mage_Adminhtml_Block_Widget_Grid->_beforeToHtml()
#6 app/code/core/Mage/Core/Block/Abstract.php(582): Mage_Core_Block_Abstract->toHtml()
#7 app/code/core/Mage/Core/Block/Abstract.php(526): Mage_Core_Block_Abstract->_getChildHtml('grid', true)
#8 app/code/core/Mage/Adminhtml/Block/Widget/Grid/Container.php(77): Mage_Core_Block_Abstract->getChildHtml('grid')
#9 app/design/adminhtml/default/default/template/widget/grid/container.phtml(36): Mage_Adminhtml_Block_Widget_Grid_Container->getGridHtml()
#10 app/code/core/Mage/Core/Block/Template.php(241): include('/var/www/html/m...')
#11 app/code/core/Mage/Core/Block/Template.php(272): Mage_Core_Block_Template->fetchView('adminhtml/defau...')
#12 app/code/core/Mage/Core/Block/Template.php(286): Mage_Core_Block_Template->renderView()
#13 app/code/core/Mage/Adminhtml/Block/Template.php(81): Mage_Core_Block_Template->_toHtml()
#14 app/code/core/Mage/Adminhtml/Block/Widget/Container.php(308): Mage_Adminhtml_Block_Template->_toHtml()
#15 app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Adminhtml_Block_Widget_Container->_toHtml()
#16 app/code/core/Mage/Core/Block/Text/List.php(43): Mage_Core_Block_Abstract->toHtml()
#17 app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Core_Block_Text_List->_toHtml()
#18 app/code/core/Mage/Core/Block/Abstract.php(582): Mage_Core_Block_Abstract->toHtml()
#19 app/code/core/Mage/Core/Block/Abstract.php(526): Mage_Core_Block_Abstract->_getChildHtml('content', true)
#20 app/design/adminhtml/default/default/template/page.phtml(74): Mage_Core_Block_Abstract->getChildHtml('content')
#21 app/code/core/Mage/Core/Block/Template.php(241): include('/var/www/html/m...')
#22 app/code/core/Mage/Core/Block/Template.php(272): Mage_Core_Block_Template->fetchView('adminhtml/defau...')
#23 app/code/core/Mage/Core/Block/Template.php(286): Mage_Core_Block_Template->renderView()
#24 app/code/core/Mage/Adminhtml/Block/Template.php(81): Mage_Core_Block_Template->_toHtml()
#25 app/code/core/Mage/Core/Block/Abstract.php(863): Mage_Adminhtml_Block_Template->_toHtml()
#26 app/code/core/Mage/Core/Model/Layout.php(555): Mage_Core_Block_Abstract->toHtml()
#27 app/code/core/Mage/Core/Controller/Varien/Action.php(390): Mage_Core_Model_Layout->getOutput()
#28 app/code/core/Mage/Adminhtml/controllers/Sales/OrderController.php(95): Mage_Core_Controller_Varien_Action->renderLayout()
#29 app/code/core/Mage/Core/Controller/Varien/Action.php(419): Mage_Adminhtml_Sales_OrderController->indexAction()
#30 app/code/core/Mage/Core/Controller/Varien/Router/Standard.php(250): Mage_Core_Controller_Varien_Action->dispatch('index')
#31 app/code/core/Mage/Core/Controller/Varien/Front.php(176): Mage_Core_Controller_Varien_Router_Standard->match(Object(Mage_Core_Controller_Request_Http))
#32 app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch()
#33 app/Mage.php(683): Mage_Core_Model_App->run(Array)
#34 index.php(71): Mage::run('base', 'website')
#35 {main}";s:3:"url";s:72:"/index.php/admin/sales_order/index/key/0b7375aca52608483edc0cf879bd4361/";s:11:"script_name";s:10:"/index.php";s:4:"skin";s:5:"admin";}
Jongosi
fonte
8
FWIW Eu odeio esse erro idiota e gastei mais tempo do que gostaria de admitir a depuração.
philwinkle
Você pode incluir sua consulta de coleção ou código php?
Sukeshini

Respostas:

10

Você adicionou algo à coleção, que adiciona duplicatas ao resultado da consulta.

O que o magento faz com o resultado da consulta é gerar objeto a partir de cada linha e adicionar esses itens à coleção. Se o item já existir, este erro será lançado.

Solução: Qualquer que seja a junção que você adicionou, verifique se o resultado é distinto.

Se você adicionou mais campos ao lado dos sales_flat_order, esses campos podem diferir e, portanto, são filtrados por notas DISTINCT.

Fabian Blechschmidt
fonte
6

Estou adicionando uma resposta, pois ainda não consegui adicionar um comentário. Concordo com o @fabian - no entanto, desencorajo o uso de DISTINCTe GROUP BY, geralmente você pode filtrar sua associação para um único resultado distinto se planejar corretamente.

Por exemplo (eu sei que este é um exemplo trivial):

Se você deveria coletar um pedido usando sales/flat_ordere ingressou no endereço do cliente, existem dois registros armazenados no endereço de cobrança e no endereço de entrega . Para resolver esse problema, é possível especificar em qual tipo de endereço eles desejam ingressar.

Isso soa semelhante à sua situação, exceto não neste cenário.

cinza
fonte
3

Também enfrentamos alguns problemas em nosso sistema. Analisamos o problema e encontramos meu Grid.php(exemplo: /namespace/modulename/Block/Adminhtml/Sales/Order/Grid.php)

Encontramos a _prepareCollection()função no Grid.phparquivo.

A codificação do erro é:

//Error coding
$collection->join(array('payment' => 'sales/order_payment'), 'main_table.entity_id = parent_id', 'method')
            ->getSelect()
            ->where("`payment`.`method` like '%paypal%'");

Solução:

//Solution coding
$collection->join(array('payment' => 'sales/order_payment'), 'main_table.entity_id = parent_id', 'method')
            ->getSelect()
            ->where("`payment`.`method` like '%paypal%'")
            ->group('method');

Temos uso ->group('value')na função de filtro. Agora funcionando bem ... !!!

Sankar_k
fonte
3

Sei que essa é uma pergunta antiga e já foi respondida, mas quero adicionar minha resposta, pois acho que isso poderia ajudar outras pessoas a enfrentar problemas semelhantes. Estou tentando explicar as causas gerais desse tipo de erro.

Para começar, Mage_Sales_Model_Orderem uma instalação padrão do Magento nunca deve ocorrer esse erro. Portanto, suspeito que esse erro seja causado por uma extensão de terceiros (observador, método de gancho, reescrita etc.) ou por uma personalização incorreta de código que corrompeu os dados em primeiro lugar. Ao falar sobre os componentes principais que agem como "estranhos", a distinctsolução nem deveria existir, porque os dados nunca deveriam ter sido corrompidos! É melhor corrigir primeiro os dados do que alterar o código.

Eu enfrentei um problema semelhante ao criar um tipo de entidade EAV personalizado e tudo funcionou bem até que eu editei uma das entidades. De alguma forma, a edição resultou em valor duplicado para um dos atributos de texto da entidade, ou seja, duas linhas na tabela de valores de texto para o mesmo atributo da mesma entidade. A consulta bruta apenas da tabela custom_entity parecia perfeitamente bem sem duplicatas (como poderia ser? A restrição de chave primária já assegurava a integridade); portanto, o problema estava em outro lugar.

Como você já deve ter adivinhado ao carregar a coleção, devido às junções usadas para recuperar as linhas do banco de dados e considerando que havia dois mesmos valores de texto para o mesmo atributo de uma entidade, ela recuperou duas linhas com o mesmo entity_idvalor, mas diferentes value_id.

Como regra geral, quando esse erro ocorre, você deve suspeitar que os dados do banco de dados já foram corrompidos ou que as junções que ocorrem na consulta final recuperem duas linhas quase exatas do banco de dados, duplicando o identificador exclusivo da coleção Itens.

Espero que isto ajude.

PS: Quanto ao porquê do valor duplicado do eav text no meu caso, verifique o comentário de Marius aqui http://inchoo.net/magento/creating-an-eav-based-models-in-magento/

adjco
fonte
0

Este é o meu código está funcionando bem depois de ter o mesmo problema:

    $collection = Mage::getResourceModel('sales/order_grid_collection');
    $prefix = Mage::getConfig()->getTablePrefix();  

    $collection->getSelect()->joinleft(array('order'=> $prefix.'sales_flat_order'),'order.entity_id=main_table.entity_id',array('pdeliverydate'));   

    $collection->getSelect()->joinleft(array('address'=> $prefix.'sales_flat_order_address'),'address.parent_id=main_table.entity_id',array('telephone'))->group('entity_id');

    $this->setCollection($collection);
    return parent::_prepareCollection();

Eu tenho add -> group ('entity_id') para resolver o problema.

Pedro
fonte
Já sugerido há 1 ano ( magento.stackexchange.com/a/139898/46249 ) ... -1.
sv3n
-1

você deve tentar substituir o Mage_Sales_Model_Resource_Order_Grid_Collection::addItemque lança essa exceção:

<?php
class Fixed_Order_Grid_Collection extends Mage_Sales_Model_Resource_Order_Grid_Collection{

    public function addItem(Varien_Object $item)
    {
        $itemId = $this->_getItemId($item);

        if (!is_null($itemId)) {
            if (isset($this->_items[$itemId])) {
                //throw new Exception('Item ('.get_class($item).') with the same id "'.$item->getId().'" already exist');
            }
            $this->_items[$itemId] = $item;
        } else {
            $this->_addItem($item);
        }
        return $this;
    }
}
class MyCompony_MyExtention_Block_Adminhtml_OrderGrid extends Mage_Adminhtml_Block_Widget_Grid
{
     public function __construct()
    {
        parent::__construct();
        $this->setId('sales_order_grid');
        $this->setUseAjax(true);
        $this->setDefaultSort('created_at');
        $this->setDefaultDir('DESC');
        $this->setSaveParametersInSession(true);
    }
    protected function _getCollectionClass()
    {
        return 'sales/order_grid_collection';
    }

    protected function _prepareCollection()
    {
        $collection = new Fixed_Order_Grid_Collection();
        $select = $collection->getSelect();
        $select->join('sales_flat_order_item AS order_item', 'order_item.order_id=main_table.entity_id','quote_item_id',NULL);
        $select->distinct();
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }
...
Sajjad Shirazy
fonte
1
Esta não é uma solução, mas simplesmente uma maneira de se livrar da mensagem de erro.
Niels
1
Os erros de esmagamento não são o mesmo que corrigi-los. Considere adicionar distintos ao resultado da coleção ou agrupar a consulta de junção por um campo.
DWils 25/09