diff --git a/stock_reserve_rule/models/stock_reserve_rule.py b/stock_reserve_rule/models/stock_reserve_rule.py index ef74c6dc3..70c3fae23 100644 --- a/stock_reserve_rule/models/stock_reserve_rule.py +++ b/stock_reserve_rule/models/stock_reserve_rule.py @@ -219,11 +219,26 @@ class StockReserveRuleRemoval(models.Model): # Group by location (in this removal strategies, we want to consider # the total quantity held in a location). quants_per_bin = quants._group_by_location() - # We take goods only if we empty the bin. # The original ordering (fefo, fifo, ...) must be kept. - rounding = fields.first(quants).product_id.uom_id.rounding + product = fields.first(quants).product_id + rounding = product.uom_id.rounding + locations_with_other_quants = [ + group["location_id"][0] + for group in quants.read_group( + [ + ("location_id", "in", quants.location_id.ids), + ("product_id", "not in", quants.product_id.ids), + ("quantity", ">", 0), + ], + ["location_id"], + "location_id", + ) + ] for location, location_quants in quants_per_bin: + if location.id in locations_with_other_quants: + continue + location_quantity = sum(location_quants.mapped("quantity")) - sum( location_quants.mapped("reserved_quantity") ) diff --git a/stock_reserve_rule/tests/test_reserve_rule.py b/stock_reserve_rule/tests/test_reserve_rule.py index 24930732b..6b43acd9a 100644 --- a/stock_reserve_rule/tests/test_reserve_rule.py +++ b/stock_reserve_rule/tests/test_reserve_rule.py @@ -493,6 +493,37 @@ class TestReserveRule(common.SavepointCase): ) self.assertEqual(move.state, "assigned") + def test_rule_empty_bin_multiple_allocation(self): + self._update_qty_in_location(self.loc_zone1_bin1, self.product1, 10) + self._update_qty_in_location(self.loc_zone1_bin1, self.product2, 10) + self._update_qty_in_location(self.loc_zone2_bin1, self.product1, 10) + picking = self._create_picking(self.wh, [(self.product1, 10)]) + + self._create_rule( + {}, + [ + # This rule should be excluded for zone1 / bin1 because the + # bin would not be empty + { + "location_id": self.loc_zone1.id, + "sequence": 1, + "removal_strategy": "empty_bin", + }, + {"location_id": self.loc_zone2.id, "sequence": 2}, + ], + ) + picking.action_assign() + move = picking.move_lines + ml = move.move_line_ids + + self.assertRecordValues( + ml, + [ + {"location_id": self.loc_zone2_bin1.id, "product_qty": 10.0}, + ], + ) + self.assertEqual(move.state, "assigned") + def test_rule_packaging(self): self._setup_packagings( self.product1,