diff --git a/modules/price/price.py b/modules/price/price.py
index c74abc6..651fbb3 100755
--- a/modules/price/price.py
+++ b/modules/price/price.py
@@ -36,30 +36,51 @@ class Price(
('composite', 'Composite'),
], 'Index type')
price_type = fields.Many2One('price.fixtype', "Fixation type")
- price_unit = fields.Many2One('product.uom', "Unit")
- price_currency = fields.Many2One('currency.currency', "Currency")
- price_area = fields.Many2One('price.area',"Market area")
- price_calendar = fields.Many2One('price.calendar',"Calendar")
- price_values = fields.One2Many('price.price_value', 'price', "Prices Values")
- price_composite = fields.One2Many('price.composite','price',"Composites")
- price_product = fields.One2Many('price.product', 'price', "Product")
+ price_unit = fields.Many2One('product.uom', "Unit")
+ price_currency = fields.Many2One('currency.currency', "Currency")
+ enable_linked_currency = fields.Boolean("Linked currency")
+ linked_currency = fields.Many2One('currency.linked', "Linked currency",
+ domain=[
+ ('currency', '=', Eval('price_currency')),
+ ],
+ states={
+ 'invisible': ~Eval('enable_linked_currency'),
+ 'required': Eval('enable_linked_currency'),
+ }, depends=['enable_linked_currency', 'price_currency'])
+ price_area = fields.Many2One('price.area',"Market area")
+ price_calendar = fields.Many2One('price.calendar',"Calendar")
+ price_values = fields.One2Many('price.price_value', 'price', "Prices Values")
+ price_composite = fields.One2Many('price.composite','price',"Composites")
+ price_product = fields.One2Many('price.product', 'price', "Product")
price_ct_size = fields.Numeric("Ct size")
- def get_qt(self,nb_ct,unit):
- Uom = Pool().get('product.uom')
- return round(Decimal(Uom.compute_qty(self.price_unit, float(self.price_ct_size * nb_ct), unit)),4)
-
- def get_price_per_qt(self,price,unit,currency):
- price_qt = float(0)
- Uom = Pool().get('product.uom')
- Currency = Pool().get('currency.currency')
- if currency != self.price_currency:
- rates = Currency._get_rate([self.price_currency])
- if rates[self.price_currency.id]:
- price_qt = float(price) * Uom.compute_qty(unit, float(1), self.price_unit) * float(rates[self.price_currency.id])
- else:
- price_qt = float(price) * Uom.compute_qty(unit, float(1), self.price_unit)
- return round(price_qt,4)
+ def get_qt(self,nb_ct,unit):
+ Uom = Pool().get('product.uom')
+ return round(Decimal(Uom.compute_qty(self.price_unit, float(self.price_ct_size * nb_ct), unit)),4)
+
+ def _price_in_main_currency(self, price):
+ price = Decimal(str(price or 0))
+ if self.enable_linked_currency and self.linked_currency:
+ factor = Decimal(self.linked_currency.factor or 0)
+ if factor:
+ price *= factor
+ return price
+
+ def get_price_per_qt(self,price,unit,currency):
+ price_qt = Decimal(0)
+ Uom = Pool().get('product.uom')
+ Currency = Pool().get('currency.currency')
+ price = self._price_in_main_currency(price)
+ unit_factor = Decimal(str(
+ Uom.compute_qty(unit, float(1), self.price_unit) or 0))
+ if currency != self.price_currency:
+ rates = Currency._get_rate([self.price_currency])
+ if rates[self.price_currency.id]:
+ price_qt = price * unit_factor * Decimal(str(
+ rates[self.price_currency.id]))
+ else:
+ price_qt = price * unit_factor
+ return round(price_qt,4)
def get_amount_nb_ct(self,price,nb_ct,unit,currency):
amount = Decimal(0)
diff --git a/modules/price/view/price_form.xml b/modules/price/view/price_form.xml
index 6f4a3a2..1d4ed45 100755
--- a/modules/price/view/price_form.xml
+++ b/modules/price/view/price_form.xml
@@ -12,10 +12,14 @@
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py
index 3bbabda..ed27cd5 100644
--- a/modules/purchase_trade/tests/test_module.py
+++ b/modules/purchase_trade/tests/test_module.py
@@ -5536,6 +5536,65 @@ description
('price_date', '<=', '2026-04-10'),
], order=[('price_date', 'DESC')])
+ def test_price_get_price_per_qt_converts_linked_currency_to_main_currency(self):
+ 'price curve values in linked currency are normalized to main currency'
+ Price = Pool().get('price.price')
+ price = Price()
+ usd = SimpleNamespace(id=1)
+ price.price_currency = usd
+ price.enable_linked_currency = True
+ price.linked_currency = SimpleNamespace(factor=Decimal('0.01'))
+ price.price_unit = SimpleNamespace()
+
+ uom_model = Mock(compute_qty=Mock(return_value=1))
+ currency_model = Mock()
+
+ def get_model(name):
+ if name == 'product.uom':
+ return uom_model
+ if name == 'currency.currency':
+ return currency_model
+ return Mock()
+
+ with patch('trytond.modules.price.price.Pool') as PricePool:
+ PricePool.return_value.get.side_effect = get_model
+ result = price.get_price_per_qt(Decimal('72.5'), Mock(), usd)
+
+ self.assertEqual(result, Decimal('0.7250'))
+ currency_model._get_rate.assert_not_called()
+
+ def test_price_get_price_applies_linked_currency_conversion(self):
+ 'market price lookup applies linked currency conversion'
+ Price = Pool().get('price.price')
+ price = Price()
+ price.id = 42
+ usd = SimpleNamespace(id=1)
+ price.price_currency = usd
+ price.enable_linked_currency = True
+ price.linked_currency = SimpleNamespace(factor=Decimal('0.01'))
+ price.price_unit = SimpleNamespace()
+ price.price_values = [Mock()]
+ price_value = Mock(price_value=Decimal('72.5'))
+ price_value_model = Mock(
+ search=Mock(return_value=[price_value]))
+ uom_model = Mock(compute_qty=Mock(return_value=1))
+
+ def get_model(name):
+ if name == 'price.price_value':
+ return price_value_model
+ if name == 'product.uom':
+ return uom_model
+ if name == 'currency.currency':
+ return Mock()
+ return Mock()
+
+ with patch('trytond.modules.price.price.Pool') as PricePool:
+ PricePool.return_value.get.side_effect = get_model
+ result = price.get_price(
+ datetime.date(2026, 4, 10), Mock(), usd, last=True)
+
+ self.assertEqual(result, Decimal('0.7250'))
+
def test_pricing_component_matrix_prefers_specific_line_over_generic(self):
'matrix pricing keeps generic lines as fallback below matching lines'
Component = Pool().get('pricing.component')