summaryrefslogtreecommitdiff
path: root/addons/sale_management/tests
diff options
context:
space:
mode:
Diffstat (limited to 'addons/sale_management/tests')
-rw-r--r--addons/sale_management/tests/__init__.py5
-rw-r--r--addons/sale_management/tests/test_sale_order.py285
-rw-r--r--addons/sale_management/tests/test_sale_ui.py9
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)