Szybki import stanów magazynowych w Magento

Napisany przez admin, dodany w Wtorek 22 lipca 2014r. w kategorii Nasze rozwiązania, Praktyczne porady Tagi: , ,  •  Komentowanie nie jest możliwe

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));

Współpraca przy newcraft.eu

Napisany przez admin, dodany w Wtorek 22 lipca 2014r. w kategorii Nasze realizacje Tagi:  •  Komentowanie nie jest możliwe

Wdrożenie przy którym mieliśmy okazję współuczestniczyć, nasza rola ograniczyła się do konfiguracji i instalacji Magento na serwerze klienta.
Ponadto specjalnie na potrzeby systemy newcraft.ey wykonania kilka modułów umożliwiających osiągnięcie zamierzonego przez klienta efektu.

Wiosna pod znakiem nowego layoutu strony Michelson.pl

Napisany przez admin, dodany w Wtorek 22 lipca 2014r. w kategorii Nasze realizacje Tagi: ,  •  Komentowanie nie jest możliwe

A jak wyglądają te zmiany, zobaczcie sami :

Amor zapanował w wiosennej odsłonie Michelsona i pokazał, jak bardzo ceni Zakochanych! W powietrzu unosi się miłość i świeży powiew wyjątkowych okazji. Strona teraz wygląda jeszcze ładniej niż poprzednio, a ciekawa kolorystyka współgra z ofertą sklepu.

Klasyczne i awangardowe pierścionki zaręczynowe tylko czekają na romantyczny moment oświadczyn. Piękny złoty pierścionek z brylantem już niedługo zabłyszczy na dłoni Ukochanej, kiedy wzruszona i zachwycona powie „Tak!”. Eleganckie złote obrączki ślubne są gotowe dla tych, którzy już podjęli tę radosną decyzję, by być razem na zawsze. A oryginalna biżuteria aż płonie, by stać się wyjątkową ozdobą i wzbogacić wykwintną kreację. Wszystko to z materiałów najlepszego gatunku i w wyjątkowych cenach, które zaskakują swoją dostępnością.

Jesteśmy przekonani, że nowa odświeżona szata graficzna michelson.pl pomoże naszemu partnerowi zdobyć wielu nowych klientów i pomnożyć swoje zyski.

Świąteczna odsłona michelson.pl

Napisany przez admin, dodany w Wtorek 22 lipca 2014r. w kategorii Nasze realizacje Tagi:  •  Komentowanie nie jest możliwe

W okresie świątecznym, dzięki funkcjonalności magento sklepy naszych klientów przybierają nową formę. Poprzez zastosowanie unikalnej i kojarzącej się z świątecznymi zakupami naszemu klientowi udało się pobić kolejne rekordy sprzedaży.

Prosta aktualizacja cen

Napisany przez admin, dodany w Wtorek 22 lipca 2014r. w kategorii Nasze rozwiązania, Praktyczne porady Tagi: , ,  •  Komentowanie nie jest możliwe

Jedną z podstawowych wad Magento jest bardzo czasochłonna aktualizacja ceny. Za każdym razem wymagana jest edycja produktu następnie przełączenie zakładki i zapisanie nowej ceny. W przypadku jak mamy do poprawienia kilka lub kilkanaście cen może to być bardzo uciążliwe i czasochłonne.

Poniżej prezentujemy rozwiązanie umożliwiające masową i szybka aktualizację. Dziki naszemu modułowi już na etapie list produktów kolumna zawierająca cenę umożliwi jej aktualizacją. Dzięki temu w szybki sposób możemy masowo zaktualizować wszystkie ceny w sklepie.

Teraz nasz moduł do aktualizacji ceny w nowej odsłonie w pełni kompatybilny z Magento 1.6.x, 1.7.x i bezpłatny.

Poniżej prezentujemy screen z magento z zainstalowanym modułem.

Moduł można pobrać tutaj lub na naszym profilu magento-connect gdzie zawsze będzie dostępna najnowsza wersja modułu.