From 1526af8cb5fbaafae9c6f4c2b466f7f53eb44589 Mon Sep 17 00:00:00 2001 From: Frederic van der Essen Date: Fri, 7 Nov 2014 15:05:02 +0100 Subject: [PATCH] [IMP] pos_loyalty: a new type of reward: 'resale' allow the customer to sell back their points to the shop --- addons/pos_loyalty/loyalty.py | 13 ++++++-- addons/pos_loyalty/static/src/js/loyalty.js | 36 +++++++++++++++++++-- addons/pos_loyalty/views/views.xml | 3 +- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/addons/pos_loyalty/loyalty.py b/addons/pos_loyalty/loyalty.py index ef3d5d4d924..8e8b240c74e 100644 --- a/addons/pos_loyalty/loyalty.py +++ b/addons/pos_loyalty/loyalty.py @@ -69,16 +69,16 @@ class loyalty_reward(osv.osv): '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 qualify for this reward'), - 'type': fields.selection((('gift','Gift'),('discount','Discount')), 'Type', required=True, help='The type of the reward'), + 'type': fields.selection((('gift','Gift'),('discount','Discount'),('resale','Resale')), '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'), 'discount_product_id': fields.many2one('product.product','Discount Product', help='The product used to apply discounts'), 'discount': fields.float('Discount',help='The discount percentage'), + 'point_product_id': fields.many2one('product.product', 'Point Product', help='The product that represents a point that is sold by the customer'), } def _check_gift_product(self, cr, uid, ids, context=None): for reward in self.browse(cr, uid, ids, context=context): - print reward.type if reward.type == 'gift': return bool(reward.gift_product_id) else: @@ -86,15 +86,22 @@ class loyalty_reward(osv.osv): def _check_discount_product(self, cr, uid, ids, context=None): for reward in self.browse(cr, uid, ids, context=context): - print reward.type if reward.type == 'discount': return bool(reward.discount_product_id) else: return True + def _check_point_product(self, cr, uid, ids, context=None): + for reward in self.browse(cr, uid, ids, context=context): + if reward.type == 'resale': + return bool(reward.point_product_id) + else: + return True + _constraints = [ (_check_gift_product, "The gift product field is mandatory for gift rewards", ["type","gift_product_id"]), (_check_discount_product, "The discount product field is mandatory for discount rewards", ["type","discount_product_id"]), + (_check_point_product, "The point product field is mandatory for point resale rewards", ["type","discount_product_id"]), ] class pos_config(osv.osv): diff --git a/addons/pos_loyalty/static/src/js/loyalty.js b/addons/pos_loyalty/static/src/js/loyalty.js index 7165497ef22..9e92653e35a 100644 --- a/addons/pos_loyalty/static/src/js/loyalty.js +++ b/addons/pos_loyalty/static/src/js/loyalty.js @@ -53,7 +53,7 @@ openerp.pos_loyalty = function(instance){ },{ model: 'loyalty.reward', condition: function(self){ return !!self.loyalty; }, - fields: ['name','type','minimum_points','gift_product_id','point_cost','discount_product_id','discount'], + fields: ['name','type','minimum_points','gift_product_id','point_cost','discount_product_id','discount','point_value','point_product_id'], domain: function(self){ return [['loyalty_program_id','=',self.loyalty.id]]; }, loaded: function(self,rewards){ self.loyalty.rewards = rewards; @@ -175,9 +175,12 @@ openerp.pos_loyalty = function(instance){ points += round_pr(line.get_quantity() * reward.point_cost, rounding); } else if (reward.type === 'discount') { points += round_pr(-line.get_display_price() * reward.point_cost, rounding); + } else if (reward.type === 'resale') { + points += (-line.get_quantity()); } } } + return points; } }, @@ -268,7 +271,7 @@ openerp.pos_loyalty = function(instance){ } var product = this.pos.db.get_product_by_id(reward.discount_product_id[0]); - if (!product) { + if (!product) { //FIXME, move this as a server side constraint this.pos.pos_widget.screen_selector.show_popup('error',{ 'message':'Configuration Error', 'comment':'The product associated with the reward "'+reward.name+'" could not be found. Make sure it is available for sale in the point of sale.', @@ -282,6 +285,35 @@ openerp.pos_loyalty = function(instance){ merge: false, extras: { reward_id: reward.id }, }); + + } else if (reward.type === 'resale') { + + var lrounding = this.pos.loyalty.rounding; + var crounding = this.pos.currency.rounding; + var spendable = this.get_spendable_points(); + var order_total = this.get_total_with_tax(); + var product = this.pos.db.get_product_by_id(reward.point_product_id[0]); + + if (!product) { //FIXME, move this as a server side constraint + this.pos.pos_widget.screen_selector.show_popup('error',{ + 'message':'Configuration Error', + 'comment':'The product associated with the reward "'+reward.name+'" could not be found. Make sure it is available for sale in the point of sale.', + }); + return; + } + + if ( round_pr( spendable * product.price, crounding ) > order_total ) { + spendable = round_pr( Math.floor(order_total / product.price), lrounding); + } + + if ( spendable < 0.00001 ) { + return; + } + var line = this.add_product(product, { + quantity: -spendable, + merge: false, + extras: { reward_id: reward.id }, + }); } }, diff --git a/addons/pos_loyalty/views/views.xml b/addons/pos_loyalty/views/views.xml index 9af7ebb3706..b199f97586a 100644 --- a/addons/pos_loyalty/views/views.xml +++ b/addons/pos_loyalty/views/views.xml @@ -128,9 +128,10 @@ + - +