Price linked currency
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -12,10 +12,14 @@
|
||||
<field name="price_type"/>
|
||||
<label name="price_unit"/>
|
||||
<field name="price_unit"/>
|
||||
<label name="price_currency"/>
|
||||
<field name="price_currency"/>
|
||||
<label name="price_area"/>
|
||||
<field name="price_area"/>
|
||||
<label name="price_currency"/>
|
||||
<field name="price_currency"/>
|
||||
<label name="enable_linked_currency"/>
|
||||
<field name="enable_linked_currency"/>
|
||||
<label name="linked_currency"/>
|
||||
<field name="linked_currency"/>
|
||||
<label name="price_area"/>
|
||||
<field name="price_area"/>
|
||||
<label name="price_calendar"/>
|
||||
<field name="price_calendar"/>
|
||||
<label name="price_ct_size"/>
|
||||
|
||||
@@ -5536,6 +5536,65 @@ description</t></is></c>
|
||||
('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')
|
||||
|
||||
Reference in New Issue
Block a user