Coupons in Magento – Part 2

UDATE: I found a flaw in my process. The first coupon in your list will be added, but each additional will just overwrite the previous one instead of adding a new record. I will post an update when I have a working solution.

In my first post on coupons, I discussed using direct inserts. This post will discuss a more proper way to load coupons into Magento (namely creating a salesrule object and using Mage to save the object).

I’ve spent quite a bit of time digging through the code trying to get a grasp on how Magento handles coupons. My first few attempts at populating the salesrule/rule collection and using the built in model->save() code has only served to frustrate me at how slow Magento is at processing and saving the data. I tried loading 12K coupons using the script I had built. The first 1K coupons took about 5 minutes to load. Each additional 1K coupons added approximately 5 minutes more to the run time (i.e. the second thousand took 10 minutes, the third took 15, etc..). Needless to say I stopped the process a couple of hours later with about 7K coupons loaded.

What I discovered was that the call to Mage::getModel(‘salesrule/rule’) is very expensive. I thought that I needed to call this in order to clear out the object and get a clean instance. However, the call to $model->load() actually does this for us (and is no wheres near as expensive as getModel() is). Below is a sample of how to process and load a coupon into Magento:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<span class="line"><span class="x">require_once('app/Mage.php');</span>
</span><span class="line"><span class="x">// Instantiate Mage</span>
</span><span class="line"><span class="x">Mage::app('default');</span>
</span><span class="line"><span class="x">// Status logging</span>
</span><span class="line"><span class="x">Mage::log('Beginning Coupon Import', null, 'coupons.log');</span>
</span><span class="line"><span class="x">// Get an instance of the salesrule model</span>
</span><span class="line"><span class="x">$model = Mage::getModel('salesrule/rule');</span>
</span><span class="line"><span class="x">// Insert your opening for-loop here</span>
</span><span class="line"><span class="x">// Lookup salesrule by coupon code</span>
</span><span class="line"><span class="x">$model->load('CPN1234', 'coupon_code');</span>
</span><span class="line"><span class="x">// variables to be used later</span>
</span><span class="line"><span class="x">$conditions = array();</span>
</span><span class="line"><span class="x">// Get any current conditions</span>
</span><span class="line"><span class="x">$cond = $model->getConditionsInstance();</span>
</span><span class="line"><span class="x">// Get any current acctions</span>
</span><span class="line"><span class="x">$act = $model->getActionsInstance();</span>
</span><span class="line"><span class="x">$ctype = 'to_fixed';</span>
</span><span class="line"><span class="x">// Get the conditions for the coupon</span>
</span><span class="line"><span class="x">$cond = array (</span>
</span><span class="line"><span class="x">    'type'=>'salesrule/rule_condition_combine',</span>
</span><span class="line"><span class="x">    'attribute'=>'',</span>
</span><span class="line"><span class="x">    'operator'=>'',</span>
</span><span class="line"><span class="x">    'value' => 1,</span>
</span><span class="line"><span class="x">    'is_value_processed'=>'',</span>
</span><span class="line"><span class="x">    'aggregator'=>'all',</span>
</span><span class="line"><span class="x">    'conditions'=> array()</span>
</span><span class="line"><span class="x">);</span>
</span><span class="line"><span class="x">// initialize an array to hold actions</span>
</span><span class="line"><span class="x">$act = array();</span>
</span><span class="line"><span class="x">$act[1]['type'] = 'salesrule/rule_condition_product_combine';</span>
</span><span class="line"><span class="x">// aggregator can be either 'any' or 'all'</span>
</span><span class="line"><span class="x">$act[1]['aggregator'] ='any';</span>
</span><span class="line"><span class="x">$act[1]['value'] ='1';</span>
</span><span class="line"><span class="x">$act['1--0']['type'] ='salesrule/rule_condition_product';</span>
</span><span class="line"><span class="x">$act['1--0']['attribute'] ='sku';</span>
</span><span class="line"><span class="x">$act['1--0']['operator'] ='==';</span>
</span><span class="line"><span class="x">$act['1--0']['value'] = 'SKU-1234';</span>
</span><span class="line"><span class="x">// Build the data array to be saved in the object</span>
</span><span class="line"><span class="x">$data = array(</span>
</span><span class="line"><span class="x">    'name'=> 'Coupon Name',</span>
</span><span class="line"><span class="x">    'description'=> 'Long description',</span>
</span><span class="line"><span class="x">    'from_date'=> '2010-05-01',</span>
</span><span class="line"><span class="x">    'to_date'=> '2010-05-31',</span>
</span><span class="line"><span class="x">    'coupon_code'=> 'CPN1234',</span>
</span><span class="line"><span class="x">    'customer_group_ids'=> '0,1,2,3',</span>
</span><span class="line"><span class="x">    'is_active'=> 1,</span>
</span><span class="line"><span class="x">    'conditions'=> array(1 => $cond),</span>
</span><span class="line"><span class="x">    'actions'=> $act,</span>
</span><span class="line"><span class="x">    'stop_rules_processing'=> 0,</span>
</span><span class="line"><span class="x">    'is_advanced'=> 1,</span>
</span><span class="line"><span class="x">    'simple_action'=> $ctype,</span>
</span><span class="line"><span class="x">    'discount_amount'=> '14.99',</span>
</span><span class="line"><span class="x">    'is_rss'=> 1,</span>
</span><span class="line"><span class="x">    'website_ids'=> 1</span>
</span><span class="line"><span class="x">);</span>
</span><span class="line"><span class="x">// Load the data array into the object</span>
</span><span class="line"><span class="x">$model->loadPost($data);</span>
</span><span class="line"><span class="x">// Save the object to the database</span>
</span><span class="line"><span class="x">$model->save();</span>
</span><span class="line"><span class="x">// Close your for-loop here</span>
</span>

Using this process, I have been able to load about 20K coupons in under 5 minutes. Let me know if you have any questions and I’d be happy to try to answer them.

Comments !

blogroll

social