diff --git a/models/sale_coupon_program.py b/models/sale_coupon_program.py index 657cbaa179c..6f7e7aa4669 100644 --- a/models/sale_coupon_program.py +++ b/models/sale_coupon_program.py @@ -13,14 +13,12 @@ class SaleCouponProgram(models.Model): Returns the programs when the reward is actually in the order lines """ programs = super(SaleCouponProgram, self)._filter_not_ordered_reward_programs(order) - for program in self: - if program.reward_type == 'free_shipping' and \ - not order.order_line.filtered(lambda line: line.is_delivery): - programs -= program + # Do not filter on free delivery programs. As delivery_unset is called everywhere (which is + # rather stupid), the delivery line is unliked to be created again instead of writing on it to + # modify the price_unit. That way, the reward is unlink and is not set back again. return programs def _check_promo_code(self, order, coupon_code): if self.reward_type == 'free_shipping' and not order.order_line.filtered(lambda line: line.is_delivery): return {'error': _('The shipping costs are not in the order lines.')} return super(SaleCouponProgram, self)._check_promo_code(order, coupon_code) - diff --git a/models/sale_order.py b/models/sale_order.py index 24e0097cdfc..a6968eb5a07 100644 --- a/models/sale_order.py +++ b/models/sale_order.py @@ -24,7 +24,7 @@ class SaleOrder(models.Model): return { 'name': "Discount: %s" % (program.name), 'product_id': program.discount_line_product_id.id, - 'price_unit': - delivery_line.price_unit, + 'price_unit': delivery_line and - delivery_line.price_unit or 0.0, 'product_uom_qty': 1.0, 'product_uom': program.discount_line_product_id.uom_id.id, 'order_id': self.id, @@ -34,3 +34,23 @@ class SaleOrder(models.Model): def _get_lines_unit_prices(self): return [x.price_unit for x in self.order_line.filtered(lambda x: not x.is_delivery and not x.program_id)] + +class SalesOrderLine(models.Model): + _inherit = "sale.order.line" + + def unlink(self): + # Due to delivery_set and delivery_unset methods that are called everywhere, don't unlink + # reward lines if it's a free shipping + orders = self.mapped('order_id') + applied_programs = orders.mapped('no_code_promo_program_ids') + \ + orders.mapped('code_promo_program_id') + \ + orders.mapped('applied_coupon_ids').mapped('program_id') + free_shipping_products = applied_programs.filtered( + lambda program: program.reward_type == 'free_shipping' + ).mapped('discount_line_product_id') + lines_to_unlink = self.filtered(lambda line: line.product_id not in free_shipping_products) + # Unless these lines are the last ones + res = super(SalesOrderLine, lines_to_unlink).unlink() + only_free_shipping_line_orders = orders.filtered(lambda order: len(order.order_line.ids) == 1 and order.order_line.is_reward_line) + super(SalesOrderLine, only_free_shipping_line_orders.mapped('order_line')).unlink() + return res