# Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.exceptions import UserError from odoo.fields import Command from odoo.tests import tagged, Form from odoo.addons.product.tests.common import ProductCommon @tagged('post_install', '-at_install') class TestPricelist(ProductCommon): @classmethod def setUpClass(cls): super().setUpClass() cls.datacard = cls.env['product.product'].create({'name': 'Office Lamp'}) cls.usb_adapter = cls.env['product.product'].create({'name': 'Office Chair'}) cls.sale_pricelist_id = cls.env['product.pricelist'].create({ 'name': 'Sale pricelist', 'item_ids': [ Command.create({ 'compute_price': 'formula', 'base': 'list_price', # based on public price 'price_discount': 10, 'product_id': cls.usb_adapter.id, 'applied_on': '0_product_variant', }), Command.create({ 'compute_price': 'formula', 'base': 'list_price', # based on public price 'price_surcharge': -0.5, 'product_id': cls.datacard.id, 'applied_on': '0_product_variant', }), Command.create({ 'compute_price': 'formula', 'base': 'standard_price', # based on cost 'price_markup': 99.99, 'applied_on': '3_global', }), ], }) # Enable pricelist feature cls.env.user.groups_id += cls.env.ref('product.group_product_pricelist') def test_10_discount(self): # Make sure the price using a pricelist is the same than without after # applying the computation manually self.assertEqual( self.pricelist._get_product_price(self.usb_adapter, 1.0)*0.9, self.sale_pricelist_id._get_product_price(self.usb_adapter, 1.0)) self.assertEqual( self.pricelist._get_product_price(self.datacard, 1.0)-0.5, self.sale_pricelist_id._get_product_price(self.datacard, 1.0)) self.assertAlmostEqual( self.sale_pricelist_id._get_product_price(self.usb_adapter, 1.0, uom=self.uom_unit)*12, self.sale_pricelist_id._get_product_price(self.usb_adapter, 1.0, uom=self.uom_dozen)) # price_surcharge applies to product default UoM, here "Units", so surcharge will be multiplied self.assertAlmostEqual( self.sale_pricelist_id._get_product_price(self.datacard, 1.0, uom=self.uom_unit)*12, self.sale_pricelist_id._get_product_price(self.datacard, 1.0, uom=self.uom_dozen)) def test_11_markup(self): """Ensure `price_markup` always equals negative `price_discount`.""" # Check create values for item in self.sale_pricelist_id.item_ids: self.assertEqual(item.price_markup, -item.price_discount) # Overwrite create values, and check again self.sale_pricelist_id.item_ids[0].price_discount = 0 self.sale_pricelist_id.item_ids[1].price_discount = -20.02 self.sale_pricelist_id.item_ids[2].price_markup = -0.5 for item in self.sale_pricelist_id.item_ids: self.assertEqual(item.price_markup, -item.price_discount) def test_20_pricelist_uom(self): # Verify that the pricelist rules are correctly using the product's default UoM # as reference, and return a result according to the target UoM (as specific in the context) tonne_price = 100 # make sure 'tonne' resolves down to 1 'kg'. self.uom_ton.write({'rounding': 0.001}) # setup product stored in 'tonnes', with a discounted pricelist for qty > 3 tonnes 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': tonne_price, 'type': 'consu' }) self.env['product.pricelist.item'].create({ 'pricelist_id': self.pricelist.id, 'applied_on': '0_product_variant', 'compute_price': 'formula', 'base': 'list_price', # based on public price 'min_quantity': 3, # min = 3 tonnes 'price_surcharge': -10, # -10 EUR / tonne 'product_id': spam.id }) def test_unit_price(qty, uom_id, expected_unit_price): uom = self.env['uom.uom'].browse(uom_id) unit_price = self.pricelist._get_product_price(spam, qty, uom=uom) self.assertAlmostEqual(unit_price, expected_unit_price, msg='Computed unit price is wrong') # Test prices - they are *per unit*, the quantity is only here to match the pricelist rules! test_unit_price(2, self.uom_kgm.id, tonne_price / 1000.0) test_unit_price(2000, self.uom_kgm.id, tonne_price / 1000.0) test_unit_price(3500, self.uom_kgm.id, (tonne_price - 10) / 1000.0) test_unit_price(2, self.uom_ton.id, tonne_price) test_unit_price(3, self.uom_ton.id, tonne_price - 10) def test_30_pricelists_order(self): # Verify the order of pricelists after creation ProductPricelist = self.env['product.pricelist'] res_partner = self.env['res.partner'].create({'name': 'Ready Corner'}) ProductPricelist.search([]).active = False pl_first = ProductPricelist.create({'name': 'First Pricelist'}) res_partner.invalidate_recordset(['property_product_pricelist']) self.assertEqual(res_partner.property_product_pricelist, pl_first) ProductPricelist.create({'name': 'Second Pricelist'}) res_partner.invalidate_recordset(['property_product_pricelist']) self.assertEqual(res_partner.property_product_pricelist, pl_first) def test_pricelists_multi_comp_checks(self): first_company = self.env.company second_company = self.env['res.company'].create({'name': 'Test Company'}) shared_pricelist = self.env['product.pricelist'].create({ 'name': 'Test Multi-comp pricelist', 'company_id': False, }) second_pricelist = self.env['product.pricelist'].create({ 'name': f'Second test pricelist{first_company.name}', }) self.assertEqual(self.pricelist.company_id, first_company) self.assertFalse(shared_pricelist.company_id) with self.assertRaises(UserError): shared_pricelist.item_ids = [ Command.create({ 'compute_price': 'formula', 'base': 'pricelist', 'base_pricelist_id': self.pricelist.id, }) ] self.pricelist.item_ids = [ Command.create({ 'compute_price': 'formula', 'base': 'pricelist', 'base_pricelist_id': shared_pricelist.id, }), Command.create({ 'compute_price': 'formula', 'base': 'pricelist', 'base_pricelist_id': second_pricelist.id, }) ] with self.assertRaises(UserError): self.pricelist.company_id = second_company def test_pricelists_res_partner_form(self): pricelist_europe = self.env['product.pricelist'].create({ 'name': 'Sale pricelist', 'country_group_ids': self.env.ref('base.europe').ids, }) default_pricelist = self.env['product.pricelist'].search([('name', 'ilike', ' ')], limit=1) with Form(self.env['res.partner']) as partner_form: partner_form.name = "test" self.assertEqual(partner_form.property_product_pricelist, default_pricelist) partner_form.country_id = self.env.ref('base.be') self.assertEqual(partner_form.property_product_pricelist, pricelist_europe) partner_form.property_product_pricelist = self.sale_pricelist_id self.assertEqual(partner_form.property_product_pricelist, self.sale_pricelist_id) partner = partner_form.save() with Form(partner) as partner_form: self.assertEqual(partner_form.property_product_pricelist, self.sale_pricelist_id)