Fix stock picking batch date and does not split batchs by consumer group

This commit is contained in:
snt 2026-05-18 16:07:39 +02:00 committed by GitHub Copilot
parent b73f031dfb
commit 828278573d
2 changed files with 48 additions and 59 deletions

View file

@ -890,47 +890,41 @@ class GroupOrder(models.Model):
self.ensure_one()
StockPickingBatch = self.env["stock.picking.batch"].sudo()
# Group sale orders by consumer_group_id
groups = {}
for so in sale_orders:
group_id = so.consumer_group_id.id or False
if group_id not in groups:
groups[group_id] = self.env["sale.order"]
groups[group_id] |= so
for consumer_group_id, group_sale_orders in groups.items():
# Get pickings without batch
pickings = group_sale_orders.picking_ids.filtered(
lambda p: p.state not in ("done", "cancel") and not p.batch_id
# Create batches per group order, not per consumer group.
# If multiple picking types exist, keep one batch per picking type.
grouped_pickings = {}
pickings = sale_orders.picking_ids.filtered(
lambda p: p.state not in ("done", "cancel") and not p.batch_id
)
for picking in pickings:
grouped_pickings.setdefault(
picking.picking_type_id.id, self.env["stock.picking"]
)
grouped_pickings[picking.picking_type_id.id] |= picking
scheduled_date = self.pickup_date
if not scheduled_date and self.delivery_date:
scheduled_date = self.delivery_date - timedelta(days=1)
for picking_type_id, pickings in grouped_pickings.items():
if not pickings:
continue
# Get consumer group name for batch description
consumer_group = self.env["res.partner"].browse(consumer_group_id)
batch_desc = (
f"{self.name} - {consumer_group.name}" if consumer_group else self.name
)
# Create the batch
batch_desc = self.name
batch = StockPickingBatch.create(
{
"description": batch_desc,
"company_id": self.company_id.id,
"picking_type_id": pickings[0].picking_type_id.id,
"scheduled_date": self.pickup_date,
"picking_type_id": picking_type_id,
"scheduled_date": scheduled_date,
}
)
# Assign pickings to the batch
pickings.write({"batch_id": batch.id})
_logger.info(
"Cron: Created batch %s with %d pickings for group order %s, "
"consumer group %s",
"Cron: Created batch %s with %d pickings for group order %s",
batch.name,
len(pickings),
self.name,
consumer_group.name if consumer_group else "N/A",
)

View file

@ -227,8 +227,8 @@ class TestCronPickingBatch(TransactionCase):
"Cron should snapshot and preserve the current cycle pickup_date when confirming",
)
def test_cron_creates_picking_batch_per_consumer_group(self):
"""Test that cron creates separate picking batches per consumer group."""
def test_cron_creates_single_picking_batch_for_group_order(self):
"""Test that cron creates a single picking batch for the whole group order."""
# Create group order with cutoff yesterday (past)
group_order = self._create_group_order(cutoff_in_past=True)
@ -247,39 +247,30 @@ class TestCronPickingBatch(TransactionCase):
self.assertTrue(so1.picking_ids, "Sale order 1 should have pickings")
self.assertTrue(so2.picking_ids, "Sale order 2 should have pickings")
# Check that pickings have batch_id assigned
for picking in so1.picking_ids:
self.assertTrue(
picking.batch_id,
"Picking from SO1 should be assigned to a batch",
)
for picking in so2.picking_ids:
self.assertTrue(
picking.batch_id,
"Picking from SO2 should be assigned to a batch",
)
# Check that batches are different (one per consumer group)
# Check that all pickings share the same batch
batch_1 = so1.picking_ids[0].batch_id
batch_2 = so2.picking_ids[0].batch_id
self.assertNotEqual(
self.assertEqual(
batch_1.id,
batch_2.id,
"Different consumer groups should have different batches",
"Different consumer groups in the same group order should share one batch",
)
# Check batch descriptions contain consumer group names
self.assertIn(
self.consumer_group_1.name,
batch_1.description,
"Batch 1 description should include consumer group 1 name",
# Check that there is only one batch record created
self.assertEqual(
self.env["stock.picking.batch"].search_count(
[("description", "=", group_order.name)]
),
1,
"Only one batch should be created for a single group order",
)
self.assertIn(
self.consumer_group_2.name,
batch_2.description,
"Batch 2 description should include consumer group 2 name",
# Check batch description uses the group order name only
self.assertEqual(
batch_1.description,
group_order.name,
"Batch description should be the group order name",
)
def test_cron_same_consumer_group_same_batch(self):
@ -342,10 +333,10 @@ class TestCronPickingBatch(TransactionCase):
self.assertTrue(so.picking_ids, "Sale order should have pickings")
batch = so.picking_ids[0].batch_id
self.assertTrue(batch, "Picking should have a batch")
# scheduled_date should be set (not False/None)
self.assertTrue(
batch.scheduled_date,
"Batch should have a scheduled_date set",
self.assertEqual(
batch.scheduled_date.date(),
group_order.pickup_date,
"Batch scheduled_date should be the pickup date (day before delivery)",
)
def test_cron_does_not_duplicate_batches(self):
@ -364,13 +355,17 @@ class TestCronPickingBatch(TransactionCase):
self.assertTrue(so.picking_ids, "Sale order should have pickings")
batch_first = so.picking_ids[0].batch_id
batch_count_first = self.env["stock.picking.batch"].search_count([])
batch_count_first = self.env["stock.picking.batch"].search_count(
[("description", "=", group_order.name)]
)
# Call second time
group_order._confirm_linked_sale_orders()
batch_second = so.picking_ids[0].batch_id
batch_count_second = self.env["stock.picking.batch"].search_count([])
batch_count_second = self.env["stock.picking.batch"].search_count(
[("description", "=", group_order.name)]
)
# Should be same batch, no duplicates
self.assertEqual(
@ -427,7 +422,7 @@ class TestCronPickingBatch(TransactionCase):
def _patched_action_confirm(recordset):
should_fail = any(so.name == "SO-FAIL" for so in recordset)
if should_fail and not recordset.env.context.get("from_orderpoint"):
raise UserError("Simulated stock route error")
raise UserError()
return original_action_confirm(recordset)
with patch.object(SaleOrderClass, "action_confirm", _patched_action_confirm):