diff options
| author | Mathias Mathy (MAMA) <mama@odoo.com> | 2025-01-15 12:52:20 +0000 |
|---|---|---|
| committer | svs-odoo <svs@odoo.com> | 2025-02-06 10:44:08 +0000 |
| commit | 2ab0b63b7042293f8229b29bcea478d37d4c3df5 (patch) | |
| tree | e9d70eccc128d4f9554a7f00da95c505d2e110e9 | |
| parent | 36f3f346744ef82bb76bf7593b2cd071f27570c1 (diff) | |
[FIX] stock: wrong result_package_id
When forcefully unreserving then reserving products coming from a same
package for multiple pickings, the source package is wrongly propagated
as destination package on the multiple pickings.
To reproduce:
- `-i sale_stock,sale_management`
- Create a storable product (I) with 30 qty on hand
- Create and confirm an internal transfer to put the product I in an pack (P)
- Create and confirm two SO :
- Sell 10 I
- Sell 20 I
- Check the 2 SO delivery pickings (D):
- Each are reserved from pack P
- They don't have any 'Destination Package' [Expected]
- From the picking list view, by selecting the 2 pickings D :
- 'Unreserve' them both
- 'Check Availability'them both
- Check the pickings D:
- Each are reserved from pack P
- Each have 'Destination Package' P [Faulty]
opw-4272573
closes odoo/odoo#196701
X-original-commit: 2777dfcc1cd9eee973ba59fd032d2081b8fe60a3
Signed-off-by: Steve Van Essche <svs@odoo.com>
Signed-off-by: Mathias Mathy (mama) <mama@odoo.com>
| -rw-r--r-- | addons/stock/models/stock_picking.py | 6 | ||||
| -rw-r--r-- | addons/stock/tests/test_packing.py | 48 |
2 files changed, 51 insertions, 3 deletions
diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index f006623f3d9..1a68fa4710a 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -1299,9 +1299,9 @@ class Picking(models.Model): 'move_line_ids': [(6, 0, move_lines_to_pack.ids)], 'company_id': pickings.company_id.id, }) - # Propagate the result package in the next move for disposable packages only. - if package.package_use == 'disposable': - move_lines_to_pack.write({'result_package_id': package.id}) + # Propagate the result package in the next move for disposable packages only. + if package.package_use == 'disposable': + move_lines_to_pack.write({'result_package_id': package.id}) else: move_lines_in_package_level = move_lines_to_pack.filtered(lambda ml: ml.move_id.package_level_id) move_lines_without_package_level = move_lines_to_pack - move_lines_in_package_level diff --git a/addons/stock/tests/test_packing.py b/addons/stock/tests/test_packing.py index f8e9cbb4d80..4d28ced6c0f 100644 --- a/addons/stock/tests/test_packing.py +++ b/addons/stock/tests/test_packing.py @@ -1917,3 +1917,51 @@ class TestPackagePropagation(TestPackingCommon): self.assertEqual(len(pack_lines), 2, 'Should have only 2 stock move line') self.assertFalse(pack_lines[0].result_package_id, 'Should not have the reusable package') self.assertEqual(pack_lines[1].result_package_id, disposable_package, 'Should have only the disposable package') + + def test_conditional_package_propagation(self): + """If a picking completely moves the products of a package, you want to pass it as result_package_id. + On the other hand, if the quantity of the same pack is split between several pickings, you want to leave the result_package_id empty. + """ + # Storable product : 30 qty in a package. + package = self.env['stock.quant.package'].create({'name': 'packtest'}) + self.env['stock.quant']._update_available_quantity(self.productA, self.stock_location, 30.0, package_id=package) + + # 1 delivery picking, 30 product, action_assign => On move line, package_id == result_package_id + full_delivery = self.env['stock.picking'].create({ + 'picking_type_id': self.warehouse.out_type_id.id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + 'move_ids': [Command.create({ + 'name': 'move full', + 'product_id': self.productA.id, + 'product_uom_qty': 30.0, + 'product_uom': self.productA.uom_id.id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + })] + }) + full_delivery.action_confirm() + full_delivery.action_assign() + self.assertEqual(full_delivery.move_line_ids.package_id, package, "The package should be used as source.") + self.assertEqual(full_delivery.move_line_ids.result_package_id, package, "If all the products in a package are to be moved, we must move the entire package.") + full_delivery.action_cancel() # Cancel delivery to unreserve the package/quantity. + + # Create 2 delivery picking : 10 & 20 of product each. + partial_deliveries = self.env['stock.picking'].create([{ + 'picking_type_id': self.warehouse.out_type_id.id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + 'move_ids': [Command.create({ + 'name': 'move partial', + 'product_id': self.productA.id, + 'product_uom_qty': qty, + 'product_uom': self.productA.uom_id.id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + })] + } for qty in [10, 20]]) + partial_deliveries.action_confirm() + partial_deliveries.action_assign() + # action_assign => On move lines, result_package_id is not set. + self.assertEqual(partial_deliveries.move_line_ids.package_id, package, "The package should be used as source.") + self.assertFalse(partial_deliveries.move_line_ids.result_package_id, "If the contents of a single pack are reserved by multiple picks, the entire pack can't reproduce on each pick.") |
