Magento save attribute value programmatically causes SQL error - magento

Could somebody please help?
In Magento 1.5.0.1 I am trying to save an attribute value for configurable product. I added my attribute to corresponding products using Admin.
I looked at Modify automatically an attribute with magento and Programmatically change product attribute at store view level, so was able to come up with seemingly simple code which works unfortunately only sometimes - namely for configurable products without tier prices...
Here is a snippet of code:
$id = 126; # id of existing product
$product = Mage::getModel('catalog/product')->load($id);
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$product->setx_pos(123);
// tried this too, does not make a difference: $product->setData('x_pos', 123);
$product->save();
It works perfectly IF configurable product does not have products with tier prices. It can have tier products without tier prices, it this case save works. If tier products have tier prices – than I am getting the exception:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '126-1-0-5.0000-0' for key 'UNQ_CATALOG_PRODUCT_TIER_PRICE'
Trace:
#0 C:\magento\app\code\core\Mage\Eav\Model\Entity\Abstract.php(1513): Mage_Eav_Model_Entity_Abstract->walkAttributes('backend/afterSa...', Array)
#1 C:\magento\app\code\core\Mage\Catalog\Model\Resource\Eav\Mysql4\Product.php(142): Mage_Eav_Model_Entity_Abstract->_afterSave(Object(Mage_Catalog_Model_Product))
#2 C:\magento\app\code\core\Mage\Eav\Model\Entity\Abstract.php(1013): Mage_Catalog_Model_Resource_Eav_Mysql4_Product->_afterSave(Object (Mage_Catalog_Model_Product))
#3 C:\magento\app\code\core\Mage\Core\Model\Abstract.php(318): Mage_Eav_Model_Entity_Abstract->save(Object(Mage_Catalog_Model_Product))
#4 C:\magento\app\design\frontend\default\OneOffFit\template\page\data.phtml(90): Mage_Core_Model_Abstract->save()
I Googled on this error - the only refrence is unanswered question.
Why is Magento updating tier prices in this case? Am I doing anything wrong? Should I update associated products first (they have same attribute but with unset value)? Or rather what should I do right? Could anybody help please?

Move this line above the load command;
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
Or if you're not concerned with store-specific values remove it altogether.

in my case when I put following code just above the product load, the error is gone but browser is taking so long time to stop. Finally the attribute is also not updated.
Any idea what is happening to the code?
$productId = Mage::getModel('catalog/product')->getIdBySku('68366');
$product = Mage::getModel('catalog/product')->load($productId);
$product->setMyAttribute('test')
->save();

Related

How to determine if a simple product is part of a configurable product?

Im currently writing a export tool for Mage1 in order to export products from Mage1 to Mage2.
I thereby want to determine if a product in the collection is part of a configurable product.
My current collection is set up this way:
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->setPageSize(500)
->setCurPage(1)
->addAttributeToSort('sku', 'ASC')
->addAttributeToFilter('type_id', array('eq' => 'simple'))
->addAttributeToSelect('*')
->load();
First, I request only simple products right now. If I delete this line, I get every products in the shop in the collection, but In the code every product is handled like a simple product currently.
Now, following is happening:
I request the script and get my information for all simple products. In the store I use to test there are configurable products AND bundle products. I know want to know how I could determine if a product is part of a configurable or bundle article and how I could assign those "simple" products to the respective configurable products?
I generate a CSV which I can upload in Mage2 successfully, but as I already said, it only imports simple products (as desired so far).
I googled a little (https://www.google.de/search?q=get+assigned+simple+products+for+a+configurable+product&ie=utf-8&oe=utf-8&gws_rd=cr&ei=b3i8VuD6BIevswGWtbGACw) but I'm still clueless. :/ Hopefully someone here can help me with this matter.
Also, I checked this thread: Checking if a Magento product is a child of a configurable product - but I don't get what to do with the respective name. Maybe this is already the right guess?
Thanks, Max
Yes there is a way of doing so. Have a look at the model class Mage_Catalog_Model_Product_Type_Configurable, there is a function called getParentIdsByChild.
Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($productId);
It will return an empty array if no parents id's have been found.

Magento - Updating the price of a configurable product option

Magento version 1.6.1.0. I'm attempting to write some code that will dynamically update the price of a configurable product's option. My ultimate aim is to write a module that will update the price of the configurable product's options based on the price of the children products of the configurable. The attached code pulls out all the configurable products from a catalogue and displays them along with the product options & prices and the children products' name & price. I plan to work out the difference in price between the configurable and each child product and update the price appropriate option to match. So far I have been unable to work out how to update the price of a product option.
Short version: I just need a way to update the price of a configurable product's option. Do you know how to do this?
<?php
require_once './app/Mage.php';
Mage::app();
Mage::app()->setCurrentStore(1);
// load in configurable products
$productConfig = Mage::getResourceModel('catalog/product_collection')->addAttributeToFilter('type_id', 'configurable');
foreach ($productConfig as $_product)
{
// load the configurable product
$_product = Mage::getModel('catalog/product')->load($_product->getId());
echo 'Product Name';
var_dump ($_product->getName());
var_dump ($_product->getPrice());
// Collect options applicable to the configurable product
$productAttributeOptions = $_product->getTypeInstance(true)->getConfigurableAttributesAsArray($_product);
$attributeOptions = array();
foreach ($productAttributeOptions as $productAttribute)
{
var_dump($productAttribute['label']);
foreach ($productAttribute['values'] as $attribute)
{
var_dump($attribute);
}
}
// loop through the child products
echo 'Child products';
$col = Mage::getModel('catalog/product_type_configurable')->setProduct($_product)->getUsedProductCollection()->addAttributeToSelect('*')->addFilterByRequiredOptions();
foreach($col as $simple_product)
{
var_dump($simple_product->getName());
var_dump($simple_product->getPrice());
}
}
echo '~fin';
?>
Thank you!
Well, I solved this one after quite a bit of head scratching. I don't know if I did it "right" or not.
I solved it by manually running some SQL to adjust the pricing in the catalog_product_super_attribute_pricing table. If you're going to do this, you'll need a product_super_attribute_id, which you can get from the catalog_product_super_attribute table if you have a product ID.
One caveat: If a price does not exist in the backend for an option (if the option exists, but adds £0 to the product price when selected), there will not be a record for the option in the catalog_product_super_attribute_pricing table, you'll need an insert query instead of an update in that case.
I had the same issue and I started doing the same thing: write a module to update configurable product's options.
I recently published it here: Magento Configurable Auto Pricing
I tested it just with EE 1.12 but it should work also with CE and I'd be glad if anyone wants to try it and give me any feedback or even better write his own fixes and commit them :)

Update All Product Attributes programmatically

How can I set the value of a given attribute to the same value for all products (efficiently)?
By efficient I mean in one transaction, not having to loop through the entire product collection.
In the past I've used Mage_Catalog_Model_Product_Action for bulk updates on products, and it runs pretty fast
Mage::getSingleton('catalog/product_action')
->updateAttributes($productIds, array('some_attribute' => 'some_value'), 0)
But it requires you specify which product ids you're updating, creating a huge WHERE entity_id IN(...) clause in the MySQL statement. Is there a way to do this for everything?
I had same problem before, when I added 11096 product(downloadable products) in my store then client told me to add new attributes in product so i create 1 attribute (Type is Yes/No) and set to attribute set. Now my problem is how can iIedit all product and set that attribute yes or not. If I don't set then value is null so I wrote few line code.
Please check this code may be it'll helpful to you.
$ProductId = Mage::getResourceModel('catalog/product_collection') -
addAttributeToFilter('type_id', Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) -
getAllIds(); //Now create an array of attribute_code => values
$attributeData = array("my_attribute_code" =>"my_attribute_value");
//Set the store to affect. I used admin to change all default values
$storeId = 0;
//Now Update the attribute for the given products.
Mage::getSingleton('catalog/product_action') ->updateAttributes($ProductId, $attributeData, $storeId);
It was work for me.I hope it'll work for you
Amasty "Mass Product Actions" will allow you to edit product attributes in a variety of ways. This is what we use and it's going to be a life saver once we get the Configurable Products pricing tier working properly.
http://amasty.com/mass-product-actions.html

Magento 1.6, allow SKU's to be used in catalog promotion rules

I'd like to set up catalog price rules discounts based on SKU.
However when I go to 'manage attributes' and try to edit SKU to 'use in Promo Rules: yes'. I get an error saying that SKU is a system reserved atrribute.
I have already changed the SKU attribute to user_defined=1 under eav_attribute table, but the message still appears.
It seems this was possible in earlier version of magento but not 1.6?
Any help is much appreciated.
I took a guess and managed to fix my own problem.
I had set SKU attribute to user_defined=1 under eav_attribute table earlier on along with every other attribute. I had assumed setting them all to '1' would make life easier in the future. However, setting SKU user_defined to 0 via phpmyadmin, actually allowed me to make the changes I wanted.

Magento: Add a "fake" product to cart/quote

I understand how to programmatically create a product and also add to cart. I know this might sound dumb but is it is possible to generate a product on the fly and add that to the cart/quote but never actually save it in the database.
We want to create a made to order interface and I was thinking at the end it could add a bundle product with all the selections but that bundle product wouldn't actually exist in the backend.
I figured as long as you can make sure the quote and order has what it needs in terms of the product it would be ok, but obviously there is probably a lot that is tied to looking up stuff in the db on a specific sku or ID. I know that if you delete a product and then look at an order in the admin that causes issues, at least it did for this one scenario I was dealing with.
I was thinking of creating a giant bundle product that had like 6 different bundle items and each item could potentially have like 500 products and then based on what the user selects I programmatically add the bundle to cart. But then I wasn't sure if there would be a negative affect with having a gigantic bundle product like that as well.
UPDATE:
I don't think this will work, obviously there are a lot of information tied to the product in the database and we setup a test and right away we get an error for $item->getProduct(). We are moving forward with creating a giant bundle product and also the generic product with adding custom options on the fly, which Anda pointed out below. Any other suggestions will be greatly appreciated.
I'm not sure that clockworkgeek's approach is going to work. On every page load, Magento loads the items from the cart to make sure that they are still valid (in-stock, prices correct, etc), and amends the cart to reflect those values. My understanding of the system in the past has been that a product in the cart needs to have a corresponding database value to survive this process.
The "giant bundle product" approach is a pain, but in the past has been the best approach I have found. Attempting to change the values of the product (such as price or attributes) will be overridden by the cart checks, so you need a product w/ maximal flexibility, such as an overly-customized bundle product or configurable product.
Hope that helps!
Thanks,
Joe
Why not create a generic product in db and then set the product customization as custom options (additional_options) on the fly depending on the user selection. You can add custom options to the product (actually to the quote item) without having to save them in the database. I did this once for a website that sells glasses with prescription. The prescription was added as an option.
You can programmatically create Mage_Sales_Model_Quote_Items and add them to the cart. You've noticed it needs a product to match it's product ID but it needn't be a useful one. It could be a blank, disabled product, also created in code. All that's needed is a stub.
The necessary stuff for the cart is stored in the quote item - fields like name, value and quantity. Those fields are then copied directly to the order without using a product.
Mage::getModel('catalog/product')
creates a new product. you can add it to a cart, by doing something like this:
$cart = Mage::getSingleton('checkout/cart');
$product = Mage::getModel('catalog/product')
->setStoreId($storeid)
->setTypeId($type_id)
->setQty($quantyty)
->setWhatAttributYouWant($attribute);
$cart->addProduct($product);
product attributes you can find in the DB in tables that start like catalog_product_... or take an already created product, and see what attributes it has in the _data array (with debugger or just print_r($product->getData))

Resources