Magento: Multiple Currency Conversion on Custom Options Prices - magento

I have several websites using different currencies on each store view. The base currency (default) is set to GBP.
If I add a fixed price to a custom option the currency is converted according to store currency which is fine.
The problem starts when I want to update other values afterwards as it keeps converting the price.
For example, Let’s say I have a product on Store View 1 with a custom option that adds 100 GBP for a blue color option.
The same product will appear on Store View 2 with a custom option that adds 120 EUR for a blue color option, according to the correct currency conversion.
If I change any value on Store View 2, for example, changing the name of the product or adding an image, a change that doesn’t involve the price or the custom options, and than I save the change, it will continue to convert the price of the custom option.
If it was 120 EUR it will refer to it as if it is a new value of 120 GBP and convert it to 143.5 EUR and so on.
If I’ll click save again it will convert it again to 171.5 EUR and so on.
This happens because Magento refers to the custom options added price as a new value that needs to be converted.
Any idea how can I solve this as every time I change a value of a product it changes the custom options price?

I know that this is quite old question, but this bug still occurs (even in Magento 1.9) so maybe my answer will help somebody.
You have to overwrite Mage_Catalog_Model_Resource_Product_Option_Value class.
First add this method:
protected function checkIfPriceHasNotBeenChanged($object, $storeId)
{
$newPrice = (float)sprintf('%F', $object->getPrice());
$priceTable = $this->getTable('catalog/product_option_type_price');
$select = $this->_getReadAdapter()->select()
->from($priceTable, 'price')
->where('option_type_id = ?', (int)$object->getId())
->where('store_id = ?', $storeId);
$oldPrice = $this->_getReadAdapter()->fetchOne($select);
return $newPrice == $oldPrice;
}
Then use it in _saveValuePrices method:
if ($object->getStoreId() != '0' && $scope == Mage_Core_Model_Store::PRICE_SCOPE_WEBSITE
&& !$object->getData('scope', 'price')) {
$baseCurrency = Mage::app()->getBaseCurrencyCode();
$storeIds = Mage::app()->getStore($object->getStoreId())
->getWebsite()
->getStoreIds();
if (is_array($storeIds)) {
foreach ($storeIds as $storeId) {
if ($priceType == 'fixed') {
if ($this->checkIfPriceHasNotBeenChanged($object, $storeId)) {
continue;
}
(...)

Related

Magento - Get Discount Type in Cart

I need to be able to get the discount type applied in the cart.
I can get the discount amount like so:
$cart = Mage::getModel('checkout/cart')->getQuote();
$totals = $cart->getTotals();
$discount = $totals["discount"]->getValue();
How can i check what type of discount it is - whether it is a percentage or fixed amount off?
Take a look at applied_rule_ids in sales_flat_quote and sales_flat_quote_item
You could try something like
//if the item has not had a rule applied to it skip it
if($item->getAppliedRuleIds() == '')continue;
/*
* I cant remember in the database they might be comma separated or space if multiple rules were applied
* the getAppliedRuleIds() function is the one you want
*/
foreach(explode(",",$item->getAppliedRuleIds()) as $ruleID){
//Load the rule object
$rule = Mage::getModel('catalogrule/rule')->load($ruleID);
// Throw out some information like the rule name what product it was applied to
echo "<p>".$item->getSku()." had rule ".$rule->getName()."(".$item->getAppliedRuleIds().") applied </p>";
}
See Magento - get price rules from order

What is Difference between $_product->setData() & $_product->save()?

I have found some code to update product details
$_product->setData('manage_stock', 1);
$_product->setData('qty', $newQty);
$_product->save();
What is Difference between $_product->setData() & $_product->save() here ?
$_product->setData('qty', 10); is assign the value to the column(qty,etc).
$_product->save(); is save the that value to the DB.
I will show you an example. Suppose we have a product A with quantity 1 by default. Now we need to programmatically change the quatity of the product to 5. So for that we have wrote the following code.
Without save()
$_product = Mage::Registry('current_product');
$qty_before = $_product->getQty();
$_product->setData('qty', 5);
$qty_after = $_product->getQty();
echo "Quantity Available before setting the quantity property =".$qty_before."<br>";
echo "Quantity Available after setting the quantity property =".$qty_after."<br>";
Now it will show the following result
Quantity Available before setting the quantity property = 1.
Quantity Available after setting the quantity property = 5.
Now we have commented out the third line of code and then refreshed our page. Now our result will be look like this.
Quantity Available before setting the quantity property = 1.
Quantity Available after setting the quantity property = 5.
With save()
$_product = Mage::Registry('current_product');
$qty_before = $_product->getQty();
$_product->setData('qty', 5);
$qty_after = $_product->getQty();
$_product->save();
echo "Quantity Available before setting the quantity property =".$qty_before."<br>";
echo "Quantity Available after setting the quantity property =".$qty_after."<br>";
Now it will show the following result
Quantity Available before setting the quantity property = 1.
Quantity Available after setting the quantity property = 5.
Now, again we have commented out the third line of code and then refreshed our page. Now our result will be look like this.
Quantity Available before setting the quantity property = 5.
Quantity Available after setting the quantity property = 5.
So what is the difference? If we are setting a property means, it will update that field value for that time. But actually the value is not saving in database. In order to save the data to the database, we have to use save() method. Otherwise your changes that you made by setData() will be ignored by Magento.
If you load a product and then just use setData for any attribute, the product will show that value temporarily on that page only.
but if you use. $_product->save(); after the setData that value will be permanently saved in database and can be displayed on other pages as well.

Magento Buy X Get Y free Price rules

I have added new rule in Magneto for buying x product and getting y free . I have added a configurable product with multiple simple products . This rule works fine if I buy two of simple products with same sku values. What I want is that if user buys two simple products with different sku they should get second free .
How can i achieve this ?
This cannot be done with the default implementation of cart rules. You need to create new module and add your own type of rule to the list. I have made once such a module, in the following manner:
1) I add my own option to action dropdown. Luckily there is an event adminhtml_block_salesrule_actions_prepareform where you can hook. I used something like this
$form = $observer->getEvent()->getForm();
$options = $form->getElement('simple_action')->getValues();
$options[] = array(
'value' => self::BUY_ANY_X_GET_Y_ACTION,
'label' => Mage::helper('mymodule')->__('Extended Buy X get Y free (search all cart, discount amount is Y)'),
);
$form->getElement('simple_action')->setValues($options);
2) Then I hook into salesrule_validator_process where I checked whether cart items match the rule.
This was a little bit tricky as this validator is run for each cart item so you have to count how many times it was called and which items you have checked. I used conditions tab to prepare rules that says which X items have to be bought in order to get Y items according to conditions in actions tab.
With the first run of the validator you iterate over all cart collection and divides all products in two groups: one contains items that met criteria set by conditions tab, the second one met the criteria set by actions tab. In other words you form two arrays that contains items for X and items for Y.
foreach($quote->getItemsCollection() as $item) {
if (!$item->hasParentItemId()) {
if ($rule->getActions()->validate($item)) {
$ruleItems['y'][] = $item;
}
foreach($rule->getConditions()->getConditions() as $condition) {
foreach($condition->getConditions() as $check) {
if ($check->validate($item)) {
$ruleItems['x'][] = $item;
}
}
}
}
}
You calculate how many X's are there and how many Y's products will get discount. The when the event is called for each item you check if the item is in Y array and if there is enough discounts left for that item. If so you need to set discount amount and base discount amount calculated as item_qty * price and item_qty * base_price respectively. You need to set those values on result object that is in data passed to the observer method like:
$item = $observer->getEvent()->getItem();
$result = $observer->getEvent()->getResult();
$result->setDiscountAmount($item->getQty * $item->getPrice());
$result->setBaseDiscountAmount($item->getQty * $item->getBasePrice());

Magento: Import product prices for an additional website?

I have a Magento installation, with two websites on it:
Retail (default)
Trade
Currently all the prices have been imported as default and so the prices are set the same on both websites. I now need to import the lower prices just for the trade website.
I know this can be done manually per product, but how do I go about importing these prices (with their SKU's so that they only apply to the trade store?
Any help much appreciated!
I suggest doing a Product Export first so you can see all of the columns that are used. Locate a SKU from your Trade store and see what the values are for that column.
You should see a column called _product_websites. In my installation, this column has "base" in it. On yours it will probably say "base" and "trade" (whatever you specified for your website code). You can sort by this column in Excel or other spreadsheet software and remove all of the rows that just have "base" in it so you're left with "trade". Now you can update your prices, save the sheet and re-import your file.
hth
You can simply follow the following Magento blog post:
http://www.blog.magepsycho.com/updating-product-prices-in-magento-in-easier-faster-way/
Just you need to add store_id filter in following method as:
function _updatePrices($data){
    $connection     = _getConnection('core_write');
    $sku            = $data[0];
    $newPrice       = $data[1];
$storeId = $data[2];
    $productId      = _getIdFromSku($sku);
    $attributeId    = _getAttributeId();
 
    $sql = "UPDATE " . _getTableName('catalog_product_entity_decimal') . " cped
                SET  cped.value = ?
            WHERE  cped.attribute_id = ?
            AND cped.entity_id = ?
AND store_id = ?";
    $connection->query($sql, array($newPrice, $attributeId, $productId, $storeId));
}
Of course you need to use third column of prices.csv for store_id.
Let me know if that helps.

Magento rounds up the custom product price

I'm setting a custom price depending on each customer. Using a webservice I receive the specific price for each customer in the format: XX,DD
When I use the function setprice in order to set the new price for the product:
$product->setFinalPrice($price);
Magento rounds up the price and, for example, if the $price is 38,50, then it sets the product price to 38. I've tried changing the ',' for '.' with str_replace, but in this case, it seems it can't set up the price.
How can I tell Magento to use the decimals as well?
Thanks
First you should convert your price to decimal number:
$value="38,50";
$amount = Zend_Locale_Format::getNumber($value,array('locale'=>'nl_NL'));
// or you can use str_replace
In Magento products has two types of standard price:
$product->getPrice();
$product->getSpecialPrice();
finalPrice - it is not actually product value, it will be calculated by Magento based on price, special_price, tier price and so on. You should set price value and save the product:
$value = "38,50"; //this decimalformat is used in nl_Nl locale
$amount = Zend_Locale_Format::getNumber($value,array('locale'=>'nl_NL'));
$amount = Mage::app()->getStore()->roundPrice($amount); //round price based on Magento logic
$product->setPrice($amount); //price - is actual value of product
// some extra code here
$product->save();
I'll throw in that you can use:
echo number_format($_product->getPrice(), 2)
It will give you a couple of decimal places.
I am guessing you do not want the price to round up. If that is the case then your solution depends on the version of PHP you are using.
PHP 5.3 you can simply use the round function to round it down like so:
round($price, 2, PHP_ROUND_HALF_DOWN);
If you are using PHP 5.2 you do not have the luxary of the PHP_ROUND_HALF_DOWN so you have to put the following function in somewhere (a helper makes the most sense to me) and call it:
floor($line_item_price * 100) / 100;
What this does is first multiply the value with 100 and then floor the value. This gives you a rounded down value with the precision of 2. Then divide by 100 to get the correct value.
The number 100 comes from the power(10, desired precision)
I hope you are on PHP 5.3. I did not enjoy having to do the PHP 5.2 solution very much.
To round up a price in magento you need overwrite a directory/currency model method convert.
Mage_Directory_Model_Currency::convert()
here you will find like this
return $price*$rate
and need to set like this
return round($price*$rate);

Resources