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 ...@@ -29,7 +29,10 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import PropertySheet, Permissions from Products.ERP5Type import PropertySheet, Permissions
from Products.ERP5.Document.Predicate import Predicate from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5Type.Utils import UpperCase from Products.ERP5Type.Utils import UpperCase
from decimal import Decimal
from Products.ERP5.Tool.RoundingTool import ROUNDING_OPTION_DICT
import ExtensionClass import ExtensionClass
from math import log
class RoundingModel(Predicate): class RoundingModel(Predicate):
""" """
...@@ -56,34 +59,38 @@ class RoundingModel(Predicate): ...@@ -56,34 +59,38 @@ class RoundingModel(Predicate):
def roundValue(self, value): def roundValue(self, value):
if not value: if not value:
return 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: 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: else:
from decimal import Decimal
from Products.ERP5.Tool.RoundingTool import ROUNDING_OPTION_DICT
decimal_rounding_option = self.getDecimalRoundingOption() decimal_rounding_option = self.getDecimalRoundingOption()
if (decimal_rounding_option is None or if decimal_rounding_option not in ROUNDING_OPTION_DICT:
decimal_rounding_option not in ROUNDING_OPTION_DICT): raise ValueError('Decimal rounding option must be selected.')
raise ValueError, 'Decimal rounding option must be selected.'
def rounding_method(value, decimal_exponent, precision): def rounding_method(value, precision):
if precision is None: if precision is None:
precision = 0 precision = 1
if decimal_exponent is None:
if precision > 0: scale = int(log(precision, 10))
decimal_exponent = '1.' + '0' * precision 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: else:
decimal_exponent = '1'
result = float( result = float(
Decimal(str(value)).quantize(Decimal(decimal_exponent), Decimal(str(value)).quantize(Decimal(str(precision)),
rounding=decimal_rounding_option)) rounding=decimal_rounding_option))
if precision < 0:
# FIXME!!!!!
result = round(result, precision)
return result return result
return rounding_method(value, self.getDecimalExponent(), self.getPrecision()) return rounding_method(value, self.getPrecision())
security.declareProtected(Permissions.AccessContentsInformation, 'getRoundingProxy') security.declareProtected(Permissions.AccessContentsInformation, 'getRoundingProxy')
def getRoundingProxy(self, document): def getRoundingProxy(self, document):
...@@ -99,23 +106,14 @@ class RoundingModel(Predicate): ...@@ -99,23 +106,14 @@ class RoundingModel(Predicate):
temp_document = document._getOriginalDocument() temp_document = document._getOriginalDocument()
original_document = document original_document = document
else: else:
from Products.ERP5Type import Document temp_document = document.asContext()
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__)
original_document = temp_document original_document = temp_document
for property_id in rounding_model.getRoundedPropertyIdList(): for property_id in rounding_model.getRoundedPropertyIdList():
getter_name = 'get%s' % UpperCase(property_id) getter_name = 'get%s' % UpperCase(property_id)
getter = getattr(temp_document, getter = getattr(temp_document, getter_name, None)
getter_name, None)
setter_name = 'set%s' % UpperCase(property_id) setter_name = 'set%s' % UpperCase(property_id)
setter = getattr(temp_document, setter = getattr(temp_document, setter_name, None)
setter_name, None)
if getter is not None and setter is not None: if getter is not None and setter is not None:
# round the property value itself # round the property value itself
......
...@@ -47,8 +47,8 @@ class RoundingModel(DecimalOption): ...@@ -47,8 +47,8 @@ class RoundingModel(DecimalOption):
'default' : None, 'default' : None,
}, },
{ 'id' : 'precision', { 'id' : 'precision',
'description' : 'Precision value to be used for rounding. Rounding model accepts negative precision value as same as built-in round function.', 'description' : 'Precision value to be used for rounding, specified as a minimal unit.',
'type' : 'int', 'type' : 'float',
'mode' : 'w', 'mode' : 'w',
'default' : None, 'default' : None,
}, },
......
...@@ -81,7 +81,7 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -81,7 +81,7 @@ class TestRoundingTool(ERP5TypeTestCase):
# rounding model dummy never match to sale order line # rounding model dummy never match to sale order line
rounding_model_dummy= rounding_tool.newContent(portal_type='Rounding Model') rounding_model_dummy= rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_dummy.edit(decimal_rounding_option='ROUND_DOWN', rounding_model_dummy.edit(decimal_rounding_option='ROUND_DOWN',
precision=2, precision=0.01,
rounded_property_id_list=['price', rounded_property_id_list=['price',
'quantity', 'quantity',
'total_price']) 'total_price'])
...@@ -92,7 +92,7 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -92,7 +92,7 @@ class TestRoundingTool(ERP5TypeTestCase):
# add a rounding model for price of sale order line # add a rounding model for price of sale order line
rounding_model_1 = rounding_tool.newContent(portal_type='Rounding Model') rounding_model_1 = rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_1.edit(decimal_rounding_option='ROUND_DOWN', rounding_model_1.edit(decimal_rounding_option='ROUND_DOWN',
precision=2, precision=0.01,
rounded_property_id_list=['price']) rounded_property_id_list=['price'])
rounding_model_1.setCriterionProperty('portal_type') rounding_model_1.setCriterionProperty('portal_type')
rounding_model_1.setCriterion('portal_type', identity=['Sale Order Line'], rounding_model_1.setCriterion('portal_type', identity=['Sale Order Line'],
...@@ -113,7 +113,7 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -113,7 +113,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 0.0) self.assertEqual(wrapped_line.getProperty('quantity'), 0.0)
self.assertEqual(wrapped_line.getTotalPrice(), 0.0) self.assertEqual(wrapped_line.getTotalPrice(), 0.0)
self.assertEqual(wrapped_line.getProperty('total_price'), 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('quantity'), None)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None) self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
...@@ -141,7 +141,7 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -141,7 +141,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 78.91) self.assertEqual(wrapped_line.getProperty('quantity'), 78.91)
self.assertEqual(wrapped_line.getTotalPrice(), 123.45*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.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('quantity'), None)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None) self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
...@@ -149,7 +149,7 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -149,7 +149,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.login('developer') self.login('developer')
rounding_model_2 = rounding_tool.newContent(portal_type='Rounding Model') rounding_model_2 = rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_2.edit(decimal_rounding_option='ROUND_UP', rounding_model_2.edit(decimal_rounding_option='ROUND_UP',
precision=1, precision=0.1,
rounded_property_id_list=['quantity']) rounded_property_id_list=['quantity'])
transaction.commit() transaction.commit()
...@@ -166,7 +166,7 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -166,7 +166,7 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 78.91) self.assertEqual(wrapped_line.getProperty('quantity'), 78.91)
self.assertEqual(wrapped_line.getTotalPrice(), 123.45*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.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('quantity'), None)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None) self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
...@@ -185,15 +185,15 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -185,15 +185,15 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('quantity'), 79.0) self.assertEqual(wrapped_line.getProperty('quantity'), 79.0)
self.assertEqual(wrapped_line.getTotalPrice(), 123.45*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.getProperty('total_price'), 123.45*79.0)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 2) self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 0.01)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 1) self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 0.1)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None) self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), None)
# add a rounding model for total price of any portal type # add a rounding model for total price of any portal type
self.login('developer') self.login('developer')
rounding_model_3 = rounding_tool.newContent(portal_type='Rounding Model') rounding_model_3 = rounding_tool.newContent(portal_type='Rounding Model')
rounding_model_3.edit(decimal_rounding_option='ROUND_UP', rounding_model_3.edit(decimal_rounding_option='ROUND_UP',
precision=-1, precision=10,
rounded_property_id_list=['total_price']) rounded_property_id_list=['total_price'])
self.login('assignor') self.login('assignor')
...@@ -208,11 +208,11 @@ class TestRoundingTool(ERP5TypeTestCase): ...@@ -208,11 +208,11 @@ class TestRoundingTool(ERP5TypeTestCase):
self.assertEqual(wrapped_line.getProperty('price'), 123.45) self.assertEqual(wrapped_line.getProperty('price'), 123.45)
self.assertEqual(wrapped_line.getQuantity(), 79.0) self.assertEqual(wrapped_line.getQuantity(), 79.0)
self.assertEqual(wrapped_line.getProperty('quantity'), 79.0) self.assertEqual(wrapped_line.getProperty('quantity'), 79.0)
self.assertEqual(wrapped_line.getTotalPrice(), 9750.0) self.assertEqual(wrapped_line.getTotalPrice(), 9760.0)
self.assertEqual(wrapped_line.getProperty('total_price'), 9750.0) self.assertEqual(wrapped_line.getProperty('total_price'), 9760.0)
self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 2) self.assertEqual(wrapped_line.getRoundingModelPrecision('price'), 0.01)
self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 1) self.assertEqual(wrapped_line.getRoundingModelPrecision('quantity'), 0.1)
self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), -1) self.assertEqual(wrapped_line.getRoundingModelPrecision('total_price'), 10)
def test_suite(): 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