from openerp import SUPERUSER_ID
from openerp import tools
-from openerp.osv import osv, fields
+from openerp.osv import osv, fields, expression
from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
import psycopg2
import openerp.addons.decimal_precision as dp
+from openerp.tools.float_utils import float_round
def ean_checksum(eancode):
"""returns the checksum of an ean string of length 13, returns -1 if the string has the wrong length"""
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
- amount = qty / from_unit.factor
+ # 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)
if to_unit:
amount = amount * to_unit.factor
if round:
_name = "product.template"
_inherit = ['mail.thread']
_description = "Product Template"
+ _order = "name"
def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
return self._is_product_variant_impl(cr, uid, ids, name, arg, context=context)
def _is_product_variant_impl(self, cr, uid, ids, name, arg, context=None):
- prod = self.pool.get('product.product')
- res = dict.fromkeys(ids, False)
- ctx = dict(context, active_test=True)
- for product in self.browse(cr, uid, ids, context=context):
- res[product.id] = prod.search(cr, uid, [('product_tmpl_id','=',product.id)], context=ctx, count=True) == 1
- return res
-
+ return dict.fromkeys(ids, False)
def _product_template_price(self, cr, uid, ids, name, arg, context=None):
plobj = self.pool.get('product.pricelist')
return super(product_template, self).name_get(cr, user, ids, context)
+
+
+
class product_product(osv.osv):
_name = "product.product"
_description = "Product"
_columns = {
'price': fields.function(_product_price, type='float', string='Price', digits_compute=dp.get_precision('Product Price')),
- 'price_extra': fields.function(_get_price_extra, type='float', string='Variant Extra Price', help="This is le sum of the extra price of all attributes"),
+ 'price_extra': fields.function(_get_price_extra, type='float', string='Variant Extra Price', help="This is the sum of the extra price of all attributes"),
'lst_price': fields.function(_product_lst_price, fnct_inv=_set_product_lst_price, type='float', string='Public Price', digits_compute=dp.get_precision('Product Price')),
'code': fields.function(_product_code, type='char', string='Internal Reference'),
'partner_ref' : fields.function(_product_partner_ref, type='char', string='Customer ref'),
'default_code' : fields.char('Internal Reference', select=True),
'active': fields.boolean('Active', help="If unchecked, it will allow you to hide the product without removing it."),
- 'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade", select=True),
+ 'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade", select=True, auto_join=True),
'ean13': fields.char('EAN13 Barcode', size=13, help="International Article Number used for product identification."),
'name_template': fields.related('product_tmpl_id', 'name', string="Template Name", type='char', store={
'product.template': (_get_name_template_ids, ['name'], 10),
unlink_ids = []
unlink_product_tmpl_ids = []
for product in self.browse(cr, uid, ids, context=context):
+ # Check if product still exists, in case it has been unlinked by unlinking its template
+ if not product.exists():
+ continue
tmpl_id = product.product_tmpl_id.id
# Check if the product is last product of this template
other_product_ids = self.search(cr, uid, [('product_tmpl_id', '=', tmpl_id), ('id', '!=', product.id)], context=context)
def _name_get(d):
name = d.get('name','')
- code = d.get('default_code',False)
+ code = context.get('display_default_code', True) and d.get('default_code',False) or False
if code:
name = '[%s] %s' % (code,name)
return (d['id'], name)
sellers = filter(lambda x: x.name.id == partner_id, product.seller_ids)
if sellers:
for s in sellers:
+ seller_variant = s.product_name and "%s (%s)" % (s.product_name, variant) or False
mydict = {
'id': product.id,
- 'name': s.product_name or name,
+ 'name': seller_variant or name,
'default_code': s.product_code or product.default_code,
}
result.append(_name_get(mydict))
if not args:
args = []
if name:
- ids = self.search(cr, user, [('default_code','=',name)]+ args, limit=limit, context=context)
- if not ids:
- ids = self.search(cr, user, [('ean13','=',name)]+ args, limit=limit, context=context)
- if not ids:
+ positive_operators = ['=', 'ilike', '=ilike', 'like', '=like']
+ ids = []
+ if operator in positive_operators:
+ ids = self.search(cr, user, [('default_code','=',name)]+ args, limit=limit, context=context)
+ if not ids:
+ ids = self.search(cr, user, [('ean13','=',name)]+ args, limit=limit, context=context)
+ if not ids and operator not in expression.NEGATIVE_TERM_OPERATORS:
# Do not merge the 2 next lines into one single search, SQL search performance would be abysmal
# on a database with thousands of matching products, due to the huge merge+unique needed for the
# OR operator (and given the fact that the 'name' lookup results come from the ir.translation table
limit2 = (limit - len(ids)) if limit else False
ids.update(self.search(cr, user, args + [('name', operator, name)], limit=limit2, context=context))
ids = list(ids)
- if not 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)
+ if not ids and operator in positive_operators:
ptrn = re.compile('(\[(.*?)\])')
res = ptrn.search(name)
if res:
return super(product_product, self).create(cr, uid, vals, context=ctx)
+
+ def need_procurement(self, cr, uid, ids, context=None):
+ return False
+
+
class product_packaging(osv.osv):
_name = "product.packaging"
_description = "Packaging"
'delay': 1,
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'product.supplierinfo', context=c),
}
- def price_get(self, cr, uid, supplier_ids, product_id, product_qty=1, context=None):
- """
- Calculate price from supplier pricelist.
- @param supplier_ids: Ids of res.partner object.
- @param product_id: Id of product.
- @param product_qty: specify quantity to purchase.
- """
- if type(supplier_ids) in (int,long,):
- supplier_ids = [supplier_ids]
- res = {}
- product_pool = self.pool.get('product.product')
- partner_pool = self.pool.get('res.partner')
- pricelist_pool = self.pool.get('product.pricelist')
- currency_pool = self.pool.get('res.currency')
- currency_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id
- # Compute price from standard price of product
- product_price = product_pool.price_get(cr, uid, [product_id], 'standard_price', context=context)[product_id]
- product = product_pool.browse(cr, uid, product_id, context=context)
- for supplier in partner_pool.browse(cr, uid, supplier_ids, context=context):
- price = product_price
- # Compute price from Purchase pricelist of supplier
- pricelist_id = supplier.property_product_pricelist_purchase.id
- if pricelist_id:
- price = pricelist_pool.price_get(cr, uid, [pricelist_id], product_id, product_qty, context=context).setdefault(pricelist_id, 0)
- price = currency_pool.compute(cr, uid, pricelist_pool.browse(cr, uid, pricelist_id).currency_id.id, currency_id, price)
-
- # Compute price from supplier pricelist which are in Supplier Information
- supplier_info_ids = self.search(cr, uid, [('name','=',supplier.id),('product_tmpl_id','=',product.product_tmpl_id.id)])
- if supplier_info_ids:
- cr.execute('SELECT * ' \
- 'FROM pricelist_partnerinfo ' \
- 'WHERE suppinfo_id IN %s' \
- 'AND min_quantity <= %s ' \
- 'ORDER BY min_quantity DESC LIMIT 1', (tuple(supplier_info_ids),product_qty,))
- res2 = cr.dictfetchone()
- if res2:
- price = res2['price']
- res[supplier.id] = price
- return res
+
_order = 'sequence'