diff options
Diffstat (limited to 'addons/sale_management/tests')
| -rw-r--r-- | addons/sale_management/tests/__init__.py | 5 | ||||
| -rw-r--r-- | addons/sale_management/tests/test_sale_order.py | 285 | ||||
| -rw-r--r-- | addons/sale_management/tests/test_sale_ui.py | 9 |
3 files changed, 299 insertions, 0 deletions
diff --git a/addons/sale_management/tests/__init__.py b/addons/sale_management/tests/__init__.py new file mode 100644 index 00000000..09655080 --- /dev/null +++ b/addons/sale_management/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import test_sale_ui +from . import test_sale_order diff --git a/addons/sale_management/tests/test_sale_order.py b/addons/sale_management/tests/test_sale_order.py new file mode 100644 index 00000000..2a38f8ef --- /dev/null +++ b/addons/sale_management/tests/test_sale_order.py @@ -0,0 +1,285 @@ +# -*- 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.tests import tagged + + +@tagged('-at_install', 'post_install') +class TestSaleOrder(TestSaleCommon): + + @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'] + + # some variables to ease asserts in tests + cls.pub_product_price = 100.0 + cls.pl_product_price = 80.0 + cls.tpl_discount = 10.0 + cls.pl_discount = (cls.pub_product_price - cls.pl_product_price) * 100 / cls.pub_product_price + cls.merged_discount = 100.0 - (100.0 - cls.pl_discount) * (100.0 - cls.tpl_discount) / 100.0 + + cls.pub_option_price = 200.0 + cls.pl_option_price = 100.0 + cls.tpl_option_discount = 20.0 + cls.pl_option_discount = (cls.pub_option_price - cls.pl_option_price) * 100 / cls.pub_option_price + 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, + }) + + # create some quotation templates + cls.quotation_template_no_discount = SaleOrderTemplate.create({ + 'name': 'A quotation template without discount' + }) + + SaleOrderTemplateLine.create({ + 'name': 'Product 1', + 'sale_order_template_id': cls.quotation_template_no_discount.id, + 'product_id': cls.product_1.id, + 'product_uom_id': cls.product_1.uom_id.id + }) + + SaleOrderTemplateOption.create({ + 'name': 'Optional product 1', + 'sale_order_template_id': cls.quotation_template_no_discount.id, + 'product_id': cls.optional_product.id, + 'uom_id': cls.optional_product.uom_id.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 + }), + (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 + }), + (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, + }) + + cls.sale_order_no_price_list = SaleOrder.create({ + 'partner_id': cls.partner_a.id, + 'pricelist_id': cls.company_data['default_pricelist'].id, + }) + + def test_01_template_without_pricelist(self): + """ + This test checks that without any price list, 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({ + 'sale_order_template_id': self.quotation_template_no_discount.id + }) + self.sale_order_no_price_list.onchange_sale_order_template_id() + + self.assertEqual( + len(self.sale_order_no_price_list.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.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.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), + 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.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.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.assertEqual( + len(self.sale_order_no_price_list.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.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.pub_option_price, + "Without any price list and discount, the public price of" + "the optional product shall be used.") + + def test_02_template_with_discount_included_pricelist(self): + """ + This test checks that with a 'discount included' price list, + the price used in the sale order is computed according to the + price list. + """ + + # first case, without discount in the quotation template + self.sale_order.write({ + 'pricelist_id': self.discount_included_price_list.id, + 'sale_order_template_id': self.quotation_template_no_discount.id + }) + self.sale_order.onchange_sale_order_template_id() + + self.assertEqual( + self.sale_order.order_line[0].price_unit, + self.pl_product_price, + "If a pricelist is set, the product price shall be computed" + "according to it.") + + self.assertEqual( + self.sale_order.sale_order_option_ids[0].price_unit, + self.pl_option_price, + "If a pricelist is set, the optional product price shall" + "be computed according to it.") + + # add the option to the order + self.sale_order.sale_order_option_ids[0].button_add_to_order() + + self.assertEqual( + self.sale_order.order_line[1].price_unit, + self.pl_option_price, + "If a pricelist is set, the optional product price shall" + "be computed according to it.") + + def test_03_template_with_discount_excluded_pricelist(self): + """ + This test checks that with a 'discount excluded' price list, + the price used in the sale order is the product public price and + the discount is computed according to the price list. + """ + + self.sale_order.write({ + 'pricelist_id': self.discount_excluded_price_list.id, + 'sale_order_template_id': self.quotation_template_no_discount.id + }) + self.sale_order.onchange_sale_order_template_id() + + self.assertEqual( + self.sale_order.order_line[0].price_unit, + self.pub_product_price, + "If a pricelist is set without discount included, the unit " + "price shall be the public product price.") + + self.assertEqual( + self.sale_order.order_line[0].price_subtotal, + self.pl_product_price, + "If a pricelist is set without discount included, the subtotal " + "price shall be the price computed according to the price list.") + + self.assertEqual( + self.sale_order.order_line[0].discount, + self.pl_discount, + "If a pricelist is set without discount included, the discount " + "shall be computed according to the price unit and the subtotal." + "price") + + self.assertEqual( + self.sale_order.sale_order_option_ids[0].price_unit, + self.pub_option_price, + "If a pricelist is set without discount included, the unit " + "price shall be the public optional product price.") + + self.assertEqual( + self.sale_order.sale_order_option_ids[0].discount, + self.pl_option_discount, + "If a pricelist is set without discount included, the discount " + "shall be computed according to the optional price unit and" + "the subtotal price.") + + # add the option to the order + self.sale_order.sale_order_option_ids[0].button_add_to_order() + + self.assertEqual( + self.sale_order.order_line[1].price_unit, + self.pub_option_price, + "If a pricelist is set without discount included, the unit " + "price shall be the public optional product price.") + + self.assertEqual( + self.sale_order.order_line[1].price_subtotal, + self.pl_option_price, + "If a pricelist is set without discount included, the subtotal " + "price shall be the price computed according to the price list.") + + self.assertEqual( + self.sale_order.order_line[1].discount, + self.pl_option_discount, + "If a pricelist is set without discount included, the discount " + "shall be computed according to the price unit and the subtotal." + "price") diff --git a/addons/sale_management/tests/test_sale_ui.py b/addons/sale_management/tests/test_sale_ui.py new file mode 100644 index 00000000..911b2f06 --- /dev/null +++ b/addons/sale_management/tests/test_sale_ui.py @@ -0,0 +1,9 @@ +import odoo.tests +# Part of Odoo. See LICENSE file for full copyright and licensing details. + + +@odoo.tests.tagged('post_install', '-at_install') +class TestUi(odoo.tests.HttpCase): + + def test_01_sale_tour(self): + self.start_tour("/web", 'sale_tour', login="admin", step_delay=100) |
