From 9c5683dbfdb1ed3876a49fd87a8e3d127458d3b6 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Fri, 22 Apr 2016 20:25:39 +0200 Subject: [PATCH] [FIX] purchase: use purchase UoM When a PO is created from a reordering rule, we should make sure to use the purchase UoM of the product. Any PO line automatically created or modified will be a PO line in the purchase UoM. opw-673309 --- addons/purchase/purchase.py | 26 ++++++-------- .../test/cancellation_propagated.yml | 34 ++++++++----------- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index d4b4310a9b0..0e7c8be4dde 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -812,12 +812,13 @@ class ProcurementOrder(models.Model): def _prepare_purchase_order_line(self, po, supplier): self.ensure_one() + procurement_uom_po_qty = self.env['product.uom']._compute_qty_obj(self.product_uom, self.product_qty, self.product_id.uom_po_id) seller = self.product_id._select_seller( self.product_id, partner_id=supplier.name, - quantity=self.product_qty, + quantity=procurement_uom_po_qty, date=po.date_order and po.date_order[:10], - uom_id=self.product_uom) + uom_id=self.product_id.uom_po_id) taxes = self.product_id.supplier_taxes_id fpos = po.fiscal_position_id @@ -829,9 +830,6 @@ class ProcurementOrder(models.Model): if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id: price_unit = seller.currency_id.compute(price_unit, po.currency_id) - if seller and self.product_uom and seller.product_uom != self.product_uom: - price_unit = self.env['product.uom']._compute_price(seller.product_uom.id, price_unit, to_uom_id=self.product_uom.id) - product_lang = self.product_id.with_context({ 'lang': supplier.name.lang, 'partner_id': supplier.name.id, @@ -844,9 +842,9 @@ class ProcurementOrder(models.Model): return { 'name': name, - 'product_qty': self.product_qty, + 'product_qty': procurement_uom_po_qty, 'product_id': self.product_id.id, - 'product_uom': self.product_uom.id, + 'product_uom': self.product_id.uom_po_id.id, 'price_unit': price_unit, 'date_planned': date_planned, 'taxes_id': [(6, 0, taxes_id.ids)], @@ -928,23 +926,21 @@ class ProcurementOrder(models.Model): # Create Line po_line = False for line in po.order_line: - if line.product_id == procurement.product_id and line.product_uom == procurement.product_uom: + if line.product_id == procurement.product_id and line.product_uom == procurement.product_id.uom_po_id: + procurement_uom_po_qty = self.env['product.uom']._compute_qty_obj(procurement.product_uom, procurement.product_qty, procurement.product_id.uom_po_id) seller = self.product_id._select_seller( - self.product_id, + procurement.product_id, partner_id=partner, - quantity=line.product_qty + procurement.product_qty, + quantity=line.product_qty + procurement_uom_po_qty, date=po.date_order and po.date_order[:10], - uom_id=self.product_uom) + uom_id=procurement.product_id.uom_po_id) price_unit = self.env['account.tax']._fix_tax_included_price(seller.price, line.product_id.supplier_taxes_id, line.taxes_id) if seller else 0.0 if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id: price_unit = seller.currency_id.compute(price_unit, po.currency_id) - if seller and self.product_uom and seller.product_uom != self.product_uom: - price_unit = self.env['product.uom']._compute_price(seller.product_uom.id, price_unit, to_uom_id=self.product_uom.id) - po_line = line.write({ - 'product_qty': line.product_qty + procurement.product_qty, + 'product_qty': line.product_qty + procurement_uom_po_qty, 'price_unit': price_unit, 'procurement_ids': [(4, procurement.id)] }) diff --git a/addons/stock_dropshipping/test/cancellation_propagated.yml b/addons/stock_dropshipping/test/cancellation_propagated.yml index 3461a876761..44e5ff34e6f 100644 --- a/addons/stock_dropshipping/test/cancellation_propagated.yml +++ b/addons/stock_dropshipping/test/cancellation_propagated.yml @@ -75,38 +75,34 @@ - !python {model: procurement.order}: | # Retrieve related procurement - so = self.pool.get('sale.order').browse(cr, uid, ref('sale_order_product_mto')) - procu_ids = self.search(cr, uid, [('group_id.name', '=', so.name)]) - assert len(procu_ids)>0, 'No procurement found for sale order %s (with id: %d)' %(so.name,so.id) + so1 = self.pool.get('sale.order').browse(cr, uid, ref('sale_order_product_mto')) + so2 = self.pool.get('sale.order').browse(cr, uid, ref('sale_order_product_mto2')) + procu_ids = self.browse(cr, uid, self.search(cr, uid, [('group_id.name', 'in', [so1.name, so2.name])])) + assert len(procu_ids)>0, 'No procurement found!' # Check that all procurements are running - for procu in self.browse(cr,uid,procu_ids,context=context): + for procu in procu_ids: assert procu.state == u'running', 'Procurement with id: %d should be running but is with state : %s!' %(procu.id, procu.state) # Check that one purchase order has been created - purchase_ids = [proc.purchase_line_id.order_id for proc in self.browse(cr, uid, procu_ids) if proc.purchase_line_id] + purchase_ids = procu_ids.mapped('purchase_line_id').mapped('order_id') assert len(purchase_ids) == 1, 'No purchase order found !' # Check the two purchase order lines - purchase_line = purchase_ids[0].order_line[0] - assert purchase_line.product_qty == 5.0, 'The product quantity of the first order line should be 5 and not %s' % (purchase_line.product_qty,) + assert purchase_line.product_qty == 29.0, 'The product quantity of the first order line should be 5 and not %s' % (purchase_line.product_qty,) assert purchase_line.product_uom.id == ref("product.product_uom_unit"), 'The product UoM ID of the first order line should be %s and not %s' % (ref("product.product_uom_unit"), purchase_line.product_uom.id,) - purchase_line = purchase_ids[0].order_line[1] - assert purchase_line.product_qty == 2.0, 'The product quantity of the first order line should be 2 and not %s' % (purchase_line.product_qty,) - assert purchase_line.product_uom.id == ref("product.product_uom_dozen"), 'The product UoM ID of the second order line should be %s and not %s' % (ref("product.product_uom_dozen"), purchase_line.product_uom.id,) - # Let us cancel the procurement related to the 2nd sales order first and check that the 2 Dozen(s) are subtracted correctly - so2 = self.pool.get('sale.order').browse(cr, uid, ref('sale_order_product_mto2')) + # Cancel the Sales Order 2 self.cancel(cr, uid, [so2.order_line[0].procurement_ids[0].id], context=context) - assert so2.order_line[0].procurement_ids[0].state == u'cancel', 'Main procurement should be cancelled !' + assert so2.order_line[0].procurement_ids[0].state == u'cancel', 'Procurement 2 should be cancelled !' + assert purchase_line.product_qty == 5.0, 'The product quantity of the first order line should be 5 and not %s' % (purchase_line.product_qty,) - # Cancel the main procurement from the sale order in units - main_procu_id = self.search(cr, uid, [('origin', '=', so.name)]) - assert len(main_procu_id) == 1, 'Main procurement not identified !' - self.cancel(cr, uid, main_procu_id, context=context) - assert self.browse(cr, uid, main_procu_id[0]).state == u'cancel', 'Main procurement should be cancelled !' + # Cancel the Sales Order 1 + self.cancel(cr, uid, [so1.order_line[0].procurement_ids[0].id], context=context) + assert so1.order_line[0].procurement_ids[0].state == u'cancel', 'Procurement 1 should be cancelled !' + assert purchase_line.product_qty == 0.0, 'The product quantity of the first order line should be 5 and not %s' % (purchase_line.product_qty,) # Check that all procurements related are cancelled - for procu in self.browse(cr, uid, procu_ids, context=context): + for procu in procu_ids: assert procu.state == u'cancel', 'Procurement %d should be cancelled but is with a state : %s!' %(procu.id, procu.state)