Members can now pay their eskaera at checkout, through the standard Odoo
payment machinery. Enabled per group order with a new `online_payment`
boolean, off by default: an order without it behaves exactly as before,
members save a draft and the cutoff cron confirms them in bulk.
The flow mirrors website_sale's: the checkout button becomes "Confirm and
pay", saving the cart redirects to a new /eskaera/<slug>/payment step that
renders `payment.form` from `sale`'s `_get_payment_values`, and the standard
/my/orders/<id>/transaction route takes it from there. This addon ships no
provider and configures none; the co-op publishes whichever it wants.
`website_sale`'s `_get_shop_payment_values` is deliberately not reused: it
runs `_get_shop_payment_errors`, which blocks on shippable products without a
delivery method — exactly an eskaera order, collected at the co-op with no
carrier. For the same reason the transaction route stays the portal one,
which does not call `_check_cart_is_ready_to_be_paid()`.
Payment confirms the order, which has three consequences handled here:
* `payment.transaction._check_amount_and_confirm_order` now confirms group
orders with `from_orderpoint=True`, the way the cutoff cron already does.
Without it a product with a broken replenishment route raises inside
`_post_process`, and `/payment/status/poll` rolls back and re-raises: the
member sees a payment error over a `done` transaction and the retry cron
fails forever.
* `_confirm_linked_sale_orders` also sweeps the cycle's already confirmed
orders into the picking batch, scoped by `pickup_date`. Its early return on
"no drafts" ran before any batching, so a fully prepaid cycle produced no
batch at all. `_cron_batch_paid_orders_of_closed_cycles` covers the same
hole for cycles closed by hand.
* A duplicate-order guard answers 409 on save-order, add-to-cart and
load-draft, and shows a notice on the shop, so a member whose order is
already placed cannot build and pay for a second one.
The payment policy lives in the model rather than the controller: there are
three sale.order creation paths and two are live, so `_compute_require_payment`
and `_compute_prepayment_percent` are extended instead of patching five vals
dicts. Orders are also created under the group order's company, which is what
filters the payment providers.
Along the way: eskaera drafts were invisible in /my/orders. The portal rule is
`message_partner_ids child_of` and sale.order only subscribes the customer on
send or confirm, never on a draft create, so the `_prepare_orders_domain`
override that includes drafts never had any effect. Fixed with an explicit
`message_subscribe`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Quantity control layout: changed from wrapping flex to deliberate two-row
grid so the add-to-cart button sits full-width underneath the stepper,
avoiding accidental line breaks and giving the primary action more pulsing
area. Also removed the /Kg suffix's redundant font rules.
Order card delivery row: reordered to badge-then-date (visually centred),
removed the "Delivery" label, and swapped bg-primary to text-bg-primary for
proper contrast on the home-delivery badge (3.13:1 minimum).
Tooltip translations: moved hardcoded static tooltips from data-bs-title
(untranslatable) to title (QWeb-translatable). Handled the edge case of
"Save Cart" and "Back to Cart" which had translations but no model_terms
reference in the POT, causing the merge to discard them — added the view
reference so translations now apply.
Load-from-history page: added accessibility: a visible status message
("Loading your order…"), a <noscript> fallback with link to the group
order, lang and viewport meta tags, and localised strings for all three
languages. Gave the page a minimal inline style block since it does not
inherit the token system (no website.layout).
Translations: 11 new entries (es/eu/ca) for new/reworded UI strings, plus
two code catalogue entries (products found, Close) that needed the
#. odoo-python comment for _() resolution. Documented the silent-failure
pattern in docs/TRANSLATIONS.md: the POT merge, untranslatable attributes,
and missing code comments.
Tests: 246 passing. Pre-commit: clean.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Add hardcoded fallback translations for es/eu when PO-based translation
returns the source string unchanged. Expand labels dict with all keys
needed by the frontend. Fix JSON response parsing in template
(data.result || data). Add js_translations keys. Add pot file for
stock_picking_batch_custom.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Añade botón 'Clear Cart' (fa-trash) en el header y footer del sidebar
del carrito en la página de lista de productos.
Cambios:
- views/website_templates.xml: botón clear-cart-btn en card-header y
clear-cart-btn-footer en card-footer del sidebar
- controllers/website_sale.py: nuevo endpoint POST /eskaera/clear-cart
que cancela el sale.order borrador del usuario si existe
- static/src/js/website_sale.js: método _clearCart(), listeners para
ambos botones (header + footer)
- models/js_translations.py: nuevas cadenas clear_cart, clear_cart_confirm,
cart_cleared, draft_cancelled
- i18n/es.po, i18n/eu.po: traducciones ES y EU de los nuevos labels
- Remove redundant string= from 17 field definitions where name matches string value (W8113)
- Convert @staticmethod to instance methods in selection methods for proper self.env._() access
- Fix W8161 (prefer-env-translation) by using self.env._() instead of standalone _()
- Fix W8301/W8115 (translation-not-lazy) by proper placement of % interpolation outside self.env._()
- Remove unused imports of odoo._ from group_order.py and sale_order_extension.py
- All OCA linting warnings in website_sale_aplicoop main models are now resolved
Changes:
- website_sale_aplicoop/models/group_order.py: 21 field definitions cleaned
- website_sale_aplicoop/models/sale_order_extension.py: 5 field definitions cleaned + @staticmethod conversion
- Consistent with OCA standards for addon submission