From 7d11a953442d9014e4e3da6c59cfcf73eaf9e139 Mon Sep 17 00:00:00 2001 From: snt Date: Tue, 31 Mar 2026 20:07:50 +0200 Subject: [PATCH] [FIX] website_sale_aplicoop: freeze pickup dates on cron confirm --- website_sale_aplicoop/models/group_order.py | 34 ++++++++++++++++++ .../tests/test_cron_picking_batch.py | 35 ++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/website_sale_aplicoop/models/group_order.py b/website_sale_aplicoop/models/group_order.py index 8165b8e..20b51bd 100644 --- a/website_sale_aplicoop/models/group_order.py +++ b/website_sale_aplicoop/models/group_order.py @@ -765,6 +765,40 @@ class GroupOrder(models.Model): ) try: + # Freeze cycle dates in sale orders BEFORE confirming and BEFORE + # group order dates are recomputed by the cron caller. + # This avoids displaying next cycle dates in already confirmed orders. + pickup_orders = sale_orders.filtered(lambda so: not so.home_delivery) + delivery_orders = sale_orders.filtered(lambda so: so.home_delivery) + + if pickup_orders: + pickup_orders.write( + { + "pickup_day": self.pickup_day, + "pickup_date": self.pickup_date, + "commitment_date": self.pickup_date, + } + ) + + if delivery_orders: + delivery_commitment_date = self.delivery_date or self.pickup_date + delivery_orders.write( + { + "pickup_day": self.pickup_day, + "pickup_date": self.pickup_date, + "commitment_date": delivery_commitment_date, + } + ) + + _logger.info( + "Cron: Snapshot dates applied to %d sale orders for group order %s (%s): pickup_date=%s, delivery_date=%s", + len(sale_orders), + self.id, + self.name, + self.pickup_date, + self.delivery_date, + ) + sale_orders.action_confirm() # Create picking batches after confirmation self._create_picking_batches_for_sale_orders(sale_orders) diff --git a/website_sale_aplicoop/tests/test_cron_picking_batch.py b/website_sale_aplicoop/tests/test_cron_picking_batch.py index 52fb499..d408f8f 100644 --- a/website_sale_aplicoop/tests/test_cron_picking_batch.py +++ b/website_sale_aplicoop/tests/test_cron_picking_batch.py @@ -73,7 +73,9 @@ class TestCronPickingBatch(TransactionCase): "group_ids": [ (6, 0, [self.consumer_group_1.id, self.consumer_group_2.id]) ], - "period": "once", # One-time order to avoid date recalculation + "period": "once", # One-time order; dates are set explicitly below + "cutoff_day": "0", # Monday + "pickup_day": "2", # Wednesday "state": state, } ) @@ -192,6 +194,37 @@ class TestCronPickingBatch(TransactionCase): "Sale order should be confirmed - cutoff date has passed", ) + def test_cron_freezes_pickup_date_on_confirm(self): + """Confirmed orders must keep the cycle pickup date (no next-week drift).""" + group_order = self._create_group_order(cutoff_in_past=True) + + so = self._create_sale_order(group_order, self.member_1, self.consumer_group_1) + + self.assertTrue( + group_order.pickup_date, + "Precondition failed: helper must provide a non-empty pickup_date", + ) + + # Simulate an inconsistent draft date (e.g. stale or shifted value) + wrong_pickup_date = group_order.pickup_date + timedelta(days=7) + so.write({"pickup_date": wrong_pickup_date}) + + self.assertEqual(so.state, "draft") + self.assertEqual(so.pickup_date, wrong_pickup_date) + + expected_pickup_date = group_order.pickup_date + + group_order._confirm_linked_sale_orders() + + so.invalidate_recordset() + + self.assertEqual(so.state, "sale") + self.assertEqual( + so.pickup_date, + expected_pickup_date, + "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.""" # Create group order with cutoff yesterday (past)