Merge lp:~openerp-dev/openobject-client-web/6.0-opw-584450-msh into lp:openobject-client-web

Proposed by Mohammed Shekha(Open ERP)
Status: Needs review
Proposed branch: lp:~openerp-dev/openobject-client-web/6.0-opw-584450-msh
Merge into: lp:openobject-client-web
Diff against target: 265 lines (+118/-9)
7 files modified
addons/openerp/static/javascript/form.js (+69/-1)
addons/openerp/static/javascript/wizard.js (+1/-1)
addons/openerp/utils/utils.py (+1/-1)
addons/openerp/validators.py (+28/-1)
addons/openerp/widgets/form/_form.py (+9/-5)
addons/openerp/widgets/form/templates/float.mako (+1/-0)
openobject/widgets/_base.py (+9/-0)
To merge this branch: bzr merge lp:~openerp-dev/openobject-client-web/6.0-opw-584450-msh
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+145315@code.launchpad.net

Description of the change

Hello,

Adds the feature of digits support in float field, currently in 6.0, id you have given digits=(16,2) then it does not restrict to enter value upto 16 in float field, it allows more than 16 digits, which should not happen, currently web-client only have validation for rounding precision using formencode, but here this fix will add oue own validation for digits length and rounding precision.

For demo:- add digits=(16,2) in any object's float field or use existing one, and enter digits 18, web-client will allow while submit the form, which should not happen, it should give "Invalid float literal" warning and ask client to enter proper data in float field, so for that changed the validators, mako and form.js(For submit form in formview).

Here in list editable view, submit form not going to call all the validation of editable list view done at py, so changed the validators.py for that so when to_python is called when send data to server, it will validate float data according attrs(digits).

Also checked in wizard, if wizard have float field then validation should also work in that.

Tested on on_change call when wrong data filled in float field, tested with one2many.

Please share your views on this and provide test cases, if you have any other, so that I can check this branch on that test cases also.

Thanks.

To post a comment you must log in.

Unmerged revisions

4901. By Mohammed Shekha<email address hidden>

[ADD]Adds the feature of digits support in float field, currently in 6.0, id you have given digits=(16,2) then it does not restrict to enter value upto 16 in float field, it allows more than 16 digits, which should not happen, currently web-client only have validation for rounding precision using formencode, but here this fix will add oue own validation for digits length and rounding precision.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'addons/openerp/static/javascript/form.js'
--- addons/openerp/static/javascript/form.js 2012-10-15 13:19:24 +0000
+++ addons/openerp/static/javascript/form.js 2013-01-29 07:07:22 +0000
@@ -178,6 +178,67 @@
178 return result;178 return result;
179}179}
180180
181function validate_digits(form){
182 if (typeof form == 'string') {
183 form = jQuery('#' + form).get(0);
184 }
185
186 if (!form) {
187 return true;
188 }
189
190 var elements = MochiKit.Base.filter(function(el){
191 return !el.disabled && el.id && el.name && el.id.indexOf('_terp_listfields/') == -1 && hasElementClass(el, 'digitsfield');
192 }, form.elements);
193
194 var result = true;
195 var nan_pattern = /[^0-9]/g;
196
197 for (var i = 0; i < elements.length; i++) {
198 var elem = elements[i];
199 var elem2 = elem;
200 var value = elem.value;
201 var kind = jQuery(elem).attr('kind');
202 var digits = jQuery(elem).attr('digits');
203 var set_class = false;
204
205 if(kind == 'float') {
206 // extract sign and number from input value
207 var sign = value[0] == '-' ? '-' : '';
208 var integer_part = value.substring(sign.length), decimal_part = '';
209
210 elem2 = openobject.dom.get(elem.name + '_set') || elem;
211 if(typeof(digits) == "string"){
212 digits = eval(digits)
213 }
214
215 // split float integer and decimal parts on last non decimal char
216 var decimal_sep_position = integer_part.replace(nan_pattern, '.').lastIndexOf('.');
217 if (decimal_sep_position !== -1) {
218 decimal_part = integer_part.substring(decimal_sep_position+1);
219 integer_part = integer_part.substring(0, decimal_sep_position);
220 }
221 if(value.length > digits[0] || decimal_part.length > digits[1])
222 set_class = true;
223
224 }
225
226 if (set_class) {
227 jQuery(elem2).addClass('errorfield');
228 result = false;
229 }
230 else
231 if (jQuery(elem2).hasClass('errorfield')) {
232 jQuery(elem2).removeClass('errorfield');
233 }
234 }
235
236 if (!result) {
237 error_display(_("Invalid form, correct red fields, enter value of float and integer field in range"));
238 }
239 return result;
240}
241
181function error_display(msg) {242function error_display(msg) {
182 var error = jQuery("<table>",{'width': '100%', 'height': '100%'}243 var error = jQuery("<table>",{'width': '100%', 'height': '100%'}
183 ).append(244 ).append(
@@ -228,7 +289,7 @@
228 action = get_form_action(action, args);289 action = get_form_action(action, args);
229290
230 var $form = jQuery('#view_form');291 var $form = jQuery('#view_form');
231 if (/\/save(\?|\/)?/.test(action) && !validate_required($form[0])) {292 if (/\/save(\?|\/)?/.test(action) && (!validate_required($form[0]) || !validate_digits($form[0]))) {
232 return;293 return;
233 }294 }
234295
@@ -423,6 +484,11 @@
423 attrs['required'] = 1;484 attrs['required'] = 1;
424 }485 }
425486
487 if(extended && kind=='float') {
488 var digits = $this.attr('digits');
489 attrs['digit'] = typeof(digits) == "undefined" ? '' : digits;
490 }
491
426 switch (kind) {492 switch (kind) {
427 case "picture":493 case "picture":
428 name = this.id;494 name = this.id;
@@ -806,7 +872,9 @@
806 if (fld) {872 if (fld) {
807 fld.focus();873 fld.focus();
808 fld.select();874 fld.select();
875 jQuery(fld).addClass('errorfield');
809 }876 }
877 return error_display(obj.error);
810 }878 }
811879
812 if (obj.error) {880 if (obj.error) {
813881
=== modified file 'addons/openerp/static/javascript/wizard.js'
--- addons/openerp/static/javascript/wizard.js 2011-01-17 11:57:11 +0000
+++ addons/openerp/static/javascript/wizard.js 2013-01-29 07:07:22 +0000
@@ -38,7 +38,7 @@
38 act = '/openerp/wizard/report';38 act = '/openerp/wizard/report';
39 }39 }
40 40
41 if (state != 'end' && !validate_required(form)) {41 if (state != 'end' && (!validate_required($form[0]) || !validate_digits($form[0]))) {
42 return;42 return;
43 }43 }
4444
4545
=== modified file 'addons/openerp/utils/utils.py'
--- addons/openerp/utils/utils.py 2012-05-25 16:46:25 +0000
+++ addons/openerp/utils/utils.py 2013-01-29 07:07:22 +0000
@@ -343,7 +343,7 @@
343343
344 v = _VALIDATORS.get(kind, openobject.validators.DefaultValidator)()344 v = _VALIDATORS.get(kind, openobject.validators.DefaultValidator)()
345 if kind == "float" and attrs.get("digit"):345 if kind == "float" and attrs.get("digit"):
346 v = validators.Float(digit=attrs.get("digit"))346 v = validators.Float(digits=attrs.get("digit"))
347 v.not_empty = (required or False) and True347 v.not_empty = (required or False) and True
348348
349 try:349 try:
350350
=== modified file 'addons/openerp/validators.py'
--- addons/openerp/validators.py 2012-07-30 08:07:39 +0000
+++ addons/openerp/validators.py 2013-01-29 07:07:22 +0000
@@ -70,14 +70,41 @@
70class Int(formencode.validators.Int):70class Int(formencode.validators.Int):
71 if_empty = False71 if_empty = False
7272
73class Float(formencode.validators.Number):73class Float(BaseValidator):
74 if_empty = False74 if_empty = False
75 digit = 275 digit = 2
7676
77 def __init__(self, kind="float",digits=False, *args, **kw):
78 self.digits = digits
79 super(Float, self).__init__(*args, **kw)
80
77 def _from_python(self, value, state):81 def _from_python(self, value, state):
78 return format.format_decimal(float(value) or 0.0, self.digit)82 return format.format_decimal(float(value) or 0.0, self.digit)
7983
80 def _to_python(self, value, state):84 def _to_python(self, value, state):
85 if isinstance(self.digits, basestring):
86 self.digits = eval(self.digits)
87 if self.digits:
88 try:
89 nan_pattern = r"[^0-9]";
90 sign = ''
91 if value[0] == '-':
92 sign = '-'
93 integer_part = value[len(sign):]
94 decimal_part = ''
95 # split float integer and decimal parts on last non decimal char
96 decimal_sep_position = re.subn(nan_pattern, '.', integer_part)
97 if decimal_sep_position[1] != 0:
98 decimal_sep_position = decimal_sep_position[0].rindex('.')
99 else:
100 decimal_sep_position = -1
101 if decimal_sep_position != -1:
102 decimal_part = integer_part[decimal_sep_position+1:]
103 #integer_part = integer_part.substring(0, decimal_sep_position)
104 if len(integer_part) > int(self.digits[0]) or len(decimal_part) > int(self.digits[1]):
105 raise ValueError
106 except ValueError:
107 raise formencode.api.Invalid(_('Invalid literal for float'), value, state)
81 try:108 try:
82 value = format.parse_decimal(value)109 value = format.parse_decimal(value)
83 except ValueError:110 except ValueError:
84111
=== modified file 'addons/openerp/widgets/form/_form.py'
--- addons/openerp/widgets/form/_form.py 2012-02-29 07:24:24 +0000
+++ addons/openerp/widgets/form/_form.py 2013-01-29 07:07:22 +0000
@@ -426,17 +426,20 @@
426426
427class Float(TinyInputWidget):427class Float(TinyInputWidget):
428 template = "/openerp/widgets/form/templates/float.mako"428 template = "/openerp/widgets/form/templates/float.mako"
429 params = ['digits']
429430
430 def __init__(self, **attrs):431 def __init__(self, **attrs):
431 super(Float, self).__init__(**attrs)432 super(Float, self).__init__(**attrs)
432433
433 digits = attrs.get('digits', (16,2))434 digits = attrs.get('digits', False)
434 if isinstance(digits, basestring):435 if isinstance(digits, basestring):
435 digits = eval(digits)436 digits = eval(digits)
436437 #integer, digit = digits
437 integer, digit = digits438 self.digits = digits
438439 if isinstance(self.digits, tuple):
439 self.validator = validators.Float(digit=digit)440 self.digits = list(self.digits)
441
442 self.validator = validators.Float(digits=digits)
440443
441# if not self.default:444# if not self.default:
442# self.default = 0.0445# self.default = 0.0
@@ -607,6 +610,7 @@
607 self.validator = self.widget.validator610 self.validator = self.widget.validator
608 self.relation = attrs.get('relation') or None611 self.relation = attrs.get('relation') or None
609 self.editable = self.readonly612 self.editable = self.readonly
613
610 if 'field_id' not in attrs:614 if 'field_id' not in attrs:
611 self.field_id = self.name615 self.field_id = self.name
612616
613617
=== modified file 'addons/openerp/widgets/form/templates/float.mako'
--- addons/openerp/widgets/form/templates/float.mako 2011-10-05 10:10:37 +0000
+++ addons/openerp/widgets/form/templates/float.mako 2013-01-29 07:07:22 +0000
@@ -6,6 +6,7 @@
6 id ='${name}' 6 id ='${name}'
7 value="${value}" 7 value="${value}"
8 size="1"8 size="1"
9 digits="${digits}"
9 class="${css_class}" ${py.attrs(attrs, fld_required=required and 1 or 0, fld_readonly=readonly and 1 or 0)}/>10 class="${css_class}" ${py.attrs(attrs, fld_required=required and 1 or 0, fld_readonly=readonly and 1 or 0)}/>
10% endif11% endif
1112
1213
=== modified file 'openobject/widgets/_base.py'
--- openobject/widgets/_base.py 2010-12-20 09:57:11 +0000
+++ openobject/widgets/_base.py 2013-01-29 07:07:22 +0000
@@ -264,6 +264,7 @@
264 'required': "Whether the field value is required.",264 'required': "Whether the field value is required.",
265 'readonly': "Whether the field is readonly.",265 'readonly': "Whether the field is readonly.",
266 'disabled': "Whether the field is disabled.",266 'disabled': "Whether the field is disabled.",
267 'digits': "Whether field contains digits"
267 }268 }
268269
269 validator = DefaultValidator270 validator = DefaultValidator
@@ -271,6 +272,7 @@
271 required = False272 required = False
272 readonly = False273 readonly = False
273 disabled = False274 disabled = False
275 digits = False
274276
275 strip_name = False277 strip_name = False
276278
@@ -312,6 +314,10 @@
312 def is_readonly(self):314 def is_readonly(self):
313 return self.readonly315 return self.readonly
314316
317 @property
318 def has_digits(self):
319 return self.digits
320
315 def validate(self, value, state=None):321 def validate(self, value, state=None):
316 """Validate value using validator if widget has one. If validation fails322 """Validate value using validator if widget has one. If validation fails
317 a formencode.Invalid exception will be raised.323 a formencode.Invalid exception will be raised.
@@ -386,6 +392,9 @@
386 if self.is_disabled:392 if self.is_disabled:
387 classes.append('disabledfield')393 classes.append('disabledfield')
388394
395 if self.has_digits:
396 classes.append('digitsfield')
397
389 if getattr(params, 'error', None):398 if getattr(params, 'error', None):
390 classes.append('errorfield')399 classes.append('errorfield')
391400