[IMP] pos_loyalty: allow rules by category
authorFrederic van der Essen <fva@openerp.com / fvdessen+o@gmail.com>
Mon, 20 Oct 2014 14:09:14 +0000 (16:09 +0200)
committerFrédéric van der Essen <fvdessen@gmail.com>
Wed, 26 Nov 2014 10:27:03 +0000 (11:27 +0100)
addons/pos_loyalty/loyalty.py
addons/pos_loyalty/static/src/js/loyalty.js
addons/pos_loyalty/views/views.xml

index e6b059d..ef3d5d4 100644 (file)
@@ -51,18 +51,24 @@ class loyalty_rule(osv.osv):
     _columns = {
         'name':                 fields.char('Name', size=32, select=1, required=True, help="An internal identification for this loyalty program rule"),
         'loyalty_program_id':   fields.many2one('loyalty.program', 'Loyalty Program', help='The Loyalty Program this exception belongs to'),
-        'product_id':           fields.many2one('product.product','Target Product', help='The product affected by the rule'),
-        'cumulative':             fields.boolean('Cumulative',      help='The points won from this rule will be won in addition to other rules'),
+        'type':                 fields.selection((('product','Product'),('category','Category')), 'Type', required=True, help='Does this rule affects products, or a category of products ?'),
+        'product_id':           fields.many2one('product.product','Target Product',  help='The product affected by the rule'),
+        'category_id':          fields.many2one('pos.category',   'Target Category', help='The category affected by the rule'),
+        'cumulative':           fields.boolean('Cumulative',        help='The points won from this rule will be won in addition to other rules'),
         'pp_product':           fields.float('Points per product',  help='How many points the product will earn per product ordered'),
         'pp_currency':          fields.float('Points per currency', help='How many points the product will earn per value sold'),
     }
+    _defaults = {
+        'type':'product',
+    }
+
 
 class loyalty_reward(osv.osv):
     _name = 'loyalty.reward'
     _columns = {
         'name':                 fields.char('Name', size=32, select=1, required=True, help='An internal identification for this loyalty reward'),
         'loyalty_program_id':   fields.many2one('loyalty.program', 'Loyalty Program', help='The Loyalty Program this reward belongs to'),
-        'minimum_points':       fields.float('Minimum Points', help='The minimum amount of points the customer must have to be eligible for this reward'),
+        'minimum_points':       fields.float('Minimum Points', help='The minimum amount of points the customer must have to qualify for this reward'),
         'type':                 fields.selection((('gift','Gift'),('discount','Discount')), 'Type', required=True, help='The type of the reward'),
         'gift_product_id':           fields.many2one('product.product','Gift Product', help='The product given as a reward'),
         'point_cost':           fields.float('Point Cost', help='The cost of the reward'),
index 766a5d3..4b1c1f3 100644 (file)
@@ -9,9 +9,9 @@ openerp.pos_loyalty = function(instance){
         var model = models[i];
         if (model.model === 'res.partner') {
             model.fields.push('loyalty_points');
-        } else if (model.model === 'pos.config') {
-            // load loyalty after pos.config
-            models.splice(i+1,0,{
+        } else if (model.model === 'product.product') {
+            // load loyalty after products
+            models.push(i+1,0,{
                 model: 'loyalty.program',
                 condition: function(self){ return !!self.config.loyalty_id[0]; },
                 fields: ['name','pp_currency','pp_product','pp_order','rounding'],
@@ -26,15 +26,27 @@ openerp.pos_loyalty = function(instance){
 
                     self.loyalty.rules = rules; 
                     self.loyalty.rules_by_product_id = {};
+                    self.loyalty.rules_by_category_id = {};
 
                     for (var i = 0; i < rules.length; i++){
                         var rule = rules[i];
-                        if (!self.loyalty.rules_by_product_id[rule.product_id[0]]) {
-                            self.loyalty.rules_by_product_id[rule.product_id[0]] = [rule];
-                        } else if (rule.cumulative) {
-                            self.loyalty.rules_by_product_id[rule.product_id[0]].unshift(rule);
-                        } else {
-                            self.loyalty.rules_by_product_id[rule.product_id[0]].push(rule);
+                        if (rule.type === 'product') {
+                            if (!self.loyalty.rules_by_product_id[rule.product_id[0]]) {
+                                self.loyalty.rules_by_product_id[rule.product_id[0]] = [rule];
+                            } else if (rule.cumulative) {
+                                self.loyalty.rules_by_product_id[rule.product_id[0]].unshift(rule);
+                            } else {
+                                self.loyalty.rules_by_product_id[rule.product_id[0]].push(rule);
+                            }
+                        } else if (rule.type === 'category') {
+                            var category = self.db.get_category_by_id(rule.category_id[0]);
+                            if (!self.loyalty.rules_by_category_id[category.id]) {
+                                self.loyalty.rules_by_category_id[category.id] = [rule];
+                            } else if (rule.cumulative) {
+                                self.loyalty.rules_by_category_id[category.id].unshift(rule);
+                            } else {
+                                self.loyalty.rules_by_category_id[category.id].push(rule);
+                            }
                         }
                     }
                 },
@@ -80,12 +92,32 @@ openerp.pos_loyalty = function(instance){
                     var rule = rules[j];
                     total_points += round_pr(line.get_quantity() * rule.pp_product, rounding);
                     total_points += round_pr(line.get_price_with_tax() * rule.pp_currency, rounding);
-                    if (!rule.cumulative) {
+                    // if affected by a non cumulative rule, skip the others. (non cumulative rules are put
+                    // at the beginning of the list when they are loaded )
+                    if (!rule.cumulative) { 
                         overriden = true;
                         break;
                     }
                 }
 
+                // Test the category rules
+                if ( product.pos_categ_id ) {
+                    var category = this.pos.db.get_category_by_id(product.pos_categ_id[0]);
+                    while (category && !overriden) {
+                        var rules = this.pos.loyalty.rules_by_category_id[category.id] || [];
+                        for (var j = 0; j < rules.length; j++) {
+                            var rule = rules[j];
+                            total_points += round_pr(line.get_quantity() * rule.pp_product, rounding);
+                            total_points += round_pr(line.get_price_with_tax() * rule.pp_currency, rounding);
+                            if (!rule.cumulative) {
+                                overriden = true;
+                                break;
+                            }
+                        }
+                        category = this.pos.db.get_category_by_id(this.pos.db.get_category_parent_id(category.id));
+                    }
+                }
+
                 if (!overriden) {
                     product_sold += line.get_quantity();
                     total_sold   += line.get_price_with_tax();
index 231c22e..9af7ebb 100644 (file)
                         </group>
 
                         <separator string="Rules" colspan="4"/>
-                        <p>Rules change how loyalty points are earned for specific products</p>
+                        <p>Rules change how loyalty points are earned for specific products or categories</p>
                         <field name="rule_ids" colspan="4" nolabel="1">
                             <tree string="Rules">
                                 <field name="name" />
-                                <field name="product_id" />
                                 <field name="pp_product" />
                                 <field name="pp_currency" />
                                 <field name="cumulative" />
                         <h1><field name="name" class="oe_inline"/></h1>
                     </div>
                     <group col="4">
-                        <field name="product_id" />
+                        <group col='2'>
+                            <field name="type" />
+                        </group>
+                        <group col='2'>
+                            <field name="product_id"  attrs="{ 'invisible':[('type','!=','product')],  'required':[('type','==','product')]}" />
+                            <field name="category_id" attrs="{ 'invisible':[('type','!=','category')], 'required':[('type','==','category')]}"/>
+                        </group>
+                    </group>
+                    <group col="6">
                         <field name="pp_product" />
                         <field name="pp_currency" />
                         <field name="cumulative" />
                         <field name="discount_product_id"   attrs="{ 'invisible':[('type','!=','discount')], 'required':[('type','==','discount')] }"/>
                     </group>
                     <group>
-                        <field name="minimum_points" />
                         <field name="point_cost" />
+                        <field name="minimum_points" />
                     </group>
                 </form>
             </field>