diff --git a/addons/sale_management/tests/common.py b/addons/sale_management/tests/common.py new file mode 100644 index 00000000000..5bf62a0c5bd --- /dev/null +++ b/addons/sale_management/tests/common.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.sale.tests.common import SaleCommon + +class SaleManagementCommon(SaleCommon): + + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.empty_order_template = cls.env['sale.order.template'].create({ + 'name': "Test Quotation Template", + }) diff --git a/addons/sale_management/tests/test_sale_order.py b/addons/sale_management/tests/test_sale_order.py index c391d02608d..ec1da93948d 100644 --- a/addons/sale_management/tests/test_sale_order.py +++ b/addons/sale_management/tests/test_sale_order.py @@ -1,23 +1,18 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo.addons.sale.tests.common import TestSaleCommon +from odoo.fields import Command from odoo.tests import Form, tagged +from odoo.addons.sale_management.tests.common import SaleManagementCommon + @tagged('-at_install', 'post_install') -class TestSaleOrder(TestSaleCommon): +class TestSaleOrder(SaleManagementCommon): @classmethod - def setUpClass(cls, chart_template_ref=None): - super().setUpClass(chart_template_ref=chart_template_ref) - - Pricelist = cls.env['product.pricelist'] - Product = cls.env['product.product'] - SaleOrder = cls.env['sale.order'] - SaleOrderTemplate = cls.env['sale.order.template'] - SaleOrderTemplateLine = cls.env['sale.order.template.line'] - SaleOrderTemplateOption = cls.env['sale.order.template.option'] + def setUpClass(cls): + super().setUpClass() # some variables to ease asserts in tests cls.pub_product_price = 100.0 @@ -33,147 +28,131 @@ class TestSaleOrder(TestSaleCommon): cls.merged_option_discount = 100.0 - (100.0 - cls.pl_option_discount) * (100.0 - cls.tpl_option_discount) / 100.0 # create some products - cls.product_1 = Product.create({ - 'name': 'Product 1', - 'lst_price': cls.pub_product_price, - }) - - cls.optional_product = Product.create({ - 'name': 'Optional product', - 'lst_price': cls.pub_option_price, - }) + cls.product_1, cls.optional_product = cls.env['product.product'].create([ + { + 'name': 'Product 1', + 'lst_price': cls.pub_product_price, + }, { + 'name': 'Optional product', + 'lst_price': cls.pub_option_price, + } + ]) # create some quotation templates - cls.quotation_template_no_discount = SaleOrderTemplate.create({ - 'name': 'A quotation template without discount' - }) - - SaleOrderTemplateLine.create({ - 'sale_order_template_id': cls.quotation_template_no_discount.id, - 'product_id': cls.product_1.id, - }) - - SaleOrderTemplateOption.create({ - 'sale_order_template_id': cls.quotation_template_no_discount.id, - 'product_id': cls.optional_product.id, - }) - - # create some pricelists - cls.discount_included_price_list = Pricelist.create({ - 'name': 'Discount included Pricelist', - 'discount_policy': 'with_discount', - 'item_ids': [ - (0, 0, { - 'name': 'Product 1 premium price', - 'applied_on': '1_product', - 'product_tmpl_id': cls.product_1.product_tmpl_id.id, - 'compute_price': 'fixed', - 'fixed_price': cls.pl_product_price + cls.quotation_template_no_discount = cls.env['sale.order.template'].create({ + 'name': 'A quotation template', + 'sale_order_template_line_ids': [ + Command.create({ + 'product_id': cls.product_1.id, }), - (0, 0, { - 'name': 'Optional product premium price', - 'applied_on': '1_product', - 'product_tmpl_id': cls.optional_product.product_tmpl_id.id, - 'compute_price': 'fixed', - 'fixed_price': cls.pl_option_price - })] - }) - - cls.discount_excluded_price_list = Pricelist.create({ - 'name': 'Discount excluded Pricelist', - 'discount_policy': 'without_discount', - 'item_ids': [ - (0, 0, { - 'name': 'Product 1 premium price', - 'applied_on': '1_product', - 'product_tmpl_id': cls.product_1.product_tmpl_id.id, - 'compute_price': 'fixed', - 'fixed_price': cls.pl_product_price + ], + 'sale_order_template_option_ids': [ + Command.create({ + 'product_id': cls.optional_product.id, }), - (0, 0, { - 'name': 'Optional product premium price', - 'applied_on': '1_product', - 'product_tmpl_id': cls.optional_product.product_tmpl_id.id, - 'compute_price': 'fixed', - 'fixed_price': cls.pl_option_price - })] + ], }) - # create some sale orders - cls.sale_order = SaleOrder.create({ - 'partner_id': cls.partner_a.id, - 'pricelist_id': cls.company_data['default_pricelist'].id, - }) + # create two pricelist with different discount policies (same total price) + pricelist_rule_values = [ + Command.create({ + 'name': 'Product 1 premium price', + 'applied_on': '1_product', + 'product_tmpl_id': cls.product_1.product_tmpl_id.id, + 'compute_price': 'fixed', + 'fixed_price': cls.pl_product_price, + }), + Command.create({ + 'name': 'Optional product premium price', + 'applied_on': '1_product', + 'product_tmpl_id': cls.optional_product.product_tmpl_id.id, + 'compute_price': 'fixed', + 'fixed_price': cls.pl_option_price, + }), + ] - cls.sale_order_no_price_list = SaleOrder.create({ - 'partner_id': cls.partner_a.id, - 'pricelist_id': cls.company_data['default_pricelist'].id, - }) + ( + cls.discount_included_price_list, + cls.discount_excluded_price_list + ) = cls.env['product.pricelist'].create([ + { + 'name': 'Discount included Pricelist', + 'discount_policy': 'with_discount', + 'item_ids': pricelist_rule_values, + }, { + 'name': 'Discount excluded Pricelist', + 'discount_policy': 'without_discount', + 'item_ids': pricelist_rule_values, + } + ]) + + # variable kept to reduce code diff + cls.sale_order = cls.empty_order def test_01_template_without_pricelist(self): """ - This test checks that without any price list, the public price + This test checks that without any rule in the pricelist, the public price of the product is used in the sale order after selecting a quotation template. """ # first case, without discount in the quotation template - self.sale_order_no_price_list.write({ + self.sale_order.write({ 'sale_order_template_id': self.quotation_template_no_discount.id }) - self.sale_order_no_price_list._onchange_sale_order_template_id() + self.sale_order._onchange_sale_order_template_id() self.assertEqual( - len(self.sale_order_no_price_list.order_line), + len(self.sale_order.order_line), 1, "The sale order shall contains the same number of products as" "the quotation template.") self.assertEqual( - self.sale_order_no_price_list.order_line[0].product_id.id, + self.sale_order.order_line[0].product_id.id, self.product_1.id, "The sale order shall contains the same products as the" "quotation template.") self.assertEqual( - self.sale_order_no_price_list.order_line[0].price_unit, + self.sale_order.order_line[0].price_unit, self.pub_product_price, "Without any price list and discount, the public price of" "the product shall be used.") self.assertEqual( - len(self.sale_order_no_price_list.sale_order_option_ids), + len(self.sale_order.sale_order_option_ids), 1, "The sale order shall contains the same number of optional products as" "the quotation template.") self.assertEqual( - self.sale_order_no_price_list.sale_order_option_ids[0].product_id.id, + self.sale_order.sale_order_option_ids[0].product_id.id, self.optional_product.id, "The sale order shall contains the same optional products as the" "quotation template.") self.assertEqual( - self.sale_order_no_price_list.sale_order_option_ids[0].price_unit, + self.sale_order.sale_order_option_ids[0].price_unit, self.pub_option_price, "Without any price list and discount, the public price of" "the optional product shall be used.") # add the option to the order - self.sale_order_no_price_list.sale_order_option_ids[0].button_add_to_order() + self.sale_order.sale_order_option_ids[0].button_add_to_order() self.assertEqual( - len(self.sale_order_no_price_list.order_line), + len(self.sale_order.order_line), 2, "When an option is added, a new order line is created") self.assertEqual( - self.sale_order_no_price_list.order_line[1].product_id.id, + self.sale_order.order_line[1].product_id.id, self.optional_product.id, "The sale order shall contains the same products as the" "quotation template.") self.assertEqual( - self.sale_order_no_price_list.order_line[1].price_unit, + self.sale_order.order_line[1].price_unit, self.pub_option_price, "Without any price list and discount, the public price of" "the optional product shall be used.") @@ -219,8 +198,6 @@ class TestSaleOrder(TestSaleCommon): the price used in the sale order is the product public price and the discount is computed according to the price list. """ - self.env.user.groups_id += self.env.ref('product.group_discount_per_so_line') - self.sale_order.write({ 'pricelist_id': self.discount_excluded_price_list.id, 'sale_order_template_id': self.quotation_template_no_discount.id @@ -286,12 +263,6 @@ class TestSaleOrder(TestSaleCommon): This test checks that option line's values are correctly updated after a pricelist update """ - - # Necessary for _onchange_discount() check - self.env.user.write({ - 'groups_id': [(4, self.env.ref('product.group_discount_per_so_line').id)], - }) - self.sale_order.write({ 'sale_order_template_id': self.quotation_template_no_discount.id }) diff --git a/addons/sale_management/tests/test_sale_ui.py b/addons/sale_management/tests/test_sale_ui.py index 911b2f06316..151c3109496 100644 --- a/addons/sale_management/tests/test_sale_ui.py +++ b/addons/sale_management/tests/test_sale_ui.py @@ -1,9 +1,11 @@ -import odoo.tests +# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.tests import HttpCase, tagged -@odoo.tests.tagged('post_install', '-at_install') -class TestUi(odoo.tests.HttpCase): + +@tagged('post_install', '-at_install') +class TestUi(HttpCase): def test_01_sale_tour(self): self.start_tour("/web", 'sale_tour', login="admin", step_delay=100)