Holger Brunn (Therp) has proposed merging lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons.
Requested reviews: OpenERP Community Backports Team (ocb) Related bugs: Bug #754339 in OpenERP Community Backports (Addons): "Partner assigned Price List is not applied with the creation of a customer/supplier invoice." https://bugs.launchpad.net/ocb-addons/+bug/754339 For more details, see: https://code.launchpad.net/~therp-nl/ocb-addons/lp754339/+merge/189107 This is a port of the fix to have prices in manually added invoice lines originate from the partner's pricelist, if any. If there are no pricelists involved, nothing should change. -- https://code.launchpad.net/~therp-nl/ocb-addons/lp754339/+merge/189107 Your team OpenERP Community Backports Team is requested to review the proposed merge of lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons.
=== modified file 'account/account_invoice.py' --- account/account_invoice.py 2013-09-20 09:50:26 +0000 +++ account/account_invoice.py 2013-10-03 14:56:47 +0000 @@ -1480,7 +1480,10 @@ res['arch'] = etree.tostring(doc) return res - def product_id_change(self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None): + def product_id_change( + self, cr, uid, ids, product, uom_id, qty=0, name='', type='out_invoice', + partner_id=False, fposition_id=False, price_unit=False, + currency_id=False, context=None, company_id=None): if context is None: context = {} company_id = company_id if company_id != None else context.get('company_id',False) @@ -1519,39 +1522,111 @@ else: taxes = res.supplier_taxes_id and res.supplier_taxes_id or (a and self.pool.get('account.account').browse(cr, uid, a, context=context).tax_ids or False) tax_id = fpos_obj.map_tax(cr, uid, fpos, taxes) - - if type in ('in_invoice', 'in_refund'): - result.update( {'price_unit': price_unit or res.standard_price,'invoice_line_tax_id': tax_id} ) - else: - result.update({'price_unit': res.list_price, 'invoice_line_tax_id': tax_id}) + result['invoice_line_tax_id'] = tax_id + + warning = {} + # When product changes, price ALWAYS need to be reset. If not price + # found in product, or pricelist, it should become False. Only if + # product_id has been cleared by user, we will leave price_unit as is. + if product: + price_unit, pu_warning = self._price_unit_get( + cr, uid, product, uom_id, qty, type, partner_id, + currency_id, context=context) + result['price_unit'] = price_unit # might be False + warning.update(pu_warning) + result['name'] = res.partner_ref - result['uos_id'] = uom_id or res.uom_id.id - if res.description: - result['name'] += '\n'+res.description - - domain = {'uos_id':[('category_id','=',res.uom_id.category_id.id)]} - - res_final = {'value':result, 'domain':domain} - - if not company_id or not currency_id: - return res_final - - company = self.pool.get('res.company').browse(cr, uid, company_id, context=context) - currency = self.pool.get('res.currency').browse(cr, uid, currency_id, context=context) - - if company.currency_id.id != currency.id: - if type in ('in_invoice', 'in_refund'): - res_final['value']['price_unit'] = res.standard_price - new_price = res_final['value']['price_unit'] * currency.rate - res_final['value']['price_unit'] = new_price - - if result['uos_id'] and result['uos_id'] != res.uom_id.id: - selected_uom = self.pool.get('product.uom').browse(cr, uid, result['uos_id'], context=context) - new_price = self.pool.get('product.uom')._compute_price(cr, uid, res.uom_id.id, res_final['value']['price_unit'], result['uos_id']) - res_final['value']['price_unit'] = new_price + domain = {} + result['uos_id'] = res.uom_id.id or uom_id or False + result['note'] = res.description + if result['uos_id']: + res2 = res.uom_id.category_id.id + if res2: + domain = {'uos_id':[('category_id','=',res2 )]} + + res_final = {'value': result, 'domain': domain, 'warning': warning} return res_final + def _price_unit_get( + self, cr, uid, product_id, uom_id, qty, invoice_type, partner_id, + currency_id, context=None): + price_unit = False + warning = {} + standard_currency_id = currency_id + partner_model = self.pool.get('res.partner') + partner_obj = partner_model.browse( + cr, uid, partner_id, context=context) + assert partner_obj, _('No partner found for id %d') % partner_id + if invoice_type in ('in_invoice', 'in_refund'): + field = 'list_price' + pricelist_property = 'property_product_pricelist_purchase' + else: + field = 'standard_price' + pricelist_property = 'property_product_pricelist' + if pricelist_property in partner_obj: + pricelist_id = partner_obj[pricelist_property].id + else: + pricelist_id = False + # Check whether standard price p.u. modified by pricelist + if pricelist_id: + pricelist_model = self.pool.get('product.pricelist') + price_unit = pricelist_model.price_get( + cr, uid, [pricelist_id], product_id, qty or 1.0, + partner=partner_id, + context=dict(context, uom=uom_id))[pricelist_id] + if price_unit is False: # 0.0 is OK, we night have free products + warning = { + 'title': _('No valid pricelist line found!'), + 'message': + _("Couldn't find a pricelist line matching this product" + " and quantity.\n" + "You have to change either the product, the quantity or" + " the pricelist.") + } + # Pricelist converts price from standard currency to pricelist + # currency. We have to convert this to the invoice currency. + # In practice that will often mean undoing the conversion + # done by the pricelist object + pricelist_obj = pricelist_model.browse( + cr, uid, pricelist_id, context=context) + if pricelist_obj and pricelist_obj.currency_id: + standard_currency_id = pricelist_obj.currency_id.id + else: + # Take standard price per unit directly from product + product_model = self.pool.get('product.product') + product_obj = product_model.browse( + cr, uid, product_id, context=context) + assert product_obj, _('No product found for id %d') % product_id + assert field in product_obj, _( + 'Field %s not found in product') % field + price_unit = product_obj[field] + # If price_unit not taken from price-list, we still have to + # take unit of measurement into account + if uom_id: + uom_model = self.pool.get('product.uom') + uom_obj = uom_model.browse(cr, uid, uom_id, context=context) + p_uom_category_id = product_obj.uom_id.category_id.id + if p_uom_category_id == uom_obj.category_id.id: + price_unit = price_unit * uom_obj.factor_inv + # When price not taken from pricelist, the currency is + # determined by the price_type: + price_type_model = self.pool.get('product.price.type') + price_type_ids = price_type_model.search( + cr, uid, [('field', '=', field)], context=context) + if price_type_ids: + price_type_obj = price_type_model.browse( + cr, uid, price_type_ids[0], context=context) + if price_type_obj and price_type_obj.currency_id: + standard_currency_id = price_type_obj.currency_id.id + # convert price_unit to currency of invoice + if standard_currency_id != currency_id: + currency_model = self.pool.get('res.currency') + price_unit = currency_model.compute( + cr, uid, standard_currency_id, currency_id, + price_unit, round=True, context=context) + return price_unit, warning + def uos_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, context=None, company_id=None): if context is None: context = {}
-- Mailing list: https://launchpad.net/~openerp-community-reviewer Post to : openerp-community-reviewer@lists.launchpad.net Unsubscribe : https://launchpad.net/~openerp-community-reviewer More help : https://help.launchpad.net/ListHelp