Add product volume and weight to price list formula

Closes #13926
This commit is contained in:
Cédric Krier
2025-03-17 18:24:14 +01:00
parent b7ee37bb0a
commit a5330ab1ff
7 changed files with 178 additions and 2 deletions
+1
View File
@@ -1,3 +1,4 @@
* Add volume and weight to price list formula
Version 7.6.0 - 2025-04-28
--------------------------
+70
View File
@@ -1,5 +1,8 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from decimal import Decimal
from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval, Id
@@ -120,3 +123,70 @@ class Template(metaclass=PoolMeta):
class Product(metaclass=PoolMeta):
__name__ = 'product.product'
class PriceList(metaclass=PoolMeta):
__name__ = 'product.price_list'
def get_context_formula(self, product, quantity, uom, pattern=None):
pool = Pool()
UoM = pool.get('product.uom')
ModelData = pool.get('ir.model.data')
liter = UoM(ModelData.get_id('product', 'uom_liter'))
kilogram = UoM(ModelData.get_id('product', 'uom_kilogram'))
context = super().get_context_formula(
product, quantity, uom, pattern=pattern)
volume = weight = 0
if product:
if product.volume is not None:
volume = UoM.compute_qty(
product.volume_uom, product.volume, liter, round=False)
if product.weight is not None:
weight = UoM.compute_qty(
product.weight_uom, product.weight, kilogram, round=False)
context['names']['volume'] = Decimal(str(volume))
context['names']['weight'] = Decimal(str(weight))
return context
class PriceListLine(metaclass=PoolMeta):
__name__ = 'product.price_list.line'
volume_uom = fields.Many2One(
'product.uom', "Volume UoM",
domain=[('category', '=', Id('product', 'uom_cat_volume'))],
help="Leave empty for liter.")
weight_uom = fields.Many2One(
'product.uom', "Weight UoM",
domain=[('category', '=', Id('product', 'uom_cat_weight'))],
help="Leave empty for kilogram.")
@classmethod
def __setup__(cls):
super().__setup__()
cls.formula.help += ("\n"
"-volume: the volume of 1 unit of product\n"
"-weight: the weight of 1 unit of product")
def get_unit_price(self, **context):
pool = Pool()
UoM = pool.get('product.uom')
ModelData = pool.get('ir.model.data')
if self.volume_uom:
context['names'] = context['names'].copy()
liter = UoM(ModelData.get_id('product', 'uom_liter'))
volume = UoM.compute_qty(
liter, float(context['names']['volume']), self.volume_uom,
round=False)
context['names']['volume'] = Decimal(str(volume))
if self.weight_uom:
context['names'] = context['names'].copy()
kilogram = UoM(ModelData.get_id('product', 'uom_kilogram'))
weight = UoM.compute_qty(
kilogram, float(context['names']['weight']), self.weight_uom,
round=False)
context['names']['weight'] = Decimal(str(weight))
return super().get_unit_price(**context)
+7
View File
@@ -11,4 +11,11 @@ this repository contains the full copyright notices and license terms. -->
</record>
</data>
<data depends="product_price_list">
<record model="ir.ui.view" id="product_price_list_line_view_form">
<field name="model">product.price_list.line</field>
<field name="inherit" ref="product_price_list.price_list_line_view_form"/>
<field name="name">product_price_list_line_form</field>
</record>
</data>
</tryton>
+7
View File
@@ -47,6 +47,10 @@ for dep in info.get('depends', []):
requires.append(get_require_version('trytond_%s' % dep))
requires.append(get_require_version('trytond'))
tests_require = [
get_require_version('trytond_product_price_list'),
]
setup(name=name,
version=version,
description='Tryton module to add measurements to product',
@@ -116,6 +120,9 @@ setup(name=name,
license='GPL-3',
python_requires='>=3.9',
install_requires=requires,
extras_require={
'test': tests_require,
},
zip_safe=False,
entry_points="""
[trytond.modules]
@@ -1,12 +1,85 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.tests.test_tryton import ModuleTestCase
from decimal import Decimal
from trytond.modules.company.tests import create_company, set_company
from trytond.pool import Pool
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
class ProductMeasurementsTestCase(ModuleTestCase):
'Test ProductMeasurements module'
"Test Product Measurements module"
module = 'product_measurements'
extras = ['product_price_list']
@with_transaction()
def test_price_list_context_formula_volume(self):
"Test price list context formula with volume"
pool = Pool()
Template = pool.get('product.template')
Product = pool.get('product.product')
UoM = pool.get('product.uom')
PriceList = pool.get('product.price_list')
unit, = UoM.search([('name', '=', "Unit")])
cm3, = UoM.search([('name', '=', "Cubic centimeter")])
inch3, = UoM.search([('name', '=', "Cubic inch")])
company = create_company()
with set_company(company):
template = Template(
name="Product", default_uom=unit, products=None,
list_price=Decimal('100'),
volume=2, volume_uom=cm3)
template.save()
product = Product(template=template)
product.save()
price_list = PriceList(
name="List", price='list_price',
lines=[{
'formula': 'unit_price + 5 * volume',
'volume_uom': inch3}])
price_list.save()
self.assertEqual(
price_list.compute(product, 5, unit),
Decimal('100.6102'))
@with_transaction()
def test_price_list_context_formula_weight(self):
"Test price list context formula with weight"
pool = Pool()
Template = pool.get('product.template')
Product = pool.get('product.product')
UoM = pool.get('product.uom')
PriceList = pool.get('product.price_list')
unit, = UoM.search([('name', '=', "Unit")])
gram, = UoM.search([('name', '=', "Gram")])
pound, = UoM.search([('name', '=', "Pound")])
company = create_company()
with set_company(company):
template = Template(
name="Product", default_uom=unit, products=None,
list_price=Decimal('100'),
weight=5, weight_uom=gram)
template.save()
product = Product(template=template)
product.save()
price_list = PriceList(
name="List", price='list_price',
lines=[{
'formula': 'unit_price + 5 * weight',
'weight_uom': pound}])
price_list.save()
self.assertEqual(
price_list.compute(product, 5, unit),
Decimal('100.0551'))
del ModuleTestCase
+7
View File
@@ -4,6 +4,8 @@ depends:
ir
product
res
extras_depend:
product_price_list
xml:
product.xml
@@ -11,3 +13,8 @@ xml:
model:
product.Template
product.Product
[register product_price_list]
model:
product.PriceList
product.PriceListLine
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="//field[@name='formula']" position="after">
<label name="volume_uom"/>
<field name="volume_uom" widget="selection"/>
<label name="weight_uom"/>
<field name="weight_uom" widget="selection"/>
</xpath>
</data>