diff --git a/website_sale_aplicoop/controllers/website_sale_validators.py b/website_sale_aplicoop/controllers/website_sale_validators.py index 3a774b1..940a604 100644 --- a/website_sale_aplicoop/controllers/website_sale_validators.py +++ b/website_sale_aplicoop/controllers/website_sale_validators.py @@ -63,28 +63,29 @@ def _get_salesperson_for_order(self, partner): def _find_recent_draft_order(self, partner_id, group_order, request_obj=None): + """Return the active-cycle draft sale.order for the partner, or empty. + + The active ordering period ends at group_order.cutoff_date and begins + 6 days earlier (weekly cycle). Drafts created outside this window belong + to a previous cycle and must not be reused — otherwise stale carts come + back when the user re-enters the order page. + """ req = request_obj or request - from datetime import datetime from datetime import timedelta - today = datetime.now().date() - start_of_week = today - timedelta(days=today.weekday()) - end_of_week = start_of_week + timedelta(days=6) + if not group_order or not group_order.cutoff_date: + return req.env["sale.order"] + + period_start = group_order.cutoff_date - timedelta(days=6) + period_end = group_order.cutoff_date domain = [ ("partner_id", "=", partner_id), ("group_order_id", "=", group_order.id), ("state", "=", "draft"), + ("create_date", ">=", f"{period_start} 00:00:00"), + ("create_date", "<=", f"{period_end} 23:59:59"), ] - if group_order.pickup_date: - domain.append(("pickup_date", "=", group_order.pickup_date)) - else: - domain.extend( - [ - ("create_date", ">=", f"{start_of_week} 00:00:00"), - ("create_date", "<=", f"{end_of_week} 23:59:59"), - ] - ) return ( req.env["sale.order"].sudo().search(domain, order="create_date desc", limit=1) diff --git a/website_sale_aplicoop/tests/test_group_order_status_endpoint.py b/website_sale_aplicoop/tests/test_group_order_status_endpoint.py index 082ba01..0f42dc3 100644 --- a/website_sale_aplicoop/tests/test_group_order_status_endpoint.py +++ b/website_sale_aplicoop/tests/test_group_order_status_endpoint.py @@ -134,6 +134,93 @@ class TestGroupOrderStatusEndpoint(TransactionCase): self.assertEqual(data.get("action"), "clear_cart") self.assertNotIn("items", data) + def test_find_recent_draft_excludes_previous_cycle(self): + """_find_recent_draft_order must only return drafts whose create_date + falls in [cutoff_date - 6 days, cutoff_date]. + + Regression (observed on stage.elikabilbo.eus): when the previous + cycle's draft still matched group_order.pickup_date (because both + were the same stale value), the helper returned it and the cart + was repopulated with old products on the next page load. + """ + partner = self.env.user.partner_id + + # Ensure cutoff_date is in the (near) future so the active window is + # well-defined and the cutoff-passed guard is NOT what's being tested. + future_cutoff = fields.Date.today() + timedelta(days=2) + self.group_order.sudo().write({"cutoff_date": future_cutoff}) + # Mirror production conditions where pickup_date matches between + # group_order and the stale draft — this is what made the old + # exact-pickup-date filter return the previous cycle's draft. + matching_pickup_date = self.group_order.pickup_date + + previous_cycle_create = fields.Datetime.now() - timedelta(days=10) + stale_draft = self.env["sale.order"].create( + { + "partner_id": partner.id, + "group_order_id": self.group_order.id, + "pickup_date": matching_pickup_date, + "order_line": [ + ( + 0, + 0, + { + "product_id": self.product.id, + "product_uom_qty": 3, + }, + ) + ], + } + ) + # create_date is auto-stamped; backdate it directly to simulate a draft + # left over from a previous weekly cycle. + self.env.cr.execute( + "UPDATE sale_order SET create_date = %s WHERE id = %s", + (previous_cycle_create, stale_draft.id), + ) + stale_draft.invalidate_recordset(["create_date"]) + + request_mock = self._build_request_mock({}) + with patch( + "odoo.addons.website_sale_aplicoop.controllers.website_sale.request", + request_mock, + ): + found = self.controller._find_recent_draft_order( + partner.id, self.group_order + ) + self.assertFalse( + found, + "Previous-cycle draft must not be returned (create_date is outside " + "[cutoff-6, cutoff] window) even when pickup_date matches", + ) + + # Now create a current-cycle draft and confirm it IS returned. + current_draft = self.env["sale.order"].create( + { + "partner_id": partner.id, + "group_order_id": self.group_order.id, + "pickup_date": matching_pickup_date, + "order_line": [ + ( + 0, + 0, + { + "product_id": self.product.id, + "product_uom_qty": 1, + }, + ) + ], + } + ) + with patch( + "odoo.addons.website_sale_aplicoop.controllers.website_sale.request", + request_mock, + ): + found = self.controller._find_recent_draft_order( + partner.id, self.group_order + ) + self.assertEqual(found.id, current_draft.id) + def test_save_order_endpoint_rejects_closed_group_order(self): """/eskaera/save-order must reject closed group order with clear_cart action.""" self.group_order.action_close()