[ADD] sale_coupon_delivery: Allow to offer a free shipping from a coupon
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import models
|
||||
@@ -0,0 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name': "Sale Coupon Delivery",
|
||||
'summary': """Allows to offer free shippings in coupon reward""",
|
||||
'description': """Integrate coupon mechanism with shipping costs.""",
|
||||
'category': 'Sales',
|
||||
'version': '1.0',
|
||||
'depends': ['sale_coupon', 'delivery'],
|
||||
'data': [
|
||||
],
|
||||
'demo': [
|
||||
],
|
||||
'auto_install': True,
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import sale_order
|
||||
import sale_coupon_program
|
||||
import sale_coupon_reward
|
||||
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
|
||||
from odoo import models, _
|
||||
|
||||
|
||||
class SaleCoupon(models.Model):
|
||||
_inherit = "sale.coupon"
|
||||
|
||||
def _check_coupon_code(self, order):
|
||||
if self.program_id.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(SaleCoupon, self)._check_coupon_code(order)
|
||||
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
|
||||
from odoo import models, _
|
||||
|
||||
|
||||
class SaleCouponProgram(models.Model):
|
||||
_inherit = "sale.coupon.program"
|
||||
|
||||
def _filter_not_ordered_reward_programs(self, order):
|
||||
"""
|
||||
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
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, _
|
||||
|
||||
|
||||
class SaleCouponReward(models.Model):
|
||||
_inherit = 'sale.coupon.reward'
|
||||
_description = "Sales Coupon Reward"
|
||||
|
||||
reward_type = fields.Selection(selection_add=[('free_shipping', 'Free Shipping')])
|
||||
|
||||
def name_get(self):
|
||||
result = []
|
||||
reward_names = super(SaleCouponReward, self).name_get()
|
||||
free_shipping_reward_ids = self.filtered(lambda reward: reward.reward_type == 'free_shipping').ids
|
||||
for res in reward_names:
|
||||
result.append((res[0], res[0] in free_shipping_reward_ids and _("Free Shipping") or res[1]))
|
||||
return result
|
||||
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
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_reward_line_values(self, program):
|
||||
if program.reward_type == 'free_shipping':
|
||||
return self._get_reward_values_free_shipping(program)
|
||||
else:
|
||||
return super(SaleOrder, self)._get_reward_line_values(program)
|
||||
|
||||
def _get_reward_values_free_shipping(self, program):
|
||||
return {
|
||||
'name': "Discount: %s" % (program.name),
|
||||
'product_id': program.discount_line_product_id.id,
|
||||
'price_unit': - self.order_line.filtered(lambda x: x.is_delivery).price_unit,
|
||||
'product_uom_qty': 1.0,
|
||||
'product_uom': program.discount_line_product_id.uom_id.id,
|
||||
'order_id': self.id,
|
||||
'is_reward_line': True
|
||||
}
|
||||
|
||||
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)]
|
||||
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import test_free_shipping_reward
|
||||
@@ -0,0 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.addons.sale_coupon.tests.common import TestSaleCouponCommon
|
||||
|
||||
|
||||
class TestSaleCouponProgramRules(TestSaleCouponCommon):
|
||||
# Test a free shipping reward + some expected behavior
|
||||
# (automatic line addition or removal)
|
||||
|
||||
def test_free_shipping_reward(self):
|
||||
# Test case 1: The minimum amount is not reached, the reward should
|
||||
# not be created
|
||||
self.immediate_promotion_program.active = False
|
||||
self.env['sale.coupon.program'].create({
|
||||
'name': 'Free Shipping if at least 100 euros',
|
||||
'promo_code_usage': 'no_code_needed',
|
||||
'reward_type': 'free_shipping',
|
||||
'rule_minimum_amount': 100.0,
|
||||
'active': True,
|
||||
})
|
||||
|
||||
order = self.env['sale.order'].create({
|
||||
'partner_id': self.steve.id,
|
||||
})
|
||||
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_B.id,
|
||||
'name': 'Product B',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
})
|
||||
]})
|
||||
self.assertEqual(len(order.order_line.ids), 1)
|
||||
|
||||
order.carrier_id = self.env['delivery.carrier'].search([])[1]
|
||||
order.delivery_set()
|
||||
self.assertEqual(len(order.order_line.ids), 2)
|
||||
|
||||
# Test case 2: the amount is sufficient, the shipping should
|
||||
# be reimbursed
|
||||
order.write({'order_line': [
|
||||
(0, False, {
|
||||
'product_id': self.product_A.id,
|
||||
'name': 'Product 1',
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1.0,
|
||||
'price_unit': 1000
|
||||
})
|
||||
]})
|
||||
|
||||
self.assertEqual(len(order.order_line.ids), 4)
|
||||
|
||||
# Test case 3: the amount is not sufficient now, the reward should be removed
|
||||
order.write({'order_line': [
|
||||
(2, order.order_line.filtered(lambda line: line.product_id.id == self.product_A.id).id, False)
|
||||
]})
|
||||
self.assertEqual(len(order.order_line.ids), 2)
|
||||
Reference in New Issue
Block a user