diff --git a/modules/price/price.py b/modules/price/price.py
index 651fbb3..da0f087 100755
--- a/modules/price/price.py
+++ b/modules/price/price.py
@@ -89,9 +89,15 @@ class Price(
amount = Decimal(self.get_price_per_qt(price,unit,currency)) * Decimal(Uom.compute_qty(self.price_unit, float(self.price_ct_size * nb_ct), unit))
return round(amount,4)
- def get_price(self,dt,unit,currency,last=False, relative_last=False):
+ def get_price(
+ self, dt, unit, currency, last=False, relative_last=False,
+ price_field='price_value'):
price = float(0)
PV = Pool().get('price.price_value')
+ price_field = price_field or 'price_value'
+ if price_field not in {
+ 'price_value', 'low_price', 'mid_price', 'high_price'}:
+ price_field = 'price_value'
if self.price_values:
dt = dt.strftime("%Y-%m-%d")
pv = PV.search([('price','=',self.id),('price_date','=',dt)])
@@ -103,7 +109,8 @@ class Price(
('price_date','<=',dt),
], order=[('price_date', 'DESC')])
if pv:
- price = self.get_price_per_qt(pv[0].price_value,unit,currency)
+ price = self.get_price_per_qt(
+ getattr(pv[0], price_field, None), unit, currency)
return round(price,4)
class FixType(ModelSQL,ModelView):
diff --git a/modules/purchase_trade/pricing.py b/modules/purchase_trade/pricing.py
index 8674498..768c178 100755
--- a/modules/purchase_trade/pricing.py
+++ b/modules/purchase_trade/pricing.py
@@ -886,17 +886,15 @@ class MtmStrategy(ModelSQL, ModelView):
for comp in self.components:
value = Decimal(0)
- if comp.price_source_type == 'curve' and comp.price_index:
- value = Decimal(
- comp.price_index.get_price(
- dt,
- line.unit,
- self.currency,
- relative_last=scenario.use_last_price
- )
- )
-
- elif comp.price_source_type == 'matrix' and comp.price_matrix:
+ if comp.price_source_type == 'curve' and comp.price_index:
+ value = Decimal(comp.get_price(
+ dt,
+ line.unit,
+ self.currency,
+ relative_last=scenario.use_last_price
+ ))
+
+ elif comp.price_source_type == 'matrix' and comp.price_matrix:
value = self._get_matrix_price(comp, line, dt)
elif comp.price_source_type == 'fixed':
@@ -1104,11 +1102,22 @@ class Component(ModelSQL, ModelView):
required=False, ondelete='CASCADE'
)
- price_source_type = fields.Selection([
- ('curve', 'Curve'),
- ('matrix', 'Matrix'),
- ('fixed', 'Fixed'),
- ], "Price Source", required=True)
+ price_source_type = fields.Selection([
+ ('curve', 'Curve'),
+ ('matrix', 'Matrix'),
+ ('fixed', 'Fixed'),
+ ], "Price Source", required=True)
+ curve_price_field = fields.Selection([
+ ('price_value', 'Price'),
+ ('low_price', 'Low'),
+ ('mid_price', 'Mid'),
+ ('high_price', 'High'),
+ ], "Curve Value",
+ states={
+ 'readonly': Eval('price_source_type') != 'curve',
+ 'required': Eval('price_source_type') == 'curve',
+ },
+ depends=['price_source_type'])
fix_type = fields.Many2One('price.fixtype',"Fixation type")
ratio = fields.Numeric("%",digits=(16,7))
@@ -1197,6 +1206,10 @@ class Component(ModelSQL, ModelView):
if is_itsa_company():
return Decimal('100')
+ @classmethod
+ def default_curve_price_field(cls):
+ return 'price_value'
+
@classmethod
def default_calendar(cls):
if is_itsa_company():
@@ -1393,7 +1406,8 @@ class Component(ModelSQL, ModelView):
PI = Pool().get('price.price')
pi = PI(self.price_index)
return pi.get_price(
- price_date, unit, currency, last, relative_last)
+ price_date, unit, currency, last, relative_last,
+ self.curve_price_field or 'price_value')
if self.price_source_type == 'matrix' and self.price_matrix:
if not self._matrix_valid_on(price_date):
return Decimal(0)
diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py
index 9a5ee16..fed59a6 100644
--- a/modules/purchase_trade/tests/test_module.py
+++ b/modules/purchase_trade/tests/test_module.py
@@ -6060,7 +6060,27 @@ description
self.assertEqual(price, Decimal('101'))
price_index.get_price.assert_called_once_with(
- datetime.date(2026, 4, 1), ANY, ANY, False, True)
+ datetime.date(2026, 4, 1), ANY, ANY, False, True, 'price_value')
+
+ def test_pricing_component_curve_passes_selected_price_field(self):
+ 'curve pricing can select high, mid or low values'
+ Component = Pool().get('pricing.component')
+ price_index = Mock()
+ component = Component()
+ component.price_source_type = 'curve'
+ component.price_index = price_index
+ component.curve_price_field = 'high_price'
+ price_model = Mock(return_value=price_index)
+ price_index.get_price = Mock(return_value=Decimal('103'))
+
+ with patch('trytond.modules.purchase_trade.pricing.Pool') as PricingPool:
+ PricingPool.return_value.get.return_value = price_model
+ price = component.get_price(
+ datetime.date(2026, 4, 1), Mock(), Mock(), False, True)
+
+ self.assertEqual(price, Decimal('103'))
+ price_index.get_price.assert_called_once_with(
+ datetime.date(2026, 4, 1), ANY, ANY, False, True, 'high_price')
def test_price_get_price_relative_last_uses_latest_before_date(self):
'relative last picks latest available price before target date'
@@ -6085,6 +6105,28 @@ description
('price_date', '<=', '2026-04-10'),
], order=[('price_date', 'DESC')])
+ def test_price_get_price_uses_selected_price_field(self):
+ 'market price lookup can read low, mid or high values'
+ Price = Pool().get('price.price')
+ price = Price()
+ price.id = 42
+ price.price_values = [Mock()]
+ price.get_price_per_qt = Mock(return_value=Decimal('91'))
+ price_value = Mock(
+ price_value=Decimal('88'),
+ high_price=Decimal('91'))
+ price_value_model = Mock(search=Mock(return_value=[price_value]))
+
+ with patch('trytond.modules.price.price.Pool') as PricePool:
+ PricePool.return_value.get.return_value = price_value_model
+ result = price.get_price(
+ datetime.date(2026, 4, 10), Mock(), Mock(),
+ price_field='high_price')
+
+ self.assertEqual(result, Decimal('91'))
+ price.get_price_per_qt.assert_called_once_with(
+ Decimal('91'), ANY, ANY)
+
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')
diff --git a/modules/purchase_trade/valuation.py b/modules/purchase_trade/valuation.py
index 1d63b2c..c73bd43 100644
--- a/modules/purchase_trade/valuation.py
+++ b/modules/purchase_trade/valuation.py
@@ -637,7 +637,7 @@ class ValuationBase(ModelSQL):
value = Decimal(0)
if comp.price_source_type == 'curve' and comp.price_index:
- value = Decimal(comp.price_index.get_price(
+ value = Decimal(comp.get_price(
valuation_date,
line.unit,
strategy.currency,
@@ -755,7 +755,9 @@ class ValuationBase(ModelSQL):
return abs(ratio) if ratio else Decimal(100)
@classmethod
- def _previous_curve_price(cls, curve, price_date, unit, currency):
+ def _previous_curve_price(
+ cls, curve, price_date, unit, currency,
+ price_field='price_value'):
PriceValue = Pool().get('price.price_value')
previous = PriceValue.search([
('price', '=', curve.id),
@@ -764,13 +766,14 @@ class ValuationBase(ModelSQL):
if not previous:
return None
return Decimal(curve.get_price(
- previous[0].price_date, unit, currency, last=False))
+ previous[0].price_date, unit, currency, last=False,
+ price_field=price_field))
@classmethod
def _curve_component_price(cls, component, line, strategy):
scenario = strategy.scenario
valuation_date = cls._strategy_valuation_date(strategy)
- value = Decimal(component.price_index.get_price(
+ value = Decimal(component.get_price(
valuation_date,
line.unit,
strategy.currency,
@@ -779,7 +782,8 @@ class ValuationBase(ModelSQL):
component.price_index,
valuation_date,
line.unit,
- strategy.currency)
+ strategy.currency,
+ price_field=getattr(component, 'curve_price_field', None))
return round(value, 4), (
round(previous, 4) if previous is not None else None)
diff --git a/modules/purchase_trade/view/component_form.xml b/modules/purchase_trade/view/component_form.xml
index 0410909..f795ab2 100755
--- a/modules/purchase_trade/view/component_form.xml
+++ b/modules/purchase_trade/view/component_form.xml
@@ -9,6 +9,9 @@
+
+
+
diff --git a/modules/purchase_trade/view/component_form2.xml b/modules/purchase_trade/view/component_form2.xml
index 98df723..e01edc0 100755
--- a/modules/purchase_trade/view/component_form2.xml
+++ b/modules/purchase_trade/view/component_form2.xml
@@ -9,6 +9,9 @@
+
+
+
diff --git a/modules/purchase_trade/view/component_tree.xml b/modules/purchase_trade/view/component_tree.xml
index e1aa6ae..2271bd4 100755
--- a/modules/purchase_trade/view/component_tree.xml
+++ b/modules/purchase_trade/view/component_tree.xml
@@ -3,6 +3,7 @@
+
diff --git a/modules/purchase_trade/view/component_tree_sequence.xml b/modules/purchase_trade/view/component_tree_sequence.xml
index f8a5bd4..6d590f8 100755
--- a/modules/purchase_trade/view/component_tree_sequence.xml
+++ b/modules/purchase_trade/view/component_tree_sequence.xml
@@ -3,6 +3,7 @@
+
diff --git a/modules/purchase_trade/view/component_tree_sequence2.xml b/modules/purchase_trade/view/component_tree_sequence2.xml
index 670ef23..913dfd0 100755
--- a/modules/purchase_trade/view/component_tree_sequence2.xml
+++ b/modules/purchase_trade/view/component_tree_sequence2.xml
@@ -3,6 +3,7 @@
+