Do not convert input when converting between the same unit
Applying the factor/rate twice may loose precision if one of the number is a rational with recurring decimal. Closes #14501
This commit is contained in:
@@ -130,6 +130,7 @@ class ProductTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
tests = [
|
||||
('Kilogram', 100, 'Gram', 100000, 100000),
|
||||
('Gram', 1, 'Pound', 0.0022046226218487759, 0.0),
|
||||
('Ounce', 1 / 7, 'Ounce', 1 / 7, 0.14),
|
||||
('Second', 5, 'Minute', 0.083333333333333343, 0.08),
|
||||
('Second', 25, 'Hour', 0.0069444444444444441, 0.01),
|
||||
('Millimeter', 3, 'Inch', 0.11811023622047245, 0.12),
|
||||
@@ -201,6 +202,7 @@ class ProductTestCase(CompanyTestMixin, ModuleTestCase):
|
||||
tests = [
|
||||
('Kilogram', Decimal('100'), 'Gram', Decimal('0.1')),
|
||||
('Gram', Decimal('1'), 'Pound', Decimal('453.59237')),
|
||||
('Ounce', Decimal(1 / 7), 'Ounce', Decimal(1 / 7)),
|
||||
('Second', Decimal('5'), 'Minute', Decimal('300')),
|
||||
('Second', Decimal('25'), 'Hour', Decimal('90000')),
|
||||
('Millimeter', Decimal('3'), 'Inch', Decimal('76.2')),
|
||||
|
||||
+39
-33
@@ -206,25 +206,28 @@ class Uom(SymbolMixin, DigitsMixin, DeactivableMixin, ModelSQL, ModelView):
|
||||
elif factor or rate:
|
||||
raise ValueError("factor and rate not allowed for same category")
|
||||
|
||||
if from_uom.accurate_field == 'factor':
|
||||
amount = qty * from_uom.factor
|
||||
else:
|
||||
amount = qty / from_uom.rate
|
||||
|
||||
if factor and rate:
|
||||
if _accurate_operator(factor, rate) == 'rate':
|
||||
factor = None
|
||||
if from_uom != to_uom:
|
||||
if from_uom.accurate_field == 'factor':
|
||||
amount = qty * from_uom.factor
|
||||
else:
|
||||
rate = None
|
||||
if factor:
|
||||
amount *= factor
|
||||
elif rate:
|
||||
amount /= rate
|
||||
amount = qty / from_uom.rate
|
||||
|
||||
if to_uom.accurate_field == 'factor':
|
||||
amount = amount / to_uom.factor
|
||||
if factor and rate:
|
||||
if _accurate_operator(factor, rate) == 'rate':
|
||||
factor = None
|
||||
else:
|
||||
rate = None
|
||||
if factor:
|
||||
amount *= factor
|
||||
elif rate:
|
||||
amount /= rate
|
||||
|
||||
if to_uom.accurate_field == 'factor':
|
||||
amount = amount / to_uom.factor
|
||||
else:
|
||||
amount = amount * to_uom.rate
|
||||
else:
|
||||
amount = amount * to_uom.rate
|
||||
amount = qty
|
||||
|
||||
if round:
|
||||
amount = to_uom.round(amount)
|
||||
@@ -254,27 +257,30 @@ class Uom(SymbolMixin, DigitsMixin, DeactivableMixin, ModelSQL, ModelView):
|
||||
elif factor or rate:
|
||||
raise ValueError("factor and rate not allow for same category")
|
||||
|
||||
format_ = '%%.%df' % uom_conversion_digits[1]
|
||||
if from_uom != to_uom:
|
||||
format_ = '%%.%df' % uom_conversion_digits[1]
|
||||
|
||||
if from_uom.accurate_field == 'factor':
|
||||
new_price = price / Decimal(format_ % from_uom.factor)
|
||||
else:
|
||||
new_price = price * Decimal(format_ % from_uom.rate)
|
||||
|
||||
if factor and rate:
|
||||
if _accurate_operator(factor, rate) == 'rate':
|
||||
factor = None
|
||||
if from_uom.accurate_field == 'factor':
|
||||
new_price = price / Decimal(format_ % from_uom.factor)
|
||||
else:
|
||||
rate = None
|
||||
if factor:
|
||||
new_price /= Decimal(factor)
|
||||
elif rate:
|
||||
new_price *= Decimal(rate)
|
||||
new_price = price * Decimal(format_ % from_uom.rate)
|
||||
|
||||
if to_uom.accurate_field == 'factor':
|
||||
new_price = new_price * Decimal(format_ % to_uom.factor)
|
||||
if factor and rate:
|
||||
if _accurate_operator(factor, rate) == 'rate':
|
||||
factor = None
|
||||
else:
|
||||
rate = None
|
||||
if factor:
|
||||
new_price /= Decimal(factor)
|
||||
elif rate:
|
||||
new_price *= Decimal(rate)
|
||||
|
||||
if to_uom.accurate_field == 'factor':
|
||||
new_price = new_price * Decimal(format_ % to_uom.factor)
|
||||
else:
|
||||
new_price = new_price / Decimal(format_ % to_uom.rate)
|
||||
else:
|
||||
new_price = new_price / Decimal(format_ % to_uom.rate)
|
||||
new_price = price
|
||||
|
||||
return new_price
|
||||
|
||||
|
||||
Reference in New Issue
Block a user