Posting in the Magento forums has been disabled pending the implementation of a new and improved forum solution which should better serve the community.

For new questions please post at magento.stackexchange.com, the community-run support site for the Magento community. We will be providing updates on the new forum solution soon. For questions or concerns please email community@magento.com.

Magento Forum

Page 1 of 2
Save product error, blank page. Price rules not updated…
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

Do you have problems with:
- Reloading page after saving a product/catalog, getting a blank page
- Price rules are not properly applied to new products

Do you use many catalog rules for a large amount of products/customer groups?

Do you have a large number of rows in the catalogrule_product table?

Keep on reading the following in you servers error log?

Fatal error: Allowed memory size of xxxxxxxxx bytes exhausted (tried to allocate 128 bytes) in lib/Zend/Db/Statement/Pdo.php on line 294

Came here after reading bug report?
Issue 6973

Looking for a fix for all of these issues?

If you think these questions above apply to you, please read on.

-----------------------------------------------------------------------------------------------------

Starting point
First off my situation and the numbers that I’m using. I’m running a large 5000 product webshop with around 20 different customer groups. Each group can have more than one discount percentage (10 available). All these numbers give me nicely filled catalogrule_product (~115k rows) and catalogrule_product_price (~278k rows) tables. The price display works like a charm. Magento is version 1.3.0 with quite a few extensions, the most relevant is http://www.magentocommerce.com/extension/596/simple-configurable-products

Problems
Saving products error
When I’m adding or modifying a product I will nicely see the ‘Please wait’ while Magento is saving it, after waiting for quite a while for a page reload I would always end up with a blank page (with URL, e.g. index.php/admin/catalog_product/save/id/5011/key/*****/), without any error message. It had just died without giving any clue why. Happy as I was that it saved the product I clicked the back button to get my menu’s again and continued managing the shop leaving this error for what it was assuming it would fade with the next upgrade.

Price rules not applied for new products
Due to a quite exotic price display setup and some recent changes to it I have been testing many possible variations and during these tests I noticed that for some products it would not show the price it should have according to the price rules. After some digging I discovered that all of these products were added after launching the webshop. Inserting a few new products showed that the problem was persistent, had nothing to do with inventory management (turned off in my case) but with the price rules not being fully applied. Only after firstly adding a product, secondly manually opening and saving all catalog price rules (not making any changes) and finally applying all price rules the product would show the correct price, weird!

Time for some deep digging so I got my shovel, spade and a hand grenade, hey ho, hey ho....

Digging
Extensions
Since I’m using quite some extensions and tweaks to the extensions my attention was first aimed at them. But after some hours I couldn’t find anything on the forum or in the source code. They were all working as they should, perfectly fine (thanks guys!).

Retracing steps
Since I knew that saving the product went fine and refreshing the page failed I focussed on the part between those. When the system is done saving a product it will issue a ‘catalog_product_save_after’ event. This event is then picked up by the following core observers running the specified functions:
- catalog/product_flat_observer => catalogProductSaveAfter
- catalogindex/observer => processAfterSaveEvent
- cataloginventory/observer => saveInventoryData
- catalogrule/observer => applyAllRulesOnProduct
- catalogsearch/full_text_observer => refreshProductIndex
- googlebase/observer => saveProductItem
- googleoptimizer/observer => saveProductGoogleOptimizerScripts

The order in which they are run is unknown to me.

applyAllRulesOnProduct
Since I found that manually reprocessing all the catalog rules helped in displaying the price properly I dug into the catalogrule observer. When saving a single product, applyAllRulesOnProduct is called and we end up calling these functions (in order of execution):
- applyAllRulesOnProduct @CatalogRule/Model/Observer.php
- applyToProduct @CatalogRule/Model/Rule.php
- applyToProduct @CatalogRule/Model/Mysql4/Rule.php
- applyAllRulesForDateRange @CatalogRule/Model/Mysql4/Rule.php

The last function never returns after dispatching the ‘catalogrule_after_apply’ event. Searching the source code shows there are three functions reacting to this event:
- catalogindex/observer => processPriceRuleApplication
- sales/observer => markQuotesRecollectOnCatalogRules
- weee/observer => updateDiscountPercents

The first two are run without any problems, the third crashes however....... BINGO!

updateDiscountPercents
It seems this function, located inWeee/Model/Mysql4/Tax.php, tries to do a fetchAll on my 115k catalogrule_product rows and runs out of memory along the way, making a dead stop without any error messages, apart from the apache log file (Allowed memory size of 128MB exhausted).

Consequences
Incomplete processing
Due to the dead stop, a number of functions will not run completely or not at all. With certainty I can say that the price rules are only applied to the first customer group of the first website, not any others since this function issues the ‘catalogrule_safe_after’ event and then dies quietly. It could be (not checked) that catalog-, search- and inventory-indexes are probably not processed properly and any events coming from any of these functions will not be run either. Depending on your setup this might have big consequences.

Performance
Even if you would not have my problem that the system does not handle a product save completely there are some performance implications. This is due to the way the updateDiscountPercents works. First it empties out the entire ‘weee_discount’ table and then starts filling it again. It does this for ALL the products in ‘catalogrule_product’ and it happens for each customer group where price rules are applied. In my case it would run the entire delete/fill sequence if 115k rows about 20 times (now that I think of it I’m glad it actually doesn’t). When you only have a small number of ‘catalogrule_product’ rows the impact is not that large but when that number is a bit bigger it will eat away time and resources.

Furthermore, if you have your MySQL bin-log turned on, be prepared to see these files GROW as you edit your products.

Version info
I’m running Magento 1.3.0 and to make sure that this thing wasn’t fixed in any of the other releases since I’ve also checked 1.3.2. The code in the WEEE module is the same as under 1.3.0, including xml files. In addition, the called events haven’t changed either.

-----------------------------------------------------------------------------------------------------

Your eyes are probably 16:10 squares by now, like mine, so I’ll put my possible workarounds in the next post below.

A bit further down I’ve added notes on applying my workaround to my production environment, I had a small issue with saving the first product after applying the workaround.

Edit: Added the exact fatal error message I keep on getting. (all the way at the top of this post)

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

Workarounds
Since the problem has quite a big impact on the webshop I have been working on a few workaround options. I must add that I will use the first one in my case, the other two are merely two alternative approaches. Please keep in mind that using any of the workarounds could cause undesired effects so please play with it in a non-production environment, after backing up all of your files and database of course.

The easiest way to use the workaround is to copy the

app/code/core/Mage/Weee/Model/Mysql4/Tax.php

into

app/code/local/Mage/Weee/Model/Mysql4/Tax.php

and make your changes there. If I’m not mistaken Magento should now use this file instead of the original, no configuration changes needed.

I’ve attached the workarounds at the bottom (all files are put under local).

Workaround 1
Since I am not using the WEEE facilities at all I created a simple workaround. Replace the updateDiscountPercents function with the following:

@ Weee/Model/Mysql4/Tax.php:

public function updateDiscountPercents()
    
{
        
//Ignore this function
        
return;
    
}

This is the one I’ve tested the effects with and it works well in my case and will just ignore the weee update.

Workaround 2
This one needs some more changes to more files but should let you keep on using the weee discounts as long as the function is called with ONE product at a time, else it will probably revert to its old self. It will use the product in the $observer object to only update the product that actually changed.

@ Weee/Model/Mysql4/Tax.php:

public function updateDiscountPercents(Varien_Event_Observer $observer null)
    
{
          $productId 
null;
          
//Is there a product in the observer?
        
if(!is_null($observer) && is_callable(array($observer->getEvent(),'getProduct'))){
            $product 
$observer->getEvent()->getProduct();
            
$productId $product->getId();
            
            
//Only delete the rows of this product
            
$where $this->_getWriteAdapter()->quoteInto('entity_id = ?'$productId);             
            
$this->_getWriteAdapter()->delete($this->getTable('weee/discount'),$where);
        
}
        else{
            
//Empty the entire weee_discount table  
            
$this->_getWriteAdapter()->delete($this->getTable('weee/discount'));
        
}
        $now 
strtotime(now());
        
$select $this->_getReadAdapter()->select();

        
$select->from(array('data'=>$this->getTable('catalogrule/rule_product')))
            ->
where('(from_time <= ? OR from_time = 0)'$now)
            ->
where('(to_time >= ? OR to_time = 0)'$now)
            ->
order(array('data.website_id''data.customer_group_id''data.product_id''data.sort_order'));
        
        
//Limit the fetching of rows to the product_id, if available
        
if(!is_null($productId)){
            $select
->where('product_id = ?'$productId);
        
}
        
        
//Code below is the same as original
           
$data $this->_getReadAdapter()->fetchAll($select);
        
$productData = array();
        
$stops = array();

        foreach (
$data as $row{
            $key 
"{$row['product_id']}-{$row['website_id']}-{$row['customer_group_id']}";
            if (isset(
$stops[$key]) && $stops[$key]{
                
continue;
            
}

            
if ($row['action_operator'== 'by_percent'{
                
if (isset($productData[$key])) {
                    $productData[$key][
'value'+= $productData[$key]['value']/100*$row['action_amount'];
                
else {
                    $productData[$key] 
= array(
                        
'entity_id'         => $row['product_id'],
                        
'customer_group_id' => $row['customer_group_id'],
                        
'website_id'        => $row['website_id'],
                        
'value'             => 100-max(0min(100$row['action_amount'])),
                    );
                
}                
            }

            
if ($row['action_stop']{
                $stops[$key] 
true;
            
}
        }
        
foreach ($productData as $product{
            $this
->_getWriteAdapter()->insert($this->getTable('weee/discount'), $product);
        
}
    }

@Weee/Model/Observer.php:

public function updateDiscountPercents(Varien_Event_Observer $observer null)
    
{
        
//Give the observer along
        
Mage::getModel('weee/tax')->updateDiscountPercents($observer);
        return 
$this;
    
}

@Weee/Model/Tax.php:

public function updateDiscountPercents(Varien_Event_Observer $observer null)
    
{
        
//Give the observer along
        
$this->getResource()->updateDiscountPercents($observer);
        return 
$this;
    
}

Workaround 3
This workaround still does the original fetchAll on the catalogrule_product table but limits it by getting only the specified number of rows (1000) at a time until it hits the last one. The product data to be inserted is kept outside the while loop, this might also create memory problems because all new rows are put here before inserting them into the database. With my 115k rows it still hung. Putting the last foreach inside the while could make a difference, haven’t tried it.

@ Weee/Model/Mysql4/Tax.php:

public function updateDiscountPercents(Varien_Event_Observer $observer null)
    
{
           $this
->_getWriteAdapter()->delete($this->getTable('weee/discount'));
        
           
$now strtotime(now());
        
$select $this->_getReadAdapter()->select();

        
$select->from(array('data'=>$this->getTable('catalogrule/rule_product')))
            ->
where('(from_time <= ? OR from_time = 0)'$now)
            ->
where('(to_time >= ? OR to_time = 0)'$now)
            ->
order(array('data.website_id''data.customer_group_id''data.product_id''data.sort_order'));
        
        
//Fetch only a limited amount of rows and continue doing this until we've had all rows
        
$limit 1000;
        
$offset 0;
        
        
//By placing productData outside of the while loop it could also cause a memory error
        //Because we will try to put all new rows in there before inserting it into the database
        
$productData = array();
        
$stops = array();
        
        while(
true){
            
            
//Use the original select statement and add the limits
            
$selectPart $select->limit($limit,$offset);    
            
            
$data = array();            
            
$data $this->_getReadAdapter()->fetchAll($selectPart);
            if(
count($data) === FALSE || !count($data)){
                
break;                
            
}
               $offset 
+= $limit;

               foreach (
$data as $row{
                $key 
"{$row['product_id']}-{$row['website_id']}-{$row['customer_group_id']}";
                if (isset(
$stops[$key]) && $stops[$key]{
                    
continue;
                
}
    
                
if ($row['action_operator'== 'by_percent'{
                    
if (isset($productData[$key])) {
                        $productData[$key][
'value'+= $productData[$key]['value']/100*$row['action_amount'];
                    

                    
else {
                    $productData[$key] 
= array(
                        
'entity_id'         => $row['product_id'],
                        
'customer_group_id' => $row['customer_group_id'],
                            
'website_id'        => $row['website_id'],
                            
'value'             => 100-max(0min(100$row['action_amount'])),
                        );
                    
}                
                }
        
                
if ($row['action_stop']{
                    $stops[$key] 
true;
                
}
            }
        }
            
        
//We have all the info we need so insert it into the db
        
foreach ($productData as $product{
            $this
->_getWriteAdapter()->insert($this->getTable('weee/discount'), $product);
        
}
    }

@Weee/Model/Observer.php: same code as workaround 2
@Weee/Model/Tax.php: same code as workaround 2

File Attachments
workaround 1.zip  (File Size: 1KB - Downloads: 223)
workaround 2.zip  (File Size: 7KB - Downloads: 204)
workaround 3.zip  (File Size: 7KB - Downloads: 207)
 
Magento Community Magento Community
Magento Community
Magento Community
 
pablosecca
Jr. Member
 
Total Posts:  3
Joined:  2009-07-23
 

I’m getting this problem as well. Thank you for your work on this issue and I’ll try to apply the workarounds that you described. I’ll post back if it’s effective for me.

 
Magento Community Magento Community
Magento Community
Magento Community
 
pablosecca
Jr. Member
 
Total Posts:  3
Joined:  2009-07-23
 

Unfortunately, this bizarre bug keeps affecting my implementation of Magento. Needless to say the ability to add products is an essential function of any online e-commerce application. Thus this does kind of bring our development to a halt.

I am able to save on new products, which will send me back to the product management page however if I click Save and Continue Edit or if I save a product and then try to go back to edit the product that’s when I get a blank page.

Here are some entries from my PHP log:

[23-Jul-2009 18:03:45] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 1966080 bytes) in [redacted]/lib/Zend/Date.php on line 2484
[23-Jul-2009 18:03:48] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 1966080 bytes) in [redacted]/lib/Zend/Date.php on line 2484
[23-Jul-2009 18:04:18] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 74 bytes) in [redacted]/lib/Zend/Locale/Data.php on line 303
[23-Jul-2009 18:05:27] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 1966080 bytes) in [redacted]/lib/Zend/Date.php on line 2484
[23-Jul-2009 18:06:05] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 74 bytes) in [redacted]/lib/Zend/Locale/Data.php on line 303
[23-Jul-2009 18:07:08] PHP Fatal error:  Allowed memory size of 33554432 bytes exhausted (tried to allocate 7680 bytes) in [redacted]/app/code/core/Mage/Eav/Model/Mysql4/Entity/Attribute/Set/Collection.php on line 41

Is this the same error you’re experiencing?

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

It seems your problem has a different origin than mine. My errors are always happening in ‘lib/Zend/Db/Statement/Pdo.php on line 294’ which is in the fetchAll statement. Yours seems to be originating elsewhere, from different places. 32MB seems a bit on the tight side. During development I noticed that my install was running stable at around 48MB when working in the backend, however more is always better. If you would want to get an idea of how much Magento is actually using, try turning the debug profiler on @ Configuration ->Developer. It’ll display the diagnostics at the bottom of every page.

 
Magento Community Magento Community
Magento Community
Magento Community
 
pablosecca
Jr. Member
 
Total Posts:  3
Joined:  2009-07-23
 

I think this is a case of different cause, same effect. In any event thank you for pointing out that it was some kind of memory error.

To resolve the issue my host (Rackspace) advised me to edit my htaccess file and add the line

php_value memory_limit 128M

to give my implementation enough memory. For some reason by default my host has it set to a very low level. Go figure.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

Workaround application notes
When I applied workaround 1 to my production environment and re-saved an existing product, it took almost three hours, yes 3 x 60 minutes, to complete the process. This was just a bit longer than the 30 seconds I got used to on my development machine. Curious and scared (what if I had to wait that long for every product....) at the same time I started digging (again).

First thing I did when it took too long was look at the server processes, MySQL was consuming quite a lot of CPU time. After looking at my tables I noticed that ‘catalogrule_affected_product’ was extremely large with over 6,5 million rows. This large number must have accumulated over time since this table should be emptied out after each product save when coming back from the dispatched ‘catalog_product_save_after’ event. Obviously it had never been cleared before.

Taking a peek at the code shows that Magento passes the affected_product table along as the collection of products affected when dispatching the ‘catalog_product_save_after’ event. Because the system does not crash anymore CatalogIndex can actually start re-indexing and finds itself working on a joined collection of products and affected products, effectively re-indexing all rows in ‘catalogrule_affected_product’, which are mostly double product_id’s. Please check your ‘catalogrule_affected_product’ table before applying the patch or be prepared to wait, long…

In my case I only had a problem with about 30 products, added after launch of the site. I had to open and re-save every product individually, mass product editing did not work for this. With a now empty affected products table the saving went amazingly smooth.

It seems I have everything in proper working order again :D

 
Magento Community Magento Community
Magento Community
Magento Community
 
james244
Jr. Member
 
Total Posts:  2
Joined:  2009-05-14
 

I am getting this same error:
...Pdo.php on line 294
It happens when I try to do a catalog rule update.
We have a fairly large product catalog.

The WEEE tax solution did not work for us.  We still get the error. 
Anything else you know of that we could try?

Thanks a million for your time.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

Hi James,

Thanks for your question. Interesting to see the error happens at another point besides the WEEE taxes. But judging the nature of the error you could expect it to appear in more places, especially when having a large product base.

After some quick searching I found that a catalogrule update has two events bound to it:
- catalogrule_before_apply
- catalogrule_after_apply

Looking at the xml files there are two observers connected to these events other than the weee->updateDiscountPrices, these are:
- catalogindex->processPriceRuleApplication (@CatalogIndex/Model/Observer.php)
- sales->markQuotesRecollectOnCatalogRules (@Sales/Model/Mysql4/Quote.php)

What I would suggest is that you create a copy of your Magento install and database and open up your favourite editor and add Magento log statements to the beginning and end of the various functions to see where the script crashes, for example “Mage::log(’start: mark quotes’);”.  Make sure Magento is logging to its own log file. If you run into for or foreach loops it might be good to keep track of printing the current memory usage of the script every 10/100/1000 loops “Mage::log(memory_get_usage(true));” You should be able to find the point of crashing this way.

I hope this points you in the right direction. Please ask if there is something unclear and please let me know if you’ve found where it crashes. What version are you using by the way?

Please also keep in mind that a third party extension could have functions running after either of the events, this might also cause the crash.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Dannyz1984
Sr. Member
 
Avatar
Total Posts:  153
Joined:  2009-04-12
 

thank you for these workarounds

by any chance could these problems arise from a corrupted database?

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

Hi pharmokan,

I’m not sure if a corrupted database would throw this error. (Luckily) I don’t have any experience with a corrupt database. In this case the error is caused by a fetchAll fetching too many rows causing the script to run out of memory. My guess would be that, if you have a corrupted database, the error would occur BEFORE you run out of memory. So I would assume this error is not caused by a corrupted database....

 
Magento Community Magento Community
Magento Community
Magento Community
 
7thSENSE Magento E-Commerce Systeme
Jr. Member
 
Avatar
Total Posts:  27
Joined:  2008-11-18
Stuttgart, München, Reutlingen
 

Hi Finn,

nice workarounds. My Problem is a little bit ... let me say ... huger… wink
We implemented a way to grant cutomer based catalog discounts. With about 7.000 Customers and 1.000 products that damned catalogrule_product_price table grew and grew. Now we have about 1.200.000 rows in this table and with the indexes the table size is about 250MB.

Does your workarounds also work for this dimensions? How is it possible to get Magento running again? The frontend performance is fairly ok, but if you want to save a product in the backend, mostly you get a timout. Do you think it would help if I put the database on another server?

Regards,
Sebastian

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

Hi Sebastian,

Thanks for the specific additional info via PM, it helped in getting a better understanding of the whole situation. As usual it takes some looping around to actually get to the core of a problem, I think I’ve found out why WEEE is giving us trouble!

Workaround 1 would probably be the easiest, I’ve implemented it as a quick fix but it completely ignores WEEE.... The other two and your own workaround would probably work well in your situation too, but.... I think we’ve both been missing something here.

If I’m not mistaken weee is some kind of additional tax, next to regular VAT, that you need to charge your customers. It is something European and is applied to all kinds of electronics (http://ec.europa.eu/environment/waste/weee_index.htm). See http://www.magentocommerce.com/wiki/gestion_de_la_taxe_deee for setup instructions (try Google Translate if your French is a bit rusty). In the Magento backend it is called FIXED product taxes.... I’m probably missing the point but if it is a fixed taxes why have a ‘weee_discount’ table?

Anyway back to our problem.

What does the original updateDiscountPercents actually do? It updates the ‘weee_discount’ table. This table contains a percentage of discount on the weee taxes which is based on a summation of the percentual discounts of products in the catalog price rules.

Now if we save a product, at some point along the way applyAllRulesOnProduct is called and it makes sense so far. This function dispatches a ‘catalogrule_after_apply’ event which is still understandable as we have just applied price rules to a product. Because of this event updateDiscountPercents is called and hey, wait, that’s our trouble maker.
If we are saving a new product updateDiscountPercents should be run as ‘weee_discount’ has no record(s) for this product. HOWEVER, when saving an existing product the function runs in vain! Why? Because it doesn’t use any of the existing products’ attributes in this function. It doesn’t look at the new price you set or at the new product images you’ve added. It just looks at the ‘catalogrule_product’ table and recalculates a percentage solely based on those percentage based price rules and you didn’t change the price rules, you changed the product!

To get around the problem check if you are using WEEE at all (System->Configuration->TAX->Fixed Product Taxes), if not, use workaround 1, if so, you’ll need a different workaround, one that notices the difference between a new or an existing product being saved. When you save the new product you’ll need updateDiscountPercents (and the wait that comes along with it), if you save an existing product you can revert back to workaround 1.

I hope it all makes sense and that I’m on the right track here, could anyone confirm this?

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

It seems there is a bit more going on than just the WEEE recalculation (applyToProduct in CatalogRule/ModelMysql4/Rule.php). I’ll try to post back on it soon, probably early next week.

 
Magento Community Magento Community
Magento Community
Magento Community
 
7thSENSE Magento E-Commerce Systeme
Jr. Member
 
Avatar
Total Posts:  27
Joined:  2008-11-18
Stuttgart, München, Reutlingen
 

Hi Finn,

did you come any further with searching the timeout reasons?

Regards
Sebastian

 
Magento Community Magento Community
Magento Community
Magento Community
 
Finn
Member
 
Total Posts:  75
Joined:  2008-12-03
Finland & The Netherlands
 

Hi Sebastian,

I have got a “little” further with my analysis. It is becoming more and more complex to keep overview of the situation as the Catalog Price Rule application is deeply woven into the ‘save product’ action. The price rule actions after saving a product are eventually responsible for calling weee’s updateDiscountPercent function. I’m trying create a more efficient price rule application by skipping steps that would seem to have no use only to find that these steps influence many other things down the road.... I hope it makes a bit of sense and I hope I can come with something workable soon.

One of the things that is probably slowing down your system is the huge amount of customer based price rules as they all need to be re-evaluated when you save a product, just in case you’ve changed some parameter that is used in rule price building.

 
Magento Community Magento Community
Magento Community
Magento Community
Magento Community
Magento Community
Back to top
Page 1 of 2