Commit 4e98e642 authored by Yoshinori Okuji's avatar Yoshinori Okuji

Fix various issues:

- make it really working with any precision
- change the precision to specify a minimal unit rather than a kind of scale
- fix some wrong assert conditions



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@39089 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 5d6661d0
......@@ -29,7 +29,10 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import PropertySheet, Permissions
from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5Type.Utils import UpperCase
from decimal import Decimal
from Products.ERP5.Tool.RoundingTool import ROUNDING_OPTION_DICT
import ExtensionClass
from math import log
class RoundingModel(Predicate):
"""
......@@ -56,34 +59,38 @@ class RoundingModel(Predicate):
def roundValue(self, value):
if not value:
return value
if self.getRoundingMethodId() is not None:
rounding_method = getattr(self, self.getRoundingMethodId(), None)
rounding_method_id = self.getRoundingMethodId()
if rounding_method_id is not None:
rounding_method = getattr(self, rounding_method_id, None)
if rounding_method is None:
raise ValueError, 'Rounding method (%s) was not found.'
raise ValueError('Rounding method (%s) was not found.' \
% (rounding_method_id,))
else:
from decimal import Decimal
from Products.ERP5.Tool.RoundingTool import ROUNDING_OPTION_DICT
decimal_rounding_option = self.getDecimalRoundingOption()
if (decimal_rounding_option is None or
decimal_rounding_option not in ROUNDING_OPTION_DICT):
raise ValueError, 'Decimal rounding option must be selected.'
def rounding_method(value, decimal_exponent, precision):
if decimal_rounding_option not in ROUNDING_OPTION_DICT:
raise ValueError('Decimal rounding option must be selected.')
def rounding_method(value, precision):
if precision is None:
precision = 0
if decimal_exponent is None:
if precision > 0:
decimal_exponent = '1.' + '0' * precision
else:
decimal_exponent = '1'
result = float(
Decimal(str(value)).quantize(Decimal(decimal_exponent),
rounding=decimal_rounding_option))
if precision < 0:
# FIXME!!!!!
result = round(result, precision)
precision = 1
scale = int(log(precision, 10))
if scale > 0:
value = Decimal(str(value))
scale = Decimal(str(int(precision))).quantize(value)
precision = Decimal('1')
value /= scale
value = value.quantize(precision, rounding=decimal_rounding_option)
value *= scale
result = float(value.quantize(precision))
else:
result = float(
Decimal(str(value)).quantize(Decimal(str(precision)),
rounding=decimal_rounding_option))
return result
return rounding_method(value, self.getDecimalExponent(), self.getPrecision())
return rounding_method(value, self.getPrecision())
security.declareProtected(Permissions.AccessContentsInformation, 'getRoundingProxy')
def getRoundingProxy(self, document):
......@@ -99,23 +106,14 @@ class RoundingModel(Predicate):
temp_document = document._getOriginalDocument()
original_document = document
else:
from Products.ERP5Type import Document
if document.__class__.__name__ == 'TempDocument':
class_ = document.__class__.__bases__[0]
else:
class_ = document.__class__
constructor = getattr(Document, 'newTemp%s' % class_.__name__)
temp_document = constructor(document.getParentValue(), 'id')
temp_document.__dict__.update(document.__dict__)
temp_document = document.asContext()
original_document = temp_document
for property_id in rounding_model.getRoundedPropertyIdList():
getter_name = 'get%s' % UpperCase(property_id)
getter = getattr(temp_document,
getter_name, None)
getter = getattr(temp_document, getter_name, None)
setter_name = 'set%s' % UpperCase(property_id)
setter = getattr(temp_document,
setter_name, None)
setter = getattr(temp_document, setter_name, None)
if getter is not None and setter is not None:
# round the property value itself
......
......@@ -47,8 +47,8 @@ class RoundingModel(DecimalOption):
'default' : None,
},
{ 'id' : 'precision',
'description' : 'Precision value to be used for rounding. Rounding model accepts negative precision value as same as built-in round function.',
'type' : 'int',
'description' : 'Precision value to be used for rounding, specified as a minimal unit.',
'type' : 'float',
'mode' : 'w',
'default' : None,
},
......
......@@ -81,7 +81,7 @@ class TestRoundingTool(ERP5TypeTestCase):
# rounding model dummy never match to sale order line
rounding_model_dummy= rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_dummy.edit(decimal_rounding_option='ROUND_DOWN',
precision=2,
precision=0.01,
rounded_property_id_list=['price',
'quantity',
'total_price'])
......@@ -92,7 +92,7 @@ class TestRoundingTool(ERP5TypeTestCase):
# add a rounding model for price of sale order line
rounding_model_1 = rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_1.edit(decimal_rounding_option='ROUND_DOWN',
precision=2,
precision=0.01,
rounded_property_id_list=['price'])
rounding_model_1.setCriterionProperty('portal_type')
rounding_model_1.setCriterion('portal_type', identity=['Sale Order Line'],
......@@ -113,7 +113,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 0.0)
self.assertEqual(wrapped_line.getTotalPrice(), 0.0)
self.assertEqual(wrapped_line.getProperty('total_price'), 0.0)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 2)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 0.01)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), None)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
......@@ -141,7 +141,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 78.91)
self.assertEqual(wrapped_line.getTotalPrice(), 123.45*78.91)
self.assertEqual(wrapped_line.getProperty('total_price'), 123.45*78.91)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 2)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 0.01)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), None)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
......@@ -149,7 +149,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.login('developer')
rounding_model_2 = rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_2.edit(decimal_rounding_option='ROUND_UP',
precision=1,
precision=0.1,
rounded_property_id_list=['quantity'])
transaction.commit()
......@@ -166,7 +166,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 78.91)
self.assertEqual(wrapped_line.getTotalPrice(), 123.45*78.91)
self.assertEqual(wrapped_line.getProperty('total_price'), 123.45*78.91)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 2)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 0.01)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), None)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
......@@ -185,15 +185,15 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 79.0)
self.assertEqual(wrapped_line.getTotalPrice(), 123.45*79.0)
self.assertEqual(wrapped_line.getProperty('total_price'), 123.45*79.0)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 2)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 1)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 0.01)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 0.1)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
# add a rounding model for total price of any portal type
self.login('developer')
rounding_model_3 = rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_3.edit(decimal_rounding_option='ROUND_UP',
precision=-1,
precision=10,
rounded_property_id_list=['total_price'])
self.login('assignor')
......@@ -208,11 +208,11 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('price'), 123.45)
self.assertEqual(wrapped_line.getQuantity(), 79.0)
self.assertEqual(wrapped_line.getProperty('quantity'), 79.0)
self.assertEqual(wrapped_line.getTotalPrice(), 9750.0)
self.assertEqual(wrapped_line.getProperty('total_price'), 9750.0)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 2)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 1)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), -1)
self.assertEqual(wrapped_line.getTotalPrice(), 9760.0)
self.assertEqual(wrapped_line.getProperty('total_price'), 9760.0)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 0.01)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 0.1)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), 10)
def test_suite():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment