[FIX] stock: negative move propagation

When a warehouse used multi-steps for incoming/outgoing shipments,
negative procurements could create returns pickings instead of reducing
the quantity of subsequent moves down the chain.

For example a two-step delivery, a sale order with 5 product A would
have the following pickings linked :
Pick:
- product A : 5 qty
Out:
- product A : 5 qty

Then reducing the amount of product A to 2 in the sale order would do :
Pick:
- product A : 2 qty
Out:
- product A : 5 qty
Return:
- product A : 3 qty

closes odoo/odoo#84900

X-original-commit: c9bc689468d2c775d3b3ec65c8894e4dd66e7249
Signed-off-by: Arnold Moyaux <arm@odoo.com>
This commit is contained in:
clesgow
2022-02-21 09:34:58 +00:00
parent 6806a72e45
commit 6f2ba1e1b4
2 changed files with 18 additions and 6 deletions
+13 -5
View File
@@ -1122,8 +1122,11 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
def test_17_qty_update_propagation(self):
""" Creates a sale order, then modifies the sale order lines qty and verifies
that quantity changes are correctly propagated to the delivery picking.
that quantity changes are correctly propagated to the picking and delivery picking.
"""
# Set the delivery in two steps.
warehouse = self.company_data['default_warehouse']
warehouse.delivery_steps = 'pick_ship'
# Sell a product.
product = self.company_data['product_delivery_no'] # storable
product.type = 'product' # storable
@@ -1138,8 +1141,10 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
sale_order.action_confirm()
# Check picking created
self.assertEqual(len(sale_order.picking_ids), 1, 'A delivery picking should have been created.')
move_out = sale_order.picking_ids.move_ids
self.assertEqual(len(sale_order.picking_ids), 2, 'A picking and a delivery picking should have been created.')
customer_location = self.env.ref('stock.stock_location_customers')
move_pick = sale_order.picking_ids.filtered(lambda p: p.location_dest_id.id != customer_location.id).move_ids
move_out = sale_order.picking_ids.filtered(lambda p: p.location_dest_id.id == customer_location.id).move_ids
self.assertEqual(len(move_out), 1, 'Only one move should be created for a single product.')
self.assertEqual(move_out.product_uom_qty, 50, 'The move quantity should be the same as the quantity sold.')
@@ -1149,7 +1154,9 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
(1, sale_order.order_line.id, {'product_uom_qty': 30}),
]
})
self.assertEqual(move_out.product_uom_qty, 30, 'The move quantity should have been decreased as the sale order line was.')
self.assertEqual(move_pick.product_uom_qty, 30, 'The move quantity should have been decreased as the sale order line was.')
self.assertEqual(move_out.product_uom_qty, 30, 'The move quantity should have been decreased as the sale order line and the pick line were.')
self.assertEqual(len(sale_order.picking_ids), 2, 'No additionnal picking should have been created.')
# Increase the quantity in the sale order and check the move has been updated.
sale_order.write({
@@ -1157,4 +1164,5 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
(1, sale_order.order_line.id, {'product_uom_qty': 40})
]
})
self.assertEqual(move_out.product_uom_qty, 40, 'The move quantity should have been increased as the sale order line was.')
self.assertEqual(move_pick.product_uom_qty, 40, 'The move quantity should have been increased as the sale order line was.')
self.assertEqual(move_out.product_uom_qty, 40, 'The move quantity should have been increased as the sale order line and the pick line were.')
+5 -1
View File
@@ -6,7 +6,7 @@ from collections import defaultdict
from datetime import timedelta
from operator import itemgetter
from odoo import _, api, fields, models
from odoo import _, api, Command, fields, models
from odoo.exceptions import UserError
from odoo.osv import expression
from odoo.tools.float_utils import float_compare, float_is_zero, float_round
@@ -878,6 +878,10 @@ class StockMove(models.Model):
# If quantity can be fully absorbed by a single move, update its quantity and remove the negative move
if float_compare(pos_move.product_uom_qty, abs(neg_move.product_uom_qty), precision_rounding=pos_move.product_uom.rounding) >= 0:
pos_move.product_uom_qty += neg_move.product_uom_qty
pos_move.write({
'move_dest_ids': [Command.link(m.id) for m in self.mapped('move_dest_ids')],
'move_orig_ids': [Command.link(m.id) for m in self.mapped('move_orig_ids')],
})
merged_moves |= pos_move
moves_to_unlink |= neg_move
break