Szybki import stanów magazynowych w Magento
Często zachodzi potrzeba zaimportowania stanów magazynowych z innego systemu. Najczęściej w tym celu wykorzystywane jest API, jednak ma ono jedną podstawową wadę, jest bardzo powolne. Kiedy potrzebujemy w krótkim czasie dokonać zmiany kilku tysięcy produktów, to wykorzystanie API może być nie najlepszym rozwiązaniem z powodu jego bardzo dużej pracochłonności i narzutu na zasoby.
Innym popularnym rozwiązaniem jest napisanie własnego skryptu mającego realizować to zadanie w oparciu o modele Magento.
Poniżej prezentujemy przykładowy skrypt importujący stany magazynowe na podstawie pliku CSV, oczywiście jako źródło wejściowe posłużyć inna baza danych lub API programu magazynowego.
ini_set("display_errors", 1); ini_set("memory_limit","1024M"); require_once 'app/Mage.php'; umask(0); $currentStore = Mage::app()->getStore()->getId(); Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); $path = getcwd().'/WebStockInput.csv'; $readfile = file ($path); for ($i=1; $i < count($readfile); $i++ ) { $fields = split("\t",$readfile[$i]); $product = Mage::getModel('catalog/product'); $product->load($product->getIdBySku($fields[0])); // get product's stock data such quantity, in_stock etc $stockData = $product->getStockData(); // update stock data using new data $stockData['qty'] = $fields[2]; $stockData['is_in_stock'] = 1; // then set product's stock data to update $product->setStockData($stockData); try { $product->save(); } catch (Exception $ex) { echo $ex->getMessage(); } } Mage::app()->setCurrentStore($currentStore); ?>
Niestety i to rozwiązanie nie należy do zbyt szybkich. Dlatego poniżej prezentujemy jak my to robimy. Nasz skrypt pozwala na zmianę stanów kilku tysięcy produktów w mniej niż 120 sekund. Został przetestowany w wielu rozwiązaniach i jak na razie sprawdza się bardzo dobrze. Jeżeli zajdzie potrzeba dostosowania go do współpracy z innymi programami magazynowymi lub źródłami danych zachęcamy do kontaktu z nami.
Konfiguracja
Aby skrypt działał poprawnie należy ustawić zmienną $workdir na folder z plikiem wejściowym o nazwie magento2.csv.
W tym też folderze skrypt zapisze raport z wynikiem swojej pracy.
//Centerkom.pl - najlepsze rozwiązania Magento $workdir - "/var/www/import/" function getmicrotime(){list($usec, $sec) = explode(" ",microtime());return ((float)$usec + (float)$sec);} $time_start = getmicrotime(); $mageFilename = "../app/Mage.php"; require_once $mageFilename; Mage::setIsDeveloperMode(true); ini_set("display_errors", 1); umask(0); Mage::app("admin"); Mage::register("isSecureArea", 1); Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); set_time_limit(0); ini_set("memory_limit","1024M"); /***************** UTILITY FUNCTIONS ********************/ function _getConnection($type = "core_read"){ return Mage::getSingleton("core/resource")->getConnection($type); } function _getTableName($tableName){ return Mage::getSingleton("core/resource")->getTableName($tableName); } function _getAttributeId($attribute_code = "price"){ $connection = _getConnection("core_read"); $sql = "SELECT attribute_id FROM " . _getTableName("eav_attribute") . " WHERE entity_type_id = ? AND attribute_code = ?"; $entity_type_id = _getEntityTypeId(); return $connection->fetchOne($sql, array($entity_type_id, $attribute_code)); } function _getEntityTypeId($entity_type_code = "catalog_product"){ $connection = _getConnection("core_read"); $sql = "SELECT entity_type_id FROM " . _getTableName("eav_entity_type") . " WHERE entity_type_code = ?"; return $connection->fetchOne($sql, array($entity_type_code)); } function _checkIfSkuExists($sku){ $connection = _getConnection("core_read"); $sql = "SELECT COUNT(*) AS count_no FROM " . _getTableName("catalog_product_entity") . " WHERE sku = ?"; $count = $connection->fetchOne($sql, array($sku)); if($count > 0){ return true; }else{ return false; } } function _getIdFromSku($sku){ $connection = _getConnection("core_read"); $sql = "SELECT entity_id FROM " . _getTableName("catalog_product_entity") . " WHERE sku = ?"; return $connection->fetchOne($sql, array($sku)); } function _updateStocks($data){ $connection = _getConnection("core_write"); $sku = $data[0]; $newQty = $data[1]; $productId = _getIdFromSku($sku); $attributeId = _getAttributeId(); $sql = "UPDATE " . _getTableName("cataloginventory_stock_item") . " csi, " . _getTableName("cataloginventory_stock_status") . " css SET csi.qty = ?, csi.is_in_stock = ?, css.qty = ?, css.stock_status = ? WHERE csi.product_id = ? AND csi.product_id = css.product_id"; $isInStock = $newQty > 0 ? 1 : 0; $stockStatus = $newQty > 0 ? 1 : 0; $connection->query($sql, array($newQty, $isInStock, $newQty, $stockStatus, $productId)); } /***************** UTILITY FUNCTIONS ********************/ $csv = new Varien_File_Csv(); $data = $csv->getData($workdir/"magento2.csv"); //path to csv array_shift($data); $message = ""; $count = 1; $count_success = 0; foreach($data as $_data){ if(_checkIfSkuExists($_data[0])){ try{ _updateStocks($_data); $message .= $count . "> Success:: Qty (" . $_data[1] . ") of Sku (" . $_data[0] . ") has been updated. \n"; //echo $count . "> Success:: Qty (" . $_data[1] . ") of Sku (" . $_data[0] . ") has been updated. \n"; $count_success++; }catch(Exception $e){ $message .= $count ."> Error:: while Upating Qty (" . $_data[1] . ") of Sku (" . $_data[0] . ") => ".$e->getMessage()."\n"; echo $count ."> Error:: while Upating Qty (" . $_data[1] . ") of Sku (" . $_data[0] . ") => ".$e->getMessage()."\n"; } }else{ $message .= $count ."> Error:: Product with Sku (" . $_data[0] . ") does't exist.\n"; //echo $count ."> Error:: Product with Sku (" . $_data[0] . ") does't exist.\n"; } $count++; } $fp = fopen($workdir.date("Ymd"), 'w'); $time_end = getmicrotime(); $time = $time_end - $time_start; fwrite($fp, $message); fwrite($fp, "\nZmieniono :".$count_success); fwrite($fp, "\nCzas wygenerowania strony $time s"); fwrite($fp, "\nmemory_get_usage ".((memory_get_usage()/1024)/1024)); fwrite($fp, "\nreal_memory_get_usage ".((memory_get_usage(true)/1024)/1024));