diff --git a/stock_picking_batch_creation/tests/test_clustering_conditions.py b/stock_picking_batch_creation/tests/test_clustering_conditions.py
index 73d2313e14..f0e25a72e0 100644
--- a/stock_picking_batch_creation/tests/test_clustering_conditions.py
+++ b/stock_picking_batch_creation/tests/test_clustering_conditions.py
@@ -432,6 +432,27 @@ def test_pickings_with_different_partners(self):
batch2 = self.make_picking_batch._create_batch()
self.assertEqual(self.pick1 | self.pick2, batch2.picking_ids)
+ def test_pickings_with_different_partners_max_capacity_enabled(self):
+ """same as previous test but this time use_maximum_capacity_priority_grouping
+ is enabled"""
+ partner1 = self.env["res.partner"].create({"name": "partner 1"})
+ partner2 = self.env["res.partner"].create({"name": "partner 2"})
+ self._set_quantity_in_stock(self.stock_location, self.p5)
+ self._create_picking_pick_and_assign(self.picking_type_1.id, products=self.p5)
+ (self.pick1 | self.pick2).write({"partner_id": partner1.id})
+ self.pick3.write({"partner_id": partner2.id})
+ self.make_picking_batch.write(
+ {
+ "maximum_number_of_preparation_lines": 10,
+ "restrict_to_same_partner": True,
+ "use_maximum_capacity_priority_grouping": True,
+ }
+ )
+ batch = self.make_picking_batch._create_batch()
+ self.assertEqual(self.pick1 | self.pick2, batch.picking_ids)
+ batch2 = self.make_picking_batch._create_batch()
+ self.assertEqual(self.pick3, batch2.picking_ids)
+
def test_picking_with_maximum_number_of_lines_exceed(self):
# pick 3 has 2 lines
# create a batch picking with maximum number of lines = 1
diff --git a/stock_picking_batch_creation/wizards/make_picking_batch.py b/stock_picking_batch_creation/wizards/make_picking_batch.py
index 9c4e445558..9c28744732 100644
--- a/stock_picking_batch_creation/wizards/make_picking_batch.py
+++ b/stock_picking_batch_creation/wizards/make_picking_batch.py
@@ -91,6 +91,11 @@ class MakePickingBatch(models.TransientModel):
"picking for the sole case where a device is suitable for the picking but the "
"picking has more lines than the maximum number of lines.",
)
+ use_maximum_capacity_priority_grouping = fields.Boolean(
+ help="Enable to prioritize stock picking groups based on their total weight and"
+ "number of picking lines, ensuring the highest priority groups are processed"
+ "first.",
+ )
__slots__ = (
"_volume_by_partners",
@@ -268,6 +273,8 @@ def _get_first_picking(self, no_nbr_lines_limit=False):
for device in self.stock_device_type_ids:
device_domains.append(self._get_picking_domain_for_device(device))
domain = AND([domain, OR(device_domains)])
+ if self.use_maximum_capacity_priority_grouping:
+ domain = self._get_domain_for_highest_priority_picking_group(domain)
return self._execute_search_pickings(domain, limit=1)
def _get_additional_picking(self):
@@ -466,3 +473,59 @@ def _create_batch_values(self):
"batch_nbr_bins": self._device.nbr_bins - self._remaining_nbr_bins,
"batch_nbr_lines": sum(selected_pickings.mapped("nbr_picking_lines")),
}
+
+ def _get_group_by_for_highest_priority_picking_group(self):
+ """
+ Retrieves the fields used for grouping stock pickings in order to determine
+ the highest priority picking group.
+ """
+ res = []
+ if self.restrict_to_same_priority:
+ res.append("priority")
+ if self.restrict_to_same_partner:
+ res.append("partner_id")
+ return res
+
+ @api.model
+ def _get_comparison_fields_for_highest_priority_picking_group(self):
+ """This method can be overwritten to add more comparison fields or change the
+ comparison order"""
+ return ["weight", "nbr_picking_lines"]
+
+ def _get_domain_for_highest_priority_picking_group(self, domain):
+ """
+ This method retrieves the domain for the group of stock pickings that has the
+ highest priority, based on the sum of weight, number of picking lines, and the
+ count of pickings.
+ It first groups the stock pickings by specified fields, then sorts the groups
+ in descending order of weight, number of picking lines, and count.
+ The method returns the domain for the group with the highest priority or
+ original domain if no groups are found.
+
+ Args:
+ domain (list): The original domain to filter the stock pickings.
+
+ Returns:
+ list: The domain corresponding to the group of stock pickings with the
+ highest priority, or the original domain.
+ """
+ group_by_fields = self._get_group_by_for_highest_priority_picking_group()
+ comparison_fields = (
+ self._get_comparison_fields_for_highest_priority_picking_group()
+ )
+ items = self.env["stock.picking"].read_group(
+ domain,
+ groupby=group_by_fields,
+ fields=[f"{f}:sum" for f in comparison_fields],
+ lazy=False,
+ )
+ sorted_items = sorted(
+ items,
+ key=lambda x: [x[f] for f in comparison_fields + ["__count"]],
+ reverse=True,
+ )
+ # Return the first item, which has the highest priority
+ item = sorted_items[0] if sorted_items else None
+ if item and item.get("__domain"):
+ return item.get("__domain")
+ return domain
diff --git a/stock_picking_batch_creation/wizards/make_picking_batch.xml b/stock_picking_batch_creation/wizards/make_picking_batch.xml
index c28c1fb197..c036a29306 100644
--- a/stock_picking_batch_creation/wizards/make_picking_batch.xml
+++ b/stock_picking_batch_creation/wizards/make_picking_batch.xml
@@ -14,6 +14,7 @@
+