[IMP] website_sale_aplicoop: pay on the checkout page, not a step later

The separate /eskaera/<slug>/payment step is gone. Members review the
summary, choose home delivery and pick a payment method on the checkout,
in one screen; the old URL redirects there so bookmarks and sessions that
were mid-flow do not hit a 404.

The checkout now renders the member's draft sale.order instead of the
localStorage cart. That is what fixes the products appearing "out of
nowhere" between the two pages: the summary was a snapshot of localStorage
taken at page load, and `_autoLoadDraftOnInit` then pulled the draft back
into localStorage without re-rendering. Deleting a product in the shop
removed it from the cart but left the line on the draft, so the autoload
resurrected it, the confirm button sent it back, and it only became
visible one page later. The checkout no longer auto-loads the draft — it
renders it, and what it shows is what the payment form charges.

"Proceed to Checkout" pushes the cart to that draft before navigating.
Saving is idempotent: `_merge_or_replace_draft` reuses the cycle's draft
and, through the new `_draft_matches_lines`, rewrites `order_line` only
when the lines actually differ — replacing them unlinks and recreates
every one of them, which is pure churn when nothing changed.

The home delivery checkbox goes through the new /eskaera/set-home-delivery
so the delivery line moves on the order itself. Writing only to
localStorage would have changed the summary and left the amount alone,
which with online payment on is the amount being charged.

Also fixes the confirmation notice nobody ever saw: saving answered with
the payment step URL and the frontend followed it immediately, destroying
the toast in the same tick. Saving no longer navigates; the caller decides
whether it is staying or moving on.

Along the way: checkout_labels.js and the eskaera_checkout_summary /
eskaera_payment templates are removed, superseded by the server-rendered
summary and checkout, and the stale sessionStorage delivery preference no
longer overrides the checkbox the order just rendered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
GitHub Copilot 2026-08-17 19:14:49 +02:00
parent f81c1ca8e7
commit e625b0c2f3
11 changed files with 873 additions and 746 deletions

View file

@ -116,9 +116,9 @@ class TestTemplatesRendering(TransactionCase):
# The fix ensures no <t t-set="day_names" t-value="[_(...)]"/> exists
# which was causing the NoneType error
def test_eskaera_checkout_summary_template_exists(self):
"""Test that eskaera_checkout_summary sub-template exists."""
template = self.env.ref("website_sale_aplicoop.eskaera_checkout_summary")
def test_order_lines_summary_template_exists(self):
"""The checkout summary sub-template exists and reads the sale.order."""
template = self.env.ref("website_sale_aplicoop.eskaera_order_lines_summary")
self.assertIsNotNone(template)
self.assertEqual(template.type, "qweb")
# Verify it has the expected structure
@ -127,6 +127,14 @@ class TestTemplatesRendering(TransactionCase):
template.arch_db,
"Template must have checkout-summary-table id",
)
# The summary is server-side on purpose: what it shows is what the
# payment form charges, so it can never drift from the localStorage
# cart the way the old client-rendered table did.
self.assertIn(
"sale_order.order_line",
template.arch_db,
"Template must read the order lines, not a client-side cart",
)
self.assertIn(
"Product",
template.arch_db,
@ -137,23 +145,36 @@ class TestTemplatesRendering(TransactionCase):
template.arch_db,
"Template must have Quantity label for translation",
)
self.assertIn(
"Price", template.arch_db, "Template must have Price label for translation"
)
self.assertIn(
"Subtotal",
template.arch_db,
"Template must have Subtotal label for translation",
)
def test_eskaera_checkout_summary_renders(self):
"""Test that eskaera_checkout_summary renders without errors."""
template = self.env.ref("website_sale_aplicoop.eskaera_checkout_summary")
# Render the template with empty context
html = template._render_template(template.xml_id, {})
# Should contain the basic table structure
def test_order_lines_summary_renders(self):
"""The summary renders the lines and total of a real order."""
order = self.env["sale.order"].create(
{
"partner_id": self.supplier.id,
"order_line": [
(
0,
0,
{
"product_id": self.product.id,
"product_uom_qty": 2,
"price_unit": 5.0,
},
)
],
}
)
template = self.env.ref("website_sale_aplicoop.eskaera_order_lines_summary")
html = template._render_template(template.xml_id, {"sale_order": order})
self.assertIn("<table", html)
self.assertIn("checkout-summary-table", html)
self.assertIn("Product", html)
self.assertIn("Quantity", html)
self.assertIn("This order's cart is empty", html)
self.assertIn("Test Product", html)