00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 class Mage_CatalogInventory_Model_Observer
00035 {
00036
00037
00038
00039
00040
00041
00042 protected $_checkedProductsQty = array();
00043
00044
00045
00046
00047
00048
00049
00050 public function addInventoryData($observer)
00051 {
00052 $product = $observer->getEvent()->getProduct();
00053 if ($product instanceof Mage_Catalog_Model_Product) {
00054 Mage::getModel('cataloginventory/stock_item')->assignProduct($product);
00055 }
00056 return $this;
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066 public function addStockStatusToCollection($observer)
00067 {
00068 $productCollection = $observer->getEvent()->getCollection();
00069 if ($productCollection->hasFlag('require_stock_items')) {
00070 Mage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection);
00071 } else {
00072 Mage::getModel('cataloginventory/stock_status')->addStockStatusToProducts($productCollection);
00073 }
00074 return $this;
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 public function addInventoryDataToCollection($observer)
00084 {
00085 $productCollection = $observer->getEvent()->getProductCollection();
00086 Mage::getModel('cataloginventory/stock')->addItemsToProducts($productCollection);
00087 return $this;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096 public function saveInventoryData($observer)
00097 {
00098 $product = $observer->getEvent()->getProduct();
00099
00100 if (is_null($product->getStockData())) {
00101 if ($product->getIsChangedWebsites() || $product->dataHasChangedFor('status')) {
00102 Mage::getSingleton('cataloginventory/stock_status')
00103 ->updateStatus($product->getId());
00104 }
00105 return $this;
00106 }
00107
00108 $item = $product->getStockItem();
00109 if (!$item) {
00110 $item = Mage::getModel('cataloginventory/stock_item');
00111 }
00112 $this->_prepareItemForSave($item, $product);
00113 $item->save();
00114 return $this;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123 public function copyInventoryData($observer)
00124 {
00125 $newProduct = $observer->getEvent()->getNewProduct();
00126
00127 $newProduct->unsStockItem();
00128 $newProduct->setStockData(array(
00129 'use_config_min_qty' => 1,
00130 'use_config_min_sale_qty' => 1,
00131 'use_config_max_sale_qty' => 1,
00132 'use_config_backorders' => 1,
00133 'use_config_notify_stock_qty'=> 1
00134 ));
00135
00136 return $this;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146 protected function _prepareItemForSave($item, $product)
00147 {
00148 $item->addData($product->getStockData())
00149 ->setProduct($product)
00150 ->setProductId($product->getId())
00151 ->setStockId($item->getStockId());
00152 if (!is_null($product->getData('stock_data/min_qty'))
00153 && is_null($product->getData('stock_data/use_config_min_qty'))) {
00154 $item->setData('use_config_min_qty', false);
00155 }
00156 if (!is_null($product->getData('stock_data/min_sale_qty'))
00157 && is_null($product->getData('stock_data/use_config_min_sale_qty'))) {
00158 $item->setData('use_config_min_sale_qty', false);
00159 }
00160 if (!is_null($product->getData('stock_data/max_sale_qty'))
00161 && is_null($product->getData('stock_data/use_config_max_sale_qty'))) {
00162 $item->setData('use_config_max_sale_qty', false);
00163 }
00164 if (!is_null($product->getData('stock_data/backorders'))
00165 && is_null($product->getData('stock_data/use_config_backorders'))) {
00166 $item->setData('use_config_backorders', false);
00167 }
00168 if (!is_null($product->getData('stock_data/notify_stock_qty'))
00169 && is_null($product->getData('stock_data/use_config_notify_stock_qty'))) {
00170 $item->setData('use_config_notify_stock_qty', false);
00171 }
00172 return $this;
00173
00174 }
00175
00176
00177
00178
00179
00180
00181
00182 public function checkQuoteItemQty($observer)
00183 {
00184 $quoteItem = $observer->getEvent()->getItem();
00185
00186 if (!$quoteItem || !$quoteItem->getProductId() || $quoteItem->getQuote()->getIsSuperMode()) {
00187 return $this;
00188 }
00189
00190
00191
00192
00193 $qty = $quoteItem->getQty();
00194
00195
00196
00197
00198 if (($options = $quoteItem->getQtyOptions()) && $qty > 0) {
00199 $qty = $quoteItem->getProduct()->getTypeInstance(true)->prepareQuoteItemQty($qty, $quoteItem->getProduct());
00200 $quoteItem->setData('qty', $qty);
00201
00202 foreach ($options as $option) {
00203
00204 $optionQty = $qty * $option->getValue();
00205 $increaseOptionQty = ($quoteItem->getQtyToAdd() ? $quoteItem->getQtyToAdd() : $qty) * $option->getValue();
00206
00207 $stockItem = $option->getProduct()->getStockItem();
00208
00209 if (!$stockItem instanceof Mage_CatalogInventory_Model_Stock_Item) {
00210 Mage::throwException(Mage::helper('cataloginventory')->__('Stock item for Product in option is not valid'));
00211 }
00212
00213 $qtyForCheck = $this->_getProductQtyForCheck($option->getProduct()->getId(), $increaseOptionQty);
00214
00215 $result = $stockItem->checkQuoteItemQty($optionQty, $qtyForCheck, $option->getValue());
00216
00217 if (!is_null($result->getItemIsQtyDecimal())) {
00218 $option->setIsQtyDecimal($result->getItemIsQtyDecimal());
00219 }
00220
00221 if ($result->getHasQtyOptionUpdate()) {
00222 $option->setHasQtyOptionUpdate(true);
00223 $quoteItem->updateQtyOption($option, $result->getOrigQty());
00224 $option->setValue($result->getOrigQty());
00225
00226
00227
00228 $quoteItem->setData('qty', intval($qty));
00229 }
00230 if (!is_null($result->getMessage())) {
00231 $option->setMessage($result->getMessage());
00232 }
00233 if (!is_null($result->getItemBackorders())) {
00234 $option->setBackorders($result->getItemBackorders());
00235 }
00236
00237 if ($result->getHasError()) {
00238 $option->setHasError(true);
00239 $quoteItem->setHasError(true)
00240 ->setMessage($result->getQuoteMessage());
00241 $quoteItem->getQuote()->setHasError(true)
00242 ->addMessage($result->getQuoteMessage(), $result->getQuoteMessageIndex());
00243 }
00244 }
00245 }
00246 else {
00247 $stockItem = $quoteItem->getProduct()->getStockItem();
00248
00249 if (!$stockItem instanceof Mage_CatalogInventory_Model_Stock_Item) {
00250 Mage::throwException(Mage::helper('cataloginventory')->__('Stock item for Product is not valid'));
00251 }
00252
00253
00254
00255
00256
00257 if ($quoteItem->getParentItem()) {
00258 $rowQty = $quoteItem->getParentItem()->getQty()*$qty;
00259
00260
00261
00262 $qtyForCheck = $this->_getProductQtyForCheck($quoteItem->getProduct()->getId(), 0);
00263 }
00264 else {
00265 $increaseQty = $quoteItem->getQtyToAdd() ? $quoteItem->getQtyToAdd() : $qty;
00266 $rowQty = $qty;
00267 $qtyForCheck = $this->_getProductQtyForCheck($quoteItem->getProduct()->getId(), $increaseQty);
00268 }
00269
00270 $result = $stockItem->checkQuoteItemQty($rowQty, $qtyForCheck, $qty);
00271
00272 if (!is_null($result->getItemIsQtyDecimal())) {
00273 $quoteItem->setIsQtyDecimal($result->getItemIsQtyDecimal());
00274 if ($quoteItem->getParentItem()) {
00275 $quoteItem->getParentItem()->setIsQtyDecimal($result->getItemIsQtyDecimal());
00276 }
00277 }
00278
00279
00280
00281
00282
00283
00284 if ($result->getHasQtyOptionUpdate()
00285 && (!$quoteItem->getParentItem()
00286 || $quoteItem->getParentItem()->getProduct()->getTypeInstance(true)
00287 ->getForceChildItemQtyChanges($quoteItem->getParentItem()->getProduct()))) {
00288 $quoteItem->setData('qty', $result->getOrigQty());
00289 }
00290
00291 if (!is_null($result->getItemUseOldQty())) {
00292 $quoteItem->setUseOldQty($result->getItemUseOldQty());
00293 }
00294 if (!is_null($result->getMessage())) {
00295 $quoteItem->setMessage($result->getMessage());
00296 if ($quoteItem->getParentItem()) {
00297 $quoteItem->getParentItem()->setMessage($result->getMessage());
00298 }
00299 }
00300 if (!is_null($result->getItemBackorders())) {
00301 $quoteItem->setBackorders($result->getItemBackorders());
00302 }
00303
00304 if ($result->getHasError()) {
00305 $quoteItem->setHasError(true);
00306 $quoteItem->getQuote()->setHasError(true)
00307 ->addMessage($result->getQuoteMessage(), $result->getQuoteMessageIndex());
00308 }
00309 }
00310
00311 return $this;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321 protected function _getProductQtyForCheck($productId, $itemQty)
00322 {
00323 $qty = $itemQty;
00324 if (isset($this->_checkedProductsQty[$productId])) {
00325 $qty += $this->_checkedProductsQty[$productId];
00326 }
00327 $this->_checkedProductsQty[$productId] = $qty;
00328 return $qty;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 public function lockOrderInventoryData($observer)
00341 {
00342 $order = $observer->getEvent()->getOrder();
00343 $productIds = array();
00344
00345
00346
00347
00348 if ($order->getId()) {
00349 return $this;
00350 }
00351
00352 if ($order) {
00353 foreach ($order->getAllItems() as $item) {
00354 $productIds[] = $item->getProductId();
00355 }
00356 }
00357
00358 if (!empty($productIds)) {
00359 Mage::getSingleton('cataloginventory/stock')->lockProductItems($productIds);
00360 }
00361
00362 return $this;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 public function createOrderItem($observer)
00372 {
00373 $item = $observer->getEvent()->getItem();
00374
00375
00376
00377
00378 $children = $item->getChildrenItems();
00379
00380 if (!$item->getId() && empty($children)) {
00381 Mage::getSingleton('cataloginventory/stock')->registerItemSale($item);
00382 }
00383
00384 return $this;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393 public function cancelOrderItem($observer)
00394 {
00395 $item = $observer->getEvent()->getItem();
00396
00397 $children = $item->getChildrenItems();
00398 $qty = $item->getQtyOrdered() - max($item->getQtyShipped(), $item->getQtyInvoiced()) - $item->getQtyCanceled();
00399
00400 if ($item->getId() && ($productId = $item->getProductId()) && empty($children) && $qty) {
00401 Mage::getSingleton('cataloginventory/stock')->backItemQty($productId, $qty);
00402 }
00403
00404 return $this;
00405 }
00406
00407
00408
00409
00410
00411
00412
00413 public function refundOrderItem($observer)
00414 {
00415 $item = $observer->getEvent()->getCreditmemoItem();
00416 if ($item->getId() && $item->getBackToStock() && ($productId = $item->getProductId()) && ($qty = $item->getQty())) {
00417 Mage::getSingleton('cataloginventory/stock')->backItemQty($productId, $qty);
00418 }
00419 return $this;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 public function updateItemsStockUponConfigChange($observer)
00429 {
00430 Mage::getResourceSingleton('cataloginventory/stock')->updateSetOutOfStock();
00431 Mage::getResourceSingleton('cataloginventory/stock')->updateSetInStock();
00432 Mage::getResourceSingleton('cataloginventory/stock')->updateLowStockDate();
00433 return $this;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 public function productStatusUpdate(Varien_Event_Observer $observer)
00443 {
00444 $productId = $observer->getEvent()->getProductId();
00445 Mage::getSingleton('cataloginventory/stock_status')
00446 ->updateStatus($productId);
00447 return $this;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 public function catalogProductWebsiteUpdate(Varien_Event_Observer $observer)
00457 {
00458 $websiteIds = $observer->getEvent()->getWebsiteIds();
00459 $productIds = $observer->getEvent()->getProductIds();
00460
00461 foreach ($websiteIds as $websiteId) {
00462 foreach ($productIds as $productId) {
00463 Mage::getSingleton('cataloginventory/stock_status')
00464 ->updateStatus($productId, null, $websiteId);
00465 }
00466 }
00467
00468 return $this;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477 public function addStockStatusToPrepareIndexSelect(Varien_Event_Observer $observer)
00478 {
00479 $website = $observer->getEvent()->getWebsite();
00480 $select = $observer->getEvent()->getSelect();
00481
00482 Mage::getSingleton('cataloginventory/stock_status')
00483 ->addStockStatusToSelect($select, $website);
00484
00485 return $this;
00486 }
00487 }