From ca5608e606552e827e1b5d36ff07722ec26113f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 28 Mar 2026 17:54:47 +0100 Subject: [PATCH] Add ethanol volume to price list formula --- modules/stock_ethanol/doc/design.rst | 13 +++++ modules/stock_ethanol/product.py | 55 ++++++++++++++++++- modules/stock_ethanol/product.xml | 7 +++ modules/stock_ethanol/tests/test_module.py | 40 +++++++++++++- modules/stock_ethanol/tryton.cfg | 6 ++ .../view/product_price_list_line_form.xml | 10 ++++ 6 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 modules/stock_ethanol/view/product_price_list_line_form.xml diff --git a/modules/stock_ethanol/doc/design.rst b/modules/stock_ethanol/doc/design.rst index 301d263701..02209a3c0a 100644 --- a/modules/stock_ethanol/doc/design.rst +++ b/modules/stock_ethanol/doc/design.rst @@ -30,3 +30,16 @@ properties that define whether the product contains alcohol and its volume per The `Product ` concept is introduced by the :doc:`Product Module `. + +.. _model-product.price_list: + +Price List +========== + +When the *Stock Ethanol Module* is activated, a new parameter based on the +volume of ethanol is added to the *Price List* formula. + +.. seealso:: + + The Price List concept is introduced by the :doc:`Product Price List Module + `. diff --git a/modules/stock_ethanol/product.py b/modules/stock_ethanol/product.py index 54b9a89a22..b07ed2cc2d 100644 --- a/modules/stock_ethanol/product.py +++ b/modules/stock_ethanol/product.py @@ -1,11 +1,13 @@ # 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 sql.conditionals import Coalesce from trytond.model import fields from trytond.pool import Pool, PoolMeta -from trytond.pyson import Eval, If +from trytond.pyson import Eval, Id, If class Template(metaclass=PoolMeta): @@ -173,3 +175,54 @@ class Product(metaclass=PoolMeta): volume = quantity * self.volume * ethanol_by_volume unit = self.volume_uom return UoM.compute_qty(unit, volume, unit_volume, round=round) + + +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')) + + context = super().get_context_formula( + product, quantity, uom, pattern=pattern) + ethanol_volume = None + if product: + ethanol_volume = product.compute_ethanol_volume( + 1, product.default_uom, liter, round=False) + if ethanol_volume is None: + ethanol_volume = 0 + context['names']['ethanol_volume'] = Decimal(str(ethanol_volume)) + return context + + +class PriceListLine(metaclass=PoolMeta): + __name__ = 'product.price_list.line' + + ethanol_volume_uom = fields.Many2One( + 'product.uom', "AlcoholVolume UoM", + domain=[('category', '=', Id('product', 'uom_cat_volume'))], + help="Leave empty for liter.") + + @classmethod + def __setup__(cls): + super().__setup__() + cls.formula.help += ("\n" + "-ethanol_volume: the volume of alcohol in 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.ethanol_volume_uom: + context['names'] = context['names'].copy() + liter = UoM(ModelData.get_id('product', 'uom_liter')) + ethanol_volume = UoM.compute_qty( + liter, float(context['names']['ethanol_volume']), + self.ethanol_volume_uom, round=False) + context['names']['ethanol_volume'] = Decimal(str(ethanol_volume)) + return super().get_unit_price(**context) diff --git a/modules/stock_ethanol/product.xml b/modules/stock_ethanol/product.xml index 842412b41c..c4440c092f 100644 --- a/modules/stock_ethanol/product.xml +++ b/modules/stock_ethanol/product.xml @@ -21,4 +21,11 @@ this repository contains the full copyright notices and license terms. --> product_product_list + + + product.price_list.line + + product_price_list_line_form + + diff --git a/modules/stock_ethanol/tests/test_module.py b/modules/stock_ethanol/tests/test_module.py index 08512dc5d3..76b4fce254 100644 --- a/modules/stock_ethanol/tests/test_module.py +++ b/modules/stock_ethanol/tests/test_module.py @@ -1,6 +1,9 @@ # 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.modules.company.tests import create_company, set_company from trytond.pool import Pool from trytond.tests.test_tryton import ModuleTestCase, with_transaction @@ -8,7 +11,10 @@ from trytond.tests.test_tryton import ModuleTestCase, with_transaction class StockEthanolTestCase(ModuleTestCase): "Test Stock Ethanol module" module = 'stock_ethanol' - extras = ['account_stock_eu_excise', 'product_measurements'] + extras = [ + 'account_stock_eu_excise', + 'product_measurements', + 'product_price_list'] @with_transaction() def test_convert_quantity(self): @@ -53,5 +59,37 @@ class StockEthanolTestCase(ModuleTestCase): self.assertEqual(excise_tax.convert_quantity(product, 10), 1) + @with_transaction() + def test_price_list_context_formula(self): + "Test price list context formula" + 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', '=', "Liter")]) + cm3, = UoM.search([('name', '=', "Cubic centimeter")]) + + company = create_company() + with set_company(company): + template = Template( + name="Product", default_uom=unit, products=None, + list_price=Decimal('100'), + contain_ethanol=True, ethanol_by_volume=.2) + template.save() + product = Product(template=template) + product.save() + + price_list = PriceList( + name="List", price='list_price', + lines=[{ + 'formula': 'unit_price - .05 * ethanol_volume', + 'ethanol_volume_uom': cm3, + }]) + price_list.save() + + self.assertEqual(price_list.compute(product, 5, unit), Decimal(90)) + del ModuleTestCase diff --git a/modules/stock_ethanol/tryton.cfg b/modules/stock_ethanol/tryton.cfg index 68c27036b6..b620b9b1de 100644 --- a/modules/stock_ethanol/tryton.cfg +++ b/modules/stock_ethanol/tryton.cfg @@ -8,6 +8,7 @@ depends: extras_depend: account_stock_eu_excise product_measurements + product_price_list xml: product.xml stock.xml @@ -26,3 +27,8 @@ model: model: account_stock_eu.ExciseTax account_stock_eu.ExciseTaxRate + +[register product_price_list] +model: + product.PriceList + product.PriceListLine diff --git a/modules/stock_ethanol/view/product_price_list_line_form.xml b/modules/stock_ethanol/view/product_price_list_line_form.xml new file mode 100644 index 0000000000..852578e640 --- /dev/null +++ b/modules/stock_ethanol/view/product_price_list_line_form.xml @@ -0,0 +1,10 @@ + + + + + +