Smile_Warehouse - Version 0.0.5

Version Notes

First stable release

Download this release

Release Info

Developer Smile
Extension Smile_Warehouse
Version 0.0.5
Comparing to
See all releases


Version 0.0.5

Files changed (42) hide show
  1. app/code/community/Smile/Warehouse/Block/Adminhtml/Catalog/Product/Edit/Tab/Inventory.php +92 -0
  2. app/code/community/Smile/Warehouse/Block/Adminhtml/Catalog/Product/Edit/Tab/Super/Config.php +27 -0
  3. app/code/community/Smile/Warehouse/Block/Adminhtml/Catalog/Product/Edit/Tab/Super/Config/Simple.php +26 -0
  4. app/code/community/Smile/Warehouse/Block/Adminhtml/Report/Product/Lowstock/Grid.php +61 -0
  5. app/code/community/Smile/Warehouse/Block/Adminhtml/System/Store/Grid.php +54 -0
  6. app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse.php +25 -0
  7. app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse/Edit.php +53 -0
  8. app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse/Edit/Form.php +64 -0
  9. app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse/Grid.php +108 -0
  10. app/code/community/Smile/Warehouse/Block/Adminhtml/Widget/Grid/Column/Renderer/Implode.php +33 -0
  11. app/code/community/Smile/Warehouse/Block/Rss/Catalog/NotifyStock.php +104 -0
  12. app/code/community/Smile/Warehouse/Helper/Data.php +96 -0
  13. app/code/community/Smile/Warehouse/Model/Catalog/Convert/Parser/Product.php +112 -0
  14. app/code/community/Smile/Warehouse/Model/Mysql4/Reports/Product/Lowstock/Collection.php +79 -0
  15. app/code/community/Smile/Warehouse/Model/Mysql4/Setup.php +12 -0
  16. app/code/community/Smile/Warehouse/Model/Mysql4/Stock.php +177 -0
  17. app/code/community/Smile/Warehouse/Model/Mysql4/Stock/Collection.php +42 -0
  18. app/code/community/Smile/Warehouse/Model/Mysql4/Stock/Item.php +51 -0
  19. app/code/community/Smile/Warehouse/Model/Mysql4/Stock/Status.php +72 -0
  20. app/code/community/Smile/Warehouse/Model/Observer.php +514 -0
  21. app/code/community/Smile/Warehouse/Model/Stock.php +213 -0
  22. app/code/community/Smile/Warehouse/Model/Stock/Item.php +42 -0
  23. app/code/community/Smile/Warehouse/Model/Stock/Item/Api.php +90 -0
  24. app/code/community/Smile/Warehouse/Model/Stock/Item/Api/V2.php +82 -0
  25. app/code/community/Smile/Warehouse/controllers/Adminhtml/Catalog/Product/Action/AttributeController.php +156 -0
  26. app/code/community/Smile/Warehouse/controllers/Adminhtml/Catalog/ProductController.php +149 -0
  27. app/code/community/Smile/Warehouse/controllers/Adminhtml/WarehouseController.php +257 -0
  28. app/code/community/Smile/Warehouse/etc/adminhtml.xml +36 -0
  29. app/code/community/Smile/Warehouse/etc/api.xml +49 -0
  30. app/code/community/Smile/Warehouse/etc/config.xml +194 -0
  31. app/code/community/Smile/Warehouse/etc/wsdl.xml +52 -0
  32. app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-install-0.0.1.php +19 -0
  33. app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-upgrade-0.0.1-0.0.2.php +29 -0
  34. app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-upgrade-0.0.2-0.0.3.php +18 -0
  35. app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-upgrade-0.0.3-0.0.5.php +18 -0
  36. app/design/adminhtml/default/default/layout/smile/warehouse.xml +9 -0
  37. app/design/adminhtml/default/default/template/smile/warehouse/catalog/product/edit/action/inventory.phtml +171 -0
  38. app/design/adminhtml/default/default/template/smile/warehouse/catalog/product/tab/inventory.phtml +237 -0
  39. app/design/adminhtml/default/default/template/smile/warehouse/report/store/switcher.phtml +48 -0
  40. app/etc/modules/Smile_Warehouse.xml +13 -0
  41. app/locale/en_US/Smile_Warehouse.csv +35 -0
  42. package.xml +22 -0
app/code/community/Smile/Warehouse/Block/Adminhtml/Catalog/Product/Edit/Tab/Inventory.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Product inventory data
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Catalog_Product_Edit_Tab_Inventory extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Inventory
11
+ {
12
+ /**
13
+ * Stock items collection
14
+ *
15
+ * @var Mage_CatalogInventory_Model_Mysql4_Stock_Item_Collection|array
16
+ */
17
+ protected $_stockItems;
18
+
19
+ /**
20
+ * Set custom template for the block
21
+ *
22
+ * @return void
23
+ */
24
+ public function __construct()
25
+ {
26
+ parent::__construct();
27
+ $this->setTemplate('smile/warehouse/catalog/product/tab/inventory.phtml');
28
+ }
29
+
30
+ /**
31
+ * Get stock qty info for all warehouses
32
+ *
33
+ * @return Mage_CatalogInventory_Model_Mysql4_Stock_Item_Collection|array
34
+ */
35
+ public function getStockItems()
36
+ {
37
+ if ($this->getProduct()->getId() && is_null($this->_stockItems)) {
38
+ $stockCollection = Mage::getResourceModel('cataloginventory/stock_item_collection');
39
+ $warehouseCollection = Mage::getModel('cataloginventory/stock')->getCollection();
40
+
41
+ $stockCollection->addProductsFilter(array($this->getProduct()->getId()));
42
+
43
+ $websiteIds = $this->getProduct()->getWebsiteIds();
44
+ $stockIds = array();
45
+ foreach ($websiteIds as $website) {
46
+ if (!isset($stockIds[Mage::app()->getWebsite($website)->getStockId()])) {
47
+ $stockIds[Mage::app()->getWebsite($website)->getStockId()] = Mage::app()->getWebsite($website)->getStockId();
48
+ }
49
+ }
50
+ if ($stockIds) {
51
+ $stockCollection->addFieldToFilter('stock_id', array('in' => $stockIds));
52
+ } else {
53
+ $this->_stockItems = array();
54
+ return $this->_stockItems;
55
+ }
56
+
57
+ $warehouses = array();
58
+ foreach ($stockCollection as $item) {
59
+ $warehouses[$item->getStockId()] = $item->getStockId();
60
+ }
61
+
62
+ if ($warehouses) {
63
+ $warehouseCollection->addFieldToFilter('stock_id', array('in' => $warehouses));
64
+ }
65
+
66
+ foreach ($stockCollection as $item) {
67
+ $item->setStockCode($warehouseCollection->getItemByColumnValue('stock_id', $item->getStockId())->getStockCode());
68
+ }
69
+ $this->_stockItems = $stockCollection;
70
+ }
71
+
72
+ return $this->_stockItems;
73
+ }
74
+
75
+ /**
76
+ * Check is inventory tab available
77
+ *
78
+ * @return bool
79
+ */
80
+ public function isInventoryTabAvailable()
81
+ {
82
+ if ($storeId = $this->getProduct()->getStoreId()) {
83
+ $websiteIds = $this->getProduct()->getWebsiteIds();
84
+ $websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
85
+ if (!in_array($websiteId, $websiteIds)) {
86
+ return false;
87
+ }
88
+ }
89
+
90
+ return true;
91
+ }
92
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Catalog/Product/Edit/Tab/Super/Config.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adminhtml catalog super product configurable tab
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Catalog_Product_Edit_Tab_Super_Config extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config
11
+ {
12
+ /**
13
+ * Retrieve Quick create product URL
14
+ *
15
+ * @return string
16
+ */
17
+ public function getQuickCreationUrl()
18
+ {
19
+ return $this->getUrl(
20
+ '*/*/quickCreate',
21
+ array(
22
+ 'product' => $this->_getProduct()->getId(),
23
+ 'store' => $this->getRequest()->getParam('store', 0)
24
+ )
25
+ );
26
+ }
27
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Catalog/Product/Edit/Tab/Super/Config/Simple.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Quick simple product creation
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Catalog_Product_Edit_Tab_Super_Config_Simple extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config_Simple
11
+ {
12
+ /**
13
+ * Remove quantity field
14
+ *
15
+ * @return void
16
+ */
17
+ protected function _prepareForm()
18
+ {
19
+ parent::_prepareForm();
20
+ if (!$this->_getProduct()->getId() || !$this->_getProduct()->getStoreId()) {
21
+ $this->getForm()->getElement('simple_product')
22
+ ->removeField('simple_product_inventory_qty')
23
+ ->removeField('simple_product_inventory_is_in_stock');
24
+ }
25
+ }
26
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Report/Product/Lowstock/Grid.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adminhtml low stock products report grid block
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Report_Product_Lowstock_Grid
11
+ extends Mage_Adminhtml_Block_Report_Product_Lowstock_Grid
12
+ {
13
+ /**
14
+ * Prepare collection
15
+ *
16
+ * @return Smile_Warehouse_Block_Adminhtml_Report_Product_Lowstock_Grid
17
+ */
18
+ protected function _prepareCollection()
19
+ {
20
+ parent::_prepareCollection();
21
+ $collection = $this->getCollection();
22
+ if (!$collection->getStoreId()) {
23
+ // Add websites to collection
24
+ $collection->addWebsiteNamesToResult();
25
+
26
+ // Add stocks qty to product collection
27
+ Mage::getModel('cataloginventory/stock')->addStocksQtyToCollection($collection);
28
+ }
29
+
30
+ return $this;
31
+ }
32
+
33
+ /**
34
+ * Add qty column
35
+ *
36
+ * @return Smile_Warehouse_Block_Adminhtml_Report_Product_Lowstock_Grid
37
+ */
38
+ protected function _prepareColumns()
39
+ {
40
+ parent::_prepareColumns();
41
+ $storeId = (int) $this->getRequest()->getParam('store', 0);
42
+ $groupId = (int) $this->getRequest()->getParam('group', 0);
43
+ $websiteId = (int) $this->getRequest()->getParam('website', 0);
44
+
45
+ if (!$storeId && !$groupId && !$websiteId) {
46
+ $this->addColumn(
47
+ 'qty',
48
+ array(
49
+ 'header' => Mage::helper('reports')->__('Stock Qty'),
50
+ 'width' => '215px',
51
+ 'sortable' => false,
52
+ 'filter' => false,
53
+ 'index' =>'qty',
54
+ 'renderer' => 'smile_warehouse/adminhtml_widget_grid_column_renderer_implode',
55
+ 'separator' => (!$this->_isExport) ? '<br/>' : '; ',
56
+ )
57
+ );
58
+ }
59
+ return $this;
60
+ }
61
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/System/Store/Grid.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Store grid
4
+ * Add stock data
5
+ *
6
+ * @category Smile
7
+ * @package Smile_Warehouse
8
+ * @author Smile <solution.magento@smile.fr>
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+ class Smile_Warehouse_Block_Adminhtml_System_Store_Grid extends Mage_Adminhtml_Block_System_Store_Grid
12
+ {
13
+ /**
14
+ * Join stock table to collection
15
+ *
16
+ * @return Smile_Warehouse_Block_Adminhtml_System_Store_Grid
17
+ */
18
+ protected function _prepareCollection()
19
+ {
20
+ $collection = Mage::getModel('core/website')
21
+ ->getCollection()
22
+ ->joinGroupAndStore();
23
+
24
+ $collection->getSelect()->join(
25
+ array('stock_table' => $collection->getTable('cataloginventory/stock')),
26
+ 'main_table.stock_id=stock_table.stock_id',
27
+ array('stock_name')
28
+ );
29
+
30
+ $this->setCollection($collection);
31
+ Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();
32
+
33
+ return $this;
34
+ }
35
+
36
+ /**
37
+ * Prepare columns. Add stock name
38
+ *
39
+ * @return Smile_Warehouse_Block_Adminhtml_System_Store_Grid
40
+ */
41
+ protected function _prepareColumns()
42
+ {
43
+ $this->addColumnAfter(
44
+ 'stock_name',
45
+ array(
46
+ 'header' => Mage::helper('smile_warehouse')->__('Warehouse'),
47
+ 'index' => 'stock_name',
48
+ 'filter_index' => 'stock_table.stock_name'
49
+ ),
50
+ 'store_title'
51
+ );
52
+ return parent::_prepareColumns();
53
+ }
54
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse manage page
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Warehouse extends Mage_Adminhtml_Block_Widget_Grid_Container
11
+ {
12
+ /**
13
+ * Initialize warehouses manage page
14
+ *
15
+ * @return void
16
+ */
17
+ public function __construct()
18
+ {
19
+ $this->_controller = 'adminhtml_warehouse';
20
+ $this->_blockGroup = 'smile_warehouse';
21
+ $this->_headerText = Mage::helper('smile_warehouse')->__('Manage Warehouses');
22
+ $this->_addButtonLabel = Mage::helper('smile_warehouse')->__('Add New Warehouse');
23
+ parent::__construct();
24
+ }
25
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse/Edit.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse edit page
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Warehouse_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
11
+ {
12
+ public function __construct()
13
+ {
14
+ $this->_objectId = 'id';
15
+ $this->_controller = 'adminhtml_warehouse';
16
+ $this->_blockGroup = 'smile_warehouse';
17
+ $this->_mode = 'edit';
18
+
19
+ parent::__construct();
20
+ }
21
+
22
+ /**
23
+ * Get warehouse model
24
+ *
25
+ * @return Smile_Warehouse_Model_Stock
26
+ */
27
+ public function getWarehouse()
28
+ {
29
+ return Mage::registry('current_warehouse');
30
+ }
31
+
32
+ /**
33
+ * Get header text
34
+ *
35
+ * @return string
36
+ */
37
+ public function getHeaderText()
38
+ {
39
+ return $this->getWarehouse()->getStockId()
40
+ ? $this->htmlEscape($this->getWarehouse()->getStockName())
41
+ : Mage::helper('smile_warehouse')->__('New Warehouse');
42
+ }
43
+
44
+ /**
45
+ * Get form action URL
46
+ *
47
+ * @return string
48
+ */
49
+ public function getFormActionUrl()
50
+ {
51
+ return $this->getUrl('*/*/save');
52
+ }
53
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse/Edit/Form.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse edit form
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Warehouse_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
11
+ {
12
+ /**
13
+ * Prepare form
14
+ *
15
+ * @return Smile_Warehouse_Block_Adminhtml_Warehouse_Edit_Form
16
+ */
17
+ protected function _prepareForm()
18
+ {
19
+ $form = new Varien_Data_Form(array('id' => 'edit_form', 'action' => $this->getData('action'), 'method' => 'post'));
20
+
21
+ $warehouse = Mage::registry('current_warehouse');
22
+
23
+ if ($warehouse->getStockId()) {
24
+ $form->addField('stock_id', 'hidden', array('name' => 'id', 'value'=> $warehouse->getStockId()));
25
+ }
26
+
27
+ $fieldset = $form->addFieldset('base_fieldset', array('legend' => Mage::helper('smile_warehouse')->__('Warehouse')));
28
+
29
+ $fieldset->addField(
30
+ 'stock_code',
31
+ 'text',
32
+ array(
33
+ 'name' =>'stock_code',
34
+ 'label' => Mage::helper('smile_warehouse')->__('Warehouse Code'),
35
+ 'required' => true,
36
+ 'value' => $warehouse->getStockCode()
37
+ )
38
+ );
39
+
40
+ $fieldset->addField(
41
+ 'stock_name',
42
+ 'text',
43
+ array(
44
+ 'name' =>'stock_name',
45
+ 'label' => Mage::helper('smile_warehouse')->__('Warehouse Name'),
46
+ 'required' => true,
47
+ 'value' => $warehouse->getStockName()
48
+ )
49
+ );
50
+
51
+ $fieldset->addField(
52
+ 'form_key',
53
+ 'hidden',
54
+ array(
55
+ 'name' => 'form_key',
56
+ 'value' => Mage::getSingleton('core/session')->getFormKey(),
57
+ )
58
+ );
59
+
60
+ $form->setUseContainer(true);
61
+ $this->setForm($form);
62
+ return parent::_prepareForm();
63
+ }
64
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Warehouse/Grid.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse grid
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Adminhtml_Warehouse_Grid extends Mage_Adminhtml_Block_Widget_Grid
11
+ {
12
+ /**
13
+ * Set defaults
14
+ *
15
+ * @return void
16
+ */
17
+ protected function _construct()
18
+ {
19
+ parent::_construct();
20
+ $this->setId('warehouseGrid');
21
+ $this->setDefaultSort('stock_id');
22
+ $this->setDefaultDir('desc');
23
+ $this->setSaveParametersInSession(true);
24
+ }
25
+
26
+ /**
27
+ * Instantiate and prepare collection
28
+ *
29
+ * @return Smile_Warehouse_Block_Adminhtml_Warehouse_Collection
30
+ */
31
+ protected function _prepareCollection()
32
+ {
33
+ $collection = Mage::getModel('cataloginventory/stock')->getCollection()->addNonDefaultWarehouseCondition();
34
+ $this->setCollection($collection);
35
+ return parent::_prepareCollection();
36
+ }
37
+
38
+ /**
39
+ * Define grid columns
40
+ *
41
+ * @return Smile_Warehouse_Block_Adminhtml_Warehouse_Collection
42
+ */
43
+ protected function _prepareColumns()
44
+ {
45
+ $this->addColumn(
46
+ 'stock_id',
47
+ array(
48
+ 'header'=> Mage::helper('smile_warehouse')->__('ID'),
49
+ 'width' => 1,
50
+ 'type' => 'number',
51
+ 'index' => 'stock_id',
52
+ )
53
+ );
54
+
55
+ $this->addColumn(
56
+ 'code',
57
+ array(
58
+ 'header' => Mage::helper('smile_warehouse')->__('Code'),
59
+ 'type' => 'text',
60
+ 'width' => '100px',
61
+ 'index' => 'stock_code',
62
+ )
63
+ );
64
+
65
+ $this->addColumn(
66
+ 'name',
67
+ array(
68
+ 'header' => Mage::helper('smile_warehouse')->__('Name'),
69
+ 'type' => 'text',
70
+ 'index' => 'stock_name',
71
+ )
72
+ );
73
+
74
+ return parent::_prepareColumns();
75
+ }
76
+
77
+ /**
78
+ * Prepare mass action options for this grid
79
+ *
80
+ * @return Smile_Warehouse_Block_Adminhtml_Warehouse_Collection
81
+ */
82
+ protected function _prepareMassaction()
83
+ {
84
+ $this->setMassactionIdField('stock_id');
85
+ $this->getMassactionBlock()->setFormFieldName('warehouse');
86
+
87
+ $this->getMassactionBlock()->addItem(
88
+ 'delete',
89
+ array(
90
+ 'label' => Mage::helper('smile_warehouse')->__('Delete'),
91
+ 'url' => $this->getUrl('*/*/massDelete'),
92
+ 'confirm' => Mage::helper('smile_warehouse')->__('Are you sure you want to delete these warehouses?')
93
+ )
94
+ );
95
+
96
+ return $this;
97
+ }
98
+
99
+ /**
100
+ * Grid row URL getter
101
+ *
102
+ * @return string
103
+ */
104
+ public function getRowUrl($row)
105
+ {
106
+ return $this->getUrl('*/*/edit', array('id' => $row->getStockId()));
107
+ }
108
+ }
app/code/community/Smile/Warehouse/Block/Adminhtml/Widget/Grid/Column/Renderer/Implode.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Grid column widget for rendering grid cells that contains mapped values
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
8
+ */
9
+ class Smile_Warehouse_Block_Adminhtml_Widget_Grid_Column_Renderer_Implode extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
10
+ {
11
+ /**
12
+ * Renders grid column
13
+ *
14
+ * @param Varien_Object $row row
15
+ *
16
+ * @return string
17
+ */
18
+ public function render(Varien_Object $row)
19
+ {
20
+ $defaultValue = $this->getColumn()->getDefault();
21
+ $data = parent::_getValue($row);
22
+ if (is_array($data) && $data) {
23
+ foreach ($data as &$str) {
24
+ $str = htmlspecialchars($str);
25
+ }
26
+ $data = implode($this->getColumn()->getSeparator(), $data);
27
+ } else {
28
+ $data = htmlspecialchars((is_null($data) ? $defaultValue : $data));
29
+ }
30
+
31
+ return $data;
32
+ }
33
+ }
app/code/community/Smile/Warehouse/Block/Rss/Catalog/NotifyStock.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * RSS block
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Block_Rss_Catalog_NotifyStock extends Mage_Rss_Block_Catalog_NotifyStock
11
+ {
12
+ /**
13
+ * Render rss xml
14
+ *
15
+ * @return string
16
+ */
17
+ protected function _toHtml()
18
+ {
19
+ $newurl = Mage::getUrl('rss/catalog/notifystock');
20
+ $title = Mage::helper('rss')->__('Low Stock Products');
21
+
22
+ $rssObj = Mage::getModel('rss/rss');
23
+ $data = array(
24
+ 'title' => $title,
25
+ 'description' => $title,
26
+ 'link' => $newurl,
27
+ 'charset' => 'UTF-8',
28
+ );
29
+ $rssObj->_addHeader($data);
30
+
31
+ $_configManageStock = (int)Mage::getStoreConfigFlag(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK);
32
+ $stockItemWhere = "({{table}}.low_stock_date is not null) "
33
+ . " and ({{table}}.low_stock_date>'0000-00-00') "
34
+ . " and IF({{table}}.use_config_manage_stock=1," . $_configManageStock . ",{{table}}.manage_stock) = 1"
35
+ . " and {{table}}.stock_id <> " . Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID;
36
+
37
+ $product = Mage::getModel('catalog/product');
38
+ $collection = $product->getCollection()
39
+ ->addAttributeToSelect('name', true)
40
+ ->addAttributeToSelect('name', true)
41
+ ->joinTable(
42
+ 'cataloginventory/stock_item',
43
+ 'product_id=entity_id',
44
+ array(
45
+ 'qty'=>'qty',
46
+ 'notify_stock_qty' => 'notify_stock_qty',
47
+ 'use_config' => 'use_config_notify_stock_qty',
48
+ 'low_stock_date' => 'low_stock_date',
49
+ 'stock_id' => 'stock_id'
50
+ ),
51
+ $stockItemWhere,
52
+ 'inner'
53
+ )
54
+ ->joinTable('cataloginventory/stock', 'stock_id=stock_id', array('stock_code'=>'stock_code'), null, 'inner')
55
+ ->setOrder('low_stock_date');
56
+
57
+ $_globalNotifyStockQty = (float) Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_NOTIFY_STOCK_QTY);
58
+
59
+ Mage::dispatchEvent('rss_catalog_notify_stock_collection_select', array('collection' => $collection));
60
+
61
+ /*
62
+ * Using resource iterator to load the data one by one instead of loading all at the same time.
63
+ * Loading all data at the same time can cause the big memory allocation.
64
+ */
65
+ Mage::getSingleton('core/resource_iterator')
66
+ ->walk(
67
+ $collection->getSelect(),
68
+ array(array($this, 'addNotifyItemXmlCallback')),
69
+ array('rssObj' => $rssObj, 'product' => $product, 'globalQty' => $_globalNotifyStockQty)
70
+ );
71
+
72
+ return $rssObj->createRssXml();
73
+ }
74
+
75
+ /**
76
+ * Create xml-node with item info
77
+ *
78
+ * @param array $args arguments
79
+ *
80
+ * @return void
81
+ */
82
+ public function addNotifyItemXmlCallback($args)
83
+ {
84
+ $product = $args['product'];
85
+ $product->setData($args['row']);
86
+ $url = Mage::helper('adminhtml')->getUrl(
87
+ 'adminhtml/catalog_product/edit/',
88
+ array('id'=>$product->getId(),'_secure' => true,'_nosecret' => true)
89
+ );
90
+ $description = Mage::helper('rss')->__(
91
+ '%s has reached a quantity of %s in "%s" warehouse',
92
+ $product->getName(),
93
+ (1 * $product->getQty()),
94
+ Mage::helper('rss')->escapeHtml($product->getStockCode())
95
+ );
96
+ $rssObj = $args['rssObj'];
97
+ $data = array(
98
+ 'title' => $product->getName(),
99
+ 'link' => $url,
100
+ 'description' => $description,
101
+ );
102
+ $rssObj->_addEntry($data);
103
+ }
104
+ }
app/code/community/Smile/Warehouse/Helper/Data.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse helper
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Helper_Data extends Mage_Core_Helper_Abstract
11
+ {
12
+ /**
13
+ * List of warehouse stock fields
14
+ *
15
+ * @return array
16
+ */
17
+ public function getWarehouseStockFields()
18
+ {
19
+ return array('qty', 'stock_location', 'is_in_stock', 'notify_stock_qty', 'use_config_notify_stock_qty');
20
+ }
21
+
22
+ /**
23
+ * Check if the warehouse stock edit allowed
24
+ *
25
+ * @return boolean
26
+ */
27
+ public function isStockAllowed()
28
+ {
29
+ return Mage::getSingleton('admin/session')->isAllowed('catalog/stock');
30
+ }
31
+
32
+ /**
33
+ * Check, if current admin user allowed to change inventory data for the particular stock item
34
+ *
35
+ * @param Smile_Warehouse_Model_Stock_Item|int $stockItem stock item
36
+ *
37
+ * @return boolean
38
+ */
39
+ public function canUpdateInventory($stockItem)
40
+ {
41
+ $result = false;
42
+
43
+ if ($stockItem instanceof Smile_Warehouse_Model_Stock_Item) {
44
+ $stockId = $stockItem->getStockId();
45
+ } else {
46
+ $stockId = $stockItem;
47
+ }
48
+
49
+ $role = Mage::getSingleton('enterprise_admingws/role');
50
+ if ($role->getIsAll()) {
51
+ return true; // super admin is found
52
+ }
53
+
54
+ if ($this->isStockAllowed() && $stockId) {
55
+ if ($stockId == Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID) {
56
+ $result = true;
57
+ } else {
58
+ $assignedWebsites = Mage::getModel('smile_warehouse/stock')->load($stockId)->getAssignedWebsites();
59
+ $websites = $role->getWebsiteIds();
60
+ $diff = array_diff($assignedWebsites, $websites);
61
+ if (empty($diff)) {
62
+ $result = true;
63
+ }
64
+ }
65
+ } else if ($this->isStockAllowed() && !$stockId) {
66
+ $result = true;
67
+ }
68
+
69
+ return $result;
70
+ }
71
+
72
+ /**
73
+ * Check is stock item exists for product
74
+ *
75
+ * @param Mage_Catalog_Model_Product|int $product product object or id
76
+ * @param Mage_CatalogInventory_Model_Stock|int $stock stock object or id
77
+ *
78
+ * @return bool
79
+ */
80
+ public function isStockItemExists($product, $stock)
81
+ {
82
+ if ($product instanceof Mage_Catalog_Model_Product) {
83
+ $product = $product->getId();
84
+ }
85
+
86
+ if ($stock instanceof Mage_CatalogInventory_Model_Stock) {
87
+ $stock = $stock->getStockId();
88
+ }
89
+
90
+ $stockItem = Mage::getModel('cataloginventory/stock_item')
91
+ ->setStockId($stock)
92
+ ->loadByProduct($product);
93
+
94
+ return (bool)$stockItem->getItemId();
95
+ }
96
+ }
app/code/community/Smile/Warehouse/Model/Catalog/Convert/Parser/Product.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Product parser
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Catalog_Convert_Parser_Product extends Mage_Catalog_Model_Convert_Parser_Product
11
+ {
12
+ /**
13
+ * Unparse (prepare data) loaded products
14
+ *
15
+ * @return Mage_Catalog_Model_Convert_Parser_Product
16
+ */
17
+ public function unparse()
18
+ {
19
+ $entityIds = $this->getData();
20
+ $stock = Mage::getModel('cataloginventory/stock')->loadByStore($this->getStore()->getId());
21
+
22
+ foreach ($entityIds as $i => $entityId) {
23
+ $product = $this->getProductModel()
24
+ ->unlockAttributes()
25
+ ->setStoreId($this->getStoreId())
26
+ ->load($entityId);
27
+ $this->setProductTypeInstance($product);
28
+ /* @var $product Mage_Catalog_Model_Product */
29
+
30
+ $position = Mage::helper('catalog')->__('Line %d, SKU: %s', ($i+1), $product->getSku());
31
+ $this->setPosition($position);
32
+
33
+ $row = array(
34
+ 'store' => $this->getStore()->getCode(),
35
+ 'websites' => '',
36
+ 'attribute_set' => $this->getAttributeSetName($product->getEntityTypeId(), $product->getAttributeSetId()),
37
+ 'type' => $product->getTypeId(),
38
+ 'category_ids' => join(',', $product->getCategoryIds()),
39
+ 'stock_code' => $stock->getStockCode()
40
+ );
41
+
42
+ if ($this->getStore()->getCode() == Mage_Core_Model_Store::ADMIN_CODE) {
43
+ $websiteCodes = array();
44
+ foreach ($product->getWebsiteIds() as $websiteId) {
45
+ $websiteCode = Mage::app()->getWebsite($websiteId)->getCode();
46
+ $websiteCodes[$websiteCode] = $websiteCode;
47
+ }
48
+ $row['websites'] = join(',', $websiteCodes);
49
+ } else {
50
+ $row['websites'] = $this->getStore()->getWebsite()->getCode();
51
+ if ($this->getVar('url_field')) {
52
+ $row['url'] = $product->getProductUrl(false);
53
+ }
54
+ }
55
+
56
+ foreach ($product->getData() as $field => $value) {
57
+ if (in_array($field, $this->_systemFields) || is_object($value)) {
58
+ continue;
59
+ }
60
+
61
+ $attribute = $this->getAttribute($field);
62
+ if (!$attribute) {
63
+ continue;
64
+ }
65
+
66
+ if ($attribute->usesSource()) {
67
+ $option = $attribute->getSource()->getOptionText($value);
68
+ if ($value && empty($option)) {
69
+ $message = Mage::helper('catalog')->__("Invalid option ID specified for %s (%s), skipping the record.", $field, $value);
70
+ $this->addException($message, Mage_Dataflow_Model_Convert_Exception::ERROR);
71
+ continue;
72
+ }
73
+ if (is_array($option)) {
74
+ $value = join(self::MULTI_DELIMITER, $option);
75
+ } else {
76
+ $value = $option;
77
+ }
78
+ unset($option);
79
+ } else if (is_array($value)) {
80
+ continue;
81
+ }
82
+
83
+ $row[$field] = $value;
84
+ }
85
+
86
+ if ($stockItem = $product->getStockItem()) {
87
+ foreach ($stockItem->getData() as $field => $value) {
88
+ if (in_array($field, $this->_systemFields) || is_object($value)) {
89
+ continue;
90
+ }
91
+ $row[$field] = $value;
92
+ }
93
+ }
94
+
95
+ foreach ($this->_imageFields as $field) {
96
+ if (isset($row[$field]) && $row[$field] == 'no_selection') {
97
+ $row[$field] = null;
98
+ }
99
+ }
100
+
101
+ $batchExport = $this->getBatchExportModel()
102
+ ->setId(null)
103
+ ->setBatchId($this->getBatchModel()->getId())
104
+ ->setBatchData($row)
105
+ ->setStatus(1)
106
+ ->save();
107
+ $product->reset();
108
+ }
109
+
110
+ return $this;
111
+ }
112
+ }
app/code/community/Smile/Warehouse/Model/Mysql4/Reports/Product/Lowstock/Collection.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Product Low Stock Report Collection
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Mysql4_Reports_Product_Lowstock_Collection
11
+ extends Mage_Reports_Model_Mysql4_Product_Lowstock_Collection
12
+ {
13
+ /**
14
+ * Join catalog inventory stock item table for further stock_item values filters
15
+ *
16
+ * @return Mage_Reports_Model_Mysql4_Product_Collection
17
+ */
18
+ public function joinInventoryItem($fields = array())
19
+ {
20
+ if (!$this->_inventoryItemJoined) {
21
+
22
+ if ($this->getStoreId()) {
23
+ $stock = Mage::getModel('cataloginventory/stock')->loadByStore($this->getStoreId());
24
+ if ($stock->getStockId()) {
25
+ $stockId = $stock->getStockId();
26
+ } else {
27
+ $stockId = Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID;
28
+ }
29
+
30
+ $joinCondition = '`e`.`%s`=`%s`.`product_id` AND `%s`.stock_id=' . $stockId;
31
+
32
+ } else {
33
+ $this->getSelect()
34
+ ->join(array('cpw'=>$this->getTable('catalog/product_website')), '`e`.`entity_id`=`cpw`.`product_id`')
35
+ ->join(array('w'=>$this->getTable('core/website')), '`w`.`website_id`=`cpw`.`website_id`')
36
+ ->group($this->getEntity()->getEntityIdField());
37
+
38
+ $joinCondition = '`e`.`%s`=`%s`.`product_id` AND `lowstock_inventory_item`.`stock_id`=`w`.`stock_id`';
39
+ }
40
+
41
+ $this->getSelect()->join(
42
+ array($this->_getInventoryItemTableAlias() => $this->_getInventoryItemTable()),
43
+ sprintf(
44
+ $joinCondition,
45
+ $this->getEntity()->getEntityIdField(),
46
+ $this->_getInventoryItemTableAlias(),
47
+ $this->_getInventoryItemTableAlias()
48
+ ),
49
+ array()
50
+ );
51
+ $this->_inventoryItemJoined = true;
52
+ }
53
+
54
+ parent::joinInventoryItem($fields);
55
+
56
+ return $this;
57
+ }
58
+
59
+ /**
60
+ * Add Use Manage Stock Condition to collection
61
+ * Fix core bug related with incorrect field that used in SQL query
62
+ *
63
+ * @param int|null $storeId
64
+ * @return Mage_Reports_Model_Mysql4_Product_Collection
65
+ */
66
+ public function useManageStockFilter($storeId = null)
67
+ {
68
+ $this->joinInventoryItem();
69
+ $this->getSelect()->where(
70
+ sprintf(
71
+ 'IF(%s,%d,%s)=1',
72
+ $this->_getInventoryItemField('use_config_manage_stock'),
73
+ (int) Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK, $storeId),
74
+ $this->_getInventoryItemField('manage_stock')
75
+ )
76
+ );
77
+ return $this;
78
+ }
79
+ }
app/code/community/Smile/Warehouse/Model/Mysql4/Setup.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Resource setup model
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Mysql4_Setup extends Mage_Core_Model_Resource_Setup
11
+ {
12
+ }
app/code/community/Smile/Warehouse/Model/Mysql4/Stock.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock resource model
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Mysql4_Stock extends Mage_CatalogInventory_Model_Mysql4_Stock
11
+ {
12
+ /**
13
+ * Retrieve variable data by code
14
+ *
15
+ * @param string $code code
16
+ *
17
+ * @return array
18
+ */
19
+ public function getStockByCode($code)
20
+ {
21
+ $select = $this->_getReadAdapter()->select()
22
+ ->from($this->getMainTable())
23
+ ->where($this->getMainTable().'.stock_code = ?', $code);
24
+
25
+ return $this->_getReadAdapter()->fetchRow($select);
26
+ }
27
+
28
+ /**
29
+ * Load warehouse website id
30
+ *
31
+ * @param Smile_Warehouse_Model_Stock $object object
32
+ * @param int $websiteId website id
33
+ *
34
+ * @return void
35
+ */
36
+ public function loadByWebsiteId($object, $websiteId)
37
+ {
38
+ if (
39
+ $data = $this->getReadConnection()->fetchRow(
40
+ $this->getReadConnection()->select()
41
+ ->from(array('site' => $this->getTable('core/website')), "website_id")
42
+ ->join(array('stock' => $this->getMainTable()), "site.stock_id = stock.stock_id", array("stock.*"))
43
+ ->where('website_id = ?', $websiteId)
44
+ ->limit(1)
45
+ )
46
+ ) {
47
+ $object->addData($data);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Get websites ids that asiigned to stock
53
+ *
54
+ * @param int $stockId stock id
55
+ *
56
+ * @return array
57
+ */
58
+ public function getAssignedWebsites($stockId)
59
+ {
60
+ return $this->getReadConnection()->fetchCol(
61
+ $this->getReadConnection()->select()
62
+ ->from(array('site' => $this->getTable('core/website')), "website_id")
63
+ ->where('stock_id = ?', $stockId)
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Set items out of stock basing on their quantities and config settings
69
+ *
70
+ */
71
+ public function updateSetOutOfStock()
72
+ {
73
+ $this->_initConfig();
74
+ $this->_getWriteAdapter()->update(
75
+ $this->getTable('cataloginventory/stock_item'),
76
+ array('is_in_stock' => 0, 'stock_status_changed_automatically' => 1),
77
+ sprintf(
78
+ 'is_in_stock = 1
79
+ AND (use_config_manage_stock = 1 AND 1 = %d OR use_config_manage_stock = 0 AND manage_stock = 1)
80
+ AND (use_config_backorders = 1 AND %d = %d OR use_config_backorders = 0 AND backorders = %d)
81
+ AND (use_config_min_qty = 1 AND qty <= %d OR use_config_min_qty = 0 AND qty <= min_qty)
82
+ AND product_id IN (SELECT entity_id FROM %s WHERE type_id IN (%s))',
83
+ $this->_isConfigManageStock,
84
+ Mage_CatalogInventory_Model_Stock::BACKORDERS_NO, $this->_isConfigBackorders, Mage_CatalogInventory_Model_Stock::BACKORDERS_NO,
85
+ $this->_configMinQty,
86
+ $this->getTable('catalog/product'), $this->_getWriteAdapter()->quote($this->_configTypeIds)
87
+ )
88
+ );
89
+ }
90
+
91
+ /**
92
+ * Set items in stock basing on their quantities and config settings
93
+ *
94
+ * @return void
95
+ */
96
+ public function updateSetInStock()
97
+ {
98
+ $this->_initConfig();
99
+ $this->_getWriteAdapter()->update(
100
+ $this->getTable('cataloginventory/stock_item'),
101
+ array('is_in_stock' => 1),
102
+ sprintf(
103
+ 'is_in_stock = 0
104
+ AND stock_status_changed_automatically = 1
105
+ AND (use_config_manage_stock = 1 AND 1 = %d OR use_config_manage_stock = 0 AND manage_stock = 1)
106
+ AND (use_config_min_qty = 1 AND qty > %d OR use_config_min_qty = 0 AND qty > min_qty)
107
+ AND product_id IN (SELECT entity_id FROM %s WHERE type_id IN (%s))',
108
+ $this->_isConfigManageStock,
109
+ $this->_configMinQty,
110
+ $this->getTable('catalog/product'), $this->_getWriteAdapter()->quote($this->_configTypeIds)
111
+ )
112
+ );
113
+ }
114
+
115
+ /**
116
+ * Update items low stock date basing on their quantities and config settings
117
+ *
118
+ * @return void
119
+ */
120
+ public function updateLowStockDate()
121
+ {
122
+ $nowUTC = Mage::app()->getLocale()->date(null, null, null, false)->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
123
+ $this->_initConfig();
124
+ $this->_getWriteAdapter()->update(
125
+ $this->getTable('cataloginventory/stock_item'),
126
+ array('low_stock_date' => new Zend_Db_Expr(
127
+ sprintf(
128
+ 'CASE
129
+ WHEN (use_config_notify_stock_qty = 1 AND qty < %d) OR (use_config_notify_stock_qty = 0 AND qty < notify_stock_qty)
130
+ THEN %s ELSE NULL
131
+ END',
132
+ $this->_configNotifyStockQty,
133
+ $this->_getWriteAdapter()->quote($nowUTC)
134
+ )
135
+ )),
136
+ sprintf(
137
+ '(use_config_manage_stock = 1 AND 1 = %d OR use_config_manage_stock = 0 AND manage_stock = 1) AND product_id IN (SELECT entity_id FROM %s WHERE type_id IN (%s))',
138
+ $this->_isConfigManageStock,
139
+ $this->getTable('catalog/product'), $this->_getWriteAdapter()->quote($this->_configTypeIds)
140
+ )
141
+ );
142
+ }
143
+
144
+ /**
145
+ * add join to select only in stock products
146
+ *
147
+ * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection $collection product collection
148
+ *
149
+ * @return Mage_CatalogInventory_Model_Mysql4_Stock
150
+ */
151
+ public function setInStockFilterToCollection($collection)
152
+ {
153
+ $manageStock = Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK);
154
+ $cond = array(
155
+ '{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=1 AND {{table}}.is_in_stock=1',
156
+ '{{table}}.use_config_manage_stock = 0 AND {{table}}.manage_stock=0',
157
+ );
158
+
159
+ if ($manageStock) {
160
+ $cond[] = '{{table}}.use_config_manage_stock = 1 AND {{table}}.is_in_stock=1';
161
+ } else {
162
+ $cond[] = '{{table}}.use_config_manage_stock = 1';
163
+ }
164
+
165
+ //load stock
166
+ $stock = Mage::getModel('cataloginventory/stock')->loadByStore($collection->getStoreId());
167
+
168
+ $collection->joinField(
169
+ 'inventory_in_stock',
170
+ 'cataloginventory/stock_item',
171
+ 'is_in_stock',
172
+ 'product_id=entity_id',
173
+ '(('.join(') OR (', $cond) . ')) AND {{table}}.stock_id=' . $stock->getId()
174
+ );
175
+ return $this;
176
+ }
177
+ }
app/code/community/Smile/Warehouse/Model/Mysql4/Stock/Collection.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock collection
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Mysql4_Stock_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
11
+ {
12
+ /**
13
+ * Init model
14
+ *
15
+ * @return void
16
+ */
17
+ protected function _construct()
18
+ {
19
+ $this->_init('smile_warehouse/stock');
20
+ }
21
+
22
+ /**
23
+ * Remove default warehouse
24
+ *
25
+ * @return Smile_Warehouse_Model_Mysql4_Stock_Collection
26
+ */
27
+ public function addNonDefaultWarehouseCondition()
28
+ {
29
+ $this->getSelect()->where('stock_id != ?', Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID);
30
+ return $this;
31
+ }
32
+
33
+ /**
34
+ * Convert items array to array for select options
35
+ *
36
+ * @return array
37
+ */
38
+ public function toOptionArray()
39
+ {
40
+ return $this->_toOptionHash('stock_id', 'stock_name');
41
+ }
42
+ }
app/code/community/Smile/Warehouse/Model/Mysql4/Stock/Item.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock item resource model
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Mysql4_Stock_Item extends Mage_CatalogInventory_Model_Mysql4_Stock_Item
11
+ {
12
+ /**
13
+ * Add join for catalog in stock field to product collection
14
+ *
15
+ * @param Mage_Catalog_Model_Entity_Product_Collection $productCollection product collection
16
+ *
17
+ * @return Mage_CatalogInventory_Model_Mysql4_Stock_Item
18
+ */
19
+ public function addCatalogInventoryToProductCollection($productCollection)
20
+ {
21
+ $stockId = Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID;
22
+ $stock = Mage::getModel('cataloginventory/stock')->loadByStore($productCollection->getStoreId());
23
+ if ($stock->getStockId()) {
24
+ $stockId = $stock->getStockId();
25
+ }
26
+ $isStockManagedInConfig = (int) Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK);
27
+ $inventoryTable = $this->getTable('cataloginventory/stock_item');
28
+ $productCollection->joinTable(
29
+ 'cataloginventory/stock_item',
30
+ 'product_id=entity_id',
31
+ array(
32
+ 'is_saleable' => new Zend_Db_Expr(
33
+ "(
34
+ IF(
35
+ IF(
36
+ $inventoryTable.use_config_manage_stock,
37
+ $isStockManagedInConfig,
38
+ $inventoryTable.manage_stock
39
+ ),
40
+ $inventoryTable.is_in_stock,
41
+ 1
42
+ )
43
+ )"
44
+ ),
45
+ 'inventory_in_stock' => 'is_in_stock'
46
+ ),
47
+ '{{table}}.stock_id=' . $stockId, 'left'
48
+ );
49
+ return $this;
50
+ }
51
+ }
app/code/community/Smile/Warehouse/Model/Mysql4/Stock/Status.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock status per website resource model
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Mysql4_Stock_Status extends Mage_CatalogInventory_Model_Mysql4_Stock_Status
11
+ {
12
+ /**
13
+ * Add stock status limitation to catalog product price index select object
14
+ *
15
+ * @param Varien_Db_Select $select select object
16
+ * @param string|Zend_Db_Expr $entityField entity field
17
+ * @param string|Zend_Db_Expr $websiteField website field
18
+ *
19
+ * @return Mage_CatalogInventory_Model_Mysql4_Stock_Status
20
+ */
21
+ public function prepareCatalogProductIndexSelect(Varien_Db_Select $select, $entityField, $websiteField)
22
+ {
23
+ $stockIdField = '';
24
+ foreach ($select->getPart(Zend_Db_Select::FROM) as $alias => $from) {
25
+ if ($from['tableName'] == $this->getTable('core/website')) {
26
+ $stockIdField = $alias . '.stock_id';
27
+ break;
28
+ }
29
+ }
30
+ if (!$stockIdField) {
31
+ $select->join(
32
+ array('ciss_cw' => $this->getTable('core/website')),
33
+ $websiteField . '=ciss_cw.website_id',
34
+ array()
35
+ );
36
+ $stockIdField = 'ciss_cw.stock_id';
37
+ }
38
+ $select->join(
39
+ array('ciss' => $this->getMainTable()),
40
+ "ciss.product_id = {$entityField} AND ciss.website_id = {$websiteField} AND ciss.stock_id = {$stockIdField}",
41
+ array()
42
+ );
43
+ $select->where('ciss.stock_status=?', Mage_CatalogInventory_Model_Stock_Status::STATUS_IN_STOCK);
44
+
45
+ return $this;
46
+ }
47
+
48
+ /**
49
+ * Add only is in stock products filter to product collection
50
+ *
51
+ * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection $collection product collection
52
+ *
53
+ * @return Mage_CatalogInventory_Model_Stock_Status
54
+ */
55
+ public function addIsInStockFilterToCollection($collection)
56
+ {
57
+ $websiteId = Mage::app()->getStore($collection->getStoreId())->getWebsiteId();
58
+
59
+ //load stock
60
+ $stock = Mage::getModel('cataloginventory/stock')->loadByStore($collection->getStoreId());
61
+
62
+ $collection->getSelect()
63
+ ->join(
64
+ array('stock_status_index' => $this->getMainTable()),
65
+ 'e.entity_id = stock_status_index.product_id AND stock_status_index.website_id = '.$websiteId.' AND stock_status_index.stock_id = '.$stock->getId(),
66
+ array()
67
+ )
68
+ ->where('stock_status_index.stock_status=?', Mage_CatalogInventory_Model_Stock_Status::STATUS_IN_STOCK);
69
+
70
+ return $this;
71
+ }
72
+ }
app/code/community/Smile/Warehouse/Model/Observer.php ADDED
@@ -0,0 +1,514 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse observer
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Observer extends Mage_CatalogInventory_Model_Observer
11
+ {
12
+ /**
13
+ * Add warehouses dropdown on website create
14
+ *
15
+ * @param Varien_Event_Observer $observer observer
16
+ *
17
+ * @return Smile_Warehouse_Model_Observer
18
+ */
19
+ public function addWarehouseField(Varien_Event_Observer $observer)
20
+ {
21
+ if ($observer->getBlock() && $observer->getBlock() instanceof Mage_Adminhtml_Block_System_Store_Edit_Form) {
22
+ if (Mage::registry('store_type') == 'website') {
23
+ $observer->getBlock()
24
+ ->getForm()
25
+ ->getElement('website_fieldset')
26
+ ->addField(
27
+ 'website_warehouse',
28
+ 'select',
29
+ array(
30
+ 'name' => 'website[stock_id]',
31
+ 'label' => Mage::helper('smile_warehouse')->__('Warehouse'),
32
+ 'value' => Mage::registry('store_data')->getStockId(),
33
+ 'values' => Mage::getModel('cataloginventory/stock')->getCollection()->toOptionArray(),
34
+ 'required' => true,
35
+ 'disabled' => Mage::registry('store_data')->isReadOnly()
36
+ ),
37
+ 'website_code'
38
+ );
39
+ }
40
+ }
41
+ return $this;
42
+ }
43
+
44
+ /**
45
+ * Saving product inventory data. Product qty calculated dynamically.
46
+ *
47
+ * @param Varien_Event_Observer $observer observer
48
+ *
49
+ * @return Smile_Warehouse_Model_Observer
50
+ */
51
+ public function saveInventoryData($observer)
52
+ {
53
+ $product = $observer->getEvent()->getProduct();
54
+
55
+ if (Mage::helper('smile_warehouse')->canUpdateInventory($product->getStockItem())) {
56
+ parent::saveInventoryData($observer);
57
+ $this->_updateStockItems($product);
58
+ } else {
59
+ if (!$product->getIsMassupdate()) {
60
+ Mage::getSingleton('adminhtml/session')->addError(
61
+ Mage::helper('smile_warehouse')->__('You are not allowed to change inventory data.')
62
+ );
63
+ }
64
+ }
65
+
66
+ return $this;
67
+ }
68
+
69
+ /**
70
+ * Update stock items
71
+ *
72
+ * @param Mage_Catalog_Model_Product $product product
73
+ *
74
+ * @return void
75
+ */
76
+ protected function _updateStockItems($product)
77
+ {
78
+ $websiteCollection = Mage::getModel('core/website')->getCollection()->addIdFilter($product->getWebsiteIds());
79
+ $stockIds = array(Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID);
80
+ foreach ($websiteCollection as $website) {
81
+ if (!in_array($website->getStockId(), $stockIds)) {
82
+ array_push($stockIds, $website->getStockId());
83
+ }
84
+ }
85
+
86
+ foreach ($stockIds as $stockId) {
87
+ if (!Mage::helper('smile_warehouse')->isStockItemExists($product, $stockId)) {
88
+ $this->_createStockItem($product, $stockId);
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Create stock item for product by stock
95
+ *
96
+ * @param Mage_Catalog_Model_Product $product product
97
+ * @param int $stockId stock id
98
+ *
99
+ * @return void
100
+ */
101
+ protected function _createStockItem($product, $stockId)
102
+ {
103
+ //cover duplicate functionality
104
+ if ($product->getIsDuplicate()) {
105
+ $sourceStock = Mage::getModel('cataloginventory/stock_item')
106
+ ->setStockId($stockId)
107
+ ->loadByProduct($product->getOriginalId());
108
+ }
109
+
110
+ if (isset($sourceStock) && $sourceStock->getItemId()) {
111
+ $item = clone $sourceStock;
112
+ $item->unsItemId();
113
+ } else {
114
+ //create new stock item
115
+ $item = Mage::getModel('cataloginventory/stock_item')
116
+ ->setManageStock($this->_getStockItemConfig('manage_stock'))
117
+ ->setUseConfigManageStock(1)
118
+ ->setMinQty($this->_getStockItemConfig('min_qty'))
119
+ ->setUseConfigMinQty(1)
120
+ ->setMinSaleQty($this->_getStockItemConfig('min_sale_qty'))
121
+ ->setUseConfigMinSaleQty(1)
122
+ ->setMaxSaleQty($this->_getStockItemConfig('max_sale_qty'))
123
+ ->setUseConfigMaxSaleQty(1)
124
+ ->setIsQtyDecimal($this->_getStockItemConfig('is_qty_decimal'))
125
+ ->setBackorders($this->_getStockItemConfig('backorders'))
126
+ ->setUseConfigBackorders(1)
127
+ ->setEnableQtyIncrements($this->_getStockItemConfig('enable_qty_increments'))
128
+ ->setUseConfigEnableQtyIncrements(1);
129
+ }
130
+
131
+ //set default values
132
+ $item->setStoreLocation('')
133
+ ->setStockId($stockId)
134
+ ->setNotifyStockQty(1)
135
+ ->setQty(0)
136
+ ->setProduct($product)
137
+ ->setProductId($product->getId());
138
+
139
+ $item->save();
140
+ }
141
+
142
+ /**
143
+ * Get defualt values related to stock item from config
144
+ *
145
+ * @param string $field field
146
+ *
147
+ * @return mixed
148
+ */
149
+ protected function _getStockItemConfig($field)
150
+ {
151
+ return Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_ITEM . $field);
152
+ }
153
+
154
+ /**
155
+ * Copy product inventory data (used for product duplicate functionality)
156
+ *
157
+ * @param Varien_Event_Observer $observer observer
158
+ *
159
+ * @return Smile_Warehouse_Model_Observer
160
+ */
161
+ public function copyInventoryData($observer)
162
+ {
163
+ // Disable native copy inventory functionality, because it's clear default stock item information
164
+ return $this;
165
+ }
166
+
167
+ /**
168
+ * Manage stock items when products websites are changed
169
+ *
170
+ * @param Varien_Event_Observer $observer observer
171
+ *
172
+ * @return Smile_Warehouse_Model_Observer
173
+ */
174
+ public function updateProductsWebsites(Varien_Event_Observer $observer)
175
+ {
176
+ $productIds = $observer->getEvent()->getProductIds();
177
+
178
+ foreach ($productIds as $productId) {
179
+ $product = Mage::getModel('catalog/product')->load($productId);
180
+ $this->_updateStockItems($product);
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Add information about producs stock status to collection
186
+ * Used in for product collection after load
187
+ *
188
+ * @param Varien_Event_Observer $observer observer
189
+ *
190
+ * @return Smile_Warehouse_Model_Observer
191
+ */
192
+ public function addStockStatusToCollection($observer)
193
+ {
194
+ $productCollection = $observer->getEvent()->getCollection();
195
+ if ($productCollection->hasFlag('require_stock_items')) {
196
+ Mage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection);
197
+ } else {
198
+ $stockId = null;
199
+ $stock = Mage::getModel('cataloginventory/stock')->loadByStore($productCollection->getStoreId());
200
+ if ($stock->getStockId()) {
201
+ $stockId = $stock->getStockId();
202
+ }
203
+
204
+ $websiteId = Mage::app()->getStore($productCollection->getStoreId())->getWebsiteId();
205
+
206
+ Mage::getModel('cataloginventory/stock_status')->addStockStatusToProducts($productCollection, $websiteId, $stockId);
207
+ }
208
+ return $this;
209
+ }
210
+
211
+
212
+ /**
213
+ * Subtract quote items qtys from stock items related with quote items products.
214
+ *
215
+ * Used before order placing to make order save/place transaction smaller
216
+ * Also called after every successful order placement to ensure subtraction of inventory
217
+ *
218
+ * @param Varien_Event_Observer $observer observer
219
+ *
220
+ * @return Smile_Warehouse_Model_Observer
221
+ */
222
+ public function subtractQuoteInventory(Varien_Event_Observer $observer)
223
+ {
224
+ $quote = $observer->getEvent()->getQuote();
225
+
226
+ // Maybe we've already processed this quote in some event during order placement
227
+ // e.g. call in event 'sales_model_service_quote_submit_before' and later in 'checkout_submit_all_after'
228
+ if ($quote->getInventoryProcessed()) {
229
+ return;
230
+ }
231
+ $items = $this->_getProductsQty($quote->getAllItems());
232
+
233
+ /**
234
+ * Remember items
235
+ */
236
+ $this->_itemsForReindex = Mage::getSingleton('cataloginventory/stock')
237
+ ->setStoreId($quote->getStoreId())
238
+ ->registerProductsSale($items);
239
+
240
+ $quote->setInventoryProcessed(true);
241
+ return $this;
242
+ }
243
+
244
+ /**
245
+ * Revert quote items inventory data (cover not success order place case)
246
+ *
247
+ * @param Varien_Event_Observer $observer observer
248
+ *
249
+ * @return void
250
+ */
251
+ public function revertQuoteInventory($observer)
252
+ {
253
+ $quote = $observer->getEvent()->getQuote();
254
+ $items = $this->_getProductsQty($quote->getAllItems());
255
+ Mage::getSingleton('cataloginventory/stock')->setStoreId($quote->getStoreId())->revertProductsSale($items);
256
+
257
+ // Clear flag, so if order placement retried again with success - it will be processed
258
+ $quote->setInventoryProcessed(false);
259
+ }
260
+
261
+ /**
262
+ * Return creditmemo items qty to stock
263
+ *
264
+ * @param Varien_Event_Observer $observer observer
265
+ *
266
+ * @return void
267
+ */
268
+ public function refundOrderInventory($observer)
269
+ {
270
+ $creditmemo = $observer->getEvent()->getCreditmemo();
271
+ $items = array();
272
+ foreach ($creditmemo->getAllItems() as $item) {
273
+ $return = false;
274
+ if ($item->hasBackToStock()) {
275
+ if ($item->getBackToStock() && $item->getQty()) {
276
+ $return = true;
277
+ }
278
+ } elseif (Mage::helper('cataloginventory')->isAutoReturnEnabled()) {
279
+ $return = true;
280
+ }
281
+ if ($return) {
282
+ if (isset($items[$item->getProductId()])) {
283
+ $items[$item->getProductId()]['qty'] += $item->getQty();
284
+ } else {
285
+ $items[$item->getProductId()] = array(
286
+ 'qty' => $item->getQty(),
287
+ 'item'=> null,
288
+ );
289
+ }
290
+ }
291
+ }
292
+ Mage::getSingleton('cataloginventory/stock')->setStoreId($creditmemo->getStoreId())->revertProductsSale($items);
293
+ }
294
+
295
+ /**
296
+ * Cancel order item
297
+ *
298
+ * @param Varien_Event_Observer $observer observer
299
+ *
300
+ * @return Smile_Warehouse_Model_Observer
301
+ */
302
+ public function cancelOrderItem($observer)
303
+ {
304
+ $item = $observer->getEvent()->getItem();
305
+
306
+ $children = $item->getChildrenItems();
307
+ $qty = $item->getQtyOrdered() - max($item->getQtyShipped(), $item->getQtyInvoiced()) - $item->getQtyCanceled();
308
+
309
+ if ($item->getId() && ($productId = $item->getProductId()) && empty($children) && $qty) {
310
+ Mage::getSingleton('cataloginventory/stock')->setStoreId($item->getStoreId())->backItemQty($productId, $qty);
311
+ }
312
+
313
+ return $this;
314
+ }
315
+
316
+ /**
317
+ * Manage products stocks when website stock is changed
318
+ *
319
+ * @param Varien_Event_Observer $observer observer
320
+ *
321
+ * @return Smile_Warehouse_Model_Observer
322
+ */
323
+ public function reassignStock(Varien_Event_Observer $observer)
324
+ {
325
+ $website = $observer->getEvent()->getWebsite();
326
+
327
+ if ($website->dataHasChangedFor('stock_id')) {
328
+ $stockId = $website->getData('stock_id');
329
+
330
+ $productsCollection = Mage::getModel('catalog/product')->getCollection()->addWebsiteFilter($website)
331
+ ->joinTable(
332
+ 'cataloginventory/stock_item',
333
+ 'product_id=entity_id',
334
+ array('stock_item_id' => 'item_id'),
335
+ '{{table}}.stock_id=' . $stockId,
336
+ 'left'
337
+ );
338
+
339
+ foreach ($productsCollection as $product) {
340
+ if (!$product->getStockItemId()) {
341
+ $this->_createStockItem($product, $stockId);
342
+ }
343
+ }
344
+ }
345
+
346
+ return $this;
347
+ }
348
+
349
+ /**
350
+ * Import product by stock code
351
+ *
352
+ * @param Varien_Event_Observer $observer observer
353
+ *
354
+ * @return Smile_Warehouse_Model_Observer
355
+ */
356
+ public function importProductByStockCode(Varien_Event_Observer $observer)
357
+ {
358
+ $product = $observer->getEvent()->getProduct();
359
+
360
+ if ($product->getIsMassupdate()) {
361
+ $stockData = $product->getStockData();
362
+ if (isset($stockData['stock_code'])) {
363
+ if ($product->getStoreId() == Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID) {
364
+ $stock = Mage::getModel('cataloginventory/stock')->loadByCode($stockData['stock_code']);
365
+ if (!$stock->getId()) {
366
+ $message = Mage::helper('catalog')->__(
367
+ 'Skipping import row, unknown warehouse specified for product with sku %s.',
368
+ $product->getSku()
369
+ );
370
+ Mage::throwException($message);
371
+ } else {
372
+ if ($product->getStockItem() && $product->getStockItem()->getStockId() != $stock->getId()) {
373
+ $product->getStockItem()->setStockId($stock->getId());
374
+ $product->getStockItem()->loadByProduct($product);
375
+ }
376
+ }
377
+ } else {
378
+ $stock = Mage::getModel('cataloginventory/stock')->loadByStore($product->getStoreId());
379
+ if ($stock->getStockCode() != $stockData['stock_code']) {
380
+ $message = Mage::helper('catalog')->__(
381
+ 'Skipping import row, store and stock code mismatch for product with sku %s.',
382
+ $product->getSku()
383
+ );
384
+ Mage::throwException($message);
385
+ }
386
+ }
387
+ }
388
+
389
+ $stockId = 0;
390
+ if (!$product->getId()) {
391
+ if (isset($stock) && $stock) {
392
+ $stockId = $stock->getId();
393
+ } else {
394
+ $stockId = Mage::getModel('cataloginventory/stock')->loadByStore($product->getStoreId())->getStockId();
395
+ }
396
+ } else if ($product->getStockItem()) {
397
+ $stockId = $product->getStockItem()->getStockId();
398
+ }
399
+
400
+ if (!Mage::helper('smile_warehouse')->canUpdateInventory($stockId)) {
401
+ $message = Mage::helper('smile_warehouse')->__(
402
+ 'Skip import row, stock item for product with sku "%s" is not allowed in your current permission scope.',
403
+ $product->getSku()
404
+ );
405
+ Mage::throwException($message);
406
+ }
407
+ }
408
+
409
+ return $this;
410
+ }
411
+
412
+ /**
413
+ * Set flag that product grid block loading
414
+ *
415
+ * @param Varien_Event_Observer $observer observer
416
+ *
417
+ * @return Smile_Warehouse_Model_Observer
418
+ */
419
+ public function setProductGridFlag(Varien_Event_Observer $observer)
420
+ {
421
+ $block = $observer->getEvent()->getBlock();
422
+ /* @var $block Mage_Core_Block_Abstract */
423
+
424
+ if ($block instanceof Mage_Adminhtml_Block_Catalog_Product_Grid) {
425
+ Mage::register('product_grid_block_loading', true);
426
+ }
427
+
428
+ return $this;
429
+ }
430
+
431
+ /**
432
+ * Remove flag that product grid block loading
433
+ *
434
+ * @param Varien_Event_Observer $observer observer
435
+ *
436
+ * @return Smile_Warehouse_Model_Observer
437
+ */
438
+ public function unsetProductGridFlag(Varien_Event_Observer $observer)
439
+ {
440
+ $block = $observer->getEvent()->getBlock();
441
+ /* @var $block Mage_Core_Block_Abstract */
442
+
443
+ if ($block instanceof Mage_Adminhtml_Block_Catalog_Product_Grid) {
444
+ Mage::unregister('product_grid_block_loading');
445
+ }
446
+
447
+ return $this;
448
+ }
449
+
450
+ /**
451
+ * Fix product collection stock items join on product grid
452
+ *
453
+ * @param Varien_Event_Observer $observer observer
454
+ *
455
+ * @return Smile_Warehouse_Model_Observer
456
+ */
457
+ public function fixProductCollectionStockJoin(Varien_Event_Observer $observer)
458
+ {
459
+ if (Mage::registry('product_grid_block_loading')) {
460
+ $collection = $observer->getEvent()->getCollection();
461
+ /* @var $collection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */
462
+
463
+ if ($collection->getStoreId()) {
464
+ $fromPart = $collection->getSelect()->getPart(Zend_Db_Select::FROM);
465
+ foreach ($fromPart as &$from) {
466
+ if ($from['tableName'] == $collection->getTable('cataloginventory/stock_item') && isset($from['joinCondition'])) {
467
+ $from['joinCondition'] = str_replace(
468
+ 'stock_id=1',
469
+ 'stock_id=' . Mage::app()->getStore($collection->getStoreId())->getWebsite()->getStockId(),
470
+ $from['joinCondition']
471
+ );
472
+ }
473
+ }
474
+ $collection->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
475
+ }
476
+ }
477
+
478
+ return $this;
479
+ }
480
+
481
+ /**
482
+ * Add all stocks qty column to product grid
483
+ *
484
+ * @param Varien_Event_Observer $observer observer
485
+ *
486
+ * @return Smile_Warehouse_Model_Observer
487
+ */
488
+ public function addAllStocksQtyColumn(Varien_Event_Observer $observer)
489
+ {
490
+ $block = $observer->getEvent()->getBlock();
491
+ /* @var $block Mage_Core_Block_Abstract */
492
+
493
+ if ($block instanceof Mage_Adminhtml_Block_Catalog_Product_Grid
494
+ && !$block->getCollection()->getStoreId()) {
495
+ Mage::getModel('cataloginventory/stock')->addStocksQtyToCollection($block->getCollection());
496
+
497
+ $block->addColumn(
498
+ 'qty',
499
+ array(
500
+ 'header' => Mage::helper('catalog')->__('Qty'),
501
+ 'width' => '100px',
502
+ 'index' => 'qty',
503
+ 'renderer' => 'smile_warehouse/adminhtml_widget_grid_column_renderer_implode',
504
+ 'separator' => '<br />',
505
+ 'filter' => false,
506
+ 'sortable' => false,
507
+ )
508
+ );
509
+ $block->sortColumnsByOrder();
510
+ }
511
+
512
+ return $this;
513
+ }
514
+ }
app/code/community/Smile/Warehouse/Model/Stock.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock model
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Stock extends Mage_CatalogInventory_Model_Stock
11
+ {
12
+
13
+ /**
14
+ * Standard model initialization
15
+ *
16
+ * @param string $resourceModel resource model
17
+ *
18
+ * @return void
19
+ */
20
+ protected function _init($resourceModel)
21
+ {
22
+ $this->_setResourceModel($resourceModel, 'smile_warehouse/stock_collection');
23
+ }
24
+
25
+ /**
26
+ * Retrieve stock identifier
27
+ *
28
+ * @return int
29
+ */
30
+ public function getId()
31
+ {
32
+ $stockId = $this->getData('stock_id');
33
+ if (is_null($stockId) && ($storeId = $this->getData('store_id'))) {
34
+ $this->loadByStore($storeId);
35
+ $stockId = $this->getStockId();
36
+ }
37
+
38
+ return $stockId;
39
+ }
40
+
41
+ /**
42
+ * Add stock item objects to products
43
+ *
44
+ * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection $productCollection product collection
45
+ *
46
+ * @return Smile_Warehouse_Model_Stock
47
+ */
48
+ public function addItemsToProducts($productCollection)
49
+ {
50
+ $this->setStoreId($productCollection->getStoreId());
51
+ return parent::addItemsToProducts($productCollection);
52
+ }
53
+
54
+ /**
55
+ * Validate stock information
56
+ *
57
+ * @return Smile_Warehouse_Model_Stock
58
+ */
59
+ public function validate()
60
+ {
61
+ if ($this->getStockCode()) {
62
+ $stock = $this->getResource()->getStockByCode($this->getStockCode());
63
+ if (!empty($stock) && $stock['stock_id'] != $this->getStockId()) {
64
+ Mage::throwException(Mage::helper('smile_warehouse')->__('Warehouse code must be unique.'));
65
+ }
66
+ }
67
+
68
+ return $this;
69
+ }
70
+
71
+ /**
72
+ * Get warehouse by store id
73
+ *
74
+ * @param mixed $store store
75
+ *
76
+ * @return Smile_Warehouse_Model_Stock
77
+ */
78
+ public function loadByStore($store)
79
+ {
80
+ $websiteId = Mage::app()->getStore($store)->getWebsiteId();
81
+ $this->getResource()->loadByWebsiteId($this, $websiteId);
82
+
83
+ return $this;
84
+ }
85
+
86
+ /**
87
+ * Get assigned websites
88
+ *
89
+ * @return array
90
+ */
91
+ public function getAssignedWebsites()
92
+ {
93
+ return $this->getResource()->getAssignedWebsites($this->getStockId());
94
+ }
95
+
96
+ /**
97
+ * Get back to stock (when order is canceled or whatever else)
98
+ *
99
+ * @param int $productId product id
100
+ * @param numeric $qty quantity
101
+ *
102
+ * @return Mage_CatalogInventory_Model_Stock
103
+ */
104
+ public function backItemQty($productId, $qty)
105
+ {
106
+ $stockItem = Mage::getModel('cataloginventory/stock_item')
107
+ ->setStockId($this->getId())
108
+ ->loadByProduct($productId);
109
+
110
+ if ($stockItem->getId() && Mage::helper('cataloginventory')->isQty($stockItem->getTypeId())) {
111
+ $stockItem->addQty($qty);
112
+ if ($stockItem->getCanBackInStock() && $stockItem->getQty() > $stockItem->getMinQty()) {
113
+ $stockItem->setIsInStock(true)
114
+ ->setStockStatusChangedAutomaticallyFlag(true);
115
+ }
116
+ $stockItem->save();
117
+ }
118
+ return $this;
119
+ }
120
+
121
+ /**
122
+ * Adds filtering for collection to return only in stock products
123
+ *
124
+ * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection $collection product collection
125
+ *
126
+ * @return Mage_CatalogInventory_Model_Stock $this
127
+ */
128
+ public function addInStockFilterToCollection($collection)
129
+ {
130
+ if (!$this->getId()) {
131
+ $this->loadByStore($collection->getStoreId());
132
+ }
133
+
134
+ parent::addInStockFilterToCollection();
135
+ return $this;
136
+ }
137
+
138
+ /**
139
+ * Get warehouse stock by stock code
140
+ *
141
+ * @param string $stockCode stock code
142
+ *
143
+ * @return Smile_Warehouse_Model_Stock
144
+ */
145
+ public function loadByCode($stockCode)
146
+ {
147
+ $data = $this->getResource()->getStockByCode($stockCode);
148
+ if (!empty($data)) {
149
+ $this->addData($data);
150
+ }
151
+ return $this;
152
+ }
153
+
154
+ /**
155
+ * Add qty in all warehouses to each product in the collection
156
+ *
157
+ * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection $productCollection product collection
158
+ *
159
+ * @return Smile_Warehouse_Model_Stock
160
+ */
161
+ public function addStocksQtyToCollection($productCollection)
162
+ {
163
+ if ($productCollection) {
164
+ $stockCollection = Mage::getResourceModel('cataloginventory/stock_item_collection');
165
+ $warehouseCollection = Mage::getModel('cataloginventory/stock')->getCollection();
166
+
167
+ $stockCollection->addProductsFilter($productCollection);
168
+
169
+ $warehouses = array();
170
+ foreach ($stockCollection as $item) {
171
+ $warehouses[$item->getStockId()] = $item->getStockId();
172
+ }
173
+
174
+ if ($warehouses) {
175
+ $warehouseCollection->addFieldToFilter('stock_id', array('in' => $warehouses));
176
+ }
177
+
178
+ $warehouseCodesAssoc = array();
179
+ foreach ($warehouseCollection as $warehouse) {
180
+ $warehouseCodesAssoc[$warehouse->getStockId()] = $warehouse->getStockCode();
181
+ }
182
+
183
+ $productWarehousesAssoc = array();
184
+ foreach ($productCollection as $product) {
185
+ foreach ($product->getWebsites() as $websiteId) {
186
+ $productWarehousesAssoc[$product->getId()][Mage::app()->getWebsite($websiteId)->getStockId()] = Mage::app()->getWebsite($websiteId)->getStockId();
187
+ }
188
+ }
189
+
190
+ $productStocksQtyAssoc = array();
191
+ foreach ($stockCollection as $stockItem) {
192
+ if (isset($productWarehousesAssoc[$stockItem->getProductId()])
193
+ && isset($productWarehousesAssoc[$stockItem->getProductId()][$stockItem->getStockId()])) {
194
+ if (!isset($productStocksQtyAssoc[$stockItem->getProductId()])) {
195
+ $productStocksQtyAssoc[$stockItem->getProductId()] = array(
196
+ $stockItem->getStockId() => $warehouseCodesAssoc[$stockItem->getStockId()] . ': ' . floatval($stockItem->getQty())
197
+ );
198
+ } else {
199
+ $productStocksQtyAssoc[$stockItem->getProductId()][$stockItem->getStockId()] = $warehouseCodesAssoc[$stockItem->getStockId()] . ': ' . floatval($stockItem->getQty());
200
+ }
201
+ }
202
+ }
203
+
204
+ foreach ($productCollection as $product) {
205
+ if (isset($productStocksQtyAssoc[$product->getId()])) {
206
+ $product->setData('qty', $productStocksQtyAssoc[$product->getId()]);
207
+ }
208
+ }
209
+ }
210
+
211
+ return $this;
212
+ }
213
+ }
app/code/community/Smile/Warehouse/Model/Stock/Item.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock item
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Stock_Item extends Mage_CatalogInventory_Model_Stock_Item
11
+ {
12
+ /**
13
+ * Retrieve stock identifier
14
+ *
15
+ * @return int
16
+ */
17
+ public function getStockId()
18
+ {
19
+ $stockId = $this->getData('stock_id');
20
+ if (is_null($stockId)) {
21
+ $stockId = Mage::getModel('cataloginventory/stock')->loadByStore($this->getStoreId())->getStockId();
22
+ $this->setData('stock_id', $stockId);
23
+ }
24
+
25
+ return $stockId;
26
+ }
27
+
28
+ /**
29
+ * Adding stock data to product
30
+ *
31
+ * @param Mage_Catalog_Model_Product $product product
32
+ *
33
+ * @return Smile_Warehouse_Model_Stock_Item
34
+ */
35
+ public function assignProduct(Mage_Catalog_Model_Product $product)
36
+ {
37
+ $this->setStoreId($product->getStoreId());
38
+ parent::assignProduct($product);
39
+
40
+ return $this;
41
+ }
42
+ }
app/code/community/Smile/Warehouse/Model/Stock/Item/Api.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock item - API model
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Stock_Item_Api extends Mage_Catalog_Model_Api_Resource
11
+ {
12
+ /**
13
+ * Init session field
14
+ */
15
+ public function __construct()
16
+ {
17
+ $this->_storeIdSessionField = 'product_store_id';
18
+ }
19
+
20
+ /**
21
+ * Update product warehouse
22
+ *
23
+ * @param string $productId product id
24
+ * @param string $stockCode stock code
25
+ * @param object $data data
26
+ *
27
+ * @return bool
28
+ */
29
+ public function update($productId, $stockCode, $data)
30
+ {
31
+ $product = Mage::getModel('catalog/product');
32
+
33
+ if ($newId = $product->getIdBySku($productId)) {
34
+ $productId = $newId;
35
+ }
36
+
37
+ //load stock
38
+ $stock = Mage::getModel('smile_warehouse/stock')->loadByCode($stockCode);
39
+
40
+ if (!$stock->getStockId()) {
41
+ $this->_fault('stock_not_exists');
42
+ }
43
+
44
+ $product->load($productId);
45
+
46
+ if (!$product->getId()) {
47
+ $this->_fault('not_exists');
48
+ }
49
+
50
+ // Get store id which work with called stock
51
+ $productStockWebsites = array_intersect($stock->getAssignedWebsites(), $product->getWebsiteIds());
52
+ if (empty($productStockWebsites)) {
53
+ $this->_fault('stock_item_not_exists');
54
+ }
55
+ $websiteId = array_shift($productStockWebsites);
56
+ $websiteStores = Mage::app()->getWebsite($websiteId)->getStoreIds();
57
+ $storeId = array_shift($websiteStores);
58
+
59
+ if (is_null($storeId)) {
60
+ $this->_fault('store_not_exists');
61
+ }
62
+
63
+ // Reload product to reassign stock item by store
64
+ $product->setStoreId($storeId)->load($productId);
65
+
66
+ if (!$stockData = $product->getStockData()) {
67
+ $stockData = array();
68
+ }
69
+
70
+ $warehouseStockFields = Mage::helper('smile_warehouse')->getWarehouseStockFields();
71
+
72
+ foreach ($warehouseStockFields as $warehouseStockField) {
73
+ if (isset($data[$warehouseStockField])) {
74
+ $stockData[$warehouseStockField] = $data[$warehouseStockField];
75
+ }
76
+ }
77
+
78
+ $product->setStockData($stockData);
79
+
80
+ try {
81
+ $product->save();
82
+ } catch (Mage_Core_Exception $e) {
83
+ $this->_fault('not_updated', $e->getMessage());
84
+ } catch (Exception $e){
85
+ $this->_fault('not_updated', $e->getMessage());
86
+ }
87
+
88
+ return true;
89
+ }
90
+ }
app/code/community/Smile/Warehouse/Model/Stock/Item/Api/V2.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Stock item - API V2 model
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Model_Stock_Item_Api_V2 extends Smile_Warehouse_Model_Stock_Item_Api
11
+ {
12
+ /**
13
+ * Update product warehouse
14
+ *
15
+ * @param string $productId product id
16
+ * @param string $stockCode stock code
17
+ * @param object $data data
18
+ *
19
+ * @return bool
20
+ */
21
+ public function update($productId, $stockCode, $data)
22
+ {
23
+ $product = Mage::getModel('catalog/product');
24
+
25
+ if ($newId = $product->getIdBySku($productId)) {
26
+ $productId = $newId;
27
+ }
28
+
29
+ //load stock
30
+ $stock = Mage::getModel('smile_warehouse/stock')->loadByCode($stockCode);
31
+
32
+ if (!$stock->getStockId()) {
33
+ $this->_fault('stock_not_exists');
34
+ }
35
+
36
+ $product->load($productId);
37
+
38
+ if (!$product->getId()) {
39
+ $this->_fault('not_exists');
40
+ }
41
+
42
+ //get store id which work with called stock
43
+ $productStockWebsites = array_intersect($stock->getAssignedWebsites(), $product->getWebsiteIds());
44
+ if (empty($productStockWebsites)) {
45
+ $this->_fault('stock_item_not_exists');
46
+ }
47
+ $websiteId = array_shift($productStockWebsites);
48
+ $websiteStores = Mage::app()->getWebsite($websiteId)->getStoreIds();
49
+ $storeId = array_shift($websiteStores);
50
+
51
+ if (is_null($storeId)) {
52
+ $this->_fault('store_not_exists');
53
+ }
54
+
55
+ //reload product to reassign stock item by store
56
+ $product->setStoreId($storeId)->load($productId);
57
+
58
+ if (!$stockData = $product->getStockData()) {
59
+ $stockData = array();
60
+ }
61
+
62
+ $warehouseStockFields = Mage::helper('smile_warehouse')->getWarehouseStockFields();
63
+
64
+ foreach ($warehouseStockFields as $warehouseStockField) {
65
+ if (isset($data->$warehouseStockField)) {
66
+ $stockData[$warehouseStockField] = $data->$warehouseStockField;
67
+ }
68
+ }
69
+
70
+ $product->setStockData($stockData);
71
+
72
+ try {
73
+ $product->save();
74
+ } catch (Mage_Core_Exception $e) {
75
+ $this->_fault('not_updated', $e->getMessage());
76
+ } catch (Exception $e){
77
+ $this->_fault('not_updated', $e->getMessage());
78
+ }
79
+
80
+ return true;
81
+ }
82
+ }
app/code/community/Smile/Warehouse/controllers/Adminhtml/Catalog/Product/Action/AttributeController.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'app/code/core/Mage/Adminhtml/controllers/Catalog/Product/Action/AttributeController.php';
3
+ /**
4
+ * Product attribute controller
5
+ *
6
+ * @category Smile
7
+ * @package Smile_Warehouse
8
+ * @author Smile <solution.magento@smile.fr>
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+ class Smile_Warehouse_Adminhtml_Catalog_Product_Action_AttributeController extends Mage_Adminhtml_Catalog_Product_Action_AttributeController
12
+ {
13
+ /**
14
+ * Save action
15
+ *
16
+ * @return void
17
+ */
18
+ public function saveAction()
19
+ {
20
+ if (!$this->_validateProducts()) {
21
+ return;
22
+ }
23
+
24
+ /* Collect Data */
25
+ $inventoryData = $this->getRequest()->getParam('inventory', array());
26
+ $attributesData = $this->getRequest()->getParam('attributes', array());
27
+ $websiteRemoveData = $this->getRequest()->getParam('remove_website_ids', array());
28
+ $websiteAddData = $this->getRequest()->getParam('add_website_ids', array());
29
+
30
+ /* Prepare inventory data item options (use config settings) */
31
+ foreach (Mage::helper('cataloginventory')->getConfigItemOptions() as $option) {
32
+ if (isset($inventoryData[$option]) && !isset($inventoryData['use_config_' . $option])) {
33
+ $inventoryData['use_config_' . $option] = 0;
34
+ }
35
+ }
36
+
37
+ try {
38
+ if ($attributesData) {
39
+ $dateFormat = Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT);
40
+ $storeId = $this->_getHelper()->getSelectedStoreId();
41
+
42
+ foreach ($attributesData as $attributeCode => $value) {
43
+ $attribute = Mage::getSingleton('eav/config')
44
+ ->getAttribute('catalog_product', $attributeCode);
45
+ if (!$attribute->getAttributeId()) {
46
+ unset($attributesData[$attributeCode]);
47
+ continue;
48
+ }
49
+ if ($attribute->getBackendType() == 'datetime') {
50
+ if (!empty($value)) {
51
+ $filterInput = new Zend_Filter_LocalizedToNormalized(array(
52
+ 'date_format' => $dateFormat
53
+ ));
54
+ $filterInternal = new Zend_Filter_NormalizedToLocalized(array(
55
+ 'date_format' => Varien_Date::DATE_INTERNAL_FORMAT
56
+ ));
57
+ $value = $filterInternal->filter($filterInput->filter($value));
58
+ } else {
59
+ $value = null;
60
+ }
61
+ $attributesData[$attributeCode] = $value;
62
+ } else if ($attribute->getFrontendInput() == 'multiselect') {
63
+ if (is_array($value)) {
64
+ $value = implode(',', $value);
65
+ }
66
+ $attributesData[$attributeCode] = $value;
67
+ }
68
+ }
69
+
70
+ Mage::getSingleton('catalog/product_action')
71
+ ->updateAttributes($this->_getHelper()->getProductIds(), $attributesData, $storeId);
72
+ }
73
+
74
+ if ($websiteAddData || $websiteRemoveData) {
75
+ /* @var $actionModel Mage_Catalog_Model_Product_Action */
76
+ $actionModel = Mage::getSingleton('catalog/product_action');
77
+ $productIds = $this->_getHelper()->getProductIds();
78
+
79
+ if ($websiteRemoveData) {
80
+ $actionModel->updateWebsites($productIds, $websiteRemoveData, 'remove');
81
+ }
82
+ if ($websiteAddData) {
83
+ $actionModel->updateWebsites($productIds, $websiteAddData, 'add');
84
+ }
85
+
86
+ /**
87
+ * @deprecated since 1.3.2.2
88
+ */
89
+ Mage::dispatchEvent('catalog_product_to_website_change', array('products' => $productIds));
90
+
91
+ $this->_getSession()->addNotice(
92
+ $this->__('Please refresh "Catalog URL Rewrites" and "Product Attributes" in System -> <a href="%s">Index Management</a>', $this->getUrl('adminhtml/process/list'))
93
+ );
94
+ }
95
+
96
+ $disallowedItemQty = 0;
97
+
98
+ if ($inventoryData) {
99
+ $stockItem = Mage::getModel('cataloginventory/stock_item');
100
+ $storeId = $this->_getHelper()->getSelectedStoreId();
101
+
102
+ //prevent from edit warehouse fields for default stock
103
+ if ($storeId == Mage_Core_Model_App::ADMIN_STORE_ID) {
104
+ $warehouseStockFields = Mage::helper('smile_warehouse')->getWarehouseStockFields();
105
+ foreach ($warehouseStockFields as $warehouseStockField) {
106
+ if (isset($inventoryData[$warehouseStockField])) {
107
+ unset($inventoryData[$warehouseStockField]);
108
+ }
109
+ }
110
+ }
111
+
112
+ foreach ($this->_getHelper()->getProductIds() as $productId) {
113
+ $stockItem->setData(array());
114
+ $stockItem->setStoreId($storeId);
115
+ $stockItem->loadByProduct($productId)
116
+ ->setProductId($productId);
117
+
118
+ if (!Mage::helper('smile_warehouse')->canUpdateInventory($stockItem)) {
119
+ $disallowedItemQty++;
120
+ continue;
121
+ }
122
+ if ($stockItem->getItemId()) {
123
+ $stockDataChanged = false;
124
+ foreach ($inventoryData as $k => $v) {
125
+ $stockItem->setDataUsingMethod($k, $v);
126
+ if ($stockItem->dataHasChangedFor($k)) {
127
+ $stockDataChanged = true;
128
+ }
129
+ }
130
+ if ($stockDataChanged) {
131
+ $stockItem->save();
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ $this->_getSession()->addSuccess(
138
+ $this->__('Total of %d record(s) were updated', count($this->_getHelper()->getProductIds()))
139
+ );
140
+
141
+ if ($disallowedItemQty > 0) {
142
+ $this->_getSession()->addError(
143
+ $this->__('%d record(s) aren\'t allowed for update their inventory', $disallowedItemQty)
144
+ );
145
+ }
146
+ }
147
+ catch (Mage_Core_Exception $e) {
148
+ $this->_getSession()->addError($e->getMessage());
149
+ }
150
+ catch (Exception $e) {
151
+ $this->_getSession()->addException($e, $this->__('An error occurred while updating the product(s) attributes.'));
152
+ }
153
+
154
+ $this->_redirect('*/catalog_product/', array('store'=>$this->_getHelper()->getSelectedStoreId()));
155
+ }
156
+ }
app/code/community/Smile/Warehouse/controllers/Adminhtml/Catalog/ProductController.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once 'app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php';
3
+ /**
4
+ * Product controller
5
+ *
6
+ * @category Smile
7
+ * @package Smile_Warehouse
8
+ * @author Smile <solution.magento@smile.fr>
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+ class Smile_Warehouse_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Catalog_ProductController
12
+ {
13
+ /**
14
+ * Quick create simple product for configurable product action
15
+ *
16
+ * @return void
17
+ */
18
+ public function quickCreateAction()
19
+ {
20
+ $result = array();
21
+
22
+ $storeId = $this->getRequest()->getParam('store', 0);
23
+
24
+ /* @var $configurableProduct Mage_Catalog_Model_Product */
25
+ $configurableProduct = Mage::getModel('catalog/product')
26
+ ->setStoreId($storeId)
27
+ ->load($this->getRequest()->getParam('product'));
28
+
29
+ if (!$configurableProduct->isConfigurable()) {
30
+ // If invalid parent product
31
+ $this->_redirect('*/*/');
32
+ return;
33
+ }
34
+
35
+ /* @var $product Mage_Catalog_Model_Product */
36
+
37
+ $product = Mage::getModel('catalog/product')
38
+ ->setStoreId($storeId)
39
+ ->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE)
40
+ ->setAttributeSetId($configurableProduct->getAttributeSetId());
41
+
42
+
43
+ foreach ($product->getTypeInstance()->getEditableAttributes() as $attribute) {
44
+ if ($attribute->getIsUnique()
45
+ || $attribute->getAttributeCode() == 'url_key'
46
+ || $attribute->getFrontend()->getInputType() == 'gallery'
47
+ || $attribute->getFrontend()->getInputType() == 'media_image'
48
+ || !$attribute->getIsVisible()) {
49
+ continue;
50
+ }
51
+
52
+ $product->setData(
53
+ $attribute->getAttributeCode(),
54
+ $configurableProduct->getData($attribute->getAttributeCode())
55
+ );
56
+ }
57
+
58
+ $productData = $this->getRequest()->getParam('simple_product', array());
59
+
60
+ //prevent from edit warehouse fields for default stock
61
+ if (!$storeId && isset($productData['stock_data'])) {
62
+ $warehouseStockFields = Mage::helper('smile_warehouse')->getWarehouseStockFields();
63
+ foreach ($warehouseStockFields as $warehouseStockField) {
64
+ if (isset($productData['stock_data'][$warehouseStockField])) {
65
+ unset($productData['stock_data'][$warehouseStockField]);
66
+ }
67
+ }
68
+ }
69
+
70
+ $product->addData($productData);
71
+ $product->setWebsiteIds($configurableProduct->getWebsiteIds());
72
+
73
+ $autogenerateOptions = array();
74
+ $result['attributes'] = array();
75
+
76
+ foreach ($configurableProduct->getTypeInstance()->getConfigurableAttributes() as $attribute) {
77
+ $value = $product->getAttributeText($attribute->getProductAttribute()->getAttributeCode());
78
+ $autogenerateOptions[] = $value;
79
+ $result['attributes'][] = array(
80
+ 'label' => $value,
81
+ 'value_index' => $product->getData($attribute->getProductAttribute()->getAttributeCode()),
82
+ 'attribute_id' => $attribute->getProductAttribute()->getId()
83
+ );
84
+ }
85
+
86
+ if ($product->getNameAutogenerate()) {
87
+ $product->setName($configurableProduct->getName() . '-' . implode('-', $autogenerateOptions));
88
+ }
89
+
90
+ if ($product->getSkuAutogenerate()) {
91
+ $product->setSku($configurableProduct->getSku() . '-' . implode('-', $autogenerateOptions));
92
+ }
93
+
94
+ if (is_array($product->getPricing())) {
95
+ $result['pricing'] = $product->getPricing();
96
+ $additionalPrice = 0;
97
+ foreach ($product->getPricing() as $pricing) {
98
+ if (empty($pricing['value'])) {
99
+ continue;
100
+ }
101
+
102
+ if (!empty($pricing['is_percent'])) {
103
+ $pricing['value'] = ($pricing['value']/100)*$product->getPrice();
104
+ }
105
+
106
+ $additionalPrice += $pricing['value'];
107
+ }
108
+
109
+ $product->setPrice($product->getPrice() + $additionalPrice);
110
+ $product->unsPricing();
111
+ }
112
+
113
+ try {
114
+ /**
115
+ * @todo implement full validation process with errors returning which are ignoring now
116
+ */
117
+ // if (is_array($errors = $product->validate())) {
118
+ // $strErrors = array();
119
+ // foreach($errors as $code=>$error) {
120
+ // $codeLabel = $product->getResource()->getAttribute($code)->getFrontend()->getLabel();
121
+ // $strErrors[] = ($error === true)? Mage::helper('catalog')->__('Value for "%s" is invalid.', $codeLabel) : Mage::helper('catalog')->__('Value for "%s" is invalid: %s', $codeLabel, $error);
122
+ // }
123
+ // Mage::throwException('data_invalid', implode("\n", $strErrors));
124
+ // }
125
+
126
+ $product->validate();
127
+ $product->save();
128
+ $result['product_id'] = $product->getId();
129
+ $this->_getSession()->addSuccess(Mage::helper('catalog')->__('The product has been created.'));
130
+ $this->_initLayoutMessages('adminhtml/session');
131
+ $result['messages'] = $this->getLayout()->getMessagesBlock()->getGroupedHtml();
132
+ } catch (Mage_Core_Exception $e) {
133
+ $result['error'] = array(
134
+ 'message' => $e->getMessage(),
135
+ 'fields' => array(
136
+ 'sku' => $product->getSku()
137
+ )
138
+ );
139
+
140
+ } catch (Exception $e) {
141
+ Mage::logException($e);
142
+ $result['error'] = array(
143
+ 'message' => $this->__('An error occurred while saving the product. ') . $e->getMessage()
144
+ );
145
+ }
146
+
147
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
148
+ }
149
+ }
app/code/community/Smile/Warehouse/controllers/Adminhtml/WarehouseController.php ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse controller
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+ class Smile_Warehouse_Adminhtml_WarehouseController extends Mage_Adminhtml_Controller_Action
11
+ {
12
+ /**
13
+ * Init actions
14
+ *
15
+ * @return Smile_Warehouse_Adminhtml_WarehouseController
16
+ */
17
+ protected function _initAction()
18
+ {
19
+ // load layout, set active menu and breadcrumbs
20
+ $this->loadLayout()
21
+ ->_setActiveMenu('system/warehouse')
22
+ ->_addBreadcrumb(Mage::helper('smile_warehouse')->__('System'), Mage::helper('smile_warehouse')->__('System'))
23
+ ->_addBreadcrumb(Mage::helper('smile_warehouse')->__('Manage Warehouses'), Mage::helper('smile_warehouse')->__('Manage Warehouses'));
24
+
25
+ return $this;
26
+ }
27
+
28
+ /**
29
+ * Warehouses list
30
+ *
31
+ * @return void
32
+ */
33
+ public function indexAction()
34
+ {
35
+ $this->_title($this->__('System'))
36
+ ->_title($this->__('Warehouses'));
37
+
38
+ $this->_initAction()
39
+ ->_addContent($this->getLayout()->createBlock('smile_warehouse/adminhtml_warehouse'))
40
+ ->renderLayout();
41
+ }
42
+
43
+ /**
44
+ * Render grid
45
+ *
46
+ * @return void
47
+ */
48
+ public function gridAction()
49
+ {
50
+ $this->loadLayout();
51
+ $this->renderLayout();
52
+ }
53
+
54
+ /**
55
+ * Init warehouse
56
+ *
57
+ * @return Smile_Warehouse_Model_Stock
58
+ */
59
+ protected function _initWarehouse($idFieldName = 'id')
60
+ {
61
+ $id = $this->getRequest()->getParam($idFieldName);
62
+ $warehouse = Mage::getModel('cataloginventory/stock');
63
+
64
+ if (!empty($id)) {
65
+ $warehouse->load($id);
66
+ }
67
+
68
+ Mage::register('current_warehouse', $warehouse);
69
+ return $warehouse;
70
+ }
71
+
72
+ /**
73
+ * Create new warehouse
74
+ *
75
+ * @return void
76
+ */
77
+ public function newAction()
78
+ {
79
+ // The same form is used to create and edit
80
+ $this->_forward('edit');
81
+ }
82
+
83
+ /**
84
+ * Create/Edit warehouse
85
+ *
86
+ * @return void
87
+ */
88
+ public function editAction()
89
+ {
90
+ $warehouse = $this->_initWarehouse('id');
91
+
92
+ if ($warehouse->getStockId() == Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID) {
93
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('smile_warehouse')->__('The Default Warehouse is not available for edit'));
94
+ $this->_redirect('*/*/');
95
+ return;
96
+ }
97
+
98
+ $this->_title($this->__('System'))
99
+ ->_title($this->__('Warehouses'))
100
+ ->_title($warehouse->getStockId() ? $warehouse->getStockName() : Mage::helper('smile_warehouse')->__('New Warehouse'));
101
+
102
+ $data = Mage::getSingleton('adminhtml/session')->getFormData(true);
103
+ if (!empty($data)) {
104
+ $warehouse->addData($data);
105
+ }
106
+
107
+ $this->_initAction()
108
+ ->_addContent($this->getLayout()->createBlock('smile_warehouse/adminhtml_warehouse_edit'))
109
+ ->renderLayout();
110
+ }
111
+
112
+ /**
113
+ * Save action
114
+ *
115
+ * @return void
116
+ */
117
+ public function saveAction()
118
+ {
119
+ $redirectBack = $this->getRequest()->getParam('back', false);
120
+ if ($data = $this->getRequest()->getPost()) {
121
+
122
+ $warehouse = $this->_initWarehouse('id');
123
+ $id = $this->getRequest()->getParam('id');
124
+
125
+ if (!$warehouse->getStockId() && $id) {
126
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('smile_warehouse')->__('Warehouse with ID %s doesn\'t exist.', $id));
127
+ $this->_redirect('*/*/');
128
+ return;
129
+ }
130
+
131
+ if ($warehouse->getStockId() == Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID) {
132
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('smile_warehouse')->__('The Default Warehouse is not available for edit'));
133
+ $this->_redirect('*/*/');
134
+ return;
135
+ }
136
+
137
+ // save model
138
+ try {
139
+ if (!empty($data)) {
140
+ $warehouse->addData($data);
141
+ Mage::getSingleton('adminhtml/session')->setFormData($data);
142
+ }
143
+
144
+ $warehouse->validate()->save();
145
+ Mage::getSingleton('adminhtml/session')->setFormData(false);
146
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('smile_warehouse')->__('The warehouse has been saved.'));
147
+ } catch (Mage_Core_Exception $e) {
148
+ $this->_getSession()->addError($e->getMessage());
149
+ $redirectBack = true;
150
+ } catch (Exception $e) {
151
+ $this->_getSession()->addError(Mage::helper('smile_warehouse')->__('Unable to save the warehouse.'));
152
+ $redirectBack = true;
153
+ Mage::logException($e);
154
+ }
155
+ if ($redirectBack) {
156
+ $this->_redirect('*/*/edit', array('id' => $warehouse->getStockId()));
157
+ return;
158
+ }
159
+ }
160
+ $this->_redirect('*/*/');
161
+ }
162
+
163
+ /**
164
+ * Delete action
165
+ *
166
+ * @return void
167
+ */
168
+ public function deleteAction()
169
+ {
170
+ if ($id = $this->getRequest()->getParam('id')) {
171
+ try {
172
+ // init model and delete
173
+ $warehouse = Mage::getModel('cataloginventory/stock')->load($id);
174
+
175
+ if ($warehouse->getStockId() == Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID) {
176
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('smile_warehouse')->__('The Default Warehouse is not available for edit'));
177
+ $this->_redirect('*/*/');
178
+ return;
179
+ }
180
+
181
+ $websiteIds = $warehouse->getAssignedWebsites();
182
+ if (!empty($websiteIds)) {
183
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('smile_warehouse')->__('The warehouse can\'t be deleted because it is assigned to a website.'));
184
+ $this->_redirect('*/*/');
185
+ return;
186
+ }
187
+
188
+ $warehouse->delete();
189
+
190
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('smile_warehouse')->__('The warehouse has been deleted.'));
191
+ $this->_redirect('*/*/');
192
+ return;
193
+ } catch (Mage_Core_Exception $e) {
194
+ $this->_getSession()->addError($e->getMessage());
195
+ } catch (Exception $e) {
196
+ $this->_getSession()->addError(Mage::helper('smile_warehouse')->__('An error occurred while deleting warehouse data.'));
197
+ Mage::logException($e);
198
+ // save data in session
199
+ Mage::getSingleton('adminhtml/session')->setFormData($data);
200
+ // redirect to edit form
201
+ $this->_redirect('*/*/edit', array('id' => $id));
202
+ return;
203
+ }
204
+ }
205
+
206
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('smile_warehouse')->__('Unable to find a warehouse to delete.'));
207
+ $this->_redirect('*/*/');
208
+ }
209
+
210
+ /**
211
+ * Delete warehouses using grid massaction
212
+ *
213
+ * @return void
214
+ */
215
+ public function massDeleteAction()
216
+ {
217
+ $ids = $this->getRequest()->getParam('warehouse');
218
+
219
+ if (!is_array($ids)) {
220
+ $this->_getSession()->addError($this->__('Please select warehouse(s).'));
221
+ } else {
222
+ try {
223
+ $i = 0;
224
+ foreach ($ids as $id) {
225
+ $model = Mage::getModel('cataloginventory/stock')->load($id);
226
+ $websiteIds = $model->getAssignedWebsites();
227
+
228
+ //prevent from removing default warehouse
229
+ if ($model->getStockId() != Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID && empty($websiteIds)) {
230
+ $model->delete();
231
+ $i++;
232
+ }
233
+ }
234
+
235
+ if ($i > 0) {
236
+ $this->_getSession()->addSuccess(
237
+ $this->__('Total of %d record(s) have been deleted.', $i)
238
+ );
239
+ }
240
+
241
+ if ($i < count($ids)) {
242
+ $this->_getSession()->addError(
243
+ $this->__('Total of %d record(s) haven\'t been deleted because they are assigned to website(s).', count($ids) - $i)
244
+ );
245
+ }
246
+ } catch (Mage_Core_Exception $e) {
247
+ $this->_getSession()->addError($e->getMessage());
248
+ } catch (Exception $e) {
249
+ $this->_getSession()->addError(Mage::helper('smile_warehouse')->__('An error occurred while mass deleting warehouses.'));
250
+ Mage::logException($e);
251
+ return;
252
+ }
253
+ }
254
+
255
+ $this->_redirect('*/*/');
256
+ }
257
+ }
app/code/community/Smile/Warehouse/etc/adminhtml.xml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <menu>
4
+ <system>
5
+ <children>
6
+ <warehouse translate="title">
7
+ <title>Manage Warehouses</title>
8
+ <action>adminhtml/warehouse/</action>
9
+ <sort_order>105</sort_order>
10
+ </warehouse>
11
+ </children>
12
+ </system>
13
+ </menu>
14
+ <acl>
15
+ <resources>
16
+ <admin>
17
+ <children>
18
+ <system>
19
+ <children>
20
+ <warehouse translate="title">
21
+ <title>Manage Warehouses</title>
22
+ </warehouse>
23
+ </children>
24
+ </system>
25
+ <catalog>
26
+ <children>
27
+ <stock translate="title">
28
+ <title>Manage Warehouses Stock</title>
29
+ </stock>
30
+ </children>
31
+ </catalog>
32
+ </children>
33
+ </admin>
34
+ </resources>
35
+ </acl>
36
+ </config>
app/code/community/Smile/Warehouse/etc/api.xml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <api>
4
+ <resources>
5
+ <smile_warehouse_stock_item translate="title" module="smile_warehouse">
6
+ <model>smile_warehouse/stock_item_api</model>
7
+ <title>Warehouse API</title>
8
+ <acl>cataloginventory</acl>
9
+ <methods>
10
+ <update translate="title" module="smile_warehouse">
11
+ <title>Update warehouse stock data</title>
12
+ <acl>cataloginventory/update</acl>
13
+ </update>
14
+ </methods>
15
+ <faults module="smile_warehouse">
16
+ <not_exists>
17
+ <code>101</code>
18
+ <message>Product not exists.</message>
19
+ </not_exists>
20
+ <not_updated>
21
+ <code>102</code>
22
+ <message>Product inventory not updated. Details in error message.</message>
23
+ </not_updated>
24
+ <website_not_exists>
25
+ <code>103</code>
26
+ <message>Website not exists.</message>
27
+ </website_not_exists>
28
+ <store_not_exists>
29
+ <code>104</code>
30
+ <message>Store not exists.</message>
31
+ </store_not_exists>
32
+ <stock_not_exists>
33
+ <code>105</code>
34
+ <message>Stock not exists.</message>
35
+ </stock_not_exists>
36
+ <stock_item_not_exists>
37
+ <code>106</code>
38
+ <message>Stock Item not exists.</message>
39
+ </stock_item_not_exists>
40
+ </faults>
41
+ </smile_warehouse_stock_item>
42
+ </resources>
43
+ <v2>
44
+ <resources_function_prefix>
45
+ <smile_warehouse_stock_item>smileWarehouseStockItem</smile_warehouse_stock_item>
46
+ </resources_function_prefix>
47
+ </v2>
48
+ </api>
49
+ </config>
app/code/community/Smile/Warehouse/etc/config.xml ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Smile_Warehouse>
5
+ <version>0.0.5</version>
6
+ </Smile_Warehouse>
7
+ </modules>
8
+
9
+ <global>
10
+ <models>
11
+ <smile_warehouse>
12
+ <class>Smile_Warehouse_Model</class>
13
+ <resourceModel>smile_warehouse_mysql4</resourceModel>
14
+ </smile_warehouse>
15
+
16
+ <cataloginventory>
17
+ <rewrite>
18
+ <stock_item>Smile_Warehouse_Model_Stock_Item</stock_item>
19
+ <observer>Smile_Warehouse_Model_Observer</observer>
20
+ <stock>Smile_Warehouse_Model_Stock</stock>
21
+ </rewrite>
22
+ </cataloginventory>
23
+
24
+ <cataloginventory_mysql4>
25
+ <rewrite>
26
+ <stock_status>Smile_Warehouse_Model_Mysql4_Stock_Status</stock_status>
27
+ <stock>Smile_Warehouse_Model_Mysql4_Stock</stock>
28
+ <stock_item>Smile_Warehouse_Model_Mysql4_Stock_Item</stock_item>
29
+ </rewrite>
30
+ </cataloginventory_mysql4>
31
+
32
+ <catalog>
33
+ <rewrite>
34
+ <convert_parser_product>Smile_Warehouse_Model_Catalog_Convert_Parser_Product</convert_parser_product>
35
+ </rewrite>
36
+ </catalog>
37
+
38
+ <reports_mysql4>
39
+ <rewrite>
40
+ <product_lowstock_collection>Smile_Warehouse_Model_Mysql4_Reports_Product_Lowstock_Collection</product_lowstock_collection>
41
+ </rewrite>
42
+ </reports_mysql4>
43
+
44
+ <smile_warehouse_mysql4>
45
+ <class>Smile_Warehouse_Model_Mysql4</class>
46
+ </smile_warehouse_mysql4>
47
+ </models>
48
+
49
+ <resources>
50
+ <smile_warehouse_setup>
51
+ <setup>
52
+ <module>Smile_Warehouse</module>
53
+ <class>Smile_Warehouse_Model_Mysql4_Setup</class>
54
+ </setup>
55
+ </smile_warehouse_setup>
56
+ </resources>
57
+
58
+ <blocks>
59
+ <smile_warehouse>
60
+ <class>Smile_Warehouse_Block</class>
61
+ </smile_warehouse>
62
+ <adminhtml>
63
+ <rewrite>
64
+ <catalog_product_edit_tab_inventory>Smile_Warehouse_Block_Adminhtml_Catalog_Product_Edit_Tab_Inventory</catalog_product_edit_tab_inventory>
65
+ <catalog_product_edit_tab_super_config>Smile_Warehouse_Block_Adminhtml_Catalog_Product_Edit_Tab_Super_Config</catalog_product_edit_tab_super_config>
66
+ <report_product_lowstock_grid>Smile_Warehouse_Block_Adminhtml_Report_Product_Lowstock_Grid</report_product_lowstock_grid>
67
+ <catalog_product_edit_tab_super_config_simple>Smile_Warehouse_Block_Adminhtml_Catalog_Product_Edit_Tab_Super_Config_Simple</catalog_product_edit_tab_super_config_simple>
68
+ <system_store_grid>Smile_Warehouse_Block_Adminhtml_System_Store_Grid</system_store_grid>
69
+ </rewrite>
70
+ </adminhtml>
71
+ <rss>
72
+ <rewrite>
73
+ <catalog_notifyStock>Smile_Warehouse_Block_Rss_Catalog_NotifyStock</catalog_notifyStock>
74
+ </rewrite>
75
+ </rss>
76
+ </blocks>
77
+
78
+ <helpers>
79
+ <smile_warehouse>
80
+ <class>Smile_Warehouse_Helper</class>
81
+ </smile_warehouse>
82
+ </helpers>
83
+ </global>
84
+
85
+ <admin>
86
+ <routers>
87
+ <adminhtml>
88
+ <args>
89
+ <modules>
90
+ <Smile_Warehouse before="Mage_Adminhtml">Smile_Warehouse_Adminhtml</Smile_Warehouse>
91
+ </modules>
92
+ </args>
93
+ </adminhtml>
94
+ </routers>
95
+ <fieldsets>
96
+ <catalog_product_dataflow>
97
+ <stock_location>
98
+ <inventory>1</inventory>
99
+ <product_type>
100
+ <simple />
101
+ <virtual />
102
+ <configurable />
103
+ <grouped />
104
+ </product_type>
105
+ </stock_location>
106
+ <stock_code>
107
+ <inventory>1</inventory>
108
+ <product_type>
109
+ <simple />
110
+ <virtual />
111
+ <configurable />
112
+ <grouped />
113
+ </product_type>
114
+ </stock_code>
115
+ </catalog_product_dataflow>
116
+ </fieldsets>
117
+ </admin>
118
+
119
+ <adminhtml>
120
+ <events>
121
+ <adminhtml_block_html_before>
122
+ <observers>
123
+ <smile_warehouse_website_edit_form_observer>
124
+ <class>smile_warehouse/observer</class>
125
+ <method>addWarehouseField</method>
126
+ </smile_warehouse_website_edit_form_observer>
127
+ <smile_warehouse_add_product_grid_all_stocks_qty>
128
+ <class>smile_warehouse/observer</class>
129
+ <method>addAllStocksQtyColumn</method>
130
+ </smile_warehouse_add_product_grid_all_stocks_qty>
131
+ <smile_warehouse_product_grid_block_html_before>
132
+ <class>smile_warehouse/observer</class>
133
+ <method>unsetProductGridFlag</method>
134
+ </smile_warehouse_product_grid_block_html_before>
135
+ </observers>
136
+ </adminhtml_block_html_before>
137
+
138
+ <catalog_product_website_update>
139
+ <observers>
140
+ <smile_warehouse_update_products_websites_observer>
141
+ <class>smile_warehouse/observer</class>
142
+ <method>updateProductsWebsites</method>
143
+ </smile_warehouse_update_products_websites_observer>
144
+ </observers>
145
+ </catalog_product_website_update>
146
+
147
+ <website_save_after>
148
+ <observers>
149
+ <smile_warehouse_reassign_stock_observer>
150
+ <class>smile_warehouse/observer</class>
151
+ <method>reassignStock</method>
152
+ </smile_warehouse_reassign_stock_observer>
153
+ </observers>
154
+ </website_save_after>
155
+
156
+ <catalog_product_save_before>
157
+ <observers>
158
+ <smile_warehouse_catalog_product_save_before>
159
+ <class>smile_warehouse/observer</class>
160
+ <method>importProductByStockCode</method>
161
+ </smile_warehouse_catalog_product_save_before>
162
+ </observers>
163
+ </catalog_product_save_before>
164
+
165
+ <core_layout_block_create_after>
166
+ <observers>
167
+ <smile_warehouse_catalog_product_grid_block_create_after>
168
+ <class>smile_warehouse/observer</class>
169
+ <method>setProductGridFlag</method>
170
+ </smile_warehouse_catalog_product_grid_block_create_after>
171
+ </observers>
172
+ </core_layout_block_create_after>
173
+
174
+ <catalog_product_collection_load_before>
175
+ <observers>
176
+ <smile_warehouse_catalog_product_collection_load_before>
177
+ <class>smile_warehouse/observer</class>
178
+ <method>fixProductCollectionStockJoin</method>
179
+ </smile_warehouse_catalog_product_collection_load_before>
180
+ </observers>
181
+ </catalog_product_collection_load_before>
182
+
183
+ </events>
184
+
185
+ <layout>
186
+ <updates>
187
+ <smile_warehouse>
188
+ <file>smile/warehouse.xml</file>
189
+ </smile_warehouse>
190
+ </updates>
191
+ </layout>
192
+
193
+ </adminhtml>
194
+ </config>
app/code/community/Smile/Warehouse/etc/wsdl.xml ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
3
+ xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"
4
+ name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}">
5
+ <types>
6
+ <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento">
7
+ <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/" />
8
+ <complexType name="smileWarehouseStockItemUpdateEntity">
9
+ <all>
10
+ <element name="qty" type="xsd:string" minOccurs="0" />
11
+ <element name="is_in_stock" type="xsd:int" minOccurs="0" />
12
+ <element name="notify_stock_qty" type="xsd:int" minOccurs="0" />
13
+ <element name="use_config_notify_stock_qty" type="xsd:int" minOccurs="0" />
14
+ <element name="stock_location" type="xsd:string" minOccurs="0" />
15
+ </all>
16
+ </complexType>
17
+ </schema>
18
+ </types>
19
+ <message name="smileWarehouseStockItemUpdateRequest">
20
+ <part name="sessionId" type="xsd:string" />
21
+ <part name="product" type="xsd:string" />
22
+ <part name="stock_code" type="xsd:string" />
23
+ <part name="data" type="typens:smileWarehouseStockItemUpdateEntity" />
24
+ </message>
25
+ <message name="smileWarehouseStockItemUpdateResponse">
26
+ <part name="result" type="xsd:int" />
27
+ </message>
28
+ <portType name="{{var wsdl.handler}}PortType">
29
+ <operation name="smileWarehouseStockItemUpdate">
30
+ <documentation>Update warehouse stock data</documentation>
31
+ <input message="typens:smileWarehouseStockItemUpdateRequest" />
32
+ <output message="typens:smileWarehouseStockItemUpdateResponse" />
33
+ </operation>
34
+ </portType>
35
+ <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType">
36
+ <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
37
+ <operation name="smileWarehouseStockItemUpdate">
38
+ <soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
39
+ <input>
40
+ <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
41
+ </input>
42
+ <output>
43
+ <soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
44
+ </output>
45
+ </operation>
46
+ </binding>
47
+ <service name="{{var wsdl.name}}Service">
48
+ <port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding">
49
+ <soap:address location="{{var wsdl.url}}" />
50
+ </port>
51
+ </service>
52
+ </definitions>
app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-install-0.0.1.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse module setup
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+
11
+ $installer = $this;
12
+ /* @var $installer Smile_Warehouse_Model_Mysql4_Setup */
13
+
14
+ $installer->startSetup();
15
+
16
+ $installer->getConnection()->addColumn($installer->getTable('cataloginventory_stock'), 'stock_code', "varchar(20) NOT NULL DEFAULT ''");
17
+ $installer->getConnection()->addKey($installer->getTable('cataloginventory_stock'), 'stock_code_unique_index', 'stock_code', 'unique');
18
+
19
+ $installer->endSetup();
app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-upgrade-0.0.1-0.0.2.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse module setup
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+
11
+ $installer = $this;
12
+ /* @var $installer Smile_Warehouse_Model_Mysql4_Setup */
13
+
14
+ $installer->startSetup();
15
+
16
+ $installer->getConnection()->addColumn(
17
+ $installer->getTable('core_website'),
18
+ 'stock_id',
19
+ 'SMALLINT(4) UNSIGNED NOT NULL DEFAULT \'' . Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID . '\''
20
+ );
21
+ $installer->getConnection()->addConstraint(
22
+ 'FK_CORE_WEBSITE_STOCK',
23
+ $installer->getTable('core_website'),
24
+ 'stock_id',
25
+ $installer->getTable('cataloginventory_stock'),
26
+ 'stock_id'
27
+ );
28
+
29
+ $installer->endSetup();
app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-upgrade-0.0.2-0.0.3.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse module setup
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+
11
+ $installer = $this;
12
+ /* @var $installer Smile_Warehouse_Model_Mysql4_Setup */
13
+
14
+ $installer->startSetup();
15
+
16
+ $installer->getConnection()->addColumn($installer->getTable('cataloginventory/stock_item'), 'stock_location', 'VARCHAR(255) NOT NULL DEFAULT \'\'');
17
+
18
+ $installer->endSetup();
app/code/community/Smile/Warehouse/sql/smile_warehouse_setup/mysql4-upgrade-0.0.3-0.0.5.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Warehouse module setup
4
+ *
5
+ * @category Smile
6
+ * @package Smile_Warehouse
7
+ * @author Smile <solution.magento@smile.fr>
8
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
+ */
10
+
11
+ $installer = $this;
12
+ /* @var $installer Smile_Warehouse_Model_Mysql4_Setup */
13
+
14
+ $warehouse = Mage::getModel('cataloginventory/stock');
15
+ $warehouse->load(Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID);
16
+
17
+ $warehouse->setStockCode('Main');
18
+ $warehouse->save();
app/design/adminhtml/default/default/layout/smile/warehouse.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+ <adminhtml_catalog_product_action_attribute_edit>
4
+ <reference name="attributes_tabs">
5
+ <block type="adminhtml/catalog_product_edit_action_attribute_tab_inventory" name="tab_inventory" template="smile/warehouse/catalog/product/edit/action/inventory.phtml" />
6
+ <action method="addTab"><name>inventory</name><block>tab_inventory</block></action>
7
+ </reference>
8
+ </adminhtml_catalog_product_action_attribute_edit>
9
+ </layout>
app/design/adminhtml/default/default/template/smile/warehouse/catalog/product/edit/action/inventory.phtml ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ //<![CDATA[
3
+ function toggleValueElementsWithCheckbox(checkbox) {
4
+ var td = $(checkbox.parentNode);
5
+ var checkboxes = td.getElementsBySelector('input[type="checkbox"]');
6
+ var inputs = td.getElementsBySelector('input[type!="checkbox"]', 'select', 'textarea');
7
+ if (checkboxes.size()>1) {
8
+ inputs.each(function(input){
9
+ input.disabled = (!checkbox.checked || checkboxes[0].checked);
10
+ checkboxes[0].disabled = !checkbox.checked;
11
+ });
12
+ } else {
13
+ inputs.each(function(input){
14
+ input.disabled = !checkbox.checked;
15
+ });
16
+ }
17
+ }
18
+ //]]>
19
+ </script>
20
+ <div class="entry-edit">
21
+ <div class="entry-edit-head">
22
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('catalog')->__('Inventory') ?></h4>
23
+ </div>
24
+ <fieldset>
25
+ <legend><?php echo Mage::helper('catalog')->__('Inventory') ?></legend>
26
+ <table cellspacing="0" class="form-list" id="table_cataloginventory">
27
+ <tr>
28
+ <td class="label"><label for="inventory_manage_stock"><?php echo Mage::helper('catalog')->__('Manage Stock') ?></label></td>
29
+ <td class="value"><select id="inventory_manage_stock" name="<?php echo $this->getFieldSuffix() ?>[manage_stock]" class="select" disabled="disabled">
30
+ <option value="1"><?php echo Mage::helper('catalog')->__('Yes') ?></option>
31
+ <option value="0"<?php if ($this->getConfigFieldValue('manage_stock') == 0): ?> selected="selected"<?php endif; ?>><?php echo Mage::helper('catalog')->__('No') ?></option>
32
+ </select>
33
+ <input name="<?php echo $this->getFieldSuffix() ?>[use_config_manage_stock]" type="checkbox" id="inventory_use_config_manage_stock" onclick="toggleValueElements(this, this.parentNode, $('inventory_manage_stock_checkbox'));" value="1" checked="checked" disabled="disabled" />
34
+ <label for="inventory_use_config_manage_stock" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
35
+ <input type="checkbox" id="inventory_manage_stock_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
36
+ <label for="inventory_manage_stock_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
37
+ </td>
38
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
39
+ </tr>
40
+ <?php if ($this->getStoreId()):?>
41
+ <tr>
42
+ <td class="label"><label for="inventory_qty"><?php echo Mage::helper('catalog')->__('Qty') ?><span class="required">*</span></label></td>
43
+ <td class="value">
44
+ <input type="text" class="input-text required-entry validate-number" id="inventory_qty" name="<?php echo $this->getFieldSuffix() ?>[qty]" value="<?php echo $this->getDefaultConfigValue('qty')*1 ?>" disabled="disabled" />
45
+ <input type="checkbox" id="inventory_qty_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
46
+ <label for="inventory_qty_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
47
+ </td>
48
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
49
+ </tr>
50
+ <?php endif;?>
51
+ <tr>
52
+ <td class="label"><label for="inventory_min_qty"><?php echo Mage::helper('catalog')->__('Minimum Qty for Item\'s Status to be Out of Stock') ?></label></td>
53
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_min_qty" name="<?php echo $this->getFieldSuffix() ?>[min_qty]" value="<?php echo $this->getDefaultConfigValue('min_qty')*1 ?>" disabled="disabled" />
54
+ <input type="checkbox" id="inventory_use_config_min_qty" name="<?php echo $this->getFieldSuffix() ?>[use_config_min_qty]" value="1" onclick="toggleValueElements(this, this.parentNode, $('inventory_min_qty_checkbox'));" checked="checked" disabled="disabled" />
55
+ <label for="inventory_use_config_min_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
56
+ <input type="checkbox" id="inventory_min_qty_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
57
+ <label for="inventory_min_qty_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
58
+ </td>
59
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
60
+ </tr>
61
+ <tr>
62
+ <td class="label"><label for="inventory_min_sale_qty"><?php echo Mage::helper('catalog')->__('Minimum Qty Allowed in Shopping Cart') ?></label></td>
63
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_min_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[min_sale_qty]" value="<?php echo $this->getDefaultConfigValue('min_sale_qty')*1 ?>" disabled="disabled" />
64
+ <input type="checkbox" id="inventory_use_config_min_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[use_config_min_sale_qty]" value="1" onclick="toggleValueElements(this, this.parentNode, $('inventory_min_sale_qty_checkbox'));" checked="checked" disabled="disabled" />
65
+ <label for="inventory_use_config_min_sale_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
66
+ <input type="checkbox" id="inventory_min_sale_qty_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
67
+ <label for="inventory_min_sale_qty_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
68
+ </td>
69
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
70
+ </tr>
71
+ <tr>
72
+ <td class="label"><label for="inventory_max_sale_qty"><?php echo Mage::helper('catalog')->__('Maximum Qty Allowed in Shopping Cart') ?></label></td>
73
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_max_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[max_sale_qty]" value="<?php echo $this->getDefaultConfigValue('max_sale_qty')*1 ?>" disabled="disabled" />
74
+ <input type="checkbox" id="inventory_use_config_max_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[use_config_max_sale_qty]" value="1" onclick="toggleValueElements(this, this.parentNode, $('inventory_max_sale_checkbox'));" checked="checked" disabled="disabled" />
75
+ <label for="inventory_use_config_max_sale_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
76
+ <input type="checkbox" id="inventory_max_sale_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
77
+ <label for="inventory_max_sale_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
78
+ </td>
79
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
80
+ </tr>
81
+ <tr>
82
+ <td class="label"><label for="inventory_is_qty_decimal"><?php echo Mage::helper('catalog')->__('Qty Uses Decimals') ?></label></td>
83
+ <td class="value"><select id="inventory_is_qty_decimal" name="<?php echo $this->getFieldSuffix() ?>[is_qty_decimal]" class="select" disabled="disabled">
84
+ <option value="0"><?php echo Mage::helper('catalog')->__('No') ?></option>
85
+ <option value="1"<?php if ($this->getDefaultConfigValue('is_qty_decimal')==1): ?> selected="selected"<?php endif; ?>><?php echo Mage::helper('catalog')->__('Yes') ?></option>
86
+ </select>
87
+ <input type="checkbox" id="inventory_is_qty_decimal_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
88
+ <label for="inventory_is_qty_decimal_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
89
+ </td>
90
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
91
+ </tr>
92
+ <tr>
93
+ <td class="label"><label for="inventory_backorders"><?php echo Mage::helper('catalog')->__('Backorders') ?></label></td>
94
+ <td class="value"><select id="inventory_backorders" name="<?php echo $this->getFieldSuffix() ?>[backorders]" class="select" disabled="disabled">
95
+ <?php foreach ($this->getBackordersOption() as $option): ?>
96
+ <?php $_selected = ($option['value'] == $this->getDefaultConfigValue('backorders')) ? ' selected="selected"' : '' ?>
97
+ <option value="<?php echo $option['value'] ?>"<?php echo $_selected ?>><?php echo $option['label'] ?></option>
98
+ <?php endforeach; ?>
99
+ </select>
100
+ <input type="checkbox" id="inventory_use_config_backorders" name="<?php echo $this->getFieldSuffix() ?>[use_config_backorders]" value="1" onclick="toggleValueElements(this, this.parentNode, $('inventory_backorders_checkbox'));" checked="checked" disabled="disabled" />
101
+ <label for="inventory_use_config_backorders" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
102
+ <input type="checkbox" id="inventory_backorders_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
103
+ <label for="inventory_backorders_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
104
+ </td>
105
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
106
+ </tr>
107
+
108
+ <?php if ($this->getStoreId()):?>
109
+ <tr>
110
+ <td class="label"><label for="inventory_notify_stock_qty"><?php echo Mage::helper('catalog')->__('Notify for Quantity Below') ?></label></td>
111
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_notify_stock_qty" name="<?php echo $this->getFieldSuffix() ?>[notify_stock_qty]" value="<?php echo $this->getDefaultConfigValue('notify_stock_qty')*1 ?>" disabled="disabled" />
112
+ <input type="checkbox" id="inventory_use_config_notify_stock_qty" name="<?php echo $this->getFieldSuffix() ?>[use_config_notify_stock_qty]" value="1" onclick="toggleValueElements(this, this.parentNode, $('inventory_notify_stock_qty_checkbox'));" checked="checked" disabled="disabled" />
113
+ <label for="inventory_use_config_notify_stock_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
114
+ <input type="checkbox" id="inventory_notify_stock_qty_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
115
+ <label for="inventory_notify_stock_qty_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
116
+ </td>
117
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
118
+ </tr>
119
+ <?php endif;?>
120
+
121
+ <tr>
122
+ <td class="label"><label for="inventory_enable_qty_increments"><?php echo Mage::helper('catalog')->__('Enable Qty Increments') ?></label></td>
123
+ <td class="value"><select id="inventory_enable_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[enable_qty_increments]" class="select" disabled="disabled">
124
+ <option value="1"><?php echo Mage::helper('catalog')->__('Yes') ?></option>
125
+ <option value="0"<?php if ($this->getDefaultConfigValue('enable_qty_increments') == 0): ?> selected="selected"<?php endif; ?>><?php echo Mage::helper('catalog')->__('No') ?></option>
126
+ </select>
127
+ <input type="checkbox" id="inventory_use_config_enable_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[use_config_enable_qty_increments]" value="1" onclick="toggleValueElements(this, this.parentNode, [$('inventory_enable_qty_increments_checkbox')]);" checked="checked" disabled="disabled" />
128
+ <label for="inventory_use_config_enable_qty_increments" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
129
+ <input type="checkbox" id="inventory_enable_qty_increments_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
130
+ <label for="inventory_enable_qty_increments_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
131
+ </td>
132
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
133
+ </tr>
134
+ <tr>
135
+ <td class="label"><label for="inventory_qty_increments"><?php echo Mage::helper('catalog')->__('Qty Increments') ?></label></td>
136
+ <td class="value">
137
+ <input type="text" class="input-text validate-number" id="inventory_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[qty_increments]" value="<?php echo $this->getDefaultConfigValue('qty_increments')*1 ?>" disabled="disabled" />
138
+ <input type="checkbox" id="inventory_use_config_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[use_config_qty_increments]" value="1" onclick="toggleValueElements(this, this.parentNode, [$('inventory_qty_increments_checkbox')]);" checked="checked" disabled="disabled" />
139
+ <label for="inventory_use_config_qty_increments" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
140
+ <input type="checkbox" id="inventory_qty_increments_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
141
+ <label for="inventory_qty_increments_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
142
+ </td>
143
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
144
+ </tr>
145
+
146
+ <?php if ($this->getStoreId()):?>
147
+ <tr>
148
+ <td class="label"><label for="inventory_stock_availability"><?php echo Mage::helper('catalog')->__('Stock Availability') ?></label></td>
149
+ <td class="value"><select id="inventory_stock_availability" name="<?php echo $this->getFieldSuffix() ?>[is_in_stock]" class="select" disabled="disabled">
150
+ <option value="1"><?php echo Mage::helper('catalog')->__('In Stock') ?></option>
151
+ <option value="0"<?php if ($this->getDefaultConfigValue('is_in_stock')==0): ?> selected<?php endif; ?>><?php echo Mage::helper('catalog')->__('Out of Stock') ?></option>
152
+ </select>
153
+ <input type="checkbox" id="inventory_stock_availability_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
154
+ <label for="inventory_stock_availability_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
155
+ </td>
156
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
157
+ </tr>
158
+
159
+ <tr>
160
+ <td class="label"><label for="inventory_stock_location"><?php echo Mage::helper('smile_warehouse')->__('Stock Location') ?></label></td>
161
+ <td class="value">
162
+ <input type="text" class="input-text" id="inventory_stock_location" name="<?php echo $this->getFieldSuffix() ?>[stock_location]" value="" disabled="disabled" />
163
+ <input type="checkbox" id="inventory_stock_location_checkbox" onclick="toggleValueElementsWithCheckbox(this)" />
164
+ <label for="inventory_stock_location_checkbox" class="normal"><?php echo Mage::helper('catalog')->__('Change') ?></label>
165
+ </td>
166
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
167
+ </tr>
168
+ <?php endif;?>
169
+ </table>
170
+ </fieldset>
171
+ </div>
app/design/adminhtml/default/default/template/smile/warehouse/catalog/product/tab/inventory.phtml ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ($this->isReadonly()):?>
2
+ <?php $_readonly = ' disabled="disabled" ';?>
3
+ <?php else: ?>
4
+ <?php $_readonly = '';?>
5
+ <?php endif; ?>
6
+ <div class="entry-edit">
7
+ <div class="entry-edit-head">
8
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('catalog')->__('Inventory') ?></h4>
9
+ </div>
10
+ <fieldset>
11
+
12
+ <legend><?php echo Mage::helper('catalog')->__('Inventory') ?></legend>
13
+
14
+ <?php if($this->isInventoryTabAvailable()): ?>
15
+ <table cellspacing="0" class="form-list" id="table_cataloginventory">
16
+ <tr>
17
+ <td class="label"><label for="inventory_manage_stock"><?php echo Mage::helper('catalog')->__('Manage Stock') ?></label></td>
18
+ <td class="value"><select id="inventory_manage_stock" name="<?php echo $this->getFieldSuffix() ?>[stock_data][manage_stock]" class="select" <?php echo $_readonly;?>>
19
+ <option value="1"><?php echo Mage::helper('catalog')->__('Yes') ?></option>
20
+ <option value="0"<?php if ($this->getConfigFieldValue('manage_stock') == 0): ?> selected="selected"<?php endif; ?>><?php echo Mage::helper('catalog')->__('No') ?></option>
21
+ </select>
22
+ <input type="hidden" id="inventory_manage_stock_default" value="<?php echo $this->getDefaultConfigValue('manage_stock'); ?>" />
23
+
24
+ <?php $_checked = ($this->getFieldValue('use_config_manage_stock') || $this->IsNew()) ? 'checked="checked"' : '' ?>
25
+ <input type="checkbox" id="inventory_use_config_manage_stock" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_manage_stock]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" class="checkbox" <?php echo $_readonly;?>/>
26
+ <label for="inventory_use_config_manage_stock" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
27
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_manage_stock'), $('inventory_use_config_manage_stock').parentNode);</script><?php endif; ?></td>
28
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
29
+ </tr>
30
+
31
+ <?php if(!$this->getProduct()->isComposite()): ?>
32
+ <?php if ($this->getProduct()->getId() && $this->getProduct()->getStoreId() && Mage::helper('smile_warehouse')->isStockAllowed()): ?>
33
+ <tr>
34
+ <td class="label"><label for="inventory_qty"><?php echo Mage::helper('catalog')->__('Qty') ?><span class="required">*</span></label></td>
35
+ <td class="value">
36
+ <?php if (!$_readonly):?>
37
+ <input type="hidden" id="original_inventory_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][original_inventory_qty]" value="<?php echo $this->getFieldValue('qty')*1 ?>"/>
38
+ <?php endif;?>
39
+
40
+ <input type="text" class="input-text required-entry validate-number" id="inventory_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][qty]" value="<?php echo $this->getFieldValue('qty')*1 ?>"/>
41
+ </td>
42
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
43
+ </tr>
44
+ <?php elseif ($this->getProduct()->getId() && $this->getStockItems()): ?>
45
+ <tr>
46
+ <td class="label"><?php echo Mage::helper('catalog')->__('Qty') ?></td>
47
+ <td class="value">
48
+ <?php foreach ($this->getStockItems() as $stockItem): ?>
49
+ <?php echo $stockItem->getStockCode() ?>: <?php echo floatval($stockItem->getQty()) ?><br />
50
+ <?php endforeach; ?>
51
+ </td>
52
+ </tr>
53
+ <?php endif; ?>
54
+
55
+ <tr>
56
+ <td class="label"><label for="inventory_min_qty"><?php echo Mage::helper('catalog')->__('Qty for Item\'s Status to become Out of Stock') ?></label></td>
57
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_min_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][min_qty]" value="<?php echo $this->getFieldValue('min_qty')*1 ?>" <?php echo $_readonly;?>/>
58
+
59
+ <?php $_checked = ($this->getFieldValue('use_config_min_qty') || $this->IsNew()) ? 'checked="checked"' : '' ?>
60
+ <input type="checkbox" id="inventory_use_config_min_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_min_qty]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" <?php echo $_readonly;?> />
61
+ <label for="inventory_use_config_min_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
62
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_min_qty'), $('inventory_use_config_min_qty').parentNode);</script><?php endif; ?></td>
63
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
64
+ </tr>
65
+
66
+ <tr>
67
+ <td class="label"><label for="inventory_min_sale_qty"><?php echo Mage::helper('catalog')->__('Minimum Qty Allowed in Shopping Cart') ?></label></td>
68
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_min_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][min_sale_qty]" value="<?php echo $this->getFieldValue('min_sale_qty')*1 ?>" <?php echo $_readonly;?>/>
69
+
70
+ <?php $_checked = ($this->getFieldValue('use_config_min_sale_qty') || $this->IsNew()) ? 'checked="checked"' : '' ?>
71
+ <input type="checkbox" id="inventory_use_config_min_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_min_sale_qty]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" class="checkbox" <?php echo $_readonly;?> />
72
+ <label for="inventory_use_config_min_sale_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
73
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_min_sale_qty'), $('inventory_use_config_min_sale_qty').parentNode);</script><?php endif; ?></td>
74
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
75
+ </tr>
76
+
77
+ <tr>
78
+ <td class="label"><label for="inventory_max_sale_qty"><?php echo Mage::helper('catalog')->__('Maximum Qty Allowed in Shopping Cart') ?></label></td>
79
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_max_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][max_sale_qty]" value="<?php echo $this->getFieldValue('max_sale_qty')*1 ?>" <?php echo $_readonly;?> />
80
+
81
+ <?php $_checked = ($this->getFieldValue('use_config_max_sale_qty') || $this->IsNew()) ? 'checked="checked"' : '' ?>
82
+ <input type="checkbox" id="inventory_use_config_max_sale_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_max_sale_qty]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" class="checkbox" <?php echo $_readonly;?> />
83
+ <label for="inventory_use_config_max_sale_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
84
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_max_sale_qty'), $('inventory_use_config_max_sale_qty').parentNode);</script><?php endif; ?></td>
85
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
86
+ </tr>
87
+
88
+ <?php if($this->canUseQtyDecimals()): ?>
89
+ <tr>
90
+ <td class="label"><label for="inventory_is_qty_decimal"><?php echo Mage::helper('catalog')->__('Qty Uses Decimals') ?></label></td>
91
+ <td class="value"><select id="inventory_is_qty_decimal" name="<?php echo $this->getFieldSuffix() ?>[stock_data][is_qty_decimal]" class="select" <?php echo $_readonly;?>>
92
+ <option value="0"><?php echo Mage::helper('catalog')->__('No') ?></option>
93
+ <option value="1"<?php if($this->getFieldValue('is_qty_decimal')==1): ?> selected="selected"<?php endif; ?>><?php echo Mage::helper('catalog')->__('Yes') ?></option>
94
+ </select>
95
+ </td>
96
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
97
+ </tr>
98
+ <?php endif; ?>
99
+
100
+ <tr>
101
+ <td class="label"><label for="inventory_backorders"><?php echo Mage::helper('catalog')->__('Backorders') ?></label></td>
102
+ <td class="value"><select id="inventory_backorders" name="<?php echo $this->getFieldSuffix() ?>[stock_data][backorders]" class="select" <?php echo $_readonly;?>>
103
+ <?php foreach ($this->getBackordersOption() as $option): ?>
104
+ <?php $_selected = ($option['value'] == $this->getFieldValue('backorders')) ? 'selected="selected"' : '' ?>
105
+ <option value="<?php echo $option['value'] ?>" <?php echo $_selected ?>><?php echo $option['label'] ?></option>
106
+ <?php endforeach; ?>
107
+ </select>
108
+
109
+ <?php $_checked = ($this->getFieldValue('use_config_backorders') || $this->IsNew()) ? 'checked="checked"' : '' ?>
110
+ <input type="checkbox" id="inventory_use_config_backorders" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_backorders]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" class="checkbox" <?php echo $_readonly;?> />
111
+ <label for="inventory_use_config_backorders" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
112
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_backorders'), $('inventory_use_config_backorders').parentNode);</script><?php endif; ?></td>
113
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
114
+ </tr>
115
+
116
+ <?php if ($this->getProduct()->getStoreId()):?>
117
+ <tr>
118
+ <td class="label"><label for="inventory_notify_stock_qty"><?php echo Mage::helper('catalog')->__('Notify for Quantity Below') ?></label></td>
119
+ <td class="value"><input type="text" class="input-text validate-number" id="inventory_notify_stock_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][notify_stock_qty]" value="<?php echo $this->getFieldValue('notify_stock_qty')*1 ?>" <?php echo $_readonly;?>/>
120
+
121
+ <?php $_checked = ($this->getFieldValue('use_config_notify_stock_qty') || $this->IsNew()) ? 'checked="checked"' : '' ?>
122
+ <input type="checkbox" id="inventory_use_config_notify_stock_qty" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_notify_stock_qty]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" class="checkbox" <?php echo $_readonly;?>/>
123
+ <label for="inventory_use_config_notify_stock_qty" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
124
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_notify_stock_qty'), $('inventory_use_config_notify_stock_qty').parentNode);</script><?php endif; ?></td>
125
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
126
+ </tr>
127
+ <?php endif; ?>
128
+ <?php endif; ?>
129
+ <tr>
130
+ <td class="label"><label for="inventory_enable_qty_increments"><?php echo Mage::helper('catalog')->__('Enable Qty Increments') ?></label></td>
131
+ <td class="value"><select id="inventory_enable_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[stock_data][enable_qty_increments]" class="select" <?php echo $_readonly;?>>
132
+ <option value="1"><?php echo Mage::helper('catalog')->__('Yes') ?></option>
133
+ <option value="0"<?php if ($this->getConfigFieldValue('enable_qty_increments') == 0): ?> selected="selected"<?php endif; ?>><?php echo Mage::helper('catalog')->__('No') ?></option>
134
+ </select>
135
+ <input type="hidden" id="inventory_enable_qty_increments_default" value="<?php echo $this->getDefaultConfigValue('enable_qty_increments'); ?>" />
136
+
137
+ <?php $_checked = ($this->getFieldValue('use_config_enable_qty_increments') || $this->IsNew()) ? 'checked="checked"' : '' ?>
138
+ <input type="checkbox" id="inventory_use_config_enable_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_enable_qty_increments]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" class="checkbox" <?php echo $_readonly;?>/>
139
+ <label for="inventory_use_config_enable_qty_increments" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
140
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_enable_qty_increments'), $('inventory_use_config_enable_qty_increments').parentNode);</script><?php endif; ?></td>
141
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
142
+ </tr>
143
+ <tr>
144
+ <td class="label"><label for="inventory_qty_increments"><?php echo Mage::helper('catalog')->__('Qty Increments') ?></label></td>
145
+ <td class="value">
146
+ <input type="text" class="input-text validate-digits" id="inventory_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[stock_data][qty_increments]" value="<?php echo $this->getFieldValue('qty_increments')*1 ?>" <?php echo $_readonly;?>/>
147
+ <?php $_checked = ($this->getFieldValue('use_config_qty_increments') || $this->IsNew()) ? 'checked="checked"' : '' ?>
148
+ <input type="checkbox" id="inventory_use_config_qty_increments" name="<?php echo $this->getFieldSuffix() ?>[stock_data][use_config_qty_increments]" value="1" <?php echo $_checked ?> onclick="toggleValueElements(this, this.parentNode);" class="checkbox" <?php echo $_readonly;?>/>
149
+ <label for="inventory_use_config_qty_increments" class="normal"><?php echo Mage::helper('catalog')->__('Use Config Settings') ?></label>
150
+ <?php if (!$this->isReadonly()):?><script type="text/javascript">toggleValueElements($('inventory_use_config_qty_increments'), $('inventory_use_config_qty_increments').parentNode);</script><?php endif; ?></td>
151
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
152
+ </tr>
153
+
154
+ <?php if ($this->getProduct()->getStoreId()):?>
155
+ <tr>
156
+ <td class="label"><label for="inventory_stock_availability"><?php echo Mage::helper('catalog')->__('Stock Availability') ?></label></td>
157
+ <td class="value"><select id="inventory_stock_availability" name="<?php echo $this->getFieldSuffix() ?>[stock_data][is_in_stock]" class="select" <?php echo $_readonly;?>>
158
+ <?php foreach ($this->getStockOption() as $option): ?>
159
+ <?php $_selected = ($option['value'] == $this->getFieldValue('is_in_stock')) ? 'selected="selected"' : '' ?>
160
+ <option value="<?php echo $option['value'] ?>" <?php echo $_selected ?>><?php echo $option['label'] ?></option>
161
+ <?php endforeach; ?>
162
+ </select>
163
+ </td>
164
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
165
+ </tr>
166
+ <?php endif;?>
167
+
168
+ <?php if ($this->getProduct()->getStoreId()):?>
169
+ <tr>
170
+ <td class="label"><label for="inventory_stock_location"><?php echo Mage::helper('smile_warehouse')->__('Stock Location') ?></label></td>
171
+ <td class="value"><input type="text" class="input-text" id="inventory_stock_location" name="<?php echo $this->getFieldSuffix() ?>[stock_data][stock_location]" value="<?php echo $this->escapeHtml($this->getFieldValue('stock_location')) ?>" <?php echo $_readonly;?>/>
172
+ <td class="value scope-label"><?php echo Mage::helper('catalog')->__('[WEBSITE]') ?></td>
173
+ </tr>
174
+ <?php endif;?>
175
+ </table>
176
+ <script type="text/javascript">
177
+ //<![CDATA[
178
+ var cataloginventoryNotManagestockFields = {
179
+ inventory_min_sale_qty: true,
180
+ inventory_max_sale_qty: true
181
+ };
182
+ function changeManageStockOption()
183
+ {
184
+ $$('#table_cataloginventory tr').each(manageStockEach);
185
+ return true;
186
+ }
187
+ function manageStockEach(el)
188
+ {
189
+ if ($('inventory_use_config_manage_stock').checked) {
190
+ var manageStock = $('inventory_manage_stock_default').value;
191
+ }
192
+ else {
193
+ var manageStock = $('inventory_manage_stock').value;
194
+ }
195
+ if (el == $('inventory_manage_stock').up(1)) {
196
+ return;
197
+ }
198
+ for(field in cataloginventoryNotManagestockFields) {
199
+ if ($(field) && ($(field).up(1) == el)) {
200
+ return;
201
+ }
202
+ }
203
+ if (manageStock == 1) {
204
+ el.show();
205
+ }
206
+ else {
207
+ el.hide();
208
+ }
209
+ return;
210
+ }
211
+ Event.observe($('inventory_manage_stock'), 'change', changeManageStockOption);
212
+ Event.observe($('inventory_use_config_manage_stock'), 'change', changeManageStockOption);
213
+ changeManageStockOption();
214
+
215
+ function applyEnableQtyIncrements() {
216
+ if ($('inventory_use_config_enable_qty_increments').checked) {
217
+ var enableQtyIncrements = $('inventory_enable_qty_increments_default').value;
218
+ }
219
+ else {
220
+ var enableQtyIncrements = $('inventory_enable_qty_increments').value;
221
+ }
222
+ if (enableQtyIncrements == 1) {
223
+ $('inventory_qty_increments').up('tr').show();
224
+ } else {
225
+ $('inventory_qty_increments').up('tr').hide();
226
+ }
227
+ }
228
+ Event.observe($('inventory_enable_qty_increments'), 'change', applyEnableQtyIncrements);
229
+ Event.observe($('inventory_use_config_enable_qty_increments'), 'change', applyEnableQtyIncrements);
230
+ applyEnableQtyIncrements();
231
+ //]]>
232
+ </script>
233
+ <?php else:?>
234
+ <?php echo Mage::helper('smile_warehouse')->__('If you want to set specific inventory settings for product on the store level, you need to assign this product to the website that includes this store.') ?>
235
+ <?php endif; ?>
236
+ </fieldset>
237
+ </div>
app/design/adminhtml/default/default/template/smile/warehouse/report/store/switcher.phtml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @see Mage_Adminhtml_Block_Store_Switcher
4
+ */
5
+ ?>
6
+ <?php if ($this->isShow()): ?>
7
+ <p class="switcher"><label for="store_switcher"><?php echo $this->__('Show Report For') ?>:</label>
8
+ <select name="store_switcher" id="store_switcher" onchange="return switchStore(this);">
9
+ <?php foreach ($this->getWebsiteCollection() as $_website): ?>
10
+ <?php $showWebsite=false; ?>
11
+ <?php foreach ($this->getGroupCollection($_website) as $_group): ?>
12
+ <?php $showGroup=false; ?>
13
+ <?php foreach ($this->getStoreCollection($_group) as $_store): ?>
14
+ <?php if ($showWebsite == false): ?>
15
+ <?php $showWebsite = true; ?>
16
+ <option website="true" value="<?php echo $_website->getId() ?>"<?php if($this->getRequest()->getParam('website') == $_website->getId()): ?> selected<?php endif; ?>><?php echo $_website->getName() ?></option>
17
+ <?php endif; ?>
18
+ <?php if ($showGroup == false): ?>
19
+ <?php $showGroup = true; ?>
20
+ <!--optgroup label="&nbsp;&nbsp;&nbsp;<?php echo $_group->getName() ?>"-->
21
+ <option group="true" value="<?php echo $_group->getId() ?>"<?php if($this->getRequest()->getParam('group') == $_group->getId()): ?> selected<?php endif; ?>>&nbsp;&nbsp;&nbsp;<?php echo $_group->getName() ?></option>
22
+ <?php endif; ?>
23
+ <option value="<?php echo $_store->getId() ?>"<?php if($this->getStoreId() == $_store->getId()): ?> selected<?php endif; ?>>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<?php echo $_store->getName() ?></option>
24
+ <?php endforeach; ?>
25
+ <?php if ($showGroup): ?>
26
+ <!-- </optgroup> -->
27
+ <?php endif; ?>
28
+ <?php endforeach; ?>
29
+ <?php endforeach; ?>
30
+ </select>
31
+ </p>
32
+ <script type="text/javascript">
33
+ function switchStore(obj){
34
+ if (obj.options[obj.selectedIndex].getAttribute('website') == 'true') {
35
+ var selectionType = 'website';
36
+ } else if (obj.options[obj.selectedIndex].getAttribute('group') == 'true') {
37
+ var selectionType = 'group';
38
+ } else {
39
+ var selectionType = 'store';
40
+ }
41
+ var storeParam = obj.value ? selectionType + '/' + obj.value + '/' : '';
42
+ if(obj.switchParams){
43
+ storeParam+= obj.switchParams;
44
+ }
45
+ setLocation('<?php echo $this->getSwitchUrl() ?>'+storeParam);
46
+ }
47
+ </script>
48
+ <?php endif; ?>
app/etc/modules/Smile_Warehouse.xml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Smile_Warehouse>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Adminhtml />
9
+ <Mage_CatalogInventory />
10
+ </depends>
11
+ </Smile_Warehouse>
12
+ </modules>
13
+ </config>
app/locale/en_US/Smile_Warehouse.csv ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "New Warehouse","New Warehouse"
2
+ "Warehouse","Warehouse"
3
+ "Warehouse Code","Warehouse Code"
4
+ "Warehouse Name","Warehouse Name"
5
+ "ID","ID"
6
+ "Code","Code"
7
+ "Name","Name"
8
+ "Delete","Delete"
9
+ "Are you sure you want to delete these warehouses?","Are you sure you want to delete these warehouses?"
10
+ "Total of %d record(s) were updated","Total of %d record(s) were updated"
11
+ "An error occurred while updating the product(s) attributes.","An error occurred while updating the product(s) attributes."
12
+ "Stock Qty","Stock Qty"
13
+ "You are not allowed to change inventory data.","You are not allowed to change inventory data."
14
+ "Skipping import row, unknown warehouse specified for product with sku %s.","Skipping import row, unknown warehouse specified for product with sku %s."
15
+ "Skipping import row, store and stock code mismatch for product with sku %s.","Skipping import row, store and stock code mismatch for product with sku %s."
16
+ "Skip import row, stock item for product with sku "%s" is not allowed in your current permission scope.","Skip import row, stock item for product with sku "%s" is not allowed in your current permission scope."
17
+ "Warehouse code must be unique.","Warehouse code must be unique."
18
+ "Add New Warehouse","Add New Warehouse"
19
+ "System","System"
20
+ "The Default Warehouse is not available for edit","The Default Warehouse is not available for edit"
21
+ "Warehouse with ID %s doesn't exist.","Warehouse with ID %s doesn't exist."
22
+ "The warehouse has been saved.","The warehouse has been saved."
23
+ "Unable to save the warehouse.","Unable to save the warehouse."
24
+ "The warehouse can't be deleted because it is assigned to a website.","The warehouse can't be deleted because it is assigned to a website."
25
+ "The warehouse has been deleted.","The warehouse has been deleted."
26
+ "An error occurred while deleting warehouse data.","An error occurred while deleting warehouse data."
27
+ "Unable to find a warehouse to delete.","Unable to find a warehouse to delete."
28
+ "Please select warehouse(s).","Please select warehouse(s)."
29
+ "Total of %d record(s) have been deleted.","Total of %d record(s) have been deleted."
30
+ "Total of %d record(s) haven't been deleted because they are assigned to website(s).","Total of %d record(s) haven't been deleted because they are assigned to website(s)."
31
+ "An error occurred while mass deleting warehouses.","An error occurred while mass deleting warehouses."
32
+ "Stock Location","Stock Location"
33
+ "If you want to set specific inventory settings for product on the store level, you need to assign this product to the website that includes this store.","If you want to set specific inventory settings for product on the store level, you need to assign this product to the website that includes this store."
34
+ "Manage Warehouses","Manage Warehouses"
35
+ "Manage Warehouses Stock","Manage Warehouses Stock"
package.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Smile_Warehouse</name>
4
+ <version>0.0.5</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>This module gives a possibility to manage several stocks in Magento. </summary>
10
+ <description>"Warehouse" module gives a possibility to manage several stocks in Magento.&#xD;
11
+ Key features:&#xD;
12
+ - Warehouses list management&#xD;
13
+ - Ability to share the same warehouse between different websites&#xD;
14
+ - Additional stock attributes</description>
15
+ <notes>First stable release</notes>
16
+ <authors><author><name>Smile</name><user>smileoss</user><email>solution.magento@smile.fr</email></author></authors>
17
+ <date>2013-04-08</date>
18
+ <time>10:14:39</time>
19
+ <contents><target name="magecommunity"><dir name="Smile"><dir name="Warehouse"><dir name="Block"><dir name="Adminhtml"><dir name="Catalog"><dir name="Product"><dir name="Edit"><dir name="Tab"><file name="Inventory.php" hash="ba31f0a7a4616aab61996f28f1ddb595"/><dir name="Super"><dir name="Config"><file name="Simple.php" hash="543ab00d65f952c79644d93a0d05aeb0"/></dir><file name="Config.php" hash="94feaf51e415d71183fae1c6b030b817"/></dir></dir></dir></dir></dir><dir name="Report"><dir name="Product"><dir name="Lowstock"><file name="Grid.php" hash="041ad41670dc91f9e8708c32ba78fb05"/></dir></dir></dir><dir name="System"><dir name="Store"><file name="Grid.php" hash="aa41a37180fe288b5ad6e7dadcd11632"/></dir></dir><dir name="Warehouse"><dir name="Edit"><file name="Form.php" hash="cdfd57f55b6a4d512f7752c20caa40a9"/></dir><file name="Edit.php" hash="6a74b78a9a8be9df480f10a73f81908d"/><file name="Grid.php" hash="5897b2535b6f5eac74f4631155914759"/></dir><file name="Warehouse.php" hash="96b2058570b8341f40247539d3cf0fb0"/><dir name="Widget"><dir name="Grid"><dir name="Column"><dir name="Renderer"><file name="Implode.php" hash="42ec2cdb59d4ef6a8fb9b167cc4d9f22"/></dir></dir></dir></dir></dir><dir name="Rss"><dir name="Catalog"><file name="NotifyStock.php" hash="80e7fd7a040f515a873319a6d2b7fe6e"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="caee6ef3c892d4ca0ad5287ee0304943"/></dir><dir name="Model"><dir name="Catalog"><dir name="Convert"><dir name="Parser"><file name="Product.php" hash="4eb758d8df5dbc84f46bd89c386c3682"/></dir></dir></dir><dir name="Mysql4"><dir name="Reports"><dir name="Product"><dir name="Lowstock"><file name="Collection.php" hash="05d7b706b8c0f82643c667b2c476da6b"/></dir></dir></dir><file name="Setup.php" hash="5144b02e3c4cec6dc79a4a61116fd85b"/><dir name="Stock"><file name="Collection.php" hash="06515f1c093286a02351a412b48e6f3f"/><file name="Item.php" hash="71f84661f1a34176424cfc1a45214007"/><file name="Status.php" hash="097efb0f96fd7ece621d4c464317b52c"/></dir><file name="Stock.php" hash="2eb108bbc9b9e1c5d58aad731317dbd0"/></dir><file name="Observer.php" hash="ad206e8af2ef28bbbe356412106434ea"/><dir name="Stock"><dir name="Item"><dir name="Api"><file name="V2.php" hash="ce5793a5418a1dcabc4cf1a75e8da8af"/></dir><file name="Api.php" hash="d694be80d2e3eef7546701d5b8d49de7"/></dir><file name="Item.php" hash="317e2fa1e73f3e0742f73593987b73e9"/></dir><file name="Stock.php" hash="00985c752584fdaed0b3918d314a7d71"/></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Catalog"><dir name="Product"><dir name="Action"><file name="AttributeController.php" hash="2e555153c47f8a13a6e6cac9d997bfe6"/></dir></dir><file name="ProductController.php" hash="9e54010295c0c6eceef6ffa427d41947"/></dir><file name="WarehouseController.php" hash="d49e9ca4987e6153e0a18f746d3ecb2a"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="3efb728ab81c237f89a7c3ae3325b8e7"/><file name="api.xml" hash="d81f6f4f03e09266dbd5efcbabfbd49e"/><file name="config.xml" hash="03d3a958c77a2dfd936b5b2638534db0"/><file name="wsdl.xml" hash="ba2414e0ac9613ee29cc38bba591fb5e"/></dir><dir name="sql"><dir name="smile_warehouse_setup"><file name="mysql4-install-0.0.1.php" hash="4fd89db28aecc3200e0e867d46bed3ab"/><file name="mysql4-upgrade-0.0.1-0.0.2.php" hash="4f44db2faf8c062b1ea53c233ef7e0f2"/><file name="mysql4-upgrade-0.0.2-0.0.3.php" hash="5f5e56f0265aaaacd3eeb53bd7649c3e"/><file name="mysql4-upgrade-0.0.3-0.0.5.php" hash="2ec97da7e7fb37133ec2befb77ad59ca"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="smile"><file name="warehouse.xml" hash="ab932ecc371dbb120cda411f95967935"/></dir></dir><dir name="template"><dir name="smile"><dir name="warehouse"><dir name="catalog"><dir name="product"><dir name="edit"><dir name="action"><file name="inventory.phtml" hash="a254582ab4627540475de1eddc772cc0"/></dir></dir><dir name="tab"><file name="inventory.phtml" hash="9ecce1492562ea65bf1e31150cb5153c"/></dir></dir></dir><dir name="report"><dir name="store"><file name="switcher.phtml" hash="d7c13c944f06736952865fdde15ebe5b"/></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Smile_Warehouse.xml" hash="1fe62a521e00cc3307e8abb8cc9610f7"/></dir></target><target name="magelocale"><dir><dir name="en_US"><file name="Smile_Warehouse.csv" hash="b10bea3b71990425d001dcd103fce509"/></dir></dir></target></contents>
20
+ <compatible/>
21
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
22
+ </package>