187 lines
7.8 KiB
Python
187 lines
7.8 KiB
Python
# Copyright 2020 Tecnativa - David Vidal
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
from odoo import exceptions
|
|
from odoo.tests import common
|
|
|
|
|
|
class TestSaleGlobalDiscount(common.SavepointCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.account_type = cls.env['account.account.type'].create({
|
|
'name': 'Test',
|
|
'type': 'receivable',
|
|
})
|
|
cls.account = cls.env['account.account'].create({
|
|
'name': 'Test account',
|
|
'code': 'TEST',
|
|
'user_type_id': cls.account_type.id,
|
|
'reconcile': True,
|
|
})
|
|
cls.global_discount_obj = cls.env['global.discount']
|
|
cls.global_discount_1 = cls.global_discount_obj.create({
|
|
'name': 'Test Discount 1',
|
|
'sequence': 1,
|
|
'discount_scope': 'sale',
|
|
'discount': 20,
|
|
'account_id': cls.account.id,
|
|
})
|
|
cls.global_discount_2 = cls.global_discount_obj.create({
|
|
'name': 'Test Discount 2',
|
|
'sequence': 2,
|
|
'discount_scope': 'sale',
|
|
'discount': 30,
|
|
'account_id': cls.account.id,
|
|
})
|
|
cls.global_discount_3 = cls.global_discount_obj.create({
|
|
'name': 'Test Discount 3',
|
|
'sequence': 3,
|
|
'discount_scope': 'sale',
|
|
'discount': 50,
|
|
'account_id': cls.account.id,
|
|
})
|
|
cls.partner_1 = cls.env['res.partner'].create({
|
|
'name': 'Mr. Odoo',
|
|
})
|
|
cls.partner_2 = cls.env['res.partner'].create({
|
|
'name': 'Mrs. Odoo',
|
|
})
|
|
cls.partner_2.customer_global_discount_ids = (
|
|
cls.global_discount_2 + cls.global_discount_3)
|
|
cls.product_1 = cls.env['product.product'].create({
|
|
'name': 'Test Product 1',
|
|
'type': 'service',
|
|
})
|
|
cls.product_2 = cls.product_1.copy({
|
|
'name': 'Test Product 2',
|
|
})
|
|
cls.tax_group_5pc = cls.env['account.tax.group'].create({
|
|
'name': 'Test Tax Group 5%',
|
|
'sequence': 1,
|
|
})
|
|
cls.tax_group_15pc = cls.env['account.tax.group'].create({
|
|
'name': 'Test Tax Group 15%',
|
|
'sequence': 2,
|
|
})
|
|
cls.tax_1 = cls.env['account.tax'].create({
|
|
'name': 'Test TAX 15%',
|
|
'amount_type': 'percent',
|
|
'type_tax_use': 'sale',
|
|
'tax_group_id': cls.tax_group_15pc.id,
|
|
'amount': 15.0,
|
|
})
|
|
cls.tax_2 = cls.env['account.tax'].create({
|
|
'name': 'TAX 5%',
|
|
'amount_type': 'percent',
|
|
'tax_group_id': cls.tax_group_5pc.id,
|
|
'type_tax_use': 'sale',
|
|
'amount': 5.0,
|
|
})
|
|
cls.sale = cls.env['sale.order'].create({
|
|
'partner_id': cls.partner_1.id,
|
|
'order_line': [(0, 0, {
|
|
'product_id': cls.product_1.id,
|
|
'product_uom_qty': 2,
|
|
'price_unit': 75.00,
|
|
# Test compound taxes as they tend to provoke corner cases
|
|
'tax_id': [(6, 0, [cls.tax_1.id, cls.tax_2.id])]
|
|
}), (0, 0, {
|
|
'name': 'On Site Assistance',
|
|
'product_id': cls.product_2.id,
|
|
'product_uom_qty': 3,
|
|
'price_unit': 33.33,
|
|
'tax_id': [(6, 0, [cls.tax_1.id, cls.tax_2.id])]
|
|
})],
|
|
})
|
|
|
|
def test_01_global_sale_succesive_discounts(self):
|
|
"""Add global discounts to the sale order"""
|
|
self.assertAlmostEqual(self.sale.amount_total, 299.99)
|
|
self.assertAlmostEqual(self.sale.amount_tax, 50)
|
|
self.assertAlmostEqual(self.sale.amount_untaxed, 249.99)
|
|
# Apply a single 20% global discount
|
|
self.sale.global_discount_ids = self.global_discount_1
|
|
# Discount is computed over the base and global taxes are computed
|
|
# according to it line by line with the core method
|
|
self.assertAlmostEqual(self.sale.amount_global_discount, 50)
|
|
self.assertAlmostEqual(self.sale.amount_untaxed, 199.99)
|
|
self.assertAlmostEqual(
|
|
self.sale.amount_untaxed_before_global_discounts, 249.99)
|
|
self.assertAlmostEqual(self.sale.amount_total, 239.99)
|
|
self.assertAlmostEqual(
|
|
self.sale.amount_total_before_global_discounts, 299.99)
|
|
self.assertAlmostEqual(self.sale.amount_tax, 40)
|
|
# Apply an additional 30% global discount
|
|
self.sale.global_discount_ids += self.global_discount_2
|
|
self.assertAlmostEqual(self.sale.amount_global_discount, 110)
|
|
self.assertAlmostEqual(self.sale.amount_untaxed, 139.99)
|
|
self.assertAlmostEqual(
|
|
self.sale.amount_untaxed_before_global_discounts, 249.99)
|
|
self.assertAlmostEqual(self.sale.amount_total, 167.99)
|
|
self.assertAlmostEqual(
|
|
self.sale.amount_total_before_global_discounts, 299.99)
|
|
self.assertAlmostEqual(self.sale.amount_tax, 28)
|
|
|
|
def test_02_global_sale_discounts_from_partner(self):
|
|
"""Change the partner and his global discounts go to the invoice"""
|
|
# (30% then 50%)
|
|
self.sale.partner_id = self.partner_2
|
|
self.sale.onchange_partner_id()
|
|
self.assertAlmostEqual(self.sale.amount_global_discount, 162.49)
|
|
self.assertAlmostEqual(self.sale.amount_untaxed, 87.5)
|
|
self.assertAlmostEqual(
|
|
self.sale.amount_untaxed_before_global_discounts, 249.99)
|
|
self.assertAlmostEqual(self.sale.amount_total, 105.01)
|
|
self.assertAlmostEqual(
|
|
self.sale.amount_total_before_global_discounts, 299.99)
|
|
self.assertAlmostEqual(self.sale.amount_tax, 17.51)
|
|
|
|
def test_03_global_sale_discounts_to_invoice(self):
|
|
"""All the discounts go to the invoice"""
|
|
self.sale.partner_id = self.partner_2
|
|
self.sale.onchange_partner_id()
|
|
self.sale.action_confirm()
|
|
self.sale.action_invoice_create()
|
|
invoice = self.sale.invoice_ids
|
|
self.assertEqual(len(invoice.invoice_global_discount_ids), 2)
|
|
line_tax_1 = invoice.tax_line_ids.filtered(
|
|
lambda x: x.tax_id == self.tax_1)
|
|
line_tax_2 = invoice.tax_line_ids.filtered(
|
|
lambda x: x.tax_id == self.tax_2)
|
|
self.assertAlmostEqual(line_tax_1.base, 87.5)
|
|
self.assertAlmostEqual(line_tax_2.base, 87.5)
|
|
self.assertAlmostEqual(line_tax_1.amount, 13.13)
|
|
self.assertAlmostEqual(line_tax_2.amount, 4.38)
|
|
discount_amount = sum(
|
|
invoice.invoice_global_discount_ids.mapped('discount_amount'))
|
|
self.assertAlmostEqual(discount_amount, 162.49)
|
|
self.assertAlmostEqual(
|
|
invoice.amount_untaxed_before_global_discounts, 249.99)
|
|
self.assertAlmostEqual(invoice.amount_untaxed, 87.5)
|
|
self.assertAlmostEqual(invoice.amount_total, 105.01)
|
|
|
|
def test_04_report_taxes(self):
|
|
"""Taxes by group shown in reports"""
|
|
self.sale.partner_id = self.partner_2
|
|
self.sale.onchange_partner_id()
|
|
self.sale._amount_by_group()
|
|
# Taxes
|
|
taxes_groups = self.sale.amount_by_group
|
|
self.assertAlmostEqual(taxes_groups[0][1], 4.38)
|
|
self.assertAlmostEqual(taxes_groups[1][1], 13.13)
|
|
# Bases
|
|
self.assertAlmostEqual(taxes_groups[0][2], 87.5)
|
|
self.assertAlmostEqual(taxes_groups[1][2], 87.5)
|
|
|
|
def test_05_incompatible_taxes(self):
|
|
# Line 1 with tax 1 and tax 2
|
|
# Line 2 with only tax 2
|
|
self.sale.order_line[1].tax_id = [(6, 0, self.tax_1.ids)]
|
|
with self.assertRaises(exceptions.UserError):
|
|
self.sale.global_discount_ids = self.global_discount_1
|
|
|
|
def test_06_no_taxes(self):
|
|
self.sale.order_line[1].tax_id = False
|
|
with self.assertRaises(exceptions.UserError):
|
|
self.sale.global_discount_ids = self.global_discount_1
|