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.
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.
Prestashop 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.
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.
Leave a Reply