From 2e4c8bb553621454fc1018bb83b8e0f321f96669 Mon Sep 17 00:00:00 2001 From: bMancone Date: Mon, 19 Dec 2011 18:34:31 +0000 Subject: [PATCH] // Webservice: Stock --- classes/shop/Shop.php | 9 +- classes/stock/Stock.php | 24 ++ classes/stock/StockAvailable.php | 28 +- classes/stock/StockMvt.php | 6 +- classes/stock/StockMvtReason.php | 5 +- classes/stock/StockMvtWS.php | 292 +++++++++++++++++++++ classes/stock/Warehouse.php | 95 +++++++ classes/stock/WarehouseProductLocation.php | 13 + classes/webservice/WebserviceRequest.php | 14 +- 9 files changed, 469 insertions(+), 17 deletions(-) create mode 100644 classes/stock/StockMvtWS.php diff --git a/classes/shop/Shop.php b/classes/shop/Shop.php index 439a89f91..8dcd80cf0 100644 --- a/classes/shop/Shop.php +++ b/classes/shop/Shop.php @@ -92,7 +92,7 @@ class ShopCore extends ObjectModel 'store' => array('type' => 'shop'), 'webservice_account' => array('type' => 'shop'), 'warehouse' => array('type' => 'shop'), - 'stock_available' => array('type' => 'fk_shop', 'primary' => 'id_stock_available'), + /* 'stock_available' => array('type' => 'fk_shop', 'primary' => 'id_stock_available'), */ ); protected $webserviceParameters = array( @@ -166,6 +166,11 @@ class ShopCore extends ObjectModel ); } + // removes stock available + $res &= Db::getInstance()->execute(' + DELETE FROM '._DB_PREFIX_.'stock_available + WHERE id_shop = '.(int)$this->id); + Shop::cacheShops(true); return $res; @@ -214,7 +219,7 @@ class ShopCore extends ObjectModel /** * Find the shop from current domain / uri and get an instance of this shop * if INSTALL_VERSION is defined, will return an empty shop object - * + * * @return Shop */ public static function initialize() diff --git a/classes/stock/Stock.php b/classes/stock/Stock.php index cb2fea26f..de09c711d 100644 --- a/classes/stock/Stock.php +++ b/classes/stock/Stock.php @@ -78,6 +78,20 @@ class StockCore extends ObjectModel ), ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_warehouse' => array('xlink_resource' => 'warehouses'), + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'real_quantity' => array('getter' => 'getWsRealQuantity', 'setter' => false), + ), + 'hidden_fields' => array( + ), + ); + /** * @see ObjectModel::update() */ @@ -130,4 +144,14 @@ class StockCore extends ObjectModel } } } + + /** + * Webservice : used to get the real quantity of a product + */ + public function getWsRealQuantity() + { + $manager = StockManagerFactory::getManager(); + $quantity = $manager->getProductRealQuantities($this->id_product, $this->id_product_attribute, $this->id_warehouse, true); + return $quantity; + } } \ No newline at end of file diff --git a/classes/stock/StockAvailable.php b/classes/stock/StockAvailable.php index f1b721609..ed4342951 100644 --- a/classes/stock/StockAvailable.php +++ b/classes/stock/StockAvailable.php @@ -71,6 +71,20 @@ class StockAvailableCore extends ObjectModel ), ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'id_shop' => array('xlink_resource' => 'shops'), + 'id_group_shop' => array('xlink_resource' => 'shop_groups'), + ), + 'hidden_fields' => array( + ), + ); + /** * For a given {id_product, id_product_attribute and id_shop}, gets the stock available id associated * @@ -268,7 +282,7 @@ class StockAvailableCore extends ObjectModel foreach ($items as $item) if (!$item->isAvailableWhenOutOfStock((int)$item->out_of_stock)) $quantities[] = Product::getQuantity($item->id) / ($item->pack_quantity !== 0 ? $item->pack_quantity : 1); - + // gets the minimum $quantity = $quantities[0]; foreach ($quantities as $value) @@ -276,24 +290,24 @@ class StockAvailableCore extends ObjectModel if ($quantity > $value) $quantity = $value; } - + // returns the number of pack available return $quantity; } else // else { - $query = new DbQuery(); + $query = new DbQuery(); $query->select('SUM(quantity)'); $query->from('stock_available'); - + // if null, it's a product without attributes if (!is_null($id_product)) $query->where('id_product = '.(int)$id_product); - + $query->where('id_product_attribute = '.(int)$id_product_attribute); - + $query = StockAvailable::addSqlShopRestriction($query, $id_shop); - + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); } } diff --git a/classes/stock/StockMvt.php b/classes/stock/StockMvt.php index 9e8cc9a6f..35c295458 100644 --- a/classes/stock/StockMvt.php +++ b/classes/stock/StockMvt.php @@ -25,6 +25,9 @@ * International Registered Trademark & Property of PrestaShop SA */ +/** + * @since 1.5.0 It now defines stock movements when the advanced stock management system is available + */ class StockMvtCore extends ObjectModel { public $id; @@ -153,7 +156,8 @@ class StockMvtCore extends ObjectModel 'id_employee' => array('xlink_resource'=> 'employees'), 'id_stock' => array('xlink_resource'=> 'stock'), 'id_stock_mvt_reason' => array('xlink_resource'=> 'stock_movement_reasons'), - 'id_order' => array('xlink_resource'=> 'orders') + 'id_order' => array('xlink_resource'=> 'orders'), + 'id_supply_order' => array('xlink_resource'=> 'supply_order'), ), ); diff --git a/classes/stock/StockMvtReason.php b/classes/stock/StockMvtReason.php index f13088f1b..3778bf46d 100644 --- a/classes/stock/StockMvtReason.php +++ b/classes/stock/StockMvtReason.php @@ -57,8 +57,6 @@ class StockMvtReasonCore extends ObjectModel 'deleted' => array('type' => self::TYPE_BOOL), 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), - - // Lang fields 'name' => array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 255), ), ); @@ -66,6 +64,9 @@ class StockMvtReasonCore extends ObjectModel protected $webserviceParameters = array( 'objectsNodeName' => 'stock_movement_reasons', 'objectNodeName' => 'stock_movement_reason', + 'fields' => array( + 'sign' => array(), + ), ); public static function getStockMvtReasons($id_lang, $sign = null) diff --git a/classes/stock/StockMvtWS.php b/classes/stock/StockMvtWS.php new file mode 100644 index 000000000..d765be8fb --- /dev/null +++ b/classes/stock/StockMvtWS.php @@ -0,0 +1,292 @@ + +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +/** + * Webservice entity for stock movements + * @since 1.5.0 + */ +class StockMvtWS extends ObjectModelCore +{ + public $id; + + /** + * @var string The creation date of the movement + */ + public $date_add; + + /** + * @var int The employee id, responsible of the movement + */ + public $id_employee; + + /** + * @var string The first name of the employee responsible of the movement + */ + public $employee_firstname; + + /** + * @var string The last name of the employee responsible of the movement + */ + public $employee_lastname; + + /** + * @var int The stock id on wtich the movement is applied + */ + public $id_stock; + + /** + * @var int the quantity of product with is moved + */ + public $physical_quantity; + + /** + * @var int id of the movement reason assoiated to the movement + */ + public $id_stock_mvt_reason; + + /** + * @var int Used when the movement is due to a customer order + */ + public $id_order = null; + + /** + * @var int detrmine if the movement is a positive or negative operation + */ + public $sign; + + /** + * @var int Used when the movement is due to a supplier order + */ + public $id_supply_order = null; + + /** + * @var float Last value of the weighted-average method + */ + public $last_wa = null; + + /** + * @var float Current value of the weighted-average method + */ + public $current_wa = null; + + /** + * @var float The unit price without tax of the product associated to the movement + */ + public $price_te; + + /** + * @var int Refers to an other id_stock_mvt : used for LIFO/FIFO implementation in StockManager + */ + public $referer; + + /** + * @var int id_product (@see Stock::id_product) + */ + public $id_product; + + /** + * @var int id_product_attribute (@see Stock::id_product_attribute) + */ + public $id_product_attribute; + + /** + * @var int id_warehouse (@see Stock::id_warehouse) + */ + public $id_warehouse; + + /** + * @var int id_currency (@see Warehouse::id_currency) + */ + public $id_currency; + + /** + * @var string management_type (@see Warehouse::management_type) + */ + public $management_type; + + /* + * @var string : Name of the product (@see Product::getProductName) + */ + public $product_name; + + /** + * @var string EAN13 of the product (@see Stock::product_ean13) + */ + public $ean13; + + /** + * @var string UPC of the product (@see Stock::product_upc) + */ + public $upc; + + /** + * @var string Reference of the product (@see Stock::product_reference) + */ + public $reference; + + /** + * @see ObjectModel::$definition + */ + public static $definition = array( + 'table' => 'stock_mvt', + 'primary' => 'id_stock_mvt', + 'fields' => array( + 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'employee_firstname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'employee_lastname' => array('type' => self::TYPE_STRING, 'validate' => 'isName'), + 'id_stock' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'physical_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true), + 'id_stock_mvt_reason' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_supply_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'sign' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true), + 'last_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'current_wa' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice'), + 'price_te' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true), + 'referer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate', 'required' => true), + ), + ); + + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'id_warehouse' => array('xlink_resource' => 'warehouses'), + 'id_currency' => array('xlink_resource' => 'currencies'), + 'management_type' => array(), + 'id_employee' => array('xlink_resource' => 'employees'), + 'id_stock' => array('xlink_resource' => 'stocks'), + 'id_stock_mvt_reason' => array('xlink_resource' => 'stock_movement_reasons'), + 'id_order' => array('xlink_resource' => 'orders'), + 'id_supply_order' => array('xlink_resource' => 'supply_orders'), + 'product_name' => array('getter' => 'getWSProductName', 'i18n' => true), + 'ean13' => array(), + 'upc' => array(), + 'reference' => array(), + ), + 'hidden_fields' => array( + 'referer', + 'employee_firstname', + 'employee_lastname', + ), + ); + + /** + * Associations tables for attributes that require different tables than stated in ObjectModel::definition + * @var Array + */ + protected $tables_assoc = array( + 'id_product' => array('table' => 's'), + 'id_product_attribute' => array('table' => 's'), + 'id_warehouse' => array('table' => 's'), + 'id_currency' => array('table' => 's'), + 'management_type' => array('table' => 'w'), + 'ean13' => array('table' => 's'), + 'upc' => array('table' => 's'), + 'reference' => array('table' => 's'), + ); + + /** + * @see ObjectModel + */ + public function __construct($id = null, $id_lang = null, $id_shop = null) + { + // calls parent + parent::__construct($id, $id_lang, $id_shop); + + if ((int)$this->id != 0) + { + $res = $this->getWebserviceObjectList(null, (' AND '.$this->def['primary'].' = '.(int)$this->id), null, null, true); + if (isset($res[0])) + { + foreach ($this->tables_assoc as $key => $param) + $this->{$key} = $res[0][$key]; + } + } + } + + /** + * @see ObjectModel::getWebserviceObjectList() + * Added $full for this specific object + */ + public function getWebserviceObjectList($join, $filter, $sort, $limit, $full = false) + { + $query = 'SELECT DISTINCT main.'.$this->def['primary'].' '; + + if ($full) + $query .= ', s.id_product, s.id_product_attribute, s.id_warehouse, w.id_currency, w.management_type, + s.ean13, s.upc, s.reference '; + + $old_filter = $filter; + if ($filter) + foreach ($this->tables_assoc as $key => $value) + $filter = str_replace('main.`'.$key.'`', $value['table'].'.`'.$key.'`', $filter); + + $query .= 'FROM '._DB_PREFIX_.$this->def['table'].' as main '; + + if ($filter !== $old_filter || $full) + { + $query .= 'LEFT JOIN '._DB_PREFIX_.'stock s ON (s.id_stock = main.id_stock) '; + $query .= 'LEFT JOIN '._DB_PREFIX_.'warehouse w ON (w.id_warehouse = s.id_warehouse) '; + $query .= 'LEFT JOIN '._DB_PREFIX_.'currency c ON (c.id_currency = w.id_currency) '; + } + + if ($join) + $query .= $join; + + $query .= 'WHERE 1 '; + + if ($filter) + $query .= $filter.' '; + + if ($sort) + $query .= $sort.' '; + + if ($limit) + $query .= $limit.' '; + + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } + + /** + * Webservice : getter for the product name + */ + public function getWSProductName() + { + $languages = Language::getLanguages(true); + $res = array(); + foreach ($languages as $language) + $res[$language['id_lang']] = Product::getProductName($this->id_product, $this->id_product_attribute, $language['id_lang']); + + return $res; + } + +} diff --git a/classes/stock/Warehouse.php b/classes/stock/Warehouse.php index bd19df9e3..d5952dfb3 100644 --- a/classes/stock/Warehouse.php +++ b/classes/stock/Warehouse.php @@ -76,6 +76,40 @@ class WarehouseCore extends ObjectModel ), ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_address' => array('xlink_resource' => 'addresses'), + 'id_employee' => array('xlink_resource' => 'employees'), + 'id_currency' => array('xlink_resource' => 'currencies'), + 'valuation' => array('getter' => 'getWsStockValue', 'setter' => false), + 'deleted' => array(), + ), + 'associations' => array( + 'stocks' => array( + 'resource' => 'stock', + 'fields' => array( + 'id' => array(), + ), + ), + 'carriers' => array( + 'resource' => 'carrier', + 'fields' => array( + 'id' => array(), + ), + ), + 'shops' => array( + 'resource' => 'shop', + 'fields' => array( + 'id' => array(), + 'name' => array(), + ), + ), + ), + ); + /** * Gets the shops (id and name) associated to the current warehouse * @@ -421,4 +455,65 @@ class WarehouseCore extends ObjectModel return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query); } + /** + * Webservice : gets the value of the warehouse + * @return int + */ + public function getWsStockValue() + { + return $this->getStockValue(); + } + + /** + * Webservice : gets the ids stock associated to this warehouse + * @return array + */ + public function getWsStocks() + { + $query = new DbQuery(); + $query->select('s.id_stock as id'); + $query->from('stock', 's'); + $query->where('s.id_warehouse ='.(int)$this->id); + + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + } + + /** + * Webservice : gets the ids shops associated to this warehouse + * @return array + */ + public function getWsShops() + { + $query = new DbQuery(); + $query->select('ws.id_shop as id, s.name'); + $query->from('warehouse_shop', 'ws'); + $query->leftJoin('shop', 's', 's.id_shop = ws.id_shop'); + $query->where($this->def['primary'].' = '.(int)$this->id); + + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + return $res; + } + + /** + * Webservice : gets the ids carriers associated to this warehouse + * @return array + */ + public function getWsCarriers() + { + $ids_carrier = array(); + + $query = new DbQuery(); + $query->select('wc.id_carrier as id'); + $query->from('warehouse_carrier', 'wc'); + $query->where($this->def['primary'].' = '.(int)$this->id); + + $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query); + + foreach ($res as $carriers) + foreach ($carriers as $carrier) + $ids_carrier[] = $carrier; + + return $ids_carrier; + } + } diff --git a/classes/stock/WarehouseProductLocation.php b/classes/stock/WarehouseProductLocation.php index 34ee61183..296b5852e 100644 --- a/classes/stock/WarehouseProductLocation.php +++ b/classes/stock/WarehouseProductLocation.php @@ -63,6 +63,19 @@ class WarehouseProductLocationCore extends ObjectModel ), ); + /** + * @see ObjectModel::$webserviceParameters + */ + protected $webserviceParameters = array( + 'fields' => array( + 'id_product' => array('xlink_resource' => 'products'), + 'id_product_attribute' => array('xlink_resource' => 'combinations'), + 'id_warehouse' => array('xlink_resource' => 'warehouses'), + ), + 'hidden_fields' => array( + ), + ); + /** * For a given product and warehouse, get the location * diff --git a/classes/webservice/WebserviceRequest.php b/classes/webservice/WebserviceRequest.php index f41460386..7abc94bd2 100644 --- a/classes/webservice/WebserviceRequest.php +++ b/classes/webservice/WebserviceRequest.php @@ -260,13 +260,17 @@ class WebserviceRequestCore 'weight_ranges' => array('description' => 'Weight ranges', 'class' => 'RangeWeight'), 'zones' => array('description' => 'The Countries zones','class' => 'Zone'), 'employees' => array('description' => 'The Employees', 'class' => 'Employee'), - 'stock_movements' => array('description' => 'Stock movements management', 'class' => 'StockMvt', 'forbidden_method' => array('PUT')), 'search' => array('description' => 'Search', 'specific_management' => true, 'forbidden_method' => array('PUT', 'POST', 'DELETE')), - 'stock_movement_reasons' => array('description' => 'The stock movement reason', 'class' => 'StockMvtReason'), - 'content_management_system' => array('description' => 'Content management system', 'class' => 'CMS'), + 'content_management_system' => array('description' => 'Content management system', 'class' => 'CMS'), 'shops' => array('description' => 'Shops from multi-shop feature', 'class' => 'Shop'), 'shop_groups' => array('description' => 'Shop groups from multi-shop feature', 'class' => 'GroupShop'), 'taxes' => array('description' => 'The tax rate', 'class' => 'Tax'), + 'stock_movements' => array('description' => 'Stock movements', 'class' => 'StockMvtWS', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'stock_movement_reasons' => array('description' => 'Stock movement reason', 'class' => 'StockMvtReason'), + 'warehouses' => array('description' => 'Warehouses', 'class' => 'Warehouse', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'stocks' => array('description' => 'Stocks', 'class' => 'Stock', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'available_quantities' => array('description' => 'Available quantities', 'class' => 'StockAvailable', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), + 'warehouse_product_locations' => array('description' => 'Location of products in warehouses', 'class' => 'WarehouseProductLocation', 'forbidden_method' => array('PUT', 'POST', 'DELETE')), ); ksort($resources); return $resources; @@ -309,7 +313,7 @@ class WebserviceRequestCore $arr_return = $this->specificPriceCalculation($parameters); return $arr_return; } - + public function specificPriceCalculation($parameters) { $arr_return = array(); @@ -386,7 +390,7 @@ class WebserviceRequestCore $this->wsUrl = Tools::getHttpHost(true).__PS_BASE_URI__.'api/'; // set the output object which manage the content and header structure and informations $this->objOutput = new WebserviceOutputBuilder($this->wsUrl); - + // Error handler set_error_handler(array($this, 'webserviceErrorHandler')); ini_set('html_errors', 'off');