@@ -1,3 +1,4 @@
|
||||
* Add volume and weight to price list formula
|
||||
|
||||
Version 7.6.0 - 2025-04-28
|
||||
--------------------------
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user