[IMP] point_of_sale: performance improvement in pricelist (price_get)
bzr revid: olt@tinyerp.com-20100929095742-yi2ldls09prywt48
This commit is contained in:
parent
960fc8e27c
commit
47867b8d71
|
@ -1079,8 +1079,6 @@ class pos_order_line(osv.osv):
|
|||
else:
|
||||
res[line.id][f] = line.price_unit * line.qty
|
||||
res[line.id][f] += tax_amount
|
||||
print ids
|
||||
print res
|
||||
return res
|
||||
|
||||
def price_by_product_multi(self, cr, uid, ids, context=None):
|
||||
|
@ -1090,20 +1088,11 @@ class pos_order_line(osv.osv):
|
|||
res = {}.fromkeys(ids, 0.0)
|
||||
|
||||
lines = self.browse(cr, uid, ids, context=context)
|
||||
# product_map:
|
||||
# {10, 1): {'qty': 5, 'uom_id': 1, 'partner_id': 512},
|
||||
# (22, 3): {'qty': 10, 'uom_id': 2, 'partner_id', 35},
|
||||
# }
|
||||
# key = (product_id, pricelist_id)
|
||||
product_map = dict([((line.product_id.id, line.order_id.pricelist_id.id), {
|
||||
'qty': line.qty,
|
||||
'uom_id': line.product_id.uom_po_id.id,
|
||||
'partner_id': line.order_id.partner_id.id,
|
||||
})
|
||||
for line
|
||||
in lines])
|
||||
|
||||
price_get_multi_res = self.pool.get('product.pricelist').price_get_multi(cr, uid, product_map)
|
||||
pricelist_ids = [line.order_id.pricelist_id.id for line in lines]
|
||||
products_by_qty_by_partner = [(line.product_id.id, line.qty, line.order_id.partner_id.id) for line in lines]
|
||||
|
||||
price_get_multi_res = self.pool.get('product.pricelist').price_get_multi(cr, uid, pricelist_ids, products_by_qty_by_partner, context=context)
|
||||
|
||||
for line in lines:
|
||||
pricelist = line.order_id.pricelist_id.id
|
||||
|
|
|
@ -126,7 +126,7 @@ class product_pricelist(osv.osv):
|
|||
"currency_id": _get_currency
|
||||
}
|
||||
|
||||
def price_get_multi(self, cr, uid, product_map, context=None):
|
||||
def price_get_multi_old(self, cr, uid, product_map, context=None):
|
||||
"""multi products 'price_get'
|
||||
@param context: {
|
||||
'date': Date of the pricelist (%Y-%m-%d),
|
||||
|
@ -155,6 +155,7 @@ class product_pricelist(osv.osv):
|
|||
currency_obj = self.pool.get('res.currency')
|
||||
product_obj = self.pool.get('product.product')
|
||||
product_category_obj = self.pool.get('product.category')
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
supplierinfo_obj = self.pool.get('product.supplierinfo')
|
||||
price_type_obj = self.pool.get('product.price.type')
|
||||
product_pricelist_version_obj = self.pool.get('product.pricelist.version')
|
||||
|
@ -178,7 +179,7 @@ class product_pricelist(osv.osv):
|
|||
|
||||
# product.product:
|
||||
product_ids = list(set([k[0] for k in product_map.keys()]))
|
||||
products = dict([(item['id'], item) for item in product_obj.read(cr, uid, product_ids, ['categ_id', 'product_tmpl_id'])])
|
||||
products = dict([(item['id'], item) for item in product_obj.read(cr, uid, product_ids, ['categ_id', 'product_tmpl_id', 'uos_id', 'uom_id'])])
|
||||
|
||||
# product.category:
|
||||
product_category_ids = product_category_obj.search(cr, uid, [])
|
||||
|
@ -191,7 +192,6 @@ class product_pricelist(osv.osv):
|
|||
|
||||
partner = line['partner_id']
|
||||
qty = line['qty']
|
||||
uom_id = line['uom_id']
|
||||
tmpl_id = products[product_id]['product_tmpl_id'] and products[product_id]['product_tmpl_id'][0] or False
|
||||
|
||||
categ_id = products[product_id]['categ_id'] and products[product_id]['categ_id'][0] or False
|
||||
|
@ -269,20 +269,192 @@ class product_pricelist(osv.osv):
|
|||
# exception here because it breaks the search
|
||||
price = False
|
||||
|
||||
if price:
|
||||
p_uom_id = products[product_id]['uos_id'] and products[product_id]['uos_id'][0] or products[product_id]['uom_id'] and products[product_id]['uom_id'][0] or False
|
||||
if p_uom_id:
|
||||
price = product_uom_obj._compute_price(cr, uid, p_uom_id, price, context.get('uom', False))
|
||||
|
||||
if results.get(product_id):
|
||||
results[product_id][pricelist_id] = price
|
||||
else:
|
||||
results[product_id] = {pricelist_id: price}
|
||||
|
||||
# XXX
|
||||
#if 'uom' in context:
|
||||
# product = product_obj.browse(cr, uid, product_id)
|
||||
# uom = product.uos_id or product.uom_id
|
||||
# results[product_id] = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, result[id], context['uom'])
|
||||
return results
|
||||
|
||||
#def price_get_multi(self, cr, uid, product_ids, context=None):
|
||||
def price_get_multi(self, cr, uid, pricelist_ids, products_by_qty_by_partner, context=None):
|
||||
"""multi products 'price_get'.
|
||||
@param pricelist_ids:
|
||||
@param products_by_qty:
|
||||
@param partner:
|
||||
@param context: {
|
||||
'date': Date of the pricelist (%Y-%m-%d),}
|
||||
@return: a dict of dict with product_id as key and a dict 'price by pricelist' as value
|
||||
"""
|
||||
|
||||
def _create_parent_category_list(id, lst):
|
||||
if not id:
|
||||
return []
|
||||
parent = product_category_tree.get(id)
|
||||
if parent:
|
||||
lst.append(parent)
|
||||
return _create_parent_category_list(parent, lst)
|
||||
else:
|
||||
return lst
|
||||
# _create_parent_category_list
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
date = time.strftime('%Y-%m-%d')
|
||||
if 'date' in context:
|
||||
date = context['date']
|
||||
|
||||
currency_obj = self.pool.get('res.currency')
|
||||
product_obj = self.pool.get('product.product')
|
||||
product_category_obj = self.pool.get('product.category')
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
supplierinfo_obj = self.pool.get('product.supplierinfo')
|
||||
price_type_obj = self.pool.get('product.price.type')
|
||||
product_pricelist_version_obj = self.pool.get('product.pricelist.version')
|
||||
|
||||
# product.pricelist.version:
|
||||
if pricelist_ids:
|
||||
pricelist_version_ids = pricelist_ids
|
||||
else:
|
||||
# all pricelists:
|
||||
pricelist_version_ids = product_pricelist_version_obj.search(cr, uid, [])
|
||||
|
||||
pricelist_version_ids = list(set(pricelist_version_ids))
|
||||
|
||||
plversions_search_args = [
|
||||
('pricelist_id', 'in', pricelist_version_ids),
|
||||
'|',
|
||||
('date_start', '=', False),
|
||||
('date_start', '<=', date),
|
||||
'|',
|
||||
('date_end', '=', False),
|
||||
('date_end', '>=', date),
|
||||
]
|
||||
|
||||
plversion_ids = product_pricelist_version_obj.search(cr, uid, plversions_search_args)
|
||||
if len(pricelist_version_ids) != len(plversion_ids):
|
||||
msg = "At least one pricelist has no active version !\nPlease create or activate one."
|
||||
raise osv.except_osv(_('Warning !'), _(msg))
|
||||
|
||||
# product.product:
|
||||
product_ids = [i[0] for i in products_by_qty_by_partner]
|
||||
#products = dict([(item['id'], item) for item in product_obj.read(cr, uid, product_ids, ['categ_id', 'product_tmpl_id', 'uos_id', 'uom_id'])])
|
||||
products = product_obj.browse(cr, uid, product_ids, context=context)
|
||||
products_dict = dict([(item.id, item) for item in products])
|
||||
|
||||
# product.category:
|
||||
product_category_ids = product_category_obj.search(cr, uid, [])
|
||||
product_categories = product_category_obj.read(cr, uid, product_category_ids, ['parent_id'])
|
||||
product_category_tree = dict([(item['id'], item['parent_id'][0]) for item in product_categories if item['parent_id']])
|
||||
|
||||
results = {}
|
||||
for product_id, qty, partner in products_by_qty_by_partner:
|
||||
for pricelist_id in pricelist_version_ids:
|
||||
price = False
|
||||
|
||||
tmpl_id = products_dict[product_id].product_tmpl_id and products_dict[product_id].product_tmpl_id.id or False
|
||||
|
||||
categ_id = products_dict[product_id].categ_id and products_dict[product_id].categ_id.id or False
|
||||
categ_ids = _create_parent_category_list(categ_id, [categ_id])
|
||||
if categ_ids:
|
||||
categ_where = '(categ_id IN (' + ','.join(map(str, categ_ids)) + '))'
|
||||
else:
|
||||
categ_where = '(categ_id IS NULL)'
|
||||
|
||||
cr.execute(
|
||||
'SELECT i.*, pl.currency_id '
|
||||
'FROM product_pricelist_item AS i, '
|
||||
'product_pricelist_version AS v, product_pricelist AS pl '
|
||||
'WHERE (product_tmpl_id IS NULL OR product_tmpl_id = %s) '
|
||||
'AND (product_id IS NULL OR product_id = %s) '
|
||||
'AND (' + categ_where + ' OR (categ_id IS NULL)) '
|
||||
'AND price_version_id = %s '
|
||||
'AND (min_quantity IS NULL OR min_quantity <= %s) '
|
||||
'AND i.price_version_id = v.id AND v.pricelist_id = pl.id '
|
||||
'ORDER BY sequence',
|
||||
(tmpl_id, product_id, pricelist_id, qty))
|
||||
res1 = cr.dictfetchall()
|
||||
|
||||
for res in res1:
|
||||
if res:
|
||||
if res['base'] == -1:
|
||||
if not res['base_pricelist_id']:
|
||||
price = 0.0
|
||||
else:
|
||||
price_tmp = self.price_get(cr, uid,
|
||||
[res['base_pricelist_id']], prod_id,
|
||||
qty)[res['base_pricelist_id']]
|
||||
ptype_src = self.browse(cr, uid, res['base_pricelist_id']).currency_id.id
|
||||
price = currency_obj.compute(cr, uid, ptype_src, res['currency_id'], price_tmp, round=False)
|
||||
break
|
||||
elif res['base'] == -2:
|
||||
# this section could be improved by moving the queries outside the loop:
|
||||
where = []
|
||||
if partner:
|
||||
where = [('name', '=', partner) ]
|
||||
sinfo = supplierinfo_obj.search(cr, uid,
|
||||
[('product_id', '=', tmpl_id)] + where)
|
||||
price = 0.0
|
||||
if sinfo:
|
||||
cr.execute('SELECT * ' \
|
||||
'FROM pricelist_partnerinfo ' \
|
||||
'WHERE suppinfo_id IN %s' \
|
||||
'AND min_quantity <= %s ' \
|
||||
'ORDER BY min_quantity DESC LIMIT 1', (tuple(sinfo),qty,))
|
||||
res2 = cr.dictfetchone()
|
||||
if res2:
|
||||
price = res2['price']
|
||||
break
|
||||
else:
|
||||
price_type = price_type_obj.browse(cr, uid, int(res['base']))
|
||||
price = currency_obj.compute(cr, uid,
|
||||
price_type.currency_id.id, res['currency_id'],
|
||||
product_obj.price_get(cr, uid, [product_id],
|
||||
price_type.field)[product_id], round=False, context=context)
|
||||
|
||||
if price:
|
||||
price_limit = price
|
||||
|
||||
price = price * (1.0+(res['price_discount'] or 0.0))
|
||||
price = rounding(price, res['price_round'])
|
||||
price += (res['price_surcharge'] or 0.0)
|
||||
if res['price_min_margin']:
|
||||
price = max(price, price_limit+res['price_min_margin'])
|
||||
if res['price_max_margin']:
|
||||
price = min(price, price_limit+res['price_max_margin'])
|
||||
break
|
||||
|
||||
else:
|
||||
# False means no valid line found ! But we may not raise an
|
||||
# exception here because it breaks the search
|
||||
price = False
|
||||
|
||||
if price:
|
||||
if 'uom' in context:
|
||||
product = products_dict[product_id]
|
||||
uom = product.uos_id or product.uom_id
|
||||
price = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, price, context['uom'])
|
||||
|
||||
if results.get(product_id):
|
||||
results[product_id][pricelist_id] = price
|
||||
else:
|
||||
results[product_id] = {pricelist_id: price}
|
||||
|
||||
return results
|
||||
|
||||
def price_get(self, cr, uid, ids, prod_id, qty, partner=None, context=None):
|
||||
res_multi = self.price_get_multi(cr, uid, pricelist_ids=ids, products_by_qty_by_partner=[(prod_id, qty, partner)], context=context)
|
||||
res = res_multi[prod_id]
|
||||
res.update({'item_id': {ids[-1]: ids[-1]}})
|
||||
return res
|
||||
|
||||
def price_get_old(self, cr, uid, ids, prod_id, qty, partner=None, context=None):
|
||||
'''
|
||||
context = {
|
||||
'uom': Unit of Measure (int),
|
||||
|
|
|
@ -503,7 +503,15 @@ class product_product(osv.osv):
|
|||
#
|
||||
# Could be overrided for variants matrices prices
|
||||
#
|
||||
def price_get(self, cr, uid, ids, ptype='list_price', context={}):
|
||||
def price_get(self, cr, uid, ids, ptype='list_price', context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
if 'currency_id' in context:
|
||||
pricetype_obj = self.pool.get('product.price.type')
|
||||
price_type_id = pricetype_obj.search(cr, uid, [('field','=',ptype)])[0]
|
||||
price_type_currency_id = pricetype_obj.browse(cr,uid,price_type_id).currency_id.id
|
||||
|
||||
res = {}
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
|
@ -517,11 +525,8 @@ class product_product(osv.osv):
|
|||
uom.id, res[product.id], context['uom'])
|
||||
# Convert from price_type currency to asked one
|
||||
if 'currency_id' in context:
|
||||
pricetype_obj = self.pool.get('product.price.type')
|
||||
# Take the price_type currency from the product field
|
||||
# This is right cause a field cannot be in more than one currency
|
||||
price_type_id = pricetype_obj.search(cr, uid, [('field','=',ptype)])[0]
|
||||
price_type_currency_id = pricetype_obj.browse(cr,uid,price_type_id).currency_id.id
|
||||
res[product.id] = self.pool.get('res.currency').compute(cr, uid, price_type_currency_id,
|
||||
context['currency_id'], res[product.id],context=context)
|
||||
|
||||
|
|
Loading…
Reference in New Issue