product/tests/test_product_pricelist.py

313 lines
14 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
import time
from odoo.fields import Command, first
from odoo.tools import float_compare
from odoo.addons.product.tests.common import ProductCommon
class TestProductPricelist(ProductCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.category_5_id = cls.env['product.category'].create({
'name': 'Office Furniture',
'parent_id': cls.product_category.id
}).id
cls.computer_SC234 = cls.env['product.product'].create({
'name': 'Desk Combination',
'categ_id': cls.category_5_id,
})
cls.ipad_retina_display = cls.env['product.product'].create({
'name': 'Customizable Desk',
})
cls.custom_computer_kit = cls.env['product.product'].create({
'name': 'Corner Desk Right Sit',
'categ_id': cls.category_5_id,
})
cls.ipad_mini = cls.env['product.product'].create({
'name': 'Large Cabinet',
'categ_id': cls.category_5_id,
'standard_price': 800.0,
})
cls.monitor = cls.env['product.product'].create({
'name': 'Super nice monitor',
'categ_id': cls.category_5_id,
'list_price': 1000.0,
})
cls.apple_in_ear_headphones = cls.env['product.product'].create({
'name': 'Storage Box',
'categ_id': cls.category_5_id,
})
cls.laptop_E5023 = cls.env['product.product'].create({
'name': 'Office Chair',
'categ_id': cls.category_5_id,
})
cls.laptop_S3450 = cls.env['product.product'].create({
'name': 'Acoustic Bloc Screens',
'categ_id': cls.category_5_id,
})
cls.product_multi_price = cls.env['product.product'].create({
'name': 'Multi Price',
'categ_id': cls.product_category.id,
})
cls.new_currency = cls.env['res.currency'].create({
'name': 'Wonderful Currency',
'symbol': ':)',
'rate_ids': [Command.create({'rate': 10, 'name': time.strftime('%Y-%m-%d')})],
})
cls.ipad_retina_display.write({'uom_id': cls.uom_unit.id, 'categ_id': cls.category_5_id})
cls.customer_pricelist = cls.env['product.pricelist'].create({
'name': 'Customer Pricelist',
'item_ids': [
Command.create({
'name': 'Default pricelist',
'compute_price': 'formula',
'base': 'pricelist',
'base_pricelist_id': cls.pricelist.id,
}),
Command.create({
'name': '10% Discount on Assemble Computer',
'applied_on': '1_product',
'product_tmpl_id': cls.ipad_retina_display.product_tmpl_id.id,
'compute_price': 'formula',
'base': 'list_price',
'price_discount': 10,
}),
Command.create({
'name': '1 surchange on Laptop',
'applied_on': '1_product',
'product_tmpl_id': cls.laptop_E5023.product_tmpl_id.id,
'compute_price': 'formula',
'base': 'list_price',
'price_surcharge': 1,
}),
Command.create({
'name': '5% Discount on all Computer related products',
'applied_on': '2_product_category',
'min_quantity': 2,
'compute_price': 'formula',
'base': 'list_price',
'categ_id': cls.product_category.id,
'price_discount': 5,
}),
Command.create({
'name': '30% Discount on all products',
'applied_on': '3_global',
'date_start': '2011-12-27',
'date_end': '2011-12-31',
'compute_price': 'formula',
'price_discount': 30,
'base': 'list_price',
}),
Command.create({
'name': 'Fixed on all products',
'applied_on': '1_product',
'product_tmpl_id': cls.monitor.product_tmpl_id.id,
'date_start': '2020-04-06 09:00:00',
'date_end': '2020-04-09 12:00:00',
'compute_price': 'formula',
'price_discount': 50,
'base': 'list_price',
}),
Command.create({
'name': 'Multi Price Customer',
'applied_on': '1_product',
'product_tmpl_id': cls.product_multi_price.product_tmpl_id.id,
'compute_price': 'fixed',
'fixed_price': 99,
'base': 'list_price',
}),
],
})
cls.business_pricelist = cls.env['product.pricelist'].create({
'name': 'Business Pricelist',
'item_ids': [(0, 0, {
'name': 'Multi Price Business',
'applied_on': '1_product',
'product_tmpl_id': cls.product_multi_price.product_tmpl_id.id,
'compute_price': 'fixed',
'fixed_price': 50,
'base': 'list_price'
})]
})
def test_10_calculation_price_of_products_pricelist(self):
"""Test calculation of product price based on pricelist"""
# I check sale price of Customizable Desk
context = {}
context.update({'pricelist': self.customer_pricelist.id, 'quantity': 1})
product = self.ipad_retina_display
price = self.customer_pricelist._get_product_price(product, quantity=1.0)
msg = "Wrong sale price: Customizable Desk. should be %s instead of %s" % (price, (product.lst_price-product.lst_price*(0.10)))
self.assertEqual(float_compare(
price, (product.lst_price-product.lst_price*(0.10)), precision_digits=2), 0, msg)
# I check sale price of Laptop.
product = self.laptop_E5023
price = self.customer_pricelist._get_product_price(product, quantity=1.0)
msg = "Wrong sale price: Laptop. should be %s instead of %s" % (price, (product.lst_price + 1))
self.assertEqual(float_compare(price, product.lst_price + 1, precision_digits=2), 0, msg)
# I check sale price of IT component.
product = self.apple_in_ear_headphones
price = self.customer_pricelist._get_product_price(product, quantity=1.0)
msg = "Wrong sale price: IT component. should be %s instead of %s" % (price, product.lst_price)
self.assertEqual(float_compare(price, product.lst_price, precision_digits=2), 0, msg)
# I check sale price of IT component if more than 3 Unit.
context.update({'quantity': 5})
product = self.laptop_S3450
price = self.customer_pricelist._get_product_price(product, quantity=5.0)
msg = "Wrong sale price: IT component if more than 3 Unit. should be %s instead of %s" % (price, (product.lst_price-product.lst_price*(0.05)))
self.assertEqual(float_compare(price, product.lst_price-product.lst_price*(0.05), precision_digits=2), 0, msg)
# I check sale price of LCD Monitor.
product = self.ipad_mini
price = self.customer_pricelist._get_product_price(product, quantity=1.0)
msg = "Wrong sale price: LCD Monitor. should be %s instead of %s" % (price, product.lst_price)
self.assertEqual(float_compare(price, product.lst_price, precision_digits=2), 0, msg)
# I check sale price of LCD Monitor on end of year.
price = self.customer_pricelist._get_product_price(product, quantity=1.0, date='2011-12-31')
msg = "Wrong sale price: LCD Monitor on end of year. should be %s instead of %s" % (price, product.lst_price-product.lst_price*(0.30))
self.assertEqual(float_compare(price, product.lst_price-product.lst_price*(0.30), precision_digits=2), 0, msg)
# Check if the pricelist is applied at precise datetime
product = self.monitor
price = self.customer_pricelist._get_product_price(product, quantity=1.0, date='2020-04-05 08:00:00')
context.update({'quantity': 1, 'date': datetime.strptime('2020-04-05 08:00:00', '%Y-%m-%d %H:%M:%S')})
msg = "Wrong cost price: LCD Monitor. should be 1000 instead of %s" % price
self.assertEqual(
float_compare(price, product.lst_price, precision_digits=2), 0,
msg)
price = self.customer_pricelist._get_product_price(product, quantity=1.0, date='2020-04-06 10:00:00')
msg = "Wrong cost price: LCD Monitor. should be 500 instead of %s" % price
self.assertEqual(
float_compare(price, product.lst_price/2, precision_digits=2), 0,
msg)
# Check if the price is different when we change the pricelist
product = self.product_multi_price
price = self.customer_pricelist._get_product_price(product, quantity=1.0)
msg = "Wrong price: Multi Product Price. should be 99 instead of %s" % price
self.assertEqual(float_compare(price, 99, precision_digits=2), 0, msg)
price = self.business_pricelist._get_product_price(product, quantity=1.0)
msg = "Wrong price: Multi Product Price. should be 50 instead of %s" % price
self.assertEqual(float_compare(price, 50, precision_digits=2), 0, msg)
def test_20_price_different_currency_pricelist(self):
pricelist = self.env['product.pricelist'].create({
'name': 'Currency Pricelist',
'currency_id': self.new_currency.id,
'item_ids': [(0, 0, {
'compute_price': 'formula',
'base': 'list_price',
'price_surcharge': 100
})]
})
price = pricelist._get_product_price(self.monitor, quantity=1.0)
# product price use the currency of the pricelist
self.assertEqual(price, 10100)
def test_21_price_diff_cur_min_margin_pricelist(self):
pricelist = self.env['product.pricelist'].create({
'name': 'Currency with Margin Pricelist',
'currency_id': self.new_currency.id,
'item_ids': [(0, 0, {
'compute_price': 'formula',
'base': 'list_price',
'price_min_margin': 10,
'price_max_margin': 100,
})]
})
price = pricelist._get_product_price(self.monitor, quantity=1.0)
# product price use the currency of the pricelist
self.assertEqual(price, 10010)
def test_22_price_diff_cur_max_margin_pricelist(self):
pricelist = self.env['product.pricelist'].create({
'name': 'Currency with Margin Pricelist',
'currency_id': self.new_currency.id,
'item_ids': [(0, 0, {
'compute_price': 'formula',
'base': 'list_price',
'price_surcharge': 100,
'price_max_margin': 90
})]
})
price = pricelist._get_product_price(self.monitor, quantity=1.0)
# product price use the currency of the pricelist
self.assertEqual(price, 10090)
def test_price_without_pricelist_fallback_product_price(self):
ProductPricelist = self.env['product.pricelist']
spam = self.env['product.product'].create({
'name': '1 tonne of spam',
'uom_id': self.uom_ton.id,
'uom_po_id': self.uom_ton.id,
'list_price': 100,
'type': 'consu'
})
self.assertEqual(
ProductPricelist._get_product_price(self.monitor, quantity=1.0),
self.monitor.list_price,
msg="without pricelist, the price should be the same as the list price",
)
self.assertEqual(
ProductPricelist._get_product_price(self.monitor, quantity=1.0, currency=self.new_currency),
self.monitor.list_price*10,
msg="without pricelist but with a currency different than the product one, the price "
"should be the same as the list price converted with the currency rate",
)
self.assertEqual(
ProductPricelist._get_product_price(spam, quantity=1.0, uom=self.uom_kgm),
spam.list_price / 1000,
msg="the product price should be converted using the specified uom",
)
self.assertEqual(
ProductPricelist._get_product_price(
spam, quantity=1.0, currency=self.new_currency, uom=self.uom_kgm
),
spam.list_price / 100,
msg="the product price should be converted using the specified uom and converted to the"
" correct currency",
)
def test_30_pricelist_delete(self):
""" Test that `unlink` on many records doesn't raise a RecursionError. """
self.customer_pricelist = self.env['product.pricelist'].create({
'name': 'Customer Pricelist',
'item_ids': [
Command.create({
'compute_price': 'formula',
'base': 'pricelist',
}),
] * 101,
})
self.customer_pricelist.unlink()
def test_40_pricelist_item_min_quantity_precision(self):
"""Test that the min_quantity has the precision of Product UoM."""
# Arrange: Change precision digits
uom_precision = self.env.ref("product.decimal_product_uom")
uom_precision.digits = 3
pricelist_item = first(self.customer_pricelist.item_ids[0])
precise_value = 1.234
# Act: Set a value for the increased precision
pricelist_item.min_quantity = precise_value
# Assert: The set value is kept
self.assertEqual(pricelist_item.min_quantity, precise_value)