[MERGE] forward port branch saas-15 up to 9aca5ca19d0

This commit is contained in:
Christophe Simonis
2018-03-01 18:18:16 +01:00
3 changed files with 117 additions and 25 deletions
-17
View File
@@ -22,20 +22,3 @@ class SaleCouponProgram(models.Model):
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)
@api.model
def _filter_on_mimimum_amount(self, order):
# To get actual total amount of SO without any reward or discount
# We exclude any line of the order that is a delivery
# get the round function of the currency: we want to imitate what the sale.order.amount is (computed field)
round_curr = order.pricelist_id.currency_id.round
order_lines = order.order_line.filtered(lambda l: not l.is_delivery)
order_amount = round_curr(sum(order_lines.mapped('price_subtotal')))
order_tax = round_curr(sum(order_lines.mapped('price_tax')))
discounted_amount = sum(order_lines.filtered(lambda line: line.is_reward_line).mapped('price_total'))
untaxed_amount = order_amount - discounted_amount
return self.filtered(lambda program:
program.rule_minimum_amount_tax_inclusion == 'tax_included' and
program._compute_program_amount('rule_minimum_amount', order.currency_id) <= untaxed_amount + order_tax or
program.rule_minimum_amount_tax_inclusion == 'tax_excluded' and
program._compute_program_amount('rule_minimum_amount', order.currency_id) <= untaxed_amount)
+13 -5
View File
@@ -1,14 +1,22 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
from odoo import models, _
class SaleOrder(models.Model):
_inherit = "sale.order"
def _get_order_lines_untaxed_amount(self):
""" Returns the untaxed sale order total amount without the rewards and shipping amount"""
return sum([x.price_subtotal for x in self.order_line.filtered(lambda x: not (x.is_reward_line or x.is_delivery))])
def _get_no_effect_on_threshold_lines(self):
self.ensure_one()
# Do not count shipping and free shipping
free_delivery_product = self.env['sale.coupon.program'].search([('reward_type', '=', 'free_shipping')]).mapped('discount_line_product_id')
lines = self.order_line.filtered(lambda line: line.is_delivery or line.product_id in free_delivery_product)
return lines + super(SaleOrder, self)._get_no_effect_on_threshold_lines()
def _get_order_lines_tax_included_amount(self):
""" Returns the taxes included sale order total amount without the rewards amount"""
free_reward_product = self.env['sale.coupon.program'].search([('reward_type', '=', 'product')]).mapped('discount_line_product_id')
return sum([x.price_total for x in self.order_line.filtered(lambda x: not (x.is_reward_line or x.is_delivery) or x.product_id in free_reward_product)])
def _get_reward_line_values(self, program):
if program.reward_type == 'free_shipping':
@@ -22,7 +30,7 @@ class SaleOrder(models.Model):
if self.fiscal_position_id:
taxes = self.fiscal_position_id.map_tax(taxes)
return {
'name': "Discount: %s" % (program.name),
'name': _("Discount: ") + program.name,
'product_id': program.discount_line_product_id.id,
'price_unit': delivery_line and - delivery_line.price_unit or 0.0,
'product_uom_qty': 1.0,
+104 -3
View File
@@ -5,6 +5,11 @@ from openerp.addons.sale_coupon.tests.common import TestSaleCouponCommon
class TestSaleCouponProgramRules(TestSaleCouponCommon):
def setUp(self):
super(TestSaleCouponProgramRules, self).setUp()
self.iPadMini = self.env.ref('product.product_product_6').copy()
# Test a free shipping reward + some expected behavior
# (automatic line addition or removal)
@@ -17,6 +22,7 @@ class TestSaleCouponProgramRules(TestSaleCouponCommon):
'promo_code_usage': 'no_code_needed',
'reward_type': 'free_shipping',
'rule_minimum_amount': 100.0,
'rule_minimum_amount_tax_inclusion': 'tax_included',
'active': True,
})
@@ -46,7 +52,6 @@ class TestSaleCouponProgramRules(TestSaleCouponCommon):
# Test Case 1b: amount is not reached but is on a threshold
# The amount of deliverable product + the one of the delivery exceeds the minimum amount
# yet the program shouldn't be applied
# Order price will be 5.75 + 81.74*1.15 = 99.75
order.write({'order_line': [
(0, False, {
@@ -57,7 +62,6 @@ class TestSaleCouponProgramRules(TestSaleCouponCommon):
'price_unit': 81.74,
})
]})
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 3)
@@ -69,7 +73,7 @@ class TestSaleCouponProgramRules(TestSaleCouponCommon):
'name': 'Product 1',
'product_uom': self.uom_unit.id,
'product_uom_qty': 1.0,
'price_unit': 1000
'price_unit': 0.30,
})
]})
@@ -82,3 +86,100 @@ class TestSaleCouponProgramRules(TestSaleCouponCommon):
]})
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 3)
def test_shipping_cost(self):
# Free delivery should not be taken into account when checking for minimum required threshold
p_minimum_threshold_free_delivery = self.env['sale.coupon.program'].create({
'name': 'free shipping if > 872 tax exl',
'promo_code_usage': 'no_code_needed',
'reward_type': 'free_shipping',
'program_type': 'promotion_program',
'rule_minimum_amount': 872,
})
p_minimum_threshold_discount = self.env['sale.coupon.program'].create({
'name': '10% reduction if > 872 tax exl',
'promo_code_usage': 'no_code_needed',
'reward_type': 'discount',
'program_type': 'promotion_program',
'discount_type': 'percentage',
'discount_percentage': 10.0,
'rule_minimum_amount': 872,
})
order = self.empty_order
self.iPadMini.taxes_id = self.tax_10pc_incl
sol1 = self.env['sale.order.line'].create({
'product_id': self.iPadMini.id,
'name': 'iPad Mini',
'product_uom_qty': 3.0,
'order_id': order.id,
})
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 2, "We should get the 10% discount line since we bought 872.73$")
order.carrier_id = self.env['delivery.carrier'].search([])[1]
order.delivery_set()
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 3, "We should get the delivery line but not the free delivery since we are below 872.73$ with the 10% discount")
p_minimum_threshold_free_delivery.sequence = 10
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 4, "We should get both promotion line since the free delivery will be applied first and won't change the SO total")
def test_shipping_cost_numbers(self):
# Free delivery should not be taken into account when checking for minimum required threshold
tax_15pc_excl = self.env['account.tax'].create({
'name': "15% Tax excl",
'amount_type': 'percent',
'amount': 15,
})
p_minimum_threshold_free_delivery = self.env['sale.coupon.program'].create({
'name': 'free shipping if > 872 tax exl',
'promo_code_usage': 'code_needed',
'promo_code': 'free_shipping',
'reward_type': 'free_shipping',
'program_type': 'promotion_program',
'rule_minimum_amount': 872,
})
self.p2 = self.env['sale.coupon.program'].create({
'name': 'Buy 4 ipads, get one for free',
'promo_code_usage': 'no_code_needed',
'reward_type': 'product',
'program_type': 'promotion_program',
'reward_product_id': self.iPadMini.id,
'rule_min_quantity': 3,
'rule_products_domain': '[["name","ilike","ipad mini"]]',
})
order = self.empty_order
self.iPadMini.taxes_id = self.tax_10pc_incl
sol1 = self.env['sale.order.line'].create({
'product_id': self.iPadMini.id,
'name': 'iPad Mini',
'product_uom_qty': 3.0,
'order_id': order.id,
})
# The delivery product has 15% tax on dball but not on dbbase. A module is probably adding the tax at some point.
# We want that tax to be set so we can be sure it is not added to the order total paid amount used in coupon as
# it was wrongly done before.
self.env.ref('delivery.delivery_carrier').taxes_id = tax_15pc_excl
order.carrier_id = self.env['delivery.carrier'].search([])[1]
order.delivery_set()
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 2, "")
self.assertEqual(order.reward_amount, 0)
# Shipping is 20 + 15%tax
self.assertEqual(sum([line.price_total for line in order._get_no_effect_on_threshold_lines()]), 23)
self.assertEqual(order.amount_untaxed, 872.73 + 20)
self.env['sale.coupon.apply.code'].sudo().apply_coupon(order, 'free_shipping')
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 3, "We should get the delivery line and the free delivery since we are below 872.73$ with the 10% discount")
self.assertEqual(order.reward_amount, -20)
self.assertEqual(sum([line.price_total for line in order._get_no_effect_on_threshold_lines()]), 0)
self.assertEqual(order.amount_untaxed, 872.73)
sol1.product_uom_qty = 4
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line.ids), 4, "We should get a free iPad Mini")
self.assertEqual(order.reward_amount, -20 -290.91)
self.assertEqual(sum([line.price_total for line in order._get_no_effect_on_threshold_lines()]), 0)
self.assertEqual(order.amount_untaxed, 872.73)