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>
318 lines
15 KiB
Markdown
318 lines
15 KiB
Markdown
# Changelog - Website Sale Aplicoop
|
|
|
|
## [18.0.1.13.0] - 2026-08-11
|
|
|
|
### Added
|
|
|
|
- **Readable URLs for group orders**: `group.order` gains a `slug` field and the
|
|
public pages move from `/eskaera/<id>` to `/eskaera/<slug>` (e.g.
|
|
`/eskaera/escola-fructuos`). The slug is generated from the order name on
|
|
creation, is editable on the form (empty it to regenerate it from the name),
|
|
is unique, and rejects values that would collide with the shop's own routes
|
|
(`labels`, `save-order`, …) or with a plain number. A post-migration script
|
|
fills the slug of the orders that already existed.
|
|
|
|
### Changed
|
|
|
|
- `/eskaera/<id>` and `/eskaera/<id>/checkout` are kept as redirects to their
|
|
slug URL, so links already shared with members keep working. The AJAX
|
|
endpoints (`/eskaera/<id>/load-page`, `/eskaera/save-order`, …) stay numeric.
|
|
- The frontend reads the order id from the `data-order-id` attribute only; it
|
|
can no longer be recovered from the URL, which now carries the slug.
|
|
|
|
## [18.0.1.12.0] - 2026-08-06
|
|
|
|
### Removed
|
|
|
|
- **Standard cart restriction extracted to `website_sale_disable_cart`**: the cart
|
|
UI removal (header cart link, add-to-cart buttons) and the `/shop/cart*` route
|
|
redirects no longer live in this module, so installing Aplicoop leaves the
|
|
standard `website_sale` shop untouched. Sites that want the previous behaviour
|
|
must install `website_sale_disable_cart` and set its *Cart Redirect URL* to
|
|
`/eskaera`. The new module also fixes the route paths (Odoo 18 uses
|
|
`/shop/cart/quantity`, not `/shop/cart_quantity`), covers the 5 header styles
|
|
that were missing (boxed, sidebar, sales two/three/four — the header cart link
|
|
was still visible on those) and overrides the standard endpoints instead of
|
|
registering duplicate ones.
|
|
Upgrade order matters: update this module **first** (so its old templates are
|
|
dropped) and install `website_sale_disable_cart` in a **second** Odoo run —
|
|
both sets of templates use the same XPaths and obsolete records are only
|
|
cleaned up at the end of a run, so a single combined run fails.
|
|
|
|
## [18.0.1.11.0] - 2026-07-15
|
|
|
|
### Added
|
|
|
|
- **Non-weekly cycle automation**: one-time (special/promotional), biweekly and
|
|
monthly group orders now follow the same cron confirmation flow as weekly orders
|
|
(confirm linked sale orders + batch their pickings once the cycle cutoff passes).
|
|
- **Biweekly/monthly recurrence**: these periods keep the weekday scheme
|
|
(`cutoff_day`/`pickup_day`) but on a recurrence grid anchored at `start_date`
|
|
(creation date as fallback): cutoffs advance every 14 days / 1 month (snapped to
|
|
`cutoff_day`), with automatic catch-up if the cron was down. Previously they
|
|
behaved as weekly.
|
|
- **One-time orders**: their single cycle is driven by `end_date`
|
|
(`cutoff_date = end_date`); once it passes, the cron confirms, batches and closes
|
|
the group order automatically.
|
|
|
|
### Changed
|
|
|
|
- `end_date` keeps its "permanent if empty" meaning for all recurring periods;
|
|
it only closes the cycle for one-time orders.
|
|
- Draft-cart lookup window on the website is now period-aware (7/14 days, 1 month,
|
|
or the full order lifetime for one-time orders) instead of always 6 days.
|
|
|
|
## [18.0.1.9.0] - 2026-05-20
|
|
|
|
### Added
|
|
|
|
- **Category sequence**: New `sequence` field on `product.category` for controlling product display order on the web shop. Migration adds the column with default 10.
|
|
- **Stock availability check on history orders**: When loading a historical order, products are validated against current stock (`virtual_available`). Out-of-stock items are flagged before adding to cart.
|
|
|
|
### Changed
|
|
|
|
- **Cart disabled / redirected to /eskaera**: Standard `website_sale` cart is fully hidden — header cart icon removed, add-to-cart buttons removed from standard shop, `/cart` and `/shop` routes redirect to `/eskaera`. Customers interact exclusively through the group order flow.
|
|
- **Product card UI overhaul**: Improved responsive layout, placeholder image for products without photo, better accessibility markup, and professional styling for mobile.
|
|
- **Stock check uses `virtual_available`**: Replaces `qty_available` so forecasted quantity (including incoming moves) is considered.
|
|
|
|
### Fixed
|
|
|
|
- Lint fixes: exception chaining (`raise ... from exc`), unused imports/vars, `disable attribute-string-redundant` annotations.
|
|
|
|
---
|
|
|
|
## [18.0.1.8.0] - 2026-04-08
|
|
|
|
### Added
|
|
|
|
- **Clear cart button**: New button in the sidebar to empty the current group order cart in one click (`eskaera_clear_cart` route).
|
|
|
|
### Changed
|
|
|
|
- **Portal access restricted to consumer group**: Portal users can only see group orders belonging to their consumer group. Security rule `rule_group_order_company_read` updated with `user.share` guard.
|
|
- **Controller filtering by consumer group**: `eskaera_list` and `eskaera_shop` routes filter orders by the logged-in user's consumer group, not just by company.
|
|
|
|
### Fixed
|
|
|
|
- Stale cart invalidation: carts linked to closed/cancelled group orders are cleared on next access.
|
|
- Home delivery draft flow: fixed state transition for home delivery orders.
|
|
- Auto-confirm `sale.order` on cutoff day: fixed off-by-one (`>` vs `>=`) in cutoff guard so orders on the cutoff day are correctly confirmed.
|
|
- Pickup dates frozen after cron confirm: cron no longer overwrites pickup dates on already-confirmed orders.
|
|
- Cron hardened against missing/invalid group order configurations.
|
|
- Cart layout: moved cart sidebar before product grid.
|
|
- i18n: added missing ES/EU translations for checkout, cart labels, Save Draft button, and weekday strings. Removed legacy `week_draft` translation keys.
|
|
|
|
---
|
|
|
|
## [18.0.1.7.0] - 2026-03-06
|
|
|
|
### Added
|
|
|
|
- **Automatic batch picking creation**: After the cutoff cron confirms sale orders, picking batches are automatically created grouped by consumer group and pickup date.
|
|
- **Consumer group propagation**: `consumer_group_id` is now propagated directly from the `group.order` to linked `sale.order` records, eliminating manual assignment.
|
|
- **Out-of-stock blocking**: Add-to-cart button is hard-disabled for out-of-stock products. `allow_out_of_stock_order` flag on product is respected.
|
|
|
|
### Changed
|
|
|
|
- **Cron auto-confirm sale orders**: Daily cron (`_cron_confirm_group_orders`) now confirms linked sale orders on the cutoff date instead of requiring manual action.
|
|
- **Order card meta extracted**: Order card metadata (dates, state badge) moved to a reusable `_eskaera_order_card_meta` template for cleaner rendering.
|
|
- Delivery toggle (reparto/envío a domicilio) wired directly from the cart sidebar.
|
|
- Pricing alignment: theoretical price and displayed price reconciled for orders with home delivery.
|
|
|
|
### Fixed
|
|
|
|
- Fixed broken `aplicoopShop` → `groupOrderShop` JS class reference.
|
|
- Ensured add-to-cart event listeners are re-attached after infinite scroll loads new products.
|
|
- i18n: translated weekday names (ES/EU).
|
|
|
|
---
|
|
|
|
## [18.0.1.6.0] - 2026-02-22
|
|
|
|
### Added
|
|
|
|
- **Category Blacklist Feature**: Category-based exclusion system for group orders
|
|
- New field: `excluded_category_ids` (Many2many to product.category)
|
|
- Recursive exclusion: Excludes products in selected categories AND all subcategories
|
|
- Blacklist has absolute priority over all inclusion sources
|
|
- Helper method: `get_all_excluded_descendants()` for recursive category tree traversal
|
|
- Comprehensive test suite in `test_product_discovery.py` (TestCategoryBlacklist class with 9 tests)
|
|
|
|
### Changed
|
|
|
|
- **Product Discovery Logic**: Extended to filter by category blacklist
|
|
- `_get_products_for_group_order()` now applies `excluded_category_ids` filter recursively
|
|
- Products in excluded categories and their subcategories are filtered out
|
|
- `_compute_available_products_count()` now depends on `excluded_category_ids`
|
|
- Detailed logging for excluded categories and affected products
|
|
|
|
- **UI Updates**: "Productos Excluidos" section now includes three blacklist types:
|
|
- `excluded_supplier_ids`: Blacklist suppliers
|
|
- `excluded_category_ids`: Blacklist categories (recursive)
|
|
- `excluded_product_ids`: Blacklist specific products
|
|
|
|
### Technical Details
|
|
|
|
- New M2M relation: `group_order_excluded_category_rel`
|
|
- Recursive logic: Walks category tree to find all descendants
|
|
- Filter logic: `products.filtered(lambda p: p.categ_id not in all_excluded_categories)`
|
|
- Works in combination with product and supplier blacklists (all filters apply)
|
|
|
|
### Use Case
|
|
|
|
- Admin wants to exclude all products in a category and its subcategories
|
|
- Example: Exclude "Fresh Produce" → automatically excludes "Fruits", "Vegetables", etc.
|
|
- Add parent category to inclusion → add problematic subcategory to exclusion
|
|
- Result: Fine-grained control over product catalog with minimal configuration
|
|
|
|
## [18.0.1.5.0] - 2026-02-22
|
|
|
|
### Added
|
|
|
|
- **Supplier Blacklist Feature**: New exclusion system by supplier for group orders
|
|
- New field: `excluded_supplier_ids` (Many2many to res.partner)
|
|
- Filters products by `main_seller_id` (from product_main_seller addon)
|
|
- Blacklist has absolute priority over all inclusion sources
|
|
- Products whose main supplier is blacklisted never appear
|
|
- Comprehensive test suite in `test_product_discovery.py` (TestSupplierBlacklist class with 9 tests)
|
|
|
|
### Changed
|
|
|
|
- **Product Discovery Logic**: Extended to filter by supplier blacklist
|
|
- `_get_products_for_group_order()` now applies `excluded_supplier_ids` filter
|
|
- Products with `main_seller_id` in excluded_supplier_ids are filtered out
|
|
- `_compute_available_products_count()` now depends on `excluded_supplier_ids`
|
|
- Detailed logging for excluded suppliers and affected products
|
|
|
|
- **UI Updates**: "Productos Excluidos" section now includes both:
|
|
- `excluded_supplier_ids`: Blacklist suppliers
|
|
- `excluded_product_ids`: Blacklist specific products
|
|
|
|
### Technical Details
|
|
|
|
- New M2M relation: `group_order_excluded_supplier_rel`
|
|
- Filter logic: `products.filtered(lambda p: p.product_tmpl_id.main_seller_id not in excluded_supplier_ids)`
|
|
- Works in combination with product blacklist (both filters apply)
|
|
- Uses `main_seller_id` from product_main_seller addon (NOT default_supplier_id)
|
|
|
|
### Use Case
|
|
|
|
- Admin wants to exclude all products from a specific supplier (e.g., temporary unavailability)
|
|
- Add category with 100 products → add problematic supplier to excluded_supplier_ids
|
|
- Result: All products from that supplier are excluded, even if directly included
|
|
- Combined workflow: Category inclusion + supplier exclusion + individual product exclusion
|
|
|
|
## [18.0.1.4.0] - 2026-02-22
|
|
|
|
### Added
|
|
|
|
- **Product Blacklist Feature**: New exclusion system for group orders
|
|
- New field: `excluded_product_ids` (Many2many to product.product)
|
|
- Blacklist has absolute priority over all inclusion sources (product_ids, category_ids, supplier_ids)
|
|
- Model method: Updated `_get_products_for_group_order()` with blacklist filter
|
|
- Comprehensive test suite in `test_product_discovery.py` (TestProductBlacklist class)
|
|
|
|
### Changed
|
|
- **UI Improvements**: Renamed "Associations" section to "Catálogo de Productos" for better user clarity
|
|
- New subsection: "Productos Incluidos" (whitelist: suppliers, categories, direct products)
|
|
- New subsection: "Productos Excluidos" (blacklist: explicit exclusions)
|
|
- Updated help texts for all inclusion fields
|
|
- Complete Spanish and Euskera translations
|
|
|
|
- **Product Discovery Logic**:
|
|
- `_get_products_for_group_order()` now applies `excluded_product_ids` filter at the end
|
|
- Products in blacklist never appear, regardless of inclusion source
|
|
- `_compute_available_products_count()` now depends on `excluded_product_ids`
|
|
- Detailed logging for excluded product count
|
|
|
|
### Technical Details
|
|
- New M2M relation: `group_order_excluded_product_rel` (separate from whitelist relations)
|
|
- Blacklist filter uses set subtraction: `products = products - order.excluded_product_ids`
|
|
- All tests validate absolute priority: direct products, category products, supplier products, and multi-source products all respect blacklist
|
|
|
|
### Use Case
|
|
- Admin selects a category with 100 products → adds to category_ids
|
|
- Admin identifies 5 unwanted products → adds to excluded_product_ids
|
|
- Result: 95 products available in the order
|
|
- Workflow: Bulk inclusion via categories/suppliers + fine-grained exclusion via blacklist
|
|
|
|
## [18.0.1.3.0] - 2026-02-16
|
|
|
|
### Added
|
|
- **Lazy Loading Feature**: Configurable product pagination for significantly faster page loads
|
|
- New Settings: `Enable Lazy Loading`, `Products Per Page`
|
|
- New endpoint: `GET /eskaera/<order_id>/load-page?page=N`
|
|
- JavaScript method: `_attachLoadMoreListener()`
|
|
- Model method: `group_order._get_products_paginated()`
|
|
|
|
- **Configuration Parameters**:
|
|
- `website_sale_aplicoop.lazy_loading_enabled` (Boolean, default: True)
|
|
- `website_sale_aplicoop.products_per_page` (Integer, default: 20)
|
|
|
|
- **Frontend Components**:
|
|
- New template: `eskaera_shop_products` (reusable for initial page + AJAX)
|
|
- Load More button with pagination controls
|
|
- Spinner during AJAX load ("Loading..." state)
|
|
- Event listener re-attachment for dynamically loaded products
|
|
|
|
- **Documentation**:
|
|
- Complete lazy loading guide: `docs/LAZY_LOADING.md`
|
|
- Configuration examples
|
|
- Troubleshooting section
|
|
- Performance metrics
|
|
|
|
### Changed
|
|
- Template `eskaera_shop`:
|
|
- Products grid now has `id="products-grid"`
|
|
- Calls reusable `eskaera_shop_products` template
|
|
- Conditional "Load More" button display
|
|
|
|
- JavaScript `website_sale.js`:
|
|
- `_attachEventListeners()` now calls `_attachLoadMoreListener()`
|
|
- Re-attaches listeners after AJAX loads new products
|
|
|
|
- README.md:
|
|
- Added lazy loading feature to features list
|
|
- Added version 18.0.1.3.0 to changelog
|
|
|
|
### Performance Impact
|
|
- **Initial page load**: 10-20s → 500-800ms (20x faster)
|
|
- **Product DOM size**: 1000 elements → 20 elements (initial)
|
|
- **Subsequent page loads**: 200-400ms via AJAX
|
|
- **Price calculation**: Only for visible products (reduced from 1000+ to 20)
|
|
|
|
### Technical Details
|
|
- Zero-impact if lazy loading disabled
|
|
- Transparent pagination (no URL changes)
|
|
- Maintains cart synchronization
|
|
- Compatible with existing search/filter
|
|
- No changes to pricing logic or validation
|
|
|
|
---
|
|
|
|
## [18.0.1.2.0] - 2026-02-02
|
|
|
|
### Added
|
|
- Improved UI elements in cart and checkout
|
|
|
|
### Fixed
|
|
- Pickup date calculation (was adding extra week)
|
|
- Delivery date display on order pages
|
|
|
|
### Changed
|
|
- Cart styling: 2x text size, larger icons
|
|
- Checkout button: Enhanced visibility
|
|
|
|
---
|
|
|
|
## [18.0.1.0.0] - 2024-12-20
|
|
|
|
### Added
|
|
- Initial release of Website Sale Aplicoop
|
|
- Group order management system
|
|
- Multi-language support (ES, PT, GL, CA, EU, FR, IT)
|
|
- Member management and tracking
|
|
- Order state machine (draft → confirmed → collected → invoiced → completed)
|
|
- Separate shopping carts per group order
|
|
- Cutoff and pickup date validation
|
|
- Integration with OCA ecosystem (pricing, taxes, etc.)
|