Magento add product for different storeview in one step - magento

currently when I add or edit products for magento via api I will do something like this for each storeview:
$product = Mage::getModel('catalog/product');
$product->setStoreId($default_store_id); // 0 = default/all store view.
// do something
try
{
$product->save();
}
catch (Exception $e)
{
echo $e->getMessage();
}
This will takes 1 second for each storeview. When I edit 1 product for 10 storeviews it will takes 10 seconds.
Is there any way to edit alle storeview data (different languages) in one step?

No is the simple answer. You can create optimised code though for editing and only save the attribute you are updating as opposed to the entire product object but this depends on the scenario you are catering for.
$product = Mage::getModel('catalog/product')->setStoreId($storeId)->load($product_id);
$product->setName('Product Name');
$product->getResource()->saveAttribute($product, 'name');
Other option is to work directly on the database for updates rather than use magento objects.

Related

Update Magento product meta description for different store

i am trying to update meta description for different store but magento keep showing error :
Product with URL key already exist.
what i am trying to do i have two stores on one magento. so we want seprate meta information for different stores. so when i try to update meta info for specific store then shows me error. any one facing same problem :
$pid = Mage::getModel('catalog/product')->getResource()->getIdBySku($sku);
$product = Mage::getModel('catalog/product')->load($pid);
if($product)
{
$product->setStoreId(6);
$product->setmeta_keyword($newKeyWord);
$product->setmeta_description($newmeta_metadescription);
try {
$product->save();
echo 'Product Updated successfully --- '.$sku."\n";
}
catch (Exception $ex) {
echo $ex->getMessage();
}
There are lot of issue in your code:
Setter function is wrong:
$product->setMetaKeyword($newKeyWord);
$product->setMetaDescription($newmeta_metadescription);
Best way to do this:
$product = Mage::getModel('catalog/product')->load($pid);
Please use below format,which more faster then your code
$product->addAttributeUpdate($Attributecode, $value, $storeId)
then
$product->addAttributeUpdate('meta_keyword', $newKeyWord, $storeId=6);
$product->addAttributeUpdate('meta_description', $newmeta_metadescription, $storeId=6);
No need use save() function in this case.

magento target rule not applying to a specific product

A simple product is in specific category other products have that rule applied.This is happening on magento enterprise 1.13.0.1 version.
A rule is applicable to that category but when I look in catalogrule_product table then there is no entry for that product. This means no rule applies to that product.
http://www.solvingmagento.com/quick-tip-magento-catalog-price-rules-dont-work/ is the link I refered.
I want to know if for some reason a product has no target rules applied then:
1. Is there no cron job that will handle this and populate catalogrule_product table.
If yes then which cron job does this.
Also when we saved product its expected that catalog_product_save_after event should get fired resulting in Mage_CatalogRule module’s observer method applyAllRulesOnProduct getting executed but still no luck.
When I click via admin apply rule then it works.
I want to know is has magento not provided any cron job/indexer to handle this.
Thanks in Advance.
If you are creating products outside of the magento backend (using php, or soap) you may have to use the following code after you have called the $product->save() method...
public function applyActiveRulesToProduct($productId)
{
try {
$product = Mage::getModel('catalog/product') -> load($productId);
$rules = Mage::getModel('catalogrule/rule')->getCollection()->addFieldToFilter('is_active', 1);
foreach ($rules as $rule) {
$rule->applyAllRulesToProduct($product);
}
return "Applied rules to " . $productId;
} catch (Exception $e) {
return $e->getMessage();
}
}
It is code that i wrote for my own soap api extension. I could not get the rules to apply using applyToProduct(product, websiteIds) but using applyAllRulesToProduct with filters on the rules array seems to do the trick.
FYI, this code is buried inside of the CatalogRule.Rule.php core code as well, but it cannot be called directly using the rule model or product model. Who knows why they did that.

Magento 1.7 - getting cart items for a specific customer

I really need to check what products (or only if any) a specific customer has in cart.
I want to create a cron task to check if customer has opened cart older than for example 2 days and then send him a mail with reminder message. I've got an array with customers:
$collection = Mage::getModel('customer/customer')->getCollection()->addAttributeToSelect('*');
$customers = array();
foreach ($collection as $customer) {
$customers[] = $customer->toArray();
But for two days I can't find the way to check the cart items for each of them.
I tried:
foreach ($customers as $item) {
$quote = Mage::getModel('sales/quote')->loadByCustomer($item['entity_id']);
if ($quote) {
$collection = $quote->getItemsCollection(false);
}
else {
echo '<script type="text/javascript">alert("test")</script>';
}
print_r($collection);
foreach ($collection as $tmp)
echo $tmp->getQty();
}
I tried also many more but nothing work for me :/
I also don't know how to print returned items, every field in the array is protected.
Please help if You can or You only think You can ;) Google didn't help with it.
Thanks
I believe you are using Magento Community since Enterprise already has an abandoned cart reminder. If you have access to Enterprise you can find the code here: Enterprise_Reminder_Model_Rule_Condition_Cart::_prepareConditionsSql($customer, $website)
This method creates a raw sql using magento Resource read adapter and adds different conditions to verify if cart is abandoned or not you can see some of them below ( don't forget to check quote.updated_at )
$select = $this->getResource()->createSelect();
$select->from(array('quote' => $table), array(new Zend_Db_Expr(1)));
...
$select->where('quote.is_active = 1');
$select->where($this->_createCustomerFilter($customer, 'quote.customer_id'));
...
I hope this excerpt helps gives you a start, I don't know if I can post the code from Enterprise here.

Reindex Product after Cronjob in Magento - Configurable Products showing Out Of Stock

I have written a Extension that updates some custom shipping value Attributes on save for Magento 1.7. All working fine, when saving the product all is updated as it should. However I also have the need for a cronjob to update them each night in case I need to change shipping costs throught the board.
Is all working, and is updating the attribute values correctly, however on the frontend all configurable products are showing as Out of Stock, Simple Products are fine.
If I go to the admin, just click in the master product and save it without doing anything it shows back as In Stock on the frontend. Also if I go to Indexes and reindex Product Attributes it again shows as In stock on the frontend. I presume then that my cronjob needs to update the indexer on saving each product.
Looking around I used the following code, however it doesn't seem to update the product, and wondered if anyone could help. I have tried different variations around the Mage_Catalog_Model_Product and TYPE_SAVE but can't find what I am supposed to use!
$updateProduct = Mage::getModel('catalog/product')->load($_product->getId());
$updateProduct->setShippingLabel($shippData['delivery_type']);
$updateProduct->setShippingPrice($shippData['price']);
$updateProduct->setShippingNote($shippData['notes']);
try {
$updateProduct->save();
$updateProduct->setForceReindexRequired(true);
Mage::getSingleton('index/indexer')->processEntityAction(
$updateProduct,
Mage_Catalog_Model_Product::ENTITY,
Mage_Index_Model_Event::TYPE_SAVE
);
echo $updateProduct->getId()." Successfully Updated \n";
} catch(Exception $e){
echo $e->getMessage().$updateProduct->getId()."\n";
}
Update 17/5/2013 20:28
Have been playing with the code and this amendment seems to work, if it is totally useless and a stupid way of doing it please let me know
$updateProduct = Mage::getModel('catalog/product')->load($_product->getId());
$updateProduct->setShippingLabel($shippData['delivery_type']);
$updateProduct->setShippingPrice($shippData['price']);
$updateProduct->setShippingNote($shippData['notes']);
try {
$updateProduct->save();
$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product->getId());
$stockItem->setForceReindexRequired(true);
Mage::getSingleton('index/indexer')->processEntityAction(
$stockItem,
Mage_CatalogInventory_Model_Stock_Item::ENTITY,
Mage_Index_Model_Event::TYPE_SAVE
);
echo $updateProduct->getId()." Successfully Updated \n";
} catch(Exception $e){
echo $e->getMessage().$updateProduct->getId()."\n";
}
After the execution of your cron job you can update your indexer:
$indexingProcesses = Mage::getSingleton('index/indexer')->getProcessesCollection();
foreach ($indexingProcesses as $process) {
$process->reindexEverything();
}
After the execution of your cron job you can update your indexer:
$indexingProcesses = Mage::getSingleton('index/indexer')->getProcessesCollection();
foreach ($indexingProcesses as $process) {
$process->reindexEverything();
}
hello dhawal if i have to run a cron job for to re-index product on site, I have to placed the code that you have mention with this code
$updateProduct = Mage::getModel('catalog/product')->load($_product->getId());
$updateProduct->`setShippingLabel`($shippData['delivery_type']);
$updateProduct->setShippingPrice($shippData['price']);
$updateProduct->setShippingNote($shippData['notes']);
try {
$updateProduct->save();
$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product->getId());
$stockItem->setForceReindexRequired(true);
Mage::getSingleton('index/indexer')->processEntityAction(
$stockItem,
Mage_CatalogInventory_Model_Stock_Item::ENTITY,
Mage_Index_Model_Event::TYPE_SAVE
);
echo $updateProduct->getId()." Successfully Updated \n";
} catch(Exception $e){
echo $e->getMessage().$updateProduct->getId()."\n";
}
at same page ??

Magento mass-assign products to category

As the title says,i need to mass-assign products to a category and from the admin i can only edit one product at a time; i dont know why it just doesnt work to mass add them from the "category products" tab in the category page.
Thats why i need another method that's fast,like using phpMyAdmin or something alike.
Any help?
Thanks in advance!
I created a simple script to do this outside of Magento. Be sure to test this first on a single product and make sure it looks as you'd expect.
// Load Magento
require_once 'path/to/app/Mage.php';
Mage::app();
// $productIds is an array of the products you want to modify.
// Create it however you want, I did it like this...
$productsIds = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('sku', array('like' => 'something'))
->getAllIds();
// Array of category_ids to add.
$newCategories = array(20);
foreach ($productIds as $id) {
$product = Mage::getModel('catalog/product')->load($id);
$product->setCategoryIds(
array_merge($product->getCategoryIds(), $newCategories)
);
$product->save();
}
If you wish to overwrite a product's existing categories, change array_merge(...) to just $newCategories.
I would shy away from tackling this problem from the database side of things. If you do go that direction make sure and take lots of backups and do it during low usage.
The following thread on the Magento forum identifies the very same problem. One poster recommends a raw sql approach with example. Again, I would be careful - make sure you take backups.
The answer I like best from the thread (posted by Magento MVP):
Go into the category you don’t want them in, find the product list.
Click the check boxes on the products you want to remove and select
delete from the little dropdown.
Now go into the category where you
do want them, go to the product list. Select the NO dropdown so it
shows items not in the category. You might have to do a selective
search to limit stuff and do it in a couple iterations. Click the
check boxes and tell it to add stuff.
You may as well do this using the magento API
This is the script I use for mass adding products. sku.txt contains one sku per line.
<?php
$wsdlUrl = "magento-root/index.php/api/soap/?wsdl";
$proxy = new SoapClient($wsdlUrl);
$sessionId = $proxy->login('apiuser', 'apipasswd');
$listOfDiscountedSKUFile = "sku.txt";
function readinFile($filePath)
{
$fp = fopen($filePath,'r') or exit("Unable to open file!");
$dataItems = array();
while(!feof($fp))
{
$dataItems[] = trim(fgets($fp));
}
fclose($fp);
var_dump($dataItems);
return $dataItems;
}
function addToCategory($sku,$categoryId)
{
global $proxy,$sessionId;
$proxy->call($sessionId, 'category.assignProduct', array($categoryId, $sku));
}
function IsNullOrEmptyString($question){
return (!isset($question) || trim($question)==='');
}
$categoryId = 82;//e.g.
$listOfSKU = readinFile($listOfDiscountedSKUFile);
foreach($listOfSKU as $sku)
{
addToCategory($sku,$category);
}
?>
I managed to resolve the problem with the following code :
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
$x = 1171;
$y = 2000;
$categoryID = 4;
$productPosition = 0;
while($x <= $y) {
$write->query("REPLACE INTO `catalog_category_product` (`category_id`, `product_id`, `position`) VALUES ($categoryID, $x++, $productPosition)");
}
echo "The job is done";
?>
I hope the code is clear for everyone,if it's not,reply and i'll try to explain it.
#nachito : here it is.

Resources