Jump to content

amoswright

Members
  • Posts

    11
  • Joined

  • Last visited

1 Follower

Profile Information

  • First Name
    Amos
  • Last Name
    Wright

Recent Profile Visitors

134 profile views

amoswright's Achievements

Newbie

Newbie (1/14)

3

Reputation

  1. 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]
  2. I had a very similar issue / error as I was trying to install my first module that uses an override. For me, it turned out to be a simple fix: The naming of the class is very specific and must be correct. Working to override getPackageList method for exaple in Cart.php this worked: class Cart extends CartCore { public function getPackageList($flush = false) { parent::getPackageList(); The basic idea I think is that your class declaration for the class that you are overriding ends up being named the same as the file name, which obviously makes sense... but which is not the case if you've simply copied the original file over to the override folder as I'd done :-) since in that file the class is called CartCore.
  3. 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!
  4. 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!
  5. yup, this problem appears to still be a problem in prestashop 1.6.1.5
  6. Update: apparently it was due to a php.ini setting: max_input_vars. Though mine was at 1,000+, had to up it! Increasing it, and then restarting apache fixed this for me. Interestingly, I figured out it was an issue due to a warning when editing language templates, but there was no such warning when editing supply orders.
  7. When creating a supply order from a supplier by selecting "automatically load products" if more than about 90 products are added I can't subsequently "edit" or update the order quantities or other information. I get an error like: Field: quantity_expected is invalid.If I delete the number of products in the supply order to say 80, it will update. Is there a setting I can adjust to allow supply orders with many items, or is this a limitation, or a bug? Have others experienced this? Thanks!
  8. I too am interested in any tricks / mods for working with advanced stock - having a difficult time getting things working correctly, and even if it were working correctly finding the mix of updating wholesale / unit price unwieldy...
  9. This problem occurred for me when I was importing a and loading a saved configuration for mapping the columns. Inadvertently I had added a blank column to the end of the .csv file as compared to the file I'd used when I saved the mapping: deleting the blank column made the issue go away. Turns out the extra column had picked up a default value as opposed to "Ignore this column". Anyway, perhaps obvious, but tripped me up for a while because in checking the columns I hadn't clicked all the way to the end of the columns list. Worth a check.
  10. I needed a sledgehammer approach: add all groups to all categories. I'm new to PrestaShop, so, can't vouch for my code, but, based upon the suggestion above, came up with a script that simply adds all groups to all categories. You save this code as a new page in your PrestaShop site root folder, then load the page in a browser: <?php require(dirname(__FILE__).'/config/config.inc.php'); $groups= Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT c.* FROM `'._DB_PREFIX_.'group` c '); $categories = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT DISTINCT c.* FROM `'._DB_PREFIX_.'category` c LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND cl.`id_lang` = '.(int)Context::getContext()->language->id.') '); foreach($groups as $group){ foreach($categories as $category){ $exists = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('select id_category, id_group from ps_category_group where id_category = "'.$category['id_category'].'" and id_group = "'.$group['id_group'].'"'); if(!$exists) { $categoryObj = new Category($category['id_category'], (int)Context::getContext()->language->id); echo $categoryObj->addGroups(array($group['id_group'])); echo $group['id_group']." added to ".$category['id_category']."<br />"; }else{ echo $group['id_group']." ALREADY added to ".$category['id_category']."<br />"; } } }
  11. We're setting up a b2b / wholesale site, which is US based, but will sell internationally, and wondering about best practices. What we're hoping for, for our setup: 1) We want customers to pay in their native currency, using country specific pricing (not just converted by currency rates). 2) Non-registered users should be able to browse products, without prices. 3) Registered / approved users should browse products/order in the multi-store specific to their country. Non-registered users should not be able to browse any stores except for the default US store. 4) Run prestashop under one domain, and use sub-directories for the multiple stores. 4) Should be easy/intuitive to use for approved customers :-) 5) Ease of maintenance for back-end pricing/product updates. I'm playing around with configurations, and seems like there are several options that are close / might work. Has anyone else made a similar set-up work well? If so, what advise / tricks to offer? My first thought was to share customers between the multi stores, allowing a single login, and then restrict the registered customers "customer group" to the appropriate store. However, if they get off-track and into one of the other stores, that does not work well (would have to code a redirect for logged in users to the appropriate multi store?). Barring that, I'm back to not sharing customers between stores, and trying to work out the details of a good user experience for login and browsing. Thoughts? Thanks!
×
×
  • Create New...