[FIX] sale_stock, purchase_stock: fix conversion qty received

Rounding in purchase order is 'UP' which is causing issue when doing
receipt in a different uom than the purchase. Rounding should be
'HALF-UP'

Added test in purchase and sales to ensure this issue is detected in the
 future.

closes odoo/odoo#76006

X-original-commit: 9d3d1949d20834c92449c989299ac8e67f26d05d
Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com>
This commit is contained in:
fja-odoo
2021-09-07 11:35:04 +00:00
parent fbaf666f6f
commit bdac1407a7
3 changed files with 62 additions and 3 deletions
+3 -3
View File
@@ -308,7 +308,7 @@ class PurchaseOrderLine(models.Model):
if move.state == 'done':
if move.location_dest_id.usage == "supplier":
if move.to_refund:
total -= move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
total -= move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom, rounding_method='HALF-UP')
elif move.origin_returned_move_id and move.origin_returned_move_id._is_dropshipped() and not move._is_dropshipped_returned():
# Edge case: the dropship is returned to the stock, no to the supplier.
# In this case, the received quantity on the PO is set although we didn't
@@ -323,9 +323,9 @@ class PurchaseOrderLine(models.Model):
[("id", "child_of", move.warehouse_id.view_location_id.id)]
)
):
total -= move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
total -= move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom, rounding_method='HALF-UP')
else:
total += move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
total += move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom, rounding_method='HALF-UP')
line._track_qty_received(total)
line.qty_received = total
@@ -336,3 +336,33 @@ class TestPurchaseOrder(ValuationReconciliationTestCommon):
po_on_time_rate = po.on_time_rate
# 4. Check both are equals.
self.assertEqual(partner_on_time_rate, po_on_time_rate)
def test_04_multi_uom(self):
yards_uom = self.env['uom.uom'].create({
'category_id': self.env.ref('uom.uom_categ_length').id,
'name': 'Yards',
'factor_inv': 0.9144,
'uom_type': 'bigger',
})
self.product_id_2.write({
'uom_id': self.env.ref('uom.product_uom_meter').id,
'uom_po_id': yards_uom.id,
})
po = self.env['purchase.order'].create({
'partner_id': self.partner_a.id,
'order_line': [
(0, 0, {
'name': self.product_id_2.name,
'product_id': self.product_id_2.id,
'product_qty': 4.0,
'product_uom': self.product_id_2.uom_po_id.id,
'price_unit': 1.0,
'date_planned': datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
})
],
})
po.button_confirm()
picking = po.picking_ids[0]
picking.move_line_ids.write({'qty_done': 3.66})
picking.button_validate()
self.assertEqual(po.order_line.mapped('qty_received'), [4.0], 'Purchase: no conversion error on receipt in different uom"')
@@ -1090,3 +1090,32 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
so.picking_ids.action_cancel()
self.assertEqual(so.invoice_status, 'no')
def test_16_multi_uom(self):
yards_uom = self.env['uom.uom'].create({
'category_id': self.env.ref('uom.uom_categ_length').id,
'name': 'Yards',
'factor_inv': 0.9144,
'uom_type': 'bigger',
})
product = self.env.ref('product.product_product_11').copy({
'uom_id': self.env.ref('uom.product_uom_meter').id,
'uom_po_id': yards_uom.id,
})
so = self.env['sale.order'].create({
'partner_id': self.partner_a.id,
'order_line': [
(0, 0, {
'name': product.name,
'product_id': product.id,
'product_uom_qty': 4.0,
'product_uom': yards_uom.id,
'price_unit': 1.0,
})
],
})
so.action_confirm()
picking = so.picking_ids[0]
picking.move_lines.write({'quantity_done': 3.66})
picking.button_validate()
self.assertEqual(so.order_line.mapped('qty_delivered'), [4.0], 'Sale: no conversion error on delivery in different uom"')