276 lines
13 KiB
PHP
276 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* 2007-2017 PrestaShop
|
|
*
|
|
* NOTICE OF LICENSE
|
|
*
|
|
* This source file is subject to the Open Software License (OSL 3.0)
|
|
* that is bundled with this package in the file LICENSE.txt.
|
|
* It is also available through the world-wide-web at this URL:
|
|
* https://opensource.org/licenses/OSL-3.0
|
|
* If you did not receive a copy of the license and are unable to
|
|
* obtain it through the world-wide-web, please send an email
|
|
* to license@prestashop.com so we can send you a copy immediately.
|
|
*
|
|
* DISCLAIMER
|
|
*
|
|
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
|
* versions in the future. If you wish to customize PrestaShop for your
|
|
* needs please refer to http://www.prestashop.com for more information.
|
|
*
|
|
* @author PrestaShop SA <contact@prestashop.com>
|
|
* @copyright 2007-2017 PrestaShop SA
|
|
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
|
* International Registered Trademark & Property of PrestaShop SA
|
|
*/
|
|
|
|
use PrestaShop\PrestaShop\Adapter\ServiceLocator;
|
|
|
|
class Cart extends CartCore
|
|
{
|
|
|
|
public function getPackageList($flush = false)
|
|
{
|
|
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) {
|
|
// Hugo : problème de transporteurs qui n'apparaissent pas et qui se scindent en deux
|
|
// if ((int)$product['id_address_delivery'] == 0) {
|
|
// $product['id_address_delivery'] = (int)$this->id_address_delivery;
|
|
// }
|
|
|
|
$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();
|
|
|
|
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']]++;
|
|
}
|
|
}
|
|
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) {
|
|
$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_quantity_in_stock;
|
|
$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;
|
|
}
|
|
|
|
}
|