Skip to content
Snippets Groups Projects
Commit 5b83f721 authored by Nicolas Martinelli's avatar Nicolas Martinelli
Browse files

[FIX] purchase_stock: UoM rounding


- Set the rounding of Unit(s) to 1.0
- Create a PO for 1.4 Unit(s), validate => the picking contains
1.4 Unit(s)
- Validate the picking

The backorder wizard is displayed, and if no backorder is selected, a
crash occurs.

The quantity should be rounded when the picking is created. Otherwise,
inconsistencies will appears when it is rounded in subsequent processes.

opw-2046965

closes odoo/odoo#35560

Signed-off-by: default avatarNicolas Martinelli (nim) <nim@odoo.com>
parent 542e9640
Branches
Tags
No related merge requests found
......@@ -338,12 +338,14 @@ class PurchaseOrderLine(models.Model):
if float_compare(diff_quantity, 0.0, precision_rounding=self.product_uom.rounding) > 0:
quant_uom = self.product_id.uom_id
get_param = self.env['ir.config_parameter'].sudo().get_param
if self.product_uom.id != quant_uom.id and get_param('stock.propagate_uom') != '1':
# Always call '_compute_quantity' to round the diff_quantity. Indeed, the PO quantity
# is not rounded automatically following the UoM.
if get_param('stock.propagate_uom') != '1':
product_qty = self.product_uom._compute_quantity(diff_quantity, quant_uom, rounding_method='HALF-UP')
template['product_uom'] = quant_uom.id
template['product_uom_qty'] = product_qty
else:
template['product_uom_qty'] = diff_quantity
template['product_uom_qty'] = self.product_uom._compute_quantity(diff_quantity, self.product_uom, rounding_method='HALF-UP')
res.append(template)
return res
......
......@@ -313,3 +313,65 @@ class TestCreatePicking(common.TestProductCommon):
purchase_order_2.picking_ids.button_validate()
self.assertEqual(sum(customer_picking.move_lines.mapped('reserved_availability')), 100.0, 'The total quantity for the customer move should be available and reserved.')
def test_04_rounding(self):
""" We set the Unit(s) rounding to 1.0 and ensure buying 1.2 units in a PO is rounded to 1.0
at reception.
"""
uom_unit = self.env.ref('uom.product_uom_unit')
uom_unit.rounding = 1.0
# buy a dozen
po = self.env['purchase.order'].create(self.po_vals)
po.order_line.product_qty = 1.2
po.button_confirm()
# the move should be 1.0 units
move1 = po.picking_ids.move_lines[0]
self.assertEqual(move1.product_uom_qty, 1.0)
self.assertEqual(move1.product_uom.id, uom_unit.id)
self.assertEqual(move1.product_qty, 1.0)
# edit the so line, buy 2.4 units, the move should now be 2.0 units
po.order_line.product_qty = 2.0
self.assertEqual(move1.product_uom_qty, 2.0)
self.assertEqual(move1.product_uom.id, uom_unit.id)
self.assertEqual(move1.product_qty, 2.0)
# deliver everything
move1.quantity_done = 2.0
po.picking_ids.button_validate()
# check the delivered quantity
self.assertEqual(po.order_line.qty_received, 2.0)
def test_05_uom_rounding(self):
""" We set the Unit(s) and Dozen(s) rounding to 1.0 and ensure buying 1.3 dozens in a PO is
rounded to 1.0 at reception.
"""
uom_unit = self.env.ref('uom.product_uom_unit')
uom_dozen = self.env.ref('uom.product_uom_dozen')
uom_unit.rounding = 1.0
uom_dozen.rounding = 1.0
# buy 1.3 dozen
po = self.env['purchase.order'].create(self.po_vals)
po.order_line.product_qty = 1.3
po.order_line.product_uom = uom_dozen.id
po.button_confirm()
# the move should be 16.0 units
move1 = po.picking_ids.move_lines[0]
self.assertEqual(move1.product_uom_qty, 16.0)
self.assertEqual(move1.product_uom.id, uom_unit.id)
self.assertEqual(move1.product_qty, 16.0)
# force the propagation of the uom, buy 2.6 dozens, the move 2 should have 2 dozens
self.env['ir.config_parameter'].sudo().set_param('stock.propagate_uom', '1')
po.order_line.product_qty = 2.6
move2 = po.picking_ids.move_lines.filtered(lambda m: m.product_uom.id == uom_dozen.id)
self.assertEqual(move2.product_uom_qty, 2)
self.assertEqual(move2.product_uom.id, uom_dozen.id)
self.assertEqual(move2.product_qty, 24)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment