// StockManager: Fixed

This commit is contained in:
bMancone
2011-10-11 14:12:40 +00:00
parent a019c36cbe
commit 998741905b
+84 -102
View File
@@ -1,29 +1,29 @@
<?php
/*
* 2007-2011 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:
* http://opensource.org/licenses/osl-3.0.php
* 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-2011 PrestaShop SA
* @version Release: $Revision: 8105 $
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
* 2007-2011 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:
* http://opensource.org/licenses/osl-3.0.php
* 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-2011 PrestaShop SA
* @version Release: $Revision: 9202 $
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
/**
* StockManager : implementation of StockManagerInterface
@@ -45,7 +45,7 @@ class StockManagerCore implements StockManagerInterface
* @see StockManagerInterface::addProduct()
*/
public function addProduct($id_product,
$id_product_attribute = null,
$id_product_attribute = 0,
$warehouse,
$quantity,
$id_stock_mvt_reason,
@@ -53,102 +53,95 @@ class StockManagerCore implements StockManagerInterface
$is_usable = true,
$id_supplier_order = null)
{
if (!is_object($warehouse) || !$price_te || !$quantity || (!$id_product || !$id_product_attribute))
if (!Validate::isLoadedObject($warehouse) || !$price_te || !$quantity || !$id_product)
return false;
if (!StockmvtReason::exists($id_stock_mvt_reason))
$id_stock_mvt_reason = StockMvtReason::STOCK_MVT_DEFAULT_REASON;
if (!StockMvtReason::exists($id_stock_mvt_reason))
$id_stock_mvt_reason = Configuration::get('PS_STOCK_MVT_INC_REASON_DEFAULT');
// Get context to have employee informations
$context = Context::getContext();
// sets mvt params to save stock mvt (only one mvt possible when adding product quantities)
$mvt_params = array(
'id_stock' => null,
'physical_quantity' => $quantity,
'id_stock_mvt_reason' => $id_stock_mvt_reason,
'id_supplier_order' => $id_supplier_order,
'price_te' => $price_te,
'price_te' => round($price_te, 6),
'last_wa' => null,
'current_wa' => null,
'id_employee' => $context->employee->id_employee
'id_employee' => $context->employee->id,
'sign' => 1
);
// Flag if an existing stock is available
$stock_exists = false;
// switch on STOCK_MANAGEMENT_MODE
switch ($warehouse->stock_management)
// switch on MANAGEMENT_TYPE
switch ($warehouse->management_type)
{
// case CUMP mode
case 'WA':
// gets stock collection for the given product
$stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id_warehouse);
$stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id);
// if the product is already in stock
// if this product is already in stock
if (count($stock_collection) > 0)
{
$stock_exists = true;
// There is one and only one stock for a given product in a warehouse in this mode
// for a warehouse using WA, there is one and only one stock for a given product
$stock = $stock_collection[0];
// determine weigthed average price
$last_wa = $stock->price_te;
$current_wa = $this->calculateWA($stock, $quantity, $price_te);
// calculates WA price
$last_wa = round($stock->price_te, 6);
$current_wa = round($this->calculateWA($stock, $quantity, $price_te), 6);
// sets mvt_params
$mvt_params['id_stock'] = $stock->id_stock;
$mvt_params['id_stock'] = $stock->id;
$mvt_params['last_wa'] = $last_wa;
$mvt_params['current_wa'] = $current_wa;
// set new stock params
$stock_params = array(
'physical_quantity' => ($stock->physical_quantity + $quantity),
'price_te' => $current_cump,
'price_te' => $current_wa,
'usable_quantity' => ($is_usable ? ($stock->usable_quantity + $quantity) : $stock->usable_quantity),
'id_warehouse' => $warehouse->id_warehouse
'id_warehouse' => $warehouse->id
);
// save stock in warehouse
// saves stock in warehouse
$stock->hydrate($stock_params);
$stock->update();
}
else // else, the product is not in sock
{
// sets mvt_params
$mvt_params['last_wa'] = 0;
$mvt_params['current_wa'] = $price_te;
$mvt_params['current_wa'] = round($price_te, 6);
}
break;
// case FIFO mode
case 'FIFO':
case 'LIFO':
// gets stock collection for the given product and the same unit price
$stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id_warehouse, $price_te);
// if the product is already in stock
$stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id, $price_te);
// if this product is already in stock
if (count($stock_collection) > 0)
{
$stock_exists = true;
// There is one and only one stock for a given product in a warehouse and at the curent unit price
// there is one and only one stock for a given product in a warehouse and at the current unit price
$stock = $stock_collection[0];
// set new stock params
$stock_params = array(
'physical_quantity' => ($stock->physical_quantity + $quantity),
'usable_quantity' => ($is_usable ? ($stock->usable_quantity + $quantity) : $stock->usable_quantity),
);
// update stock in warehouse
// updates stock in warehouse
$stock->hydrate($stock_params);
$stock->update();
// sets mvt_params
$mvt_params['id_stock'] = $stock->id_stock;
$mvt_params['id_stock'] = $stock->id;
}
@@ -161,31 +154,28 @@ class StockManagerCore implements StockManagerInterface
if (!$stock_exists)
{
// creates a new stock for this product
$stock = new Stock();
// set stock params
$stock_params = array(
'id_product_attribute' => $id_product_attribute,
'id_product' => $id_product,
'physical_quantity' => $quantity,
'price_te' => $price_te,
'price_te' => round($price_te, 6),
'usable_quantity' => ($is_usable ? $quantity : 0),
'id_warehouse' => $warehouse->id_warehouse
'id_warehouse' => $warehouse->id
);
// save stock in warehouse
// saves stock in warehouse
$stock->hydrate($stock_params);
$stock->add();
// sets mvt_params
$mvt_params['id_stock'] = $stock->id_stock;
$mvt_params['id_stock'] = $stock->id;
}
// saves stock mvt
$stock_mvt = new StockMvt();
$stock_mvt->hydrate($mvt_params);
$stock_mvt->save();
$stock_mvt->add();
return true;
}
@@ -203,37 +193,34 @@ class StockManagerCore implements StockManagerInterface
{
$return = array();
if (!is_object($warehouse) || !$price_te || !$quantity || (!$id_product || !$id_product_attribute))
if (!Validate::isLoadedObject($warehouse) || !$quantity || !$id_product)
return $return;
if (!StockmvtReason::exists($id_stock_mvt_reason))
$id_stock_mvt_reason = StockMvtReason::STOCK_MVT_DEFAULT_REASON;
if (!StockMvtReason::exists($id_stock_mvt_reason))
$id_stock_mvt_reason = Configuration::get('PS_STOCK_MVT_DEC_REASON_DEFAULT');
// gets context to have the employee informations
$context = Context::getContext();
// gets total quantitiy in stock for the current product
$quantity_in_stock = $this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id_warehouse), $usable);
// gets total quantities in stock for the current product
$quantity_in_stock = $this->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), $is_usable);
// checks if it's possible to remove the given quantity
if ($quantity_in_stock < $quantity)
return $return;
// gets stock collection for the given product
$stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id_warehouse);
$stock_collection = $this->getStockCollection($id_product, $id_product_attribute, $warehouse->id);
// check if the collection is well loaded
// check if the collection is loaded
if (count($stock_collection) <= 0)
return $return;
// prepare utils variables
$stock_history_qty_available = array();
$mvt_params = array();
$stock_params = array();
$quantity_to_decrement_by_stock = array();
$global_quantity_to_decrement = $quantity;
// switch on STOCK_MANAGEMENT_MODE
// switch on MANAGEMENT_TYPE
switch ($warehouse->management_type)
{
// case CUMP mode
@@ -241,17 +228,15 @@ class StockManagerCore implements StockManagerInterface
// There is one and only one stock for a given product in a warehouse in this mode
$stock = $stock_collection[0];
// sets mvt params to save stock mvt (only one mvt is possible when removing product quantities in this mode)
$mvt_params = array(
'id_stock' => $stock->id_stock,
'id_stock' => $stock->id,
'physical_quantity' => $quantity,
'id_stock_mvt_reason' => $id_stock_mvt_reason,
'id_order' => $id_order,
'price_te' => $stock->price_te,
'id_employee' => $context->employee->id_employee
'id_employee' => $context->employee->id,
'sign' => -1
);
// sets new stock params
$stock_params = array(
'physical_quantity' => ($stock->physical_quantity - $quantity),
'usable_quantity' => ($is_usable ? ($stock->usable_quantity - $quantity) : $stock->usable_quantity),
@@ -270,8 +255,8 @@ class StockManagerCore implements StockManagerInterface
case 'LIFO':
case 'FIFO':
// for each stock, parse its mvts history to determine left quantities for each positive mvt,
// according to instant available quantities for this stock
// for each stock, parse its mvts history to calculate the quantities left for each positive mvt,
// according to the instant available quantities for this stock
foreach ($stock_collection as $stock)
{
$left_quantity_to_check = $stock->physical_quantity;
@@ -283,14 +268,14 @@ class StockManagerCore implements StockManagerInterface
FROM `'._DB_PREFIX_.'stock_mvt` sm
JOIN `'._DB_PREFIX_.'stock_mvt` sm2 ON sm2.`stock_mvt_referer` = sm.`id_stock_mvt`
WHERE sm.`sign` = 1
AND sm.`id_stock` = '.(int)$stock->id_stock.'
AND sm.`id_stock` = '.(int)$stock->id.'
AND sm2.`sign` = -1
ORDER BY sm.`date_add` DESC'
);
while ($row = Db::getInstance()->nextRow($resource))
{
// stop while - in FIFO mode, we have to retreive the oldest positive mvts for which there are left quantities
// break - in FIFO mode, we have to retreive the oldest positive mvts for which there are left quantities
if ($warehouse->management_type == 'FIFO')
if ($row['qty'] >= $row['physical_quantity'])
break;
@@ -301,12 +286,12 @@ class StockManagerCore implements StockManagerInterface
// history of the mvt
$stock_history_qty_available[$timestamp] = array(
'id_stock' => $stock->id_stock,
'id_stock' => $stock->id,
'id_stock_mvt' => (int)$row['id_stock_mvt'],
'qty' => (int)$row['qty']
);
// stop while - in LIFO mode, checks only the necessary history to handle the global quantity for the current stock
// break - in LIFO mode, checks only the necessary history to handle the global quantity for the current stock
if ($warehouse->management_type == 'LIFO')
{
$left_quantity_to_check -= (int)$row['physical_quantity'];
@@ -343,22 +328,21 @@ class StockManagerCore implements StockManagerInterface
// for each stock, decrements it and logs the mvts
foreach ($stock_collection as $stock)
{
if (array_key_exists($stock->id_stock, $quantity_to_decrement_by_stock) && is_array($quantity_to_decrement_by_stock[$stock->id_stock]))
if (array_key_exists($stock->id, $quantity_to_decrement_by_stock) && is_array($quantity_to_decrement_by_stock[$stock->id]))
{
$total_quantity_for_current_stock = 0;
foreach ($quantity_to_decrement_by_stock[$stock->id_stock] as $id_mvt_referrer => $qte)
foreach ($quantity_to_decrement_by_stock[$stock->id] as $id_mvt_referrer => $qte)
{
// sets mvt params to save stock mvt
$mvt_params = array(
'id_stock' => $stock->id_stock,
'id_stock' => $stock->id,
'physical_quantity' => $qte,
'id_stock_mvt_reason' => $id_stock_mvt_reason,
'id_order' => $id_order,
'price_te' => $stock->price_te,
'sign' => -1,
'stock_mvt_referer' => $id_mvt_referrer,
'id_employee' => $context->employee->id_employee
'id_employee' => $context->employee->id
);
// saves stock mvt
@@ -369,14 +353,13 @@ class StockManagerCore implements StockManagerInterface
$total_quantity_for_current_stock += $qte;
}
// sets new stock params
$stock_params = array(
'physical_quantity' => ($stock->physical_quantity - $total_quantity_for_current_stock),
'usable_quantity' => ($is_usable ? ($stock->usable_quantity - $total_quantity_for_current_stock) : $stock->usable_quantity),
);
$return[$stock->id_stock]['quantity'] = $total_quantity_for_current_stock;
$return[$stock->id_stock]['price_te'] = $stock->price_te;
$return[$stock->id]['quantity'] = $total_quantity_for_current_stock;
$return[$stock->id]['price_te'] = $stock->price_te;
// saves stock in warehouse
$stock->hydrate($stock_params);
@@ -385,7 +368,6 @@ class StockManagerCore implements StockManagerInterface
}
break;
}
return $return;
}
@@ -432,7 +414,7 @@ class StockManagerCore implements StockManagerInterface
public function transferBetweenWarehouses($id_product,
$id_product_attribute,
$quantity,
$id_stock_movement_reason,
$id_stock_mvt_reason,
$id_warehouse_from,
$id_warehouse_to,
$usable_from = true,
@@ -454,7 +436,7 @@ class StockManagerCore implements StockManagerInterface
$id_product_attribute,
$warehouse_from,
$quantity,
$id_stock_movement_reason,
$id_stock_mvt_reason,
$is_usable_from)))
return false;
// Adds in warehouse_to
@@ -464,7 +446,7 @@ class StockManagerCore implements StockManagerInterface
$id_product_attribute,
$warehouse_to,
$stock['quantity'],
$id_stock_movement_reason,
$id_stock_mvt_reason,
$stock['price_te'],
$usable_to))
return false;
@@ -481,9 +463,9 @@ class StockManagerCore implements StockManagerInterface
* @param float $price_te
* @return int WA
*/
protected function calculateWA(Stock $stock, $quantity, $price_te)
protected function calculateWA($stock, $quantity, $price_te)
{
return ((($stock->physical_quantity * $stock->price_te) + ($quantity * $price_te)) / ($stock->$quantity + $quantity));
return ((($stock->physical_quantity * $stock->price_te) + ($quantity * $price_te)) / ($stock->physical_quantity + $quantity));
}
/**
@@ -497,7 +479,7 @@ class StockManagerCore implements StockManagerInterface
{
// build query
$query = new DbQuery();
$query->select('s.id_stock, s.physical_quantity, s.usable_quantity, s.price_te');
$query->select('s.id_stock, s.physical_quantity, s.usable_quantity, s.price_te, s.id_product, s.id_product_attribute, s.id_warehouse');
$query->from('stock s');
$query->where('s.id_product = '.(int)$id_product.' AND s.id_product_attribute = '.(int)$id_product_attribute);
if ($id_warehouse)