Magento product tier prices are deleted on product images update - magento

I have created a script to update programmatically my products pictures but my script delete all tier_prices on $product->save();
Here is my bilder update script :
foreach ($productCollection as $product) {
$formatted_sku = $product->getSku();
$config = $product->getMediaConfig();
// JPG files verification
$jpg_file = $images_folder.$formatted_sku.".".$extension[0];
if (file_exists($jpg_file) ) {
$fileurl = $config->getMediaUrl($jpg_file);
$product->addImageToMediaGallery($jpg_file, $visibility, false, false);
$product->save();
}
}
How can I avoid the update of my tier_prices ?
Thanks a lot.

For those of you that are still running into this issue, there is a simple fix to try. It looks like the tierprice data is not read by the default getModel for the product. To fix this, just call the product's getTierPrice method to load it.
$tp=$product->getTierPrice();
You don't have to do anything else, just load it. Then when you save the product, the tiered pricing data is saved.

I run into the same problem. I finally work it out in a very weird way, but it definitely worked. You just need to create a "fake" tierprice:
$tierPrices = array(
'website_id' => 0,
'cust_group' => 2,
'price_qty' => 3,
'price' => 10
);
(note that there are no [ ])
Then add it (it won't add anything actually), but you need to do this:
$product->setTierPrice($tierPrices);
And finally save the product:
$product->save();
It will save your product without deleting your old tier prices. Hope it helps!!

How do you created that $productCollection? Maybe product was not populated with needed data (tier_prices) so save() persist product without that data. Try to add some attributes to select with addAttributeToSelect()

The comments of others on this post helped to lead me to a solution that worked. For me, simply setting the tier price to false is what was needed to prevent it from being overwritten/modified.
$product->setTierPrice(false);
I personally prefer this option over some of the other solutions as it's clean, simple, doesn't set fake values, and it works. To those points, I would have preferred it if the solution presented by GregC would have worked as it's simply loading the tier price, but in my testing that did not work as expected - the tier price was still deleted.
Here would be the modified version of the code from the OP.
foreach ($productCollection as $product) {
$formatted_sku = $product->getSku();
$config = $product->getMediaConfig();
// JPG files verification
$jpg_file = $images_folder.$formatted_sku.".".$extension[0];
if (file_exists($jpg_file) ) {
$fileurl = $config->getMediaUrl($jpg_file);
$product->addImageToMediaGallery($jpg_file, $visibility, false, false);
$product->setTierPrice(false); // set tier price to false to prevent it from being overwritten
$product->save();
}
}
This code was tested and used with Magento EE 1.14.12.0

Related

retrieve all products and their respective attributes using getAdditionalData in magento

I've been looking all over the web on how I would go about retrieving filtered products and then get their respective attributes using getAdditionalData. Here's what I do:
$_collectionProduct=Mage::getModel('catalog/product')
->getCollection()
->addAttributeToFilter('status', array('eq' =>1))
->addAttributeToFilter('attribute_set_id',9)
->addAttributeToSelect('*');
This works and retrieves all the filtered products. However, now I need their attributes so I am looping
foreach ($_collectionProduct as $products) {
$_additional = $product->getAdditionalData();
}
What happens is that $_additional returns NULL.
Another scenario I have tried is the following
foreach ($_collectionProduct as $_products) {
$product= Mage::getModel("catalog/product")->load($_product->getId());
$_additional = $product->getAdditionalData();
}
This example still displays NULL. Would really appreciate if somebody would have a solution to the dilemma. Thanks.
I actually figured out why it wasn't working. It appears that getAdditionalData() is not really attached to a specific product. The product view is calling this function from core file. The actual function I needed to use was getAttributes().

Magento add product for different storeview in one step

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.

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.

Magento Programmatically Edit Order Payment

I need to make a change of payment method to an order after it is placed. I have the order ID ($orderID), the order object ($order), a proper payment object, etc.
$service->retrievePaymentType() Returns the payment in the form of Mage_Sales_Model_Order_Payment
All of this happens in an extension of Mage_Checkout_Model_Type_Onepage
Does anybody know how I would go about doing this?
$order = Mage::getModel('sales/order')->load($orderID);
$service = Mage::getModel('sales/service_quote', $this->getQuote());
// Update Saved Order Payment Method
// $order->getPaymentsCollection()->clear();
$order->setPayment($service->retrievePaymentType());
$order->getPaymentsCollection()->save();
$order->save();
Thanks in advance!
Unfortunately, I had to do a direct SQL query, which is not Magento spec, but it gets the job done. If someone want's the code, leave me a comment, and I will dig it up.
Thanks though!
EDIT:
I managed to in fact get this working with Magento API:
// The payment type I want to change the target order to
$service = Mage::getModel('sales/service_quote', $this->getQuote());
$payment = $service->retrievePaymentType();
$paymentData = $payment->getData();
$oldPayment = $order->getAllPayments();
$oldPayment = $oldPayment[0];
foreach ($paymentData as $n => $v) {
$oldPayment->setData($n,$v);
}
It is a little bit hackish, but pretty effective.

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