import psycopg2
import openerp.addons.decimal_precision as dp
-from openerp.tools.float_utils import float_round
+from openerp.tools.float_utils import float_round, float_compare
def ean_checksum(eancode):
"""returns the checksum of an ean string of length 13, returns -1 if the string has the wrong length"""
string='Bigger Ratio',
help='How many times this Unit of Measure is bigger than the reference Unit of Measure in this category:\n'\
'1 * (this unit) = ratio * (reference unit)', required=True),
- 'rounding': fields.float('Rounding Precision', digits_compute=dp.get_precision('Product Unit of Measure'), required=True,
+ 'rounding': fields.float('Rounding Precision', digits=0, required=True,
help="The computed quantity will be a multiple of this value. "\
"Use 1.0 for a Unit of Measure that cannot be further split, such as a piece."),
'active': fields.boolean('Active', help="By unchecking the active field you can disable a unit of measure without deleting it."),
_defaults = {
'active': 1,
'rounding': 0.01,
+ 'factor': 1,
'uom_type': 'reference',
+ 'factor': 1.0,
}
_sql_constraints = [
('factor_gt_zero', 'CHECK (factor!=0)', 'The conversion ratio for a unit of measure cannot be 0!')
]
- def _compute_qty(self, cr, uid, from_uom_id, qty, to_uom_id=False, round=True):
+ def _compute_qty(self, cr, uid, from_uom_id, qty, to_uom_id=False, round=True, rounding_method='UP'):
if not from_uom_id or not qty or not to_uom_id:
return qty
uoms = self.browse(cr, uid, [from_uom_id, to_uom_id])
from_unit, to_unit = uoms[0], uoms[-1]
else:
from_unit, to_unit = uoms[-1], uoms[0]
- return self._compute_qty_obj(cr, uid, from_unit, qty, to_unit, round=round)
+ return self._compute_qty_obj(cr, uid, from_unit, qty, to_unit, round=round, rounding_method=rounding_method)
- def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, round=True, context=None):
+ def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, round=True, rounding_method='UP', context=None):
if context is None:
context = {}
if from_unit.category_id.id != to_unit.category_id.id:
raise osv.except_osv(_('Error!'), _('Conversion from Product UoM %s to Default UoM %s is not possible as they both belong to different Category!.') % (from_unit.name,to_unit.name,))
else:
return qty
- # First round to the precision of the original unit, so that
- # float representation errors do not bias the following ceil()
- # e.g. with 1 / (1/12) we could get 12.0000048, ceiling to 13!
- amount = float_round(qty/from_unit.factor, precision_rounding=from_unit.rounding)
+ amount = qty/from_unit.factor
if to_unit:
amount = amount * to_unit.factor
if round:
- amount = ceiling(amount, to_unit.rounding)
+ amount = float_round(amount, precision_rounding=to_unit.rounding, rounding_method=rounding_method)
return amount
def _compute_price(self, cr, uid, from_uom_id, price, to_uom_id=False):
for tmpl_id in tmpl_ids:
# list of values combination
+ variant_alone = []
all_variants = [[]]
for variant_id in tmpl_id.attribute_line_ids:
- if len(variant_id.value_ids) > 1:
- temp_variants = []
+ if len(variant_id.value_ids) == 1:
+ variant_alone.append(variant_id.value_ids[0])
+ temp_variants = []
+ for variant in all_variants:
for value_id in variant_id.value_ids:
- for variant in all_variants:
- temp_variants.append(variant + [int(value_id)])
- all_variants = temp_variants
+ temp_variants.append(variant + [int(value_id)])
+ all_variants = temp_variants
+
+ # adding an attribute with only one value should not recreate product
+ # write this attribute on every product to make sure we don't lose them
+ for variant_id in variant_alone:
+ product_ids = []
+ for product_id in tmpl_id.product_variant_ids:
+ if variant_id.id not in map(int, product_id.attribute_value_ids):
+ product_ids.append(product_id.id)
+ product_obj.write(cr, uid, product_ids, {'attribute_value_ids': [(4, variant_id.id)]}, context=ctx)
# check product
variant_ids_to_active = []
context['uom'], value, uom.id)
value = value - product.price_extra
- return product.write({'list_price': value}, context=context)
+ return product.write({'list_price': value})
def _get_partner_code_name(self, cr, uid, ids, product, partner_id, context=None):
for supinfo in product.seller_ids:
res = self.write(cr, uid, [id], {'image_variant': image}, context=context)
product = self.browse(cr, uid, id, context=context)
if not product.product_tmpl_id.image:
- product.write({'image_variant': None}, context=context)
- product.product_tmpl_id.write({'image': image}, context=context)
+ product.write({'image_variant': None})
+ product.product_tmpl_id.write({'image': image})
return res
def _get_price_extra(self, cr, uid, ids, name, args, context=None):
if not limit or len(ids) < limit:
# we may underrun the limit because of dupes in the results, that's fine
limit2 = (limit - len(ids)) if limit else False
- ids.update(self.search(cr, user, args + [('name', operator, name)], limit=limit2, context=context))
+ ids.update(self.search(cr, user, args + [('name', operator, name), ('id', 'not in', list(ids))], limit=limit2, context=context))
ids = list(ids)
elif not ids and operator in expression.NEGATIVE_TERM_OPERATORS:
ids = self.search(cr, user, args + ['&', ('default_code', operator, name), ('name', operator, name)], limit=limit, context=context)
main_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id
for currency_id in ids:
if currency_id == main_currency.id:
- if main_currency.rounding < 10 ** -digits:
+ if float_compare(main_currency.rounding, 10 ** -digits, precision_digits=6) == -1:
return False
return True
main_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id
for decimal_precision in ids:
if decimal_precision == account_precision_id:
- if main_currency.rounding < 10 ** -digits:
+ if float_compare(main_currency.rounding, 10 ** -digits, precision_digits=6) == -1:
return False
return True