amoswright Posted July 28, 2016 Share Posted July 28, 2016 I want to do is make it so that when "Delayed shipping" is enabled, and when two orders are created at checkout, all products/items will only show up in one order or the other. Because our products have "dye lots" and are essentially matched, even if an item is in stock, if the customer requests more than are in stock, that we'd like to put that item wholly in the backordered order. (Currently, the "Delayed shipping" setting splits orders in two such that a backordered product/item may show up in both orders: the in-stock quantities in one order, and another order is for any remaining back ordered quantities. ) So, a Module? I have built some basic but functional modules... but am having a hard time getting oriented on this project. Will I have to override core functionality? If so, what? Or would it be possible / better to use a hook to automatically transfer products after the orders are created? Thanks in advance for any help / advise! Link to comment Share on other sites More sharing options...
chrisranjana.com Posted July 29, 2016 Share Posted July 29, 2016 (edited) It splits into 2 orders only when "Send available items first" checkbox is checked. Am I right ? Edited July 29, 2016 by chrisranjana.com (see edit history) Link to comment Share on other sites More sharing options...
amoswright Posted July 29, 2016 Author Share Posted July 29, 2016 It splits into 2 orders only when "Send available items first" checkbox is checked. Am I right ? Yes, that is correct. However, we do want it split into two orders. We just want it split into two orders differently than it is handled by default. Unchecking the "Send available items first" means that only one order is created. What we want, for example, when a customer orders: Product A. It has qty 1, and qty 2 are ordered Product B. It has qty 1 and 1 is ordered Then we want the two orders to be like this: First order has product B only and is sent immediately Second order has product A on backorder and is not sent until the whole quantity 2 is available. Prestashop, as far as I can tell, only supports by default splitting product A between the two orders, so that in the first order qty 1 of product A is sent, and in the second order another qty 1 of product A is sent to complete the requested amount. Because our products are "matched" we need to pick products from the same "batch", and so can't send qty 1, wait for re-stocking, and then send the remainder from the new batch. Of course, if there is a way to support this in existing settings that'd be awesome! If not, I'd love some advise on the best way to implement this modification. Thanks! Link to comment Share on other sites More sharing options...
chrisranjana.com Posted July 31, 2016 Share Posted July 31, 2016 classes/Cart.php around line 1882 Change $out_stock_part = $product['cart_quantity'] - $product_quantity_in_stock; to $out_stock_part = $product['cart_quantity']; Link to comment Share on other sites More sharing options...
amoswright Posted August 1, 2016 Author Share Posted August 1, 2016 (edited) Thank you chrisanjana.com!!! That was indeed what I was looking for. I made a module to override the relevant class / method in Cart.php. My override file ended up looking like this, if anyone else finds it useful :-) class Cart extends CartCore { public function getPackageList($flush = false) { parent::getPackageList(); static $cache = array(); $cache_key = (int)$this->id.'_'.(int)$this->id_address_delivery; if (isset($cache[$cache_key]) && $cache[$cache_key] !== false && !$flush) { return $cache[$cache_key]; } $product_list = $this->getProducts($flush); // 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(); $stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'); foreach ($product_list as &$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 && (int)$product['advanced_stock_management'] == 1) { $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(); $products_in_order = 0; $products_on_backorder = 0; foreach ($warehouse_list as $key => $warehouse) { $product_real_quantities = $manager->getProductRealQuantities( $product['id_product'], $product['id_product_attribute'], array($warehouse['id_warehouse']), true ); if ($product_real_quantities > 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 => array('id_warehouse' => 0)); $product['in_stock'] = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']) > 0; } foreach ($warehouse_list as $warehouse) { $product['warehouse_list'][$warehouse['id_warehouse']] = $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']]++; } $products_in_order++; $product_quantity_in_stock = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']); if ($product['cart_quantity'] > $product_quantity_in_stock) { $products_on_backorder++; } } unset($product); arsort($warehouse_count_by_address); // Step 2 : Group product by warehouse $grouped_by_warehouse = array(); foreach ($product_list as &$product) { if (!isset($grouped_by_warehouse[$product['id_address_delivery']])) { $grouped_by_warehouse[$product['id_address_delivery']] = array( 'in_stock' => array(), 'out_of_stock' => array(), ); } $product['carrier_list'] = array(); $id_warehouse = 0; foreach ($warehouse_count_by_address[$product['id_address_delivery']] as $id_war => $val) { if (array_key_exists((int)$id_war, $product['warehouse_list'])) { $product['carrier_list'] = Tools::array_replace($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 || $products_in_order==1 || $products_in_order == $products_on_backorder) {//Here, we see if they want "available products first". However, yarn colors are not split, in any case, which is a modification from stock prestashop (below). they're shipped when total qty is available. $key = 'in_stock'; } else { $key = $product['in_stock'] ? 'in_stock' : 'out_of_stock'; $product_quantity_in_stock = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']); if ($product['in_stock'] && $product['cart_quantity'] > $product_quantity_in_stock) { $out_stock_part = $product['cart_quantity']; $product_bis = $product; $product_bis['cart_quantity'] = $out_stock_part; $product_bis['in_stock'] = 0; $product['cart_quantity'] -= $out_stock_part; $grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse][] = $product_bis; } } if (empty($product['carrier_list'])) { $product['carrier_list'] = array(0 => 0); } $grouped_by_warehouse[$product['id_address_delivery']][$key][$id_warehouse][] = $product; } unset($product); // Step 3 : grouped product from grouped_by_warehouse by available carriers $grouped_by_carriers = array(); foreach ($grouped_by_warehouse as $id_address_delivery => $products_in_stock_list) { if (!isset($grouped_by_carriers[$id_address_delivery])) { $grouped_by_carriers[$id_address_delivery] = array( 'in_stock' => array(), 'out_of_stock' => array(), ); } foreach ($products_in_stock_list as $key => $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 => $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) { $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' => array(), 'carrier_list' => $product['carrier_list'], 'warehouse_list' => $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 => $products_in_stock_list) { if (!isset($package_list[$id_address_delivery])) { $package_list[$id_address_delivery] = array( 'in_stock' => array(), 'out_of_stock' => array(), ); } foreach ($products_in_stock_list as $key => $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 => $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 => $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 => $rate) { if (array_key_exists($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' => $data['carrier_list'], 'warehouse_list' => $data['warehouse_list'], 'product_list' => 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 => $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 => $warehouse_list) { foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) { foreach ($products_grouped_by_carriers as $data) { $final_package_list[$id_address_delivery][] = array( 'product_list' => $data['product_list'], 'carrier_list' => $data['carrier_list'], 'warehouse_list' => $data['warehouse_list'], 'id_warehouse' => $id_warehouse, ); } } } } $cache[$cache_key] = $final_package_list; return $final_package_list; } } [updated to reflect that any orders that are wholly backordered should not be split into an "empty" and "in-stock" order, rather only one backordered order] Edited August 10, 2016 by amoswright (see edit history) Link to comment Share on other sites More sharing options...
Chill_user Posted October 29, 2019 Share Posted October 29, 2019 (edited) Tried to do as you disccussed, but I have unexpected error and it doesn't split orders P.S. 1.7 Edited October 30, 2019 by Amantha Bill (see edit history) Link to comment Share on other sites More sharing options...
kratek Posted November 26, 2019 Share Posted November 26, 2019 Hey, should that option works? I switched it on and I my option "warehouse management" is ON, and "allow order products to be out of stock" is ON, but on the order page checkbox fot "delayed shipping" does not apear. Link to comment Share on other sites More sharing options...
kratek Posted November 27, 2019 Share Posted November 27, 2019 Is anybody here who is using this function in Prestashop 1.7? In my opinion that does not work anymore Link to comment Share on other sites More sharing options...
jaravivi Posted February 25, 2020 Share Posted February 25, 2020 En 27/11/2019 a las 9:05 AM, kratek dijo: Is anybody here who is using this function in Prestashop 1.7? In my opinion that does not work anymore Hello, I am currently with 1.7.6.3 and I have the same problem, desperately searched for information from all sides and the only thing I found has been a problem that affects all versions of PS 1.7 and they have labeled it as "minor error", a user put a prestashop ticket or something like that (I don't know very well how all that goes yet) but I think there is still no solution. Here the original ticket: http://forge.prestashop.com/browse/BOOM-4539 Here I leave the github conversation that I found, you can comment on your discontent, I hope that if more people report the error, they can correct it or give some solution "quickly". https://github.com/PrestaShop/PrestaShop/issues/9781 Greetings Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now