Pregunta

Estoy intentando agregar algunas columnas adicionales a la cuadrícula de clientes de Magento.Tengo un recuento de pedidos funcionando correctamente (cantidad total de pedidos que ha realizado un cliente)

Estoy intentando ingresar la fecha del último pedido, pero no puedo hacerlo funcionar.¿Alguien ha hecho esto antes o alguien puede indicarme la dirección correcta sobre cómo hacerlo?

Este es mi código actual, pero genera errores y solo muestra una consulta SQL.

    $orderTableName = Mage::getSingleton('core/resource')
        ->getTableName('sales/order');
    $collection->getSelect()
        ->joinLeft(
            array('orders' => $orderTableName),
            'orders.customer_id=e.entity_id',
            array(
                'order_count' => 'COUNT(customer_id)',
                'last_order' => 'MAX(created_at)'
            )
        );
    $collection->groupByAttribute('entity_id');
¿Fue útil?

Solución

Aquí está el ejemplo de trabajo para CE 1.8.1:

protected function _prepareCollection()
{
    $collection = Mage::getResourceModel('customer/customer_collection')
        ->addNameToSelect()
        ->addAttributeToSelect('email')
        ->addAttributeToSelect('created_at')
        ->addAttributeToSelect('group_id')
        ->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
        ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
        ->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
        ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
        ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');



    // add 2 new fields as sub queries      
    $sql ='SELECT MAX(o.created_at)'
        . ' FROM ' . Mage::getSingleton('core/resource')->getTableName('sales/order') . ' AS o'
        . ' WHERE o.customer_id = e.entity_id ';
    $expr = new Zend_Db_Expr('(' . $sql . ')'); 

    $collection->getSelect()->from(null, array('last_order_date'=>$expr));

    $sql ='SELECT COUNT(*)'
        . ' FROM ' . Mage::getSingleton('core/resource')->getTableName('sales/order') . ' AS o'
        . ' WHERE o.customer_id = e.entity_id ';
    $expr = new Zend_Db_Expr('(' . $sql . ')'); 

    $collection->getSelect()->from(null, array('orders_count'=>$expr));

    //echo $collection->getSelect(); exit;      

    $this->setCollection($collection);

    return parent::_prepareCollection();
}

y

protected function _prepareColumns()
{
    $this->addColumn('entity_id', array(
        'header'    => Mage::helper('customer')->__('ID'),
        'width'     => '50px',
        'index'     => 'entity_id',
        'type'  => 'number',
    ));

    $this->addColumn('last_order_date', array(
        'header'    => Mage::helper('customer')->__('Last Order Date'),
        'type'      => 'datetime',
        'align'     => 'center',
        'index'     => 'last_order_date',
        'gmtoffset' => true,        
    ));

    $this->addColumn('orders_count', array(
        'header'    => Mage::helper('customer')->__('Orders Count'),
        'index'     => 'orders_count',
    ));

    ........
    ........

La salida es

órdenes

Otros consejos

Así es como haría esto.
Yo crearía 2 atributos llamados last_order_date y orders_count en la entidad del cliente que solo son visibles en el backend.O no visible en absoluto. Aquí hay una forma posible de agregarlos..

Yo crearía un observador en el checkout_submit_all_after evento que cambiaría los valores de estos atributos.
Algo como esto:

public function checkoutSubmitAllAfter($observer) {
    $order = $observer->getEvent()->getOrder();
    if ($order) { //if on onepage checkout;
        $customer = $order->getCustomer();
        $lastOrderDate = $order->getCreatedAt();
        $increment = 1;
    }
    else { //if on multishipping checkout
       $orders = $observer->getEvent()->getOrders();
       //get last order that's the important one;
       $order = $orders[count($orders) - 1];
       $customer = $order->getCustomer();
       $lastOrderDate = $order->getCreatedAt();
       $increment = count($orders);
    }
    if ($customer && $customer->getId()) { //check if the customer is logged in
       //make sure you have a clean instance of the customer
       //this line may not be needed. Test with it and without it.
       $customer = Mage::getModel('customer/customer')->load($customer->getId());
       //set the new values on the customer entity
       $customer->setLastOrderDate($lastOrderDate);
       $customer->setOrdersCount((int)$customer->getOrdersCount() + $increment);
       $customer->save();
    }
}

No he probado el código, por lo que es posible que me haya perdido algo.

Ahora tiene los valores que necesita en el objeto del cliente y no necesita ningún orden loco de unión o clasificación y especialmente no group by.
Puede agrega tus 2 nuevas columnas en la cuadrícula de clientes e incluso puede ordenarlos y filtrarlos fácilmente.

Si ya tiene clientes en su base de datos, necesitará un script único que establezca los valores para los clientes existentes.
Pero puedes identificar estos valores fácilmente.

Si solo necesita el estado "completo" como yo, luego agregue solo agregue . ' AND o.status LIKE "complete" ' después de . ' WHERE o.customer_id = e.entity_id ';

También he agregado el dinero total gastado por el cliente (por lo que el total de todos sus pedidos completos)

    $total_pricesql ='SELECT sum(o.base_grand_total)'
        . ' FROM ' . Mage::getSingleton('core/resource')->getTableName('sales/order') . ' AS o'
        . ' WHERE o.customer_id = e.entity_id ' . ' AND o.status LIKE  "complete" ';
    $expr = new Zend_Db_Expr('(' . $total_pricesql . ')'); 

    $collection->getSelect()->from(null, array('total_price'=>$expr));

y más tarde en el mismo archivo

    $this->addColumn('total_price', array(
        'header' => Mage::helper('sales')->__('Total'),
        'index' => 'total_price',
        'type'  => 'number',
        'filter'    => false,
    ));

así que cambie los primeros códigos de la amastia:

protected function _prepareCollection() {
$collection = Mage::getResourceModel('customer/customer_collection')
    ->addNameToSelect()
    ->addAttributeToSelect('email')
    ->addAttributeToSelect('created_at')
    ->addAttributeToSelect('group_id')
    ->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
    ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
    ->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
    ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
    ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');



// add 3 new fields as sub queries      
$sql ='SELECT MAX(o.created_at)'
    . ' FROM ' . Mage::getSingleton('core/resource')->getTableName('sales/order') . ' AS o'
    . ' WHERE o.customer_id = e.entity_id ' . ' AND o.status LIKE  "complete" ';
$expr = new Zend_Db_Expr('(' . $sql . ')'); 

$collection->getSelect()->from(null, array('last_order_date'=>$expr));

$sql ='SELECT COUNT(*)'
    . ' FROM ' . Mage::getSingleton('core/resource')->getTableName('sales/order') . ' AS o'
    . ' WHERE o.customer_id = e.entity_id ' . ' AND o.status LIKE  "complete" ';
$expr = new Zend_Db_Expr('(' . $sql . ')'); 

$collection->getSelect()->from(null, array('orders_count'=>$expr));

$total_pricesql ='SELECT sum(o.base_grand_total)'
    . ' FROM ' . Mage::getSingleton('core/resource')->getTableName('sales/order') . ' AS o'
    . ' WHERE o.customer_id = e.entity_id ' . ' AND o.status LIKE  "complete" ';
$expr = new Zend_Db_Expr('(' . $total_pricesql . ')'); 

$collection->getSelect()->from(null, array('total_price'=>$expr));

//echo $collection->getSelect(); exit;      

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

y el segundo código:

protected function _prepareColumns() {
$this->addColumn('entity_id', array(
    'header'    => Mage::helper('customer')->__('ID'),
    'width'     => '50px',
    'index'     => 'entity_id',
    'type'  => 'number',
));

$this->addColumn('last_order_date', array(
    'header'    => Mage::helper('customer')->__('Last Order Date'),
    'type'      => 'datetime',
    'align'     => 'center',
    'index'     => 'last_order_date',
    'gmtoffset' => true,        
));

$this->addColumn('orders_count', array(
    'header'    => Mage::helper('customer')->__('Orders Count'),
    'index'     => 'orders_count',
));

$this->addColumn('total_price', array(
    'header' => Mage::helper('sales')->__('Total'),
    'index' => 'total_price',
    'type'  => 'number',
    'filter'    => false,
));

........
........

Aquí es la forma en que resolví el problema con el filtro y el funcionamiento de pedidos, _prepareCollection:

$collection = Mage::getResourceModel('customer/customer_collection')
    ->addNameToSelect()
    ->joinAttribute('billing_street', 'customer_address/street', 'default_billing', null, 'left')
    ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
    ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
    ->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
;

$sql = sprintf('SELECT MAX(o.created_at) AS created_at FROM %s AS o GROUP BY o.customer_id', Mage::getSingleton('core/resource')->getTableName('sales/order_grid'));
$expr = new Zend_Db_Expr('(' . $sql . ')');

$collection->joinTable(array('order' => 'sales/order_grid'), 'customer_id=entity_id', array('order_created_at' => 'created_at'), "order.created_at IN ($expr)", 'left');

luego en _prepareColumns:

$this->addColumn('order_created_at', array(
    'header'    => Mage::helper('sales')->__('Purchased On'),
    'type'      => 'datetime',
    'index'     => 'order_created_at',
    'gmtoffset' => true,
));

Licenciado bajo: CC-BY-SA con atribución
No afiliado a magento.stackexchange
scroll top