openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #00682
[Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
Holger Brunn (Therp) has proposed merging lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons.
Requested reviews:
Stefan Rijnhart (Therp) (stefan-therp)
Holger Brunn (Therp) (hbrunn)
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 subscribed to branch 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-15 14:15:30 +0000
@@ -1519,11 +1519,19 @@
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
@@ -1532,26 +1540,81 @@
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
+ 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.uom_id._compute_price(
+ cr, uid, product_obj.uom_id.id, product_obj[field], uom_id)
+ # 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 = {}
=== modified file 'account/tests/__init__.py'
--- account/tests/__init__.py 2012-11-01 20:39:35 +0000
+++ account/tests/__init__.py 2013-10-15 14:15:30 +0000
@@ -1,4 +1,6 @@
-from . import test_tax
+from . import test_tax, test_product_id_change
-fast_suite = [test_tax,
+fast_suite = [
+ test_tax,
+ test_product_id_change,
]
=== added file 'account/tests/test_product_id_change.py'
--- account/tests/test_product_id_change.py 1970-01-01 00:00:00 +0000
+++ account/tests/test_product_id_change.py 2013-10-15 14:15:30 +0000
@@ -0,0 +1,94 @@
+from openerp.tests.common import TransactionCase
+
+class TestProductIdChange(TransactionCase):
+ """Test for product_id_change on account.invoice.line
+ """
+
+ def setUp(self):
+ super(TestProductIdChange, self).setUp()
+ self.line_model = self.registry('account.invoice.line')
+
+ def get_line(self):
+ line_id = self.line_model.create(
+ self.cr,
+ self.uid,
+ {
+ 'name': 'testline',
+ })
+ return self.line_model.browse(
+ self.cr, self.uid, line_id)
+
+
+ def get_partner(self):
+ partner_id = self.registry('res.partner').search(
+ self.cr,
+ self.uid,
+ [('customer', '=', True)],
+ limit=1)[0]
+
+ return self.registry('res.partner').browse(
+ self.cr, self.uid, partner_id)
+
+ def get_product(self):
+ product_id = self.registry('product.product').search(
+ self.cr,
+ self.uid,
+ [('uom_id', '!=', False)],
+ limit=1)[0]
+ return self.registry('product.product').browse(
+ self.cr, self.uid, product_id)
+
+ def test_random_product(self):
+ line = self.get_line()
+ product = self.get_product()
+ partner = self.get_partner()
+
+ values = line.product_id_change(
+ product.id, None,
+ partner_id=partner.id)['value']
+
+ self.assertEquals(values['price_unit'], product.list_price)
+ self.assertEquals(values['uos_id'], product.uom_id.id)
+
+ def test_with_pricelist(self):
+ line = self.get_line()
+ product = self.get_product()
+
+ pricelist_id = self.registry('product.pricelist').create(
+ self.cr,
+ self.uid,
+ {
+ 'name': 'testpricelist',
+ 'type': self.browse_ref('product.pricelist_type_sale').key,
+ 'version_id': [
+ (0, 0, {
+ 'name': 'testversion',
+ 'items_id': [
+ (0, 0, {
+ 'name': 'testitem',
+ 'product_id': product.id,
+ 'price_discount': .5,
+ 'price_surcharge': 42,
+ 'base': self.browse_ref(
+ 'product.list_price').id,
+ }),
+ ],
+ }),
+ ],
+ })
+
+ partner_id = self.registry('res.partner').create(
+ self.cr,
+ self.uid,
+ {
+ 'name': 'testcustomer',
+ 'customer': True,
+ 'property_product_pricelist':
+ 'product.pricelist,%d' % pricelist_id,
+ })
+
+ values = line.product_id_change(
+ product.id, None,
+ partner_id=partner_id)['value']
+
+ self.assertEquals(values['price_unit'], product.list_price * 1.5 + 42)
Follow ups
-
[Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Holger Brunn (Therp), 2014-11-24
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Holger Brunn (Therp), 2014-11-24
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Lionel Sausin - Numérigraphe, 2014-03-31
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Holger Brunn (Therp), 2014-03-31
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Lionel Sausin - Numérigraphe, 2014-03-28
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Stefan Rijnhart (Therp), 2014-03-24
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Holger Brunn (Therp), 2014-03-24
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Stefan Rijnhart (Therp), 2014-03-17
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Holger Brunn (Therp), 2013-11-03
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Stefan Rijnhart (Therp), 2013-11-02
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Stefan Rijnhart (Therp), 2013-11-02
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Christophe CHAUVET, 2013-11-02
-
[Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Christophe CHAUVET, 2013-11-02
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Christophe CHAUVET, 2013-11-02
-
[Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: noreply, 2013-11-02
-
[Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Christophe CHAUVET, 2013-11-02
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Christophe CHAUVET, 2013-11-02
-
[Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Christophe CHAUVET, 2013-11-02
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Ronald Portier (Therp), 2013-10-21
-
Re: [Merge] lp:~therp-nl/ocb-addons/lp754339 into lp:ocb-addons
From: Holger Brunn (Therp), 2013-10-21