[FIX] product: price computation based on cost

- Standard price (cost price) is there for variants and for product template when there are no
variant, as it has no sense the have one otherwise. Templates with variantS have a cost of 0.
- On the website, product shown are the product templates, but you select and then buy the product
product (variants).
- The pricelist can be set to make a discount based on the cost.

==> If such a pricelist is used, the product templates having more than 1 variant are shown with a
price of 0 until you can select the wanted variant

opw-3232621

closes odoo/odoo#124594

X-original-commit: 561eba8f2adece4c21ea46c1bd050779ea3dc676
Signed-off-by: Morgane Demesmaeker <edm@odoo.com>
This commit is contained in:
Demesmaeker
2023-06-12 12:41:45 +02:00
parent 9addf96178
commit 39a7cdca21
2 changed files with 44 additions and 3 deletions
@@ -594,6 +594,8 @@ class ProductTemplate(models.Model):
price = template[price_type] or 0.0
price_currency = template.currency_id
if price_type == 'standard_price':
if not price and template.product_variant_ids:
price = template.product_variant_ids[0].standard_price
price_currency = template.cost_currency_id
elif price_type == 'list_price':
price += template._get_attributes_extra_price()
@@ -2,11 +2,11 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from unittest.mock import patch
from odoo.fields import Command
from odoo.tests import tagged, TransactionCase
from odoo.addons.base.tests.common import TransactionCaseWithUserDemo, HttpCaseWithUserPortal
from odoo.addons.website.tools import MockRequest
from odoo.tests import tagged
from odoo.tests.common import HttpCase, TransactionCase
from odoo.tools import DotDict
''' /!\/!\
Calling `get_pricelist_available` after setting `property_product_pricelist` on
@@ -296,6 +296,45 @@ class TestWebsitePriceList(TransactionCase):
prices = product._get_sales_prices(self.list_christmas)
self.assertFalse('base_price' in prices[product.id])
def test_pricelist_item_based_on_cost_for_templates(self):
""" Test that `_get_sales_prices` from `product_template` computes the correct price when
the pricelist item is based on the cost of the product.
"""
pricelist = self.env['product.pricelist'].create({
'name': 'Pricelist base on cost',
'item_ids': [Command.create({
'base': 'standard_price',
'compute_price': 'percentage',
'percent_price': 10,
})]
})
pa = self.env['product.attribute'].create({'name': 'Attribute'})
pav1 = self.env['product.attribute.value'].create({'name': 'Value1', 'attribute_id': pa.id})
pav2 = self.env['product.attribute.value'].create({'name': 'Value2', 'attribute_id': pa.id})
product_template = self.env['product.template'].create({
'name': 'Product Template', 'list_price': 10.0, 'standard_price': 5.0
})
self.assertEqual(product_template.standard_price, 5)
price = product_template._get_sales_prices(pricelist)[product_template.id]['price_reduce']
msg = "Template has no variants, the price should be computed based on the template's cost."
self.assertEqual(price, 4.5, msg)
product_template.attribute_line_ids = [Command.create({
'attribute_id': pa.id, 'value_ids': [Command.set([pav1.id, pav2.id])]
})]
msg = "Product template with variants should have no cost."
self.assertEqual(product_template.standard_price, 0, msg)
self.assertEqual(product_template.product_variant_ids[0].standard_price, 0)
price = product_template._get_sales_prices(pricelist)[product_template.id]['price_reduce']
msg = "Template has variants, the price should be computed based on the 1st variant's cost."
self.assertEqual(price, 0, msg)
product_template.product_variant_ids[0].standard_price = 20
price = product_template._get_sales_prices(pricelist)[product_template.id]['price_reduce']
self.assertEqual(price, 18, msg)
def simulate_frontend_context(self, website_id=1):
# Mock this method will be enough to simulate frontend context in most methods