Skip to content

Commit

Permalink
[FIX] product: remove digits_precision from uom factor fields
Browse files Browse the repository at this point in the history
Remove the hardcoded precision of 12 on factor and factor_inv,
to use the complete natural precision of NUMERIC types,
preserving all significant digits.

e.g. a UoM with a factor_inv of 6.0 used to be computed as:
factor_inv: 6.0 -> factor: 0.166666666667 (1.0/6.0, rounded to 12 digits) -> factor_inv: 5.999999999988 (1.0/factor)
which could lead to errors such 12*0.166666666667 = 2.000000000004 instead of 2.0

Slightly changed the way the ORM handles float fields to allow setting `digits=0`
as a way to explicitly require a NUMERIC value but without enforcing/rounding
the values at the ORM level, i.e. a truly full-precision field.

NUMERIC type has unlimited precision but is less efficient so should not be
used as the default behaviour, which is why we keep float8 as an alternative.

Modified the view to display the product UOM factor with a 5 digits value by default.
This value is for usability purpose only, the field still accepts bigger precision, by
setting the `digits` option on the field in the form view.

This change is safe in a stable series, the `digits=0` alternative is
treated the same as the default `digits=None` everywhere in the framework,
except when creating the database field.
  • Loading branch information
csnauwaert authored and odony committed Oct 22, 2014
1 parent 7705f88 commit fa2f7b8
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 5 deletions.
4 changes: 2 additions & 2 deletions addons/product/product.py
Expand Up @@ -132,10 +132,10 @@ def create(self, cr, uid, data, context=None):
'name': fields.char('Unit of Measure', size=64, required=True, translate=True),
'category_id': fields.many2one('product.uom.categ', 'Category', required=True, ondelete='cascade',
help="Conversion between Units of Measure can only occur if they belong to the same category. The conversion will be made based on the ratios."),
'factor': fields.float('Ratio', required=True,digits=(12, 12),
'factor': fields.float('Ratio', required=True, digits=0, # force NUMERIC with unlimited precision
help='How much bigger or smaller this unit is compared to the reference Unit of Measure for this category:\n'\
'1 * (reference unit) = ratio * (this unit)'),
'factor_inv': fields.function(_factor_inv, digits=(12,12),
'factor_inv': fields.function(_factor_inv, digits=0, # force NUMERIC with unlimited precision
fnct_inv=_factor_inv_write,
string='Ratio',
help='How many times this Unit of Measure is bigger than the reference Unit of Measure in this category:\n'\
Expand Down
4 changes: 2 additions & 2 deletions addons/product/product_view.xml
Expand Up @@ -421,8 +421,8 @@
<field name="uom_type" on_change="onchange_type(uom_type)"/>
<label for="factor"/>
<div>
<field name="factor" attrs="{'invisible':[('uom_type','!=','smaller')]}"/>
<field name="factor_inv" attrs="{'invisible':[('uom_type','!=','bigger')]}"/>
<field name="factor" digits="[42,5]" attrs="{'invisible':[('uom_type','!=','smaller')]}"/>
<field name="factor_inv" digits="[42,5]" attrs="{'invisible':[('uom_type','!=','bigger')]}"/>
<p attrs="{'invisible':[('uom_type','!=','smaller')]}" class="oe_grey">
e.g: 1 * (reference unit) = ratio * (this unit)
</p>
Expand Down
7 changes: 6 additions & 1 deletion openerp/osv/orm.py
Expand Up @@ -592,7 +592,12 @@ def get_pg_type(f, type_override=None):
if field_type in FIELDS_TO_PGTYPES:
pg_type = (FIELDS_TO_PGTYPES[field_type], FIELDS_TO_PGTYPES[field_type])
elif issubclass(field_type, fields.float):
if f.digits:
# Explicit support for "falsy" digits (0, False) to indicate a
# NUMERIC field with no fixed precision. The values will be saved
# in the database with all significant digits.
# FLOAT8 type is still the default when there is no precision because
# it is faster for most operations (sums, etc.)
if f.digits is not None:
pg_type = ('numeric', 'NUMERIC')
else:
pg_type = ('float8', 'DOUBLE PRECISION')
Expand Down

0 comments on commit fa2f7b8

Please sign in to comment.