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
1=== modified file 'addons/openerp/static/javascript/form.js'
2--- addons/openerp/static/javascript/form.js 2012-10-15 13:19:24 +0000
3+++ addons/openerp/static/javascript/form.js 2013-01-29 07:07:22 +0000
4@@ -178,6 +178,67 @@
5 return result;
6 }
7
8+function validate_digits(form){
9+ if (typeof form == 'string') {
10+ form = jQuery('#' + form).get(0);
11+ }
12+
13+ if (!form) {
14+ return true;
15+ }
16+
17+ var elements = MochiKit.Base.filter(function(el){
18+ return !el.disabled && el.id && el.name && el.id.indexOf('_terp_listfields/') == -1 && hasElementClass(el, 'digitsfield');
19+ }, form.elements);
20+
21+ var result = true;
22+ var nan_pattern = /[^0-9]/g;
23+
24+ for (var i = 0; i < elements.length; i++) {
25+ var elem = elements[i];
26+ var elem2 = elem;
27+ var value = elem.value;
28+ var kind = jQuery(elem).attr('kind');
29+ var digits = jQuery(elem).attr('digits');
30+ var set_class = false;
31+
32+ if(kind == 'float') {
33+ // extract sign and number from input value
34+ var sign = value[0] == '-' ? '-' : '';
35+ var integer_part = value.substring(sign.length), decimal_part = '';
36+
37+ elem2 = openobject.dom.get(elem.name + '_set') || elem;
38+ if(typeof(digits) == "string"){
39+ digits = eval(digits)
40+ }
41+
42+ // split float integer and decimal parts on last non decimal char
43+ var decimal_sep_position = integer_part.replace(nan_pattern, '.').lastIndexOf('.');
44+ if (decimal_sep_position !== -1) {
45+ decimal_part = integer_part.substring(decimal_sep_position+1);
46+ integer_part = integer_part.substring(0, decimal_sep_position);
47+ }
48+ if(value.length > digits[0] || decimal_part.length > digits[1])
49+ set_class = true;
50+
51+ }
52+
53+ if (set_class) {
54+ jQuery(elem2).addClass('errorfield');
55+ result = false;
56+ }
57+ else
58+ if (jQuery(elem2).hasClass('errorfield')) {
59+ jQuery(elem2).removeClass('errorfield');
60+ }
61+ }
62+
63+ if (!result) {
64+ error_display(_("Invalid form, correct red fields, enter value of float and integer field in range"));
65+ }
66+ return result;
67+}
68+
69 function error_display(msg) {
70 var error = jQuery("<table>",{'width': '100%', 'height': '100%'}
71 ).append(
72@@ -228,7 +289,7 @@
73 action = get_form_action(action, args);
74
75 var $form = jQuery('#view_form');
76- if (/\/save(\?|\/)?/.test(action) && !validate_required($form[0])) {
77+ if (/\/save(\?|\/)?/.test(action) && (!validate_required($form[0]) || !validate_digits($form[0]))) {
78 return;
79 }
80
81@@ -423,6 +484,11 @@
82 attrs['required'] = 1;
83 }
84
85+ if(extended && kind=='float') {
86+ var digits = $this.attr('digits');
87+ attrs['digit'] = typeof(digits) == "undefined" ? '' : digits;
88+ }
89+
90 switch (kind) {
91 case "picture":
92 name = this.id;
93@@ -806,7 +872,9 @@
94 if (fld) {
95 fld.focus();
96 fld.select();
97+ jQuery(fld).addClass('errorfield');
98 }
99+ return error_display(obj.error);
100 }
101
102 if (obj.error) {
103
104=== modified file 'addons/openerp/static/javascript/wizard.js'
105--- addons/openerp/static/javascript/wizard.js 2011-01-17 11:57:11 +0000
106+++ addons/openerp/static/javascript/wizard.js 2013-01-29 07:07:22 +0000
107@@ -38,7 +38,7 @@
108 act = '/openerp/wizard/report';
109 }
110
111- if (state != 'end' && !validate_required(form)) {
112+ if (state != 'end' && (!validate_required($form[0]) || !validate_digits($form[0]))) {
113 return;
114 }
115
116
117=== modified file 'addons/openerp/utils/utils.py'
118--- addons/openerp/utils/utils.py 2012-05-25 16:46:25 +0000
119+++ addons/openerp/utils/utils.py 2013-01-29 07:07:22 +0000
120@@ -343,7 +343,7 @@
121
122 v = _VALIDATORS.get(kind, openobject.validators.DefaultValidator)()
123 if kind == "float" and attrs.get("digit"):
124- v = validators.Float(digit=attrs.get("digit"))
125+ v = validators.Float(digits=attrs.get("digit"))
126 v.not_empty = (required or False) and True
127
128 try:
129
130=== modified file 'addons/openerp/validators.py'
131--- addons/openerp/validators.py 2012-07-30 08:07:39 +0000
132+++ addons/openerp/validators.py 2013-01-29 07:07:22 +0000
133@@ -70,14 +70,41 @@
134 class Int(formencode.validators.Int):
135 if_empty = False
136
137-class Float(formencode.validators.Number):
138+class Float(BaseValidator):
139 if_empty = False
140 digit = 2
141
142+ def __init__(self, kind="float",digits=False, *args, **kw):
143+ self.digits = digits
144+ super(Float, self).__init__(*args, **kw)
145+
146 def _from_python(self, value, state):
147 return format.format_decimal(float(value) or 0.0, self.digit)
148
149 def _to_python(self, value, state):
150+ if isinstance(self.digits, basestring):
151+ self.digits = eval(self.digits)
152+ if self.digits:
153+ try:
154+ nan_pattern = r"[^0-9]";
155+ sign = ''
156+ if value[0] == '-':
157+ sign = '-'
158+ integer_part = value[len(sign):]
159+ decimal_part = ''
160+ # split float integer and decimal parts on last non decimal char
161+ decimal_sep_position = re.subn(nan_pattern, '.', integer_part)
162+ if decimal_sep_position[1] != 0:
163+ decimal_sep_position = decimal_sep_position[0].rindex('.')
164+ else:
165+ decimal_sep_position = -1
166+ if decimal_sep_position != -1:
167+ decimal_part = integer_part[decimal_sep_position+1:]
168+ #integer_part = integer_part.substring(0, decimal_sep_position)
169+ if len(integer_part) > int(self.digits[0]) or len(decimal_part) > int(self.digits[1]):
170+ raise ValueError
171+ except ValueError:
172+ raise formencode.api.Invalid(_('Invalid literal for float'), value, state)
173 try:
174 value = format.parse_decimal(value)
175 except ValueError:
176
177=== modified file 'addons/openerp/widgets/form/_form.py'
178--- addons/openerp/widgets/form/_form.py 2012-02-29 07:24:24 +0000
179+++ addons/openerp/widgets/form/_form.py 2013-01-29 07:07:22 +0000
180@@ -426,17 +426,20 @@
181
182 class Float(TinyInputWidget):
183 template = "/openerp/widgets/form/templates/float.mako"
184+ params = ['digits']
185
186 def __init__(self, **attrs):
187 super(Float, self).__init__(**attrs)
188
189- digits = attrs.get('digits', (16,2))
190+ digits = attrs.get('digits', False)
191 if isinstance(digits, basestring):
192 digits = eval(digits)
193-
194- integer, digit = digits
195-
196- self.validator = validators.Float(digit=digit)
197+ #integer, digit = digits
198+ self.digits = digits
199+ if isinstance(self.digits, tuple):
200+ self.digits = list(self.digits)
201+
202+ self.validator = validators.Float(digits=digits)
203
204 # if not self.default:
205 # self.default = 0.0
206@@ -607,6 +610,7 @@
207 self.validator = self.widget.validator
208 self.relation = attrs.get('relation') or None
209 self.editable = self.readonly
210+
211 if 'field_id' not in attrs:
212 self.field_id = self.name
213
214
215=== modified file 'addons/openerp/widgets/form/templates/float.mako'
216--- addons/openerp/widgets/form/templates/float.mako 2011-10-05 10:10:37 +0000
217+++ addons/openerp/widgets/form/templates/float.mako 2013-01-29 07:07:22 +0000
218@@ -6,6 +6,7 @@
219 id ='${name}'
220 value="${value}"
221 size="1"
222+ digits="${digits}"
223 class="${css_class}" ${py.attrs(attrs, fld_required=required and 1 or 0, fld_readonly=readonly and 1 or 0)}/>
224 % endif
225
226
227=== modified file 'openobject/widgets/_base.py'
228--- openobject/widgets/_base.py 2010-12-20 09:57:11 +0000
229+++ openobject/widgets/_base.py 2013-01-29 07:07:22 +0000
230@@ -264,6 +264,7 @@
231 'required': "Whether the field value is required.",
232 'readonly': "Whether the field is readonly.",
233 'disabled': "Whether the field is disabled.",
234+ 'digits': "Whether field contains digits"
235 }
236
237 validator = DefaultValidator
238@@ -271,6 +272,7 @@
239 required = False
240 readonly = False
241 disabled = False
242+ digits = False
243
244 strip_name = False
245
246@@ -312,6 +314,10 @@
247 def is_readonly(self):
248 return self.readonly
249
250+ @property
251+ def has_digits(self):
252+ return self.digits
253+
254 def validate(self, value, state=None):
255 """Validate value using validator if widget has one. If validation fails
256 a formencode.Invalid exception will be raised.
257@@ -386,6 +392,9 @@
258 if self.is_disabled:
259 classes.append('disabledfield')
260
261+ if self.has_digits:
262+ classes.append('digitsfield')
263+
264 if getattr(params, 'error', None):
265 classes.append('errorfield')
266