Solucionado! Evitar la creación múltiple de pedidos en Prestashop

En Prestashop ocasionalmente nos encontramos con un molesto problema. Los pedidos de los clientes se dividen en mas de uno, conservando el mismo código de referencia.

PedidosDuplicados

Tras realizar una exhaustiva investigación nos dimos cuenta de que el problema tenia un nombre propio: transportistas. Concretamente el tipo de transportista asociado a los productos que componen el carrito.

ConfiguracionTransportistaPrestashop por defecto separa los items del carrito en diferentes pedidos agrupándolos por su transportista asociado. En teoría es un buen sistema para ayudar en la gestión interna del eCommerce a la hora de enviar los productos.

El problema viene si como en nuestro caso solamente utilizamos un transportista pero generamos otro gratuito para los artículos que queramos vender sin el importe de transportista, como en el caso de los obsequios.

Transportistas

Este es uno de los numerosos casos en los que Prestashop decide un comportamiento sin dar la opción a desactivarlo o ajustarlo.

La única manera para conseguirlo pasa por modificar via los overrides la clase que gestiona esta funcionalidad. Específicamente la clase Cart.php y su función getPackageList(). Las líneas destacadas son las que se han añadido a la programación original.

public function getPackageList($flush = false)
{
static $cache = array();
if (isset($cache[(int)$this - >
id . '_' . (int)$this - >
id_address_delivery]) & amp; & amp;
$cache[(int)$this - >
id . '_' . (int)$this - >
id_address_delivery] !== false & amp; & amp;
!$flush) return $cache[(int)$this - >
id . '_' . (int)$this - >
id_address_delivery];
$product_list = $this - >
getProducts();
// Step 1 : Get product informations (warehouse_list and carrier_list), count warehouse
// Determine the best warehouse to determine the packages
// For that we count the number of time we can use a warehouse for a specific delivery address
$warehouse_count_by_address = array();
$warehouse_carrier_list = array();
$stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT');
foreach ($product_list as & amp;
$product)
{
if ((int)$product['id_address_delivery'] == 0) $product['id_address_delivery'] = (int)$this - >
id_address_delivery;
if (!isset($warehouse_count_by_address[$product['id_address_delivery']])) $warehouse_count_by_address[$product['id_address_delivery']] = array();
$product['warehouse_list'] = array();
if ($stock_management_active & amp; & amp;
((int)$product['advanced_stock_management'] == 1 || Pack::usesAdvancedStockManagement((int)$product['id_product'])))
{
$warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute'], $this - >
id_shop);
if (count($warehouse_list) == 0) $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute']);
// Does the product is in stock ?
// If yes, get only warehouse where the product is in stock
$warehouse_in_stock = array();
$manager = StockManagerFactory::getManager();
foreach ($warehouse_list as $key = & gt;
$warehouse)
{
$product_real_quantities = $manager - >
getProductRealQuantities($product['id_product'], $product['id_product_attribute'], array(
$warehouse['id_warehouse']
) , true);
if ($product_real_quantities & gt;
0 || Pack::isPack((int)$product['id_product'])) $warehouse_in_stock[] = $warehouse;
}
if (!empty($warehouse_in_stock))
{
$warehouse_list = $warehouse_in_stock;
$product['in_stock'] = true;
}
else $product['in_stock'] = false;
}
else
{
//simulate default warehouse
$warehouse_list = array(
0
);
$product['in_stock'] = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']) & gt;
0;
}
foreach ($warehouse_list as $warehouse)
{
if (!isset($warehouse_carrier_list[$warehouse['id_warehouse']]))
{
$warehouse_object = new Warehouse($warehouse['id_warehouse']);
$warehouse_carrier_list[$warehouse['id_warehouse']] = $warehouse_object - >
getCarriers();
}
$product['warehouse_list'][] = $warehouse['id_warehouse'];
if (!isset($warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']])) $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']] = 0;
$warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']]++;
}
}
unset($product);
arsort($warehouse_count_by_address);
// Guardamos si hay transportistas gratuitos y de pago mezclados
$free_carriers = array();
$payment_carriers = array();
// Step 2 : Group product by warehouse
$grouped_by_warehouse = array();
foreach ($product_list as & amp;
$product)
{
if (!isset($grouped_by_warehouse[$product['id_address_delivery']])) $grouped_by_warehouse[$product['id_address_delivery']] = array(
'in_stock' = & gt;
array() ,
'out_of_stock' = & gt;
array() ,
);
$product['carrier_list'] = array();
$id_warehouse = 0;
foreach ($warehouse_count_by_address[$product['id_address_delivery']] as $id_war = & gt;
$val)
{
if (in_array((int)$id_war, $product['warehouse_list']))
{
$product['carrier_list'] = array_merge($product['carrier_list'], Carrier::getAvailableCarrierList(new Product($product['id_product']) , $id_war, $product['id_address_delivery'], null, $this));
if (!$id_warehouse) $id_warehouse = (int)$id_war;
}
}
if (!isset($grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse]))
{
$grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse] = array();
$grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse] = array();
}
if (!$this - >
allow_seperated_package) $key = 'in_stock';
else $key = $product['in_stock'] ? 'in_stock' : 'out_of_stock';
if (empty($product['carrier_list'])) $product['carrier_list'] = array(
0
);
foreach ($product['carrier_list'] as $id_carrier)
{
if (!in_array($id_carrier, $free_carriers) & amp; & amp;
!in_array($id_carrier, $payment_carriers))
{
// Si el carrier no esta clasificado lo añadimos.
$oCarrier = new Carrier((int)$id_carrier);
if ($oCarrier - >
is_free)
{
$free_carriers[] = (int)$id_carrier;
}
else
{
$payment_carriers[] = (int)$id_carrier;
}
}
}
$grouped_by_warehouse[$product['id_address_delivery']][$key][$id_warehouse][] = $product;
}
unset($product);
$first_payment_carriers = 0;
if (count($free_carriers) & amp; & amp;
count($payment_carriers))
{
$first_payment_carriers = $payment_carriers[0];
}
// Step 3 : grouped product from grouped_by_warehouse by available carriers
$grouped_by_carriers = array();
foreach ($grouped_by_warehouse as $id_address_delivery = & gt;
$products_in_stock_list)
{
if (!isset($grouped_by_carriers[$id_address_delivery])) $grouped_by_carriers[$id_address_delivery] = array(
'in_stock' = & gt;
array() ,
'out_of_stock' = & gt;
array() ,
);
foreach ($products_in_stock_list as $key = & gt;
$warehouse_list)
{
if (!isset($grouped_by_carriers[$id_address_delivery][$key])) $grouped_by_carriers[$id_address_delivery][$key] = array();
foreach ($warehouse_list as $id_warehouse = & gt;
$product_list)
{
if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse])) $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse] = array();
foreach ($product_list as $product)
{
// Si tenemos mix de transportistas de pago y demas, quitamos los gratuitos.
if (!empty($first_payment_carriers))
{
$carrier_list = array();
foreach ($product['carrier_list'] as $id_carrier)
{
if (in_array($id_carrier, $payment_carriers))
{
$carrier_list[] = (string)$id_carrier;
}
}
// Si el producto solo tiene gratuitos, fijamos el primero que haya de pago (en teoria solo hay uno)
if (empty($carrier_list))
{
$carrier_list[] = (string)$first_payment_carriers;
}
$product['carrier_list'] = $carrier_list;
}
$package_carriers_key = implode(',', $product['carrier_list']);
if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key])) $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key] = array(
'product_list' = & gt;
array() ,
'carrier_list' = & gt;
$product['carrier_list'],
'warehouse_list' = & gt;
$product['warehouse_list']
);
$grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key]['product_list'][] = $product;
}
}
}
}
$package_list = array();
// Step 4 : merge product from grouped_by_carriers into $package to minimize the number of package
foreach ($grouped_by_carriers as $id_address_delivery = & gt;
$products_in_stock_list)
{
if (!isset($package_list[$id_address_delivery])) $package_list[$id_address_delivery] = array(
'in_stock' = & gt;
array() ,
'out_of_stock' = & gt;
array() ,
);
foreach ($products_in_stock_list as $key = & gt;
$warehouse_list)
{
if (!isset($package_list[$id_address_delivery][$key])) $package_list[$id_address_delivery][$key] = array();
// Count occurance of each carriers to minimize the number of packages
$carrier_count = array();
foreach ($warehouse_list as $id_warehouse = & gt;
$products_grouped_by_carriers)
{
foreach ($products_grouped_by_carriers as $data)
{
foreach ($data['carrier_list'] as $id_carrier)
{
if (!isset($carrier_count[$id_carrier])) $carrier_count[$id_carrier] = 0;
$carrier_count[$id_carrier]++;
}
}
}
arsort($carrier_count);
foreach ($warehouse_list as $id_warehouse = & gt;
$products_grouped_by_carriers)
{
if (!isset($package_list[$id_address_delivery][$key][$id_warehouse])) $package_list[$id_address_delivery][$key][$id_warehouse] = array();
foreach ($products_grouped_by_carriers as $data)
{
foreach ($carrier_count as $id_carrier = & gt;
$rate)
{
if (in_array($id_carrier, $data['carrier_list']))
{
if (!isset($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier])) $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier] = array(
'carrier_list' = & gt;
$data['carrier_list'],
'warehouse_list' = & gt;
$data['warehouse_list'],
'product_list' = & gt;
array() ,
);
$package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'] = array_intersect($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'], $data['carrier_list']);
$package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'] = array_merge($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'], $data['product_list']);
break;
}
}
}
}
}
}
// Step 5 : Reduce depth of $package_list
$final_package_list = array();
foreach ($package_list as $id_address_delivery = & gt;
$products_in_stock_list)
{
if (!isset($final_package_list[$id_address_delivery])) $final_package_list[$id_address_delivery] = array();
foreach ($products_in_stock_list as $key = & gt;
$warehouse_list) foreach ($warehouse_list as $id_warehouse = & gt;
$products_grouped_by_carriers) foreach ($products_grouped_by_carriers as $data)
{
$final_package_list[$id_address_delivery][] = array(
'product_list' = & gt;
$data['product_list'],
'carrier_list' = & gt;
$data['carrier_list'],
'warehouse_list' = & gt;
$data['warehouse_list'],
'id_warehouse' = & gt;
$id_warehouse,
);
}
}
$cache[(int)$this - >
id] = $final_package_list;
return $final_package_list;
}

De esta manera en caso de existir más de un transportista, en nuestro caso significa que uno es el gratuito y otro de pago, con lo que asumimos que el transportista sera solo el de pago así no nos encontraremos con mas duplicidad de pedidos.


Publicado

en

por

  • Los diez negritos

    “Los Diez Negritos“, una cautivante novela de misterio escrita por Agatha Christie, es un tour de force en el género del suspense. Publicada en 1939 bajo el título original “And Then There Were None”, esta obra maestra sumerge a los lectores en una trama inquietante, donde cada página está tejida con intriga y giros sorprendentes.…

  • Sherlock Holmes – El sabueso de los Baskerville

    “El Sabueso de los Baskerville” es una obra maestra del misterio escrita por Sir Arthur Conan Doyle, y es parte de la serie de Sherlock Holmes. La novela nos transporta a los páramos sombríos y misteriosos de Dartmoor, donde la leyenda de la familia Baskerville se entrelaza con un enigma de asesinato y oscuridad. En…

  • El juego de Ender

    “El Juego de Ender” es una novela de ciencia ficción escrita por Orson Scott Card que se ha convertido en un referente del género. La historia nos sumerge en un futuro distópico, donde la humanidad se encuentra en una constante lucha contra una raza alienígena conocida como los Insectores. La trama sigue a Andrew “Ender”…

  • Wonder – La lección de August

    Su cara lo hace distinto y él solo quiere ser uno más. Camina siempre mirando al suelo, la cabeza gacha y el flequillo tratando en vano de esconder su rostro, pero, aun así, es objeto de miradas furtivas, susurros ahogados y codazos de asombro. August sale poco, su vida transcurre entre las acogedoras paredes de…

  • 20.000 leguas de viaje submarino

    “Veinte Mil Leguas de Viaje Submarino” fue originalmente publicada en Francia en 1869 por el autor Jules Verne, cuyo nombre solemos castellanizar como Julio Verne. Esta obra se clasifica principalmente como una novela de aventuras, aunque contiene matices de ciencia ficción y toques de fantasía. Con el paso del tiempo, la dimensión de ciencia ficción…

  • Obsidiana, sangre y oro

    En el año 2011, Érik de Diego se encuentra sumido en una profunda crisis existencial que lo impulsa a tomar una drástica decisión: huir y tomarse un tiempo para reflexionar sobre su vida. Su primer destino es Guatemala, un país que poco a poco lo cautiva y lo envuelve en su rica historia, conflictos, desigualdades…

Comments

7 responses to “Solucionado! Evitar la creación múltiple de pedidos en Prestashop”

  1. Jaime Avatar
    Jaime

    ¿Y si hay 2 transportistas de pago?

    1- Para Peninsula
    2- Para las Islas

    Tengo algunos productos que no quiero enviar a las islas y por ello les asigno el transportista 1 (peninsula).

    Me hacen un pedido mezclando productos de 1 transportista y del otro, el destino es Mallorca. Prestashop lo que realiza es un pedido duplicado solo cobrando los gastos de los productos que si se pueden enviar a Mallorca. Los otros los envia gratis.

    ¿Como puedo evitar esto? Que no me deje realizar el pedidos. Lo que si puedo hacer es permitir al Transportista 1 que envie a Islas y así por lo menos no palmo pasta. Pero preferiria que no me dejara terminar el pedidos.

  2. Jonathan Cortes Bastidas Avatar
    Jonathan Cortes Bastidas

    tengo un problema similar.

    Resulta que en una tienda online un cliente hizo un pedido de 3 productos (y su respectivo pago) pero al administrador de la tienda (y a mi tambien) me llegó el correo del pedido de tan solo 2 productos pero el email de Payu notificó el pago de los 3 productos, cosa que despertó la alerta a del administrador de la tienda del porqué había pagado de más si solo habían 2 productos en el email del pedido.

    Pues bien, me metí en la sección de Pedidos de Chocolate y resulta que el pedido con numero #339 tiene 2 productos pero en la parte inferior hay una sección llamada PEDIDOS RELACIONADOS, donde está el pedido con numero #340 y en ese pedido está el otro producto. La suma de los 2 pedidos efectivamente da lo que el cliente pagó, pero no sabemos el porqué Prestashop partió de esa manera los pedidos y porqué solo notificó en el que hay 2 productos y el otro no.

    la tienda solo tiene habilitado un transporte sin embargo hay creados 2, de los cuales el que está des-habilitado de envío gratis.

    no es un caso que pase a cada rato por eso se nos hace muy extraño.

    muchas gracias por su ayuda.

  3. David Garcia Avatar

    ¿Qué versión utilizas?

  4. Jonathan Cortes Bastidas Avatar
    Jonathan Cortes Bastidas

    la 1.6.1.1

    Muchas gracias.

  5. Jaume Avatar

    Hola, existe algo similar para que no duplique los pedidos cuando se trata de articulos de varios almacenes distintos?
    He probado esta opción pero al modificar el cart.php me permite solo pedir artículos del almacen principal

  6. Juan Miguel Avatar

    Hola David, tengo una web con ese problema y me gustaria solucionarlo, ¿me puedes ayudar?, ¿ donde y como me pongo encontacto contigo para darte los datos de acceso y modifiques lo que se necesite?, ya me enviaras el presupuesto. Muchas gracias.

  7. Edgar Oshinstar Avatar
    Edgar Oshinstar

    Hola muchachos tengo un problema explico:

    Tengo una tienda con 2 tipos de transportistas, los cuales estan asignados a prouctos en especifico.

    Al realizar una orden con 1 solo tipo de transportista todo se procesa de manera correcta.

    Al generar una orden que tenga 2 transportistas es donde se genera el problema con el monto TOTAL, sabemos que el monto total que es la suma de (Total products + Total shipping + Total tax ), en el resumen del pedido me lo da bien. Pero al darle al boton de CONFIRMAR MI ORDEN y me manda a la pantalla de Confirmación del pedido, el monto total no es correcto ( Me muestra el monto solo de los productos que estan asignado a 1 transportita en especifico, los otros productos asigandos al otro transportista y el costo de ese otro transportista no lo toma en cuenta)

    Me puedes ayudar por favor

Leave a Reply

Your email address will not be published. Required fields are marked *