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>
Group order pages were published under their database id (`/eskaera/1`), which
says nothing to the member opening the link. `group.order` gains a `slug` field
and the public pages move to `/eskaera/<slug>` (e.g. `/eskaera/escola-fructuos`).
The slug is generated from the order name on creation, is unique, and can be
edited under the name on the form; emptying it regenerates it from the current
name. Values that would make the order unreachable are rejected: a plain number
(the legacy numeric URLs win that match) and the static routes served under
`/eskaera/` (`labels`, `save-order`, `i18n`, ...).
`/eskaera/<id>` and `/eskaera/<id>/checkout` are kept as redirects to their slug
URL, so the links already shared with members keep working. The AJAX endpoints
(`load-page`, `save-order`, `confirm`, ...) stay numeric: they never show up in
the address bar. Consequently the frontend now reads the order id from the
`data-order-id` attribute only, as the URL no longer carries it.
The post-migration script fills the slug of the orders that already existed.
Renaming the `/eskaera` prefix itself (`/escolas` for a schools deployment)
needs no code: a *308 Redirect / Rewrite* rule per public route in Website >
Configuration > Redirects serves the pages on the new prefix, rewrites the
links in the templates and redirects the old URLs, per website. Documented in
`readme/CONFIGURE.rst`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The "shop as a read-only catalog" behaviour lived inside website_sale_aplicoop,
so every site that wanted the eskaera flow also lost the standard cart. It now
ships as its own installable addon, with the redirect target configurable
instead of hardcoded to /eskaera.
- website_sale_disable_cart: hides the cart UI (12 header styles + the product
card quick-add) and overrides the standard cart endpoints. Redirect URL is
configurable in Website settings (default /shop); only site-internal paths are
accepted, so a misconfigured value cannot turn the shop into an open redirect
nor loop back into a disabled route.
- Fixes carried over from the original code: /shop/cart/quantity is the Odoo 18
path (it was /shop/cart_quantity, which never matched), the boxed, sidebar and
sales two/three/four headers were not covered (the cart link stayed visible on
them), and the routes now override the standard methods instead of registering
duplicate ones.
- website_sale_aplicoop 18.0.1.12.0: drops the view file and the four redirect
routes; installing it no longer touches the standard shop.
Upgrade order matters: update website_sale_aplicoop first, then install
website_sale_disable_cart in a second Odoo run — both use the same XPaths and
obsolete records are only cleaned up at the end of a run.
Tests: 8/8 in website_sale_disable_cart, aplicoop unaffected (its 2 failures
predate this change). Verified live on a DB clone: /shop/cart returns 303 to the
configured URL and no cart markup remains on /shop.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One-time, biweekly and monthly group orders now follow the same cron
confirmation flow as weekly ones (confirm sale orders + batch pickings
when the cycle cutoff passes):
- Biweekly/monthly keep the cutoff_day/pickup_day weekday scheme on a
recurrence grid anchored at start_date (creation date as fallback):
cutoffs advance +14 days / +1 month snapped to cutoff_day, with
catch-up after cron downtime. Previously they behaved as weekly.
- One-time orders (specials/promotions) are driven by end_date
(cutoff_date = end_date); once passed, the cron confirms, batches
and closes the group order.
- end_date keeps its "empty = permanent" meaning for recurring orders.
- Website draft-cart lookup window is now period-aware instead of
assuming a 6-day weekly cycle.
- New cron tests for once/biweekly/monthly cycles; i18n es/eu updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- README.md: reescrito con tabla completa de los 14 addons (6 OCA + 8 custom),
versiones actuales, árbol de dependencias y comandos de desarrollo
- docs/README.md: simplificado a índice limpio, eliminadas referencias rotas
- website_sale_aplicoop/CHANGELOG.md: añadidas versiones 1.7.0, 1.8.0 y 1.9.0
con los cambios agrupados por temática desde el último registro (1.6.0)
- website_sale_aplicoop/README_DEV.md: reescrito para reflejar v1.9.0 —
modelos actuales (group.order.slot), controladores /eskaera, catálogo
whitelist/blacklist, lazy loading, crons y árbol de dependencias
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add comprehensive test suite for excluded_category_ids
- 9 tests covering: single category, recursive subcategories,
parent exclusion, direct product override, unrelated categories,
empty blacklist, multiple exclusions, combined blacklists,
available_products_count validation
- Update UI to show excluded_category_ids in 'Productos Excluidos'
- Bump version to 18.0.1.6.0
- Update CHANGELOG with category blacklist documentation
Technical notes:
- Category blacklist was already implemented in model/logic
- This commit adds missing tests and documentation
- Recursive exclusion via get_all_excluded_descendants()
- Blacklist has absolute priority over all inclusion sources
- Add excluded_supplier_ids field for supplier exclusion
- Filter products by main_seller_id (from product_main_seller addon)
- Blacklist has absolute priority over all inclusion sources
- Products with blacklisted main supplier never appear in orders
- Update _get_products_for_group_order() with supplier blacklist logic
- Add excluded_supplier_ids to 'Productos Excluidos' section in form view
- Add comprehensive test suite (TestSupplierBlacklist class with 9 tests):
* Test exclusion by main_seller_id
* Test multiple supplier exclusion
* Test products without main seller not affected
* Test blacklist with direct product inclusion
* Test blacklist priority over supplier inclusion
* Test combined product and supplier blacklist
* Test available_products_count with supplier blacklist
- Add Spanish and Euskera translations
- Update available_products_count computation to include excluded_supplier_ids
- Version bump to 18.0.1.5.0
Use case: Exclude all products from specific supplier (e.g., temporary unavailability)
Example: Category with 100 products, exclude supplier X → all products from X excluded
Workflow: Bulk inclusion via categories + supplier-level exclusion + product-level exclusion
- Add excluded_product_ids field for explicit product exclusion
- Blacklist has absolute priority over all inclusion sources (product_ids, category_ids, supplier_ids)
- Update _get_products_for_group_order() with blacklist filter logic
- Rename 'Associations' section to 'Catálogo de Productos' with subsections:
* Productos Incluidos (whitelist: suppliers, categories, direct products)
* Productos Excluidos (blacklist: explicit exclusions)
- Add comprehensive test suite (TestProductBlacklist class with 7 tests)
- Add Spanish and Euskera translations
- Update available_products_count computation to include excluded_product_ids
- Version bump to 18.0.1.4.0
Use case: Bulk inclusion via categories/suppliers + fine-grained exclusion via blacklist
Example: Select a category with 100 products, exclude 5 unwanted → 95 available
- Add LAZY_LOADING.md with complete technical documentation (600+ lines)
- Add LAZY_LOADING_QUICK_START.md for quick reference (5 min)
- Add LAZY_LOADING_DOCS_INDEX.md as navigation guide
- Add UPGRADE_INSTRUCTIONS_v18.0.1.3.0.md with step-by-step installation
- Create DOCUMENTATION.md as main documentation index
- Update README.md with lazy loading reference
- Update docs/README.md with new docs section
- Update website_sale_aplicoop/README.md with features and changelog
- Create website_sale_aplicoop/CHANGELOG.md with version history
Lazy Loading Implementation (v18.0.1.3.0):
- Reduces initial store load from 10-20s to 500-800ms (20x faster)
- Add pagination configuration to res_config_settings
- Add _get_products_paginated() method to group_order model
- Implement AJAX endpoint for product loading
- Create 'Load More' button in website templates
- Add JavaScript listener for lazy loading behavior
- Backward compatible: can be disabled in settings
Performance Improvements:
- Initial load: 500-800ms (vs 10-20s before)
- Subsequent pages: 200-400ms via AJAX
- DOM optimization: 20 products initial vs 1000+ before
- Configurable: enable/disable and items per page
Documentation Coverage:
- Technical architecture and design
- Installation and upgrade instructions
- Configuration options and best practices
- Troubleshooting and common issues
- Performance metrics and validation
- Rollback procedures
- Future improvements roadmap