From 7c0db10440416461fd2ea7af90888e93a4e48115 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com>
Date: Thu, 27 Aug 2009 09:18:17 +0000
Subject: [PATCH] support more styles (thousand separator/decimal separator)
 for float fields.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@28652 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5Form/tests/testFields.py | 71 +++++++++++++++++++++++++++-
 product/Formulator/Validator.py      | 32 ++++++++++---
 product/Formulator/Widget.py         | 36 +++++++++++---
 3 files changed, 125 insertions(+), 14 deletions(-)

diff --git a/product/ERP5Form/tests/testFields.py b/product/ERP5Form/tests/testFields.py
index f8496c422a..cf56be6156 100644
--- a/product/ERP5Form/tests/testFields.py
+++ b/product/ERP5Form/tests/testFields.py
@@ -26,6 +26,8 @@
 #
 ##############################################################################
 
+# TODO: Some tests from this file can be merged into Formulator
+
 import unittest
 
 # Make it possible to use Globals.get_request
@@ -52,6 +54,7 @@ ZopeTestCase.installProduct('ERP5Form')
 
 from Acquisition import aq_base
 from Products.Formulator.FieldRegistry import FieldRegistry
+from Products.Formulator.Validator import ValidationError
 from Products.Formulator.StandardFields import FloatField
 from Products.Formulator.StandardFields import StringField
 from Products.Formulator.StandardFields import DateTimeField
@@ -93,11 +96,29 @@ class TestFloatField(unittest.TestCase):
   def setUp(self):
     self.field = FloatField('test_field')
     self.widget = self.field.widget
+    self.validator = self.field.validator
 
-  def test_format_thousand_separator(self):
+  def test_format_thousand_separator_point(self):
     self.field.values['input_style'] = '-1 234.5'
     self.assertEquals('1 000.0', self.widget.format_value(self.field, 1000))
-
+  
+  def test_format_thousand_separator_coma(self):
+    self.field.values['input_style'] = '-1 234,5'
+    self.assertEquals('1 000,0', self.widget.format_value(self.field, 1000))
+
+  def test_format_thousand_separator_point_coma(self):
+    self.field.values['input_style'] = '-1.234,5'
+    self.assertEquals('1.000,0', self.widget.format_value(self.field, 1000))
+
+  def test_format_thousand_separator_coma_point(self):
+    self.field.values['input_style'] = '-1,234.5'
+    self.assertEquals('1,000.0', self.widget.format_value(self.field, 1000))
+
+  def test_format_thousand_separator_first_separator(self):
+    # test for an edge case bug bug, ",100,000.0" was displayed (with leading coma)
+    self.field.values['input_style'] = '-1,234.5'
+    self.assertEquals('100,000.0', self.widget.format_value(self.field, 100000))
+  
   def test_format_percent_style(self):
     self.field.values['input_style'] = '-12.3%'
     self.assertEquals('10.0%', self.widget.format_value(self.field, 0.1))
@@ -138,6 +159,52 @@ class TestFloatField(unittest.TestCase):
     self.assertEquals('10000000000000000000.00',
                       self.field.render(10000000000000000000))
 
+  def test_validate_thousand_separator_point(self):
+    self.field.values['input_style'] = '-1 234.5'
+    request.set('field_test_field', '1 000.0')
+    self.assertEquals(1000,
+        self.validator.validate(self.field, 'field_test_field', request))
+  
+  def test_validate_thousand_separator_coma(self):
+    self.field.values['input_style'] = '-1 234,5'
+    request.set('field_test_field', '1 000,0')
+    self.assertEquals(1000,
+        self.validator.validate(self.field, 'field_test_field', request))
+
+  def test_validate_thousand_separator_point_coma(self):
+    self.field.values['input_style'] = '-1.234,5'
+    request.set('field_test_field', '1.000,0')
+    self.assertEquals(1000,
+        self.validator.validate(self.field, 'field_test_field', request))
+
+  def test_validate_thousand_separator_coma_point(self):
+    self.field.values['input_style'] = '-1,234.5'
+    request.set('field_test_field', '1,000.0')
+    self.assertEquals(1000,
+        self.validator.validate(self.field, 'field_test_field', request))
+
+  def test_validate_percent_style(self):
+    self.field.values['input_style'] = '-12.3%'
+    request.set('field_test_field', '10.0%')
+    self.assertEquals(0.1,
+        self.validator.validate(self.field, 'field_test_field', request))
+
+  def test_validate_not_float(self):
+    request.set('field_test_field', 'not_float')
+    self.assertRaises(ValidationError,
+        self.validator.validate, self.field, 'field_test_field', request)
+
+  def test_validate_two_comma(self):
+    self.field.values['input_style'] = '-1.234,5'
+    request.set('field_test_field', '1,000,0')
+    self.assertRaises(ValidationError,
+        self.validator.validate, self.field, 'field_test_field', request)
+
+  def test_validate_two_dots(self):
+    self.field.values['input_style'] = '-1,234.5'
+    request.set('field_test_field', '1.000.0')
+    self.assertRaises(ValidationError,
+        self.validator.validate, self.field, 'field_test_field', request)
 
 class TestStringField(unittest.TestCase):
   """Tests string field
diff --git a/product/Formulator/Validator.py b/product/Formulator/Validator.py
index d89c5bed23..b2a54282f9 100644
--- a/product/Formulator/Validator.py
+++ b/product/Formulator/Validator.py
@@ -294,16 +294,36 @@ class FloatValidator(StringBaseValidator):
     value = StringBaseValidator.validate(self, field, key, REQUEST)
     if value == "" and not field.get_value('required'):
       return value
-    value = value.replace(' ','')
+
+    input_style = field.get_value('input_style')
+    decimal_separator = ''
+    decimal_point = '.'
+
+    if input_style == "-1234.5":
+      decimal_point = '.'
+    elif input_style == '-1 234.5':
+      decimal_separator = ' '
+      decimal_point = '.'
+    elif input_style == '-1 234,5':
+      decimal_separator = ' '
+      decimal_point = ','
+    elif input_style == '-1.234,5':
+      decimal_separator = '.'
+      decimal_point = ','
+    elif input_style == '-1,234.5':
+      decimal_separator = ','
+      decimal_point = '.'
+
+    value = value.replace(decimal_separator,'')
     input_style = field.get_value('input_style')
-    if value.find(',') >= 0:
-      value = value.replace(',','.')
-    if value.find('%')>=0:
-      value = value.replace('%','')
+    if value.find(decimal_point) >= 0:
+      value = value.replace(decimal_point, '.')
+    if value.find('%') >= 0:
+      value = value.replace('%', '')
     try:
       value = float(value)
       if input_style.find('%')>=0:
-        value = value/100
+        value = value / 100
     except ValueError:
       self.raise_error('not_float', field)
     return value
diff --git a/product/Formulator/Widget.py b/product/Formulator/Widget.py
index 8916d69701..285116647d 100644
--- a/product/Formulator/Widget.py
+++ b/product/Formulator/Widget.py
@@ -1271,8 +1271,11 @@ class FloatWidget(TextWidget):
       "The type of float we should enter. "),
                                   default="-1234.5",
                                   items=[("-1234.5",  "-1234.5"),
-                                        ("-1 234.5", "-1 234.5"),
-                                        ("-12.3%", "-12.3%"),],
+                                         ("-1 234.5", "-1 234.5"),
+                                         ("-1 234,5", "-1 234,5"),
+                                         ("-1.234,5", "-1.234,5"),
+                                         ("-1,234.5", "-1,234.5"),
+                                         ("-12.3%", "-12.3%"),],
                                   required=1,
                                   size=1)
 
@@ -1309,17 +1312,38 @@ class FloatWidget(TextWidget):
           value = '%f' % float(original_value)
       value_list = value.split('.')
       integer = value_list[0]
-      if input_style.find(' ')>=0:
+      
+      decimal_separator = ''
+      decimal_point = '.'
+      
+      if input_style == "-1234.5":
+        decimal_point = '.'
+      elif input_style == '-1 234.5':
+        decimal_separator = ' '
+        decimal_point = '.'
+      elif input_style == '-1 234,5':
+        decimal_separator = ' '
+        decimal_point = ','
+      elif input_style == '-1.234,5':
+        decimal_separator = '.'
+        decimal_point = ','
+      elif input_style == '-1,234.5':
+        decimal_separator = ','
+        decimal_point = '.'
+
+      if input_style.find(decimal_separator) >= 0:
         integer = value_list[0]
-        i = len(integer)%3
+        i = len(integer) % 3
         value = integer[:i]
         while i != len(integer):
-          value += ' ' + integer[i:i+3]
+          value += decimal_separator + integer[i:i+3]
           i += 3
+        if value[0] == decimal_separator:
+          value = value[1:]
       else:
         value = value_list[0]
       if precision != 0:
-        value += '.'
+        value += decimal_point
       if precision not in (None,''):
         for i in range(0,precision):
           if i < len(value_list[1]):
-- 
2.30.9