Commit graph

49 commits

Author SHA1 Message Date
GitHub Copilot
5a2f5d120f [ADD] website_sale_aplicoop: serve Eskaera per website
A co-op can run the plain shop on one website and the group orders on another,
but routes are registered process-wide: every /eskaera page answered on every
website of the database, and Odoo had already copied the Eskaera menu to all of
them.

`website.eskaera_enabled` decides which websites serve it, on by default so
installing changes nothing. It reaches the settings screen through `website_id`,
so it follows the website selector there. Where it is off the routes raise
NotFound and the menu is hidden.

The menu is hidden rather than deleted, by extending `_compute_visible`. That
keeps the record and any manual rename or reordering, so switching the feature
back on restores it as it was.

Note that a JSON route reports the 404 inside the JSON-RPC payload and still
answers HTTP 200; that is the transport, not a hole in the guard, and a test
pins it so the next reader does not take it for one.

The three remaining settings (lazy loading, products per page, low stock
threshold) are still `config_parameter`, so they stay global to the database.
Two websites share their values.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 17:31:03 +02:00
GitHub Copilot
817ff31d39 [REF] website_sale_aplicoop: price through website_sale instead of privately
Eskaera carried its own pricing path: a `website_sale_aplicoop.pricelist_id`
setting resolved inside the Eskaera controllers, plus a local reimplementation
of the tax and discount maths. The pricelist part meant /shop and Eskaera could
quote different prices on the same website, and the maths part had drifted from
the original it was copied from.

Pricing is now the standard one. The setting is gone (a migration drops the
parameter, which would otherwise linger looking like live configuration) and
`_resolve_pricelist` is `request.website.pricelist_id`. Scoping a pricelist to
a website is already core's job through `product.pricelist.website_id`, so
running the plain shop on one website and the co-op on another needs no code
here.

Taxes are applied by `product.template._apply_taxes_to_price`, which fixes a
real defect: it calls `_get_tax_included_unit_price_from_price` first, and this
module did not. With a fiscal position remapping a tax-included tax, a product
at 121 (100 + 21%) was displayed at 121 instead of 110, because the price was
handed to the mapped tax as if it were already that tax's gross amount. The
helper is a no-op without a remapping, so ordinary pricing is untouched. It
also means the website's `show_line_subtotals_tax_selection` is respected
rather than overridden with a hardcoded tax-included display.

Listing a page now costs one `_compute_price_rule` call instead of one per
product, which matters on the lazy-loading path.

Two smaller things found on the way. `_get_product_price_rule` was being passed
`target_currency=`, which is not one of its arguments: it fell into **kwargs
and was ignored, so the conversion never happened. And `_compute_price_info`
resolved `product.product_variant_ids[0]`, but it receives variants, so a
multi-variant template was priced from its first variant rather than the one
asked for.

The delivery display price loses its hardcoded 5.74 fallback and reuses the
same helpers as everything else.

Kept local, because none of it is pricing: the /Kg and /L suffixes, the 0.1
quantity step for bulk goods, the base unit price and the supplier name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 17:28:51 +02:00
GitHub Copilot
b3999e2283 [REM] website_sale_aplicoop: remove dead code and orphaned tests
Duplicate _translate_labels fallback, unreachable /eskaera/add-to-cart and
/eskaera/save-cart routes (the frontend cart is localStorage-only and uses
save-order), redundant pickup wrappers, unused pagination/count helpers and
fields, deprecated JS shims, and the already-empty checkout_summary.js and
i18n key/init leftovers.

Also drops 11 tests/*.py never wired into tests/__init__.py: three were
unimplemented placeholders (setUp with no assertions), and the other eight
had real assertions but were bit-rotted against the current schema (e.g.
res.partner.is_supplier no longer exists) — wiring them in surfaced 43
failures unrelated to this cleanup. Verified 0 failed/0 errors of 270 tests
both before and after.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 22:31:13 +02:00
GitHub Copilot
6ba554c91b [ADD] website_sale_aplicoop: online payment per group order
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>
2026-08-16 21:59:35 +02:00
GitHub Copilot
5de7573fba [IMP] website_sale_aplicoop: accessibility and responsive polish — phase 8
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>
2026-08-16 11:34:38 +02:00
GitHub Copilot
158933e96e [FIX] website_sale_aplicoop: two draft-reuse and compute-field bugs
- group.order.home_delivery is a stored compute field with no inverse;
  Odoo still lets write() set it directly, so a stray direct write stuck
  instead of always being re-derived from delivery_product_id. create()
  and write() now strip it from vals, same pattern already used for slug.

- _find_recent_draft_order only bounded drafts by create_date, so a
  freshly created draft for a stale/previous pickup_date (but created
  "now") was wrongly reused. Fix requires both create_date to fall in
  the active window AND pickup_date to match when set — the latter
  alone isn't enough either, per the regression already covered by
  test_find_recent_draft_excludes_previous_cycle (observed in
  production at stage.elikabilbo.eus).
2026-08-13 12:02:33 +02:00
GitHub Copilot
157b344d4b [FIX] website_sale_aplicoop: three defects in the group order slug
- create(): slugs were only checked against the database, so records created
  in the same batch (duplicating several orders from the list view, importing
  rows sharing a name) collided on group_order_slug_uniq. _generate_unique_slug
  now also skips the slugs already handed out in the batch.
- _redirect_to_slug_url(): `post` is passed as a dict instead of splatted, so a
  query parameter named `suffix` no longer binds to the keyword argument of the
  same name (HTTP 500 on /eskaera/<id>/checkout?suffix=x, and a corrupted path
  on the shop route).
- post-migrate: the backfill runs with tracking_disable, `slug` is tracked and
  the upgrade posted a chatter message on every pre-existing order.

Tests for the two reachable cases: batch create and query parameters kept
across the legacy redirect.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 22:53:09 +02:00
GitHub Copilot
23edee6154 [IMP] website_sale_aplicoop: readable slug in the group order URL
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>
2026-08-11 16:49:54 +02:00
GitHub Copilot
aba22fd230 [IMP] website_sale_aplicoop: automate non-weekly group order cycles
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>
2026-07-15 16:26:14 +02:00
GitHub Copilot
1d6747e703 [IMP] website_sale_aplicoop: filter and cap stock using forecasted net qty
Group orders are not confirmed until the cutoff date, so draft/sent
sale.order lines never generate stock.moves and are invisible to
virtual_available. This change makes the shop aware of that demand.

- group.order._compute_draft_sale_demand: queries sale.order.line in
  draft/sent state (mirroring sale_stock forecasted report logic) and
  returns pending demand per product.id in the product's own UoM.
- _get_products_for_group_order: delegates to new _apply_stock_filter_and_sort
  which excludes storable products whose forecasted net qty
  (virtual_available − draft demand) <= 0, unless allow_out_of_stock_order.
- _compute_stock_ribbons: reads draft_demand_by_product from ORM context
  so is_out_of_stock / is_low_stock / dynamic_ribbon_id reflect net qty.
- Controller: new _prepare_draft_stock_data helper calculates demand once
  per request, injects context, and builds product_max_qty dict. Applied
  in eskaera_shop, load_eskaera_page and load_products_ajax.
- Template: qty input gets max and data-max-qty from product_max_qty.
- JS: blocks add-to-cart if requested quantity exceeds data-max-qty.
- Fixes type check: type=='consu' → is_storable=True (Odoo 18 semantics).
- 21 new tests in test_forecasted_stock.py covering demand calculation,
  ribbon logic with context, and group order filtering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 18:18:40 +02:00
GitHub Copilot
87dcb4e350 cron better exception management. show supplier commercial name in product card template. linters config 2026-06-02 10:43:54 +02:00
GitHub Copilot
5eea3e2a23 [IMP] website_sale_aplicoop: improve i18n label fallbacks and response parsing
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>
2026-05-25 12:28:33 +02:00
GitHub Copilot
9d614ed79e [FIX] website_sale_aplicoop: auto-derive home_delivery from delivery_product_id
Make group.order.home_delivery a computed stored field that is True
whenever delivery_product_id is set, eliminating the manual checkbox
that could be forgotten. This fixes sale.order.home_delivery not being
set when the delivery product was configured but the boolean was left
unchecked.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:37:33 +02:00
GitHub Copilot
b14a6f84ed [IMP] website_sale_aplicoop: mostrar franjas de recogida en formulario group.order
- Añadir reglas de acceso para group.order.slot en ir.model.access.csv
- Añadir pestaña "Pickup Slots" en el formulario de group.order con lista
  editable (handle de secuencia, día, etiqueta, hora inicio/fin, activo)
- Corregir valores del campo weekday: de dígitos numéricos a nombres de día
  (Monday...Sunday) para mejor usabilidad

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:06:38 +02:00
snt
a997331c2d lint: fix linter warnings (log exceptions, disable attribute-string-redundant, suppress C901 where necessary) 2026-05-20 16:05:14 +02:00
snt
f8ef927a9e [IMP] website_sale_aplicoop: add sequence field to product.category for web ordering
- Add sequence field (default 10) to product.category with _order = "sequence, name"
- Inherit product.category tree view to add drag-handle widget
- Sort category hierarchy and available categories by sequence in controller
- Migration 18.0.1.9.0: add sequence column to product_category table
- Bump version to 18.0.1.9.0
2026-05-20 16:05:14 +02:00
snt
3ca90578ae [IMP] website_sale_aplicoop: Validar disponibilidad de productos al cargar órdenes históricas
- Backend: Agregar método _validate_items_for_group_order() para validar que los productos históricos sigan siendo disponibles en la orden de grupo actual
- Backend: Modificar load_order_from_history() para filtrar solo items disponibles antes de pasar al template
- Backend: Generar mensaje de aviso traducido cuando hay productos no disponibles
- Template: Pasar información de productos no disponibles y warnings al JavaScript
- Frontend: Mostrar notificación de advertencia si hubo productos excluidos durante la carga histórica
- Notas: Esto evita cargar productos que ya no existen en la orden actual debido a cambios en categorías, proveedores o listas negras
2026-05-20 16:05:14 +02:00
snt
828278573d Fix stock picking batch date and does not split batchs by consumer group 2026-05-20 16:05:14 +02:00
snt
ce393b6034 [FIX] TestConfirmEskaera_Integration: limpieza de decoradores @patch y corrección de bugs
- Convertir 4 tests de decorador @patch a context manager 'with patch(...)' para evitar RuntimeError en LocalProxy de Werkzeug
- Corregir patrón env(user=..., context=dict(...)) en Odoo 18 (sin .with_context())
- Agregar website real al mock para integración con helpers de pricing (_get_pricing_info)
- Añadir pickup_date en fixture de existing_order para que _find_recent_draft_order localice correctamente
- BUGFIX: Agregar (5,) a order_line para limpiar líneas previas al actualizar pedido existente

Resultado: 0 failed, 0 errors de 4 tests en Docker para TestConfirmEskaera_Integration

BREAKING: _create_or_update_sale_order ahora limpia las líneas anteriores con (5,) antes de asignar las nuevas cuando se actualiza un pedido existente. Comportamiento previo (duplicación de líneas) era un bug.
2026-04-08 17:26:57 +02:00
snt
135967019e [ADD] website_sale_aplicoop: botón limpiar carrito en sidebar
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
2026-04-07 23:50:30 +02:00
snt
0eb7957a70 [IMP] website_sale_aplicoop: remove redundant string= from Boolean fields (W8113) 2026-04-07 23:39:49 +02:00
snt
26bfa028d1 [IMP] website_sale_aplicoop: use virtual_available for stock check instead of qty_available
Use forecasted quantity (virtual_available) instead of on-hand quantity
(qty_available) for out-of-stock and low-stock calculations, so pending
incoming/outgoing moves are taken into account.
2026-04-07 23:39:00 +02:00
snt
7d11a95344 [FIX] website_sale_aplicoop: freeze pickup dates on cron confirm 2026-03-31 20:07:50 +02:00
snt
331a2e8944 [FIX] website_sale_aplicoop: harden group order cron 2026-03-31 19:36:20 +02:00
snt
813c8071d9 [I18N] website_sale_aplicoop: remove legacy week draft strings 2026-03-31 19:07:43 +02:00
snt
12d434d4c7 [IMP] website_sale_aplicoop: simplify cutoff guard in _confirm_linked_sale_orders
All group orders have cutoff configured; stale orders are already closed/cancelled.
Single guard: skip if cutoff_date >= today (cycle still open).
2026-03-30 19:29:10 +02:00
snt
7fc42625a3 [FIX] website_sale_aplicoop: robust cutoff check in _confirm_linked_sale_orders
Three guards before confirming sale orders:
1. Skip if no cutoff_date (no cutoff_day configured): avoids blindly confirming
   all draft orders for group orders without a weekly cycle defined
2. Skip if cutoff_date >= today: cycle still open
3. Skip if cutoff_date >= 7 days ago: stale date from a previous cycle
   (protects against cron gaps and confirms only within 1-6 days after cutoff)
2026-03-30 19:23:19 +02:00
snt
cd68e8bb5b [FIX] website_sale_aplicoop: revert >= to > condition in _confirm_linked_sale_orders
The cutoff day itself is still open for orders; confirmation should only
happen when the cutoff date is strictly in the past (>= today = skip).
The real bug was only the order of operations in _cron_update_dates.
2026-03-30 19:18:41 +02:00
snt
ac00294623 [FIX] website_sale_aplicoop: fix auto-confirm sale.order on cutoff day
- _cron_update_dates: call _confirm_linked_sale_orders() BEFORE recomputing
  dates so cutoff_date still points to the current cycle when the check runs
- _confirm_linked_sale_orders: change >= to > so orders are confirmed both
  on the cutoff day itself and after it has passed
2026-03-30 19:14:02 +02:00
snt
89c008441e [FIX] Resolver 3 fallos de tests en website_sale_aplicoop
- Fix: delivery product price now includes VAT (homepage/checkout)
  * Added _get_delivery_product_display_price() helper to use same pricing pipeline as regular products
  * Uses pricelist + tax calculations instead of bare list_price
  * Fallback chain: pricelist → bare list_price → default 5.74
  * Updated context in eskaera_shop() and eskaera_checkout()

- Test: test_constraint_cutoff_before_pickup_invalid
  * Constraint removed: now allows any combination of cutoff_day and pickup_day
  * Updated test to reflect this change (no ValidationError expected)

- Test: test_day_names_not_using_inline_underscore
  * Fixed to check sub-template eskaera_order_card_meta where day_names is actually used
  * eskaera_page calls this sub-template so day_names context is inherited

Results: 128 tests - 0 failed, 0 errors (100% pass rate)
2026-03-30 16:21:57 +02:00
snt
e2ced75ecd [ADD] website_sale_aplicoop: create picking batches after cutoff
- Add stock_picking_batch dependency to manifest
- Add cutoff date validation in _confirm_linked_sale_orders()
- Create _create_picking_batches_for_sale_orders() method
- Group pickings by consumer_group_id into separate batches
- Set batch scheduled_date from group order pickup_date
- Add test_cron_picking_batch.py with 7 tests covering:
  - Skip orders before cutoff
  - Confirm orders after cutoff
  - Separate batches per consumer group
  - Same group orders in same batch
  - Batch has scheduled_date
  - No duplicate batches on re-run
  - Closed group orders not processed
2026-03-06 15:45:12 +01:00
snt
80539f3e36 [IMP] website_sale_aplicoop: propagate consumer_group_id directly from group_order
- Add consumer_group_id to sale.order for tracking the consumer group
- Fix stock.picking consumer_group_id to use sale_id.consumer_group_id
- Add group_ids inverse relation in res.partner for bidirectional access
- Remove auto-calculation of consumer_group_id, data comes directly from group_order.group_ids[0]
- Add debug logging for consumer_group propagation
- commitment_date propagates directly from group_order (no recalculation)
2026-03-06 13:49:13 +01:00
snt
4141fc5ab1 [IMP] website_sale_aplicoop: respect allow_out_of_stock_order
Added website_sale_stock dependency and modified _compute_stock_ribbons
to respect the allow_out_of_stock_order field:
- If allow_out_of_stock_order=True: product can always be added to cart
- If allow_out_of_stock_order=False and qty<=0: add-to-cart is blocked

The JS logic already checks data-out-of-stock attribute from template,
so no frontend changes were needed.

Version bump: 18.0.1.7.0 -> 18.0.1.8.0
2026-03-05 22:15:50 +01:00
snt
2f57a5d14e [IMP] group_order: confirmar sale orders en cron diario 2026-02-27 15:19:41 +01:00
snt
a483925005 demo files 2026-02-27 13:43:56 +01:00
snt
2a005a9d5a feat(website_sale_aplicoop): sistema de ribbons basado en stock
- Añadidos ribbons 'Sin Stock' (rojo) y 'Pocas Existencias' (amarillo)
- Nuevo campo configurable: umbral de stock bajo (default: 5.0)
- Campos computed en product.product:
  * is_out_of_stock: True cuando qty_available <= 0
  * is_low_stock: True cuando 0 < qty_available <= threshold
  * dynamic_ribbon_id: ribbon automático según nivel de stock
- Ordenamiento mejorado: productos con stock primero, sin stock al final
- Template actualizado:
  * Muestra ribbon de stock en tarjeta de producto
  * Deshabilita botón add-to-cart cuando producto sin stock
  * Cambia icono a 'fa-ban' en productos sin stock
- Vista de configuración: campo 'Low Stock Threshold' en Settings > Shop Performance
- Solo aplica a productos type='consu' (almacenables)
- Tests: 112 pasados, 0 fallos
2026-02-25 19:48:39 +01:00
snt
539cd5cccd feat(website_sale_aplicoop): ordenar productos por website_sequence y nombre
- Ordena productos primero por website_sequence y luego alfabéticamente por nombre (case-insensitive)
- Fix test: cambiar tipo de producto de 'product' a 'consu' (Odoo 18 compatibility)
2026-02-25 19:34:49 +01:00
snt
c1226e720b [ADD] website_sale_aplicoop: Category blacklist with recursive exclusion
- 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
2026-02-22 23:04:33 +01:00
snt
d90f2cdc61 [ADD] website_sale_aplicoop: Supplier blacklist feature for group orders
- 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
2026-02-22 21:35:40 +01:00
snt
75ebb7b907 [ADD] website_sale_aplicoop: Product blacklist feature for group orders
- 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
2026-02-22 20:41:11 +01:00
snt
cafa19ffea [ADD] website_sale_aplicoop: Add sequence field to group.order for custom ordering
- Add sequence field to group.order model with default value 10
- Update _order to sort by sequence first, then start_date desc
- Add sequence field to tree view with handle widget for drag-and-drop reordering
- Add sequence field to form view for manual editing
- Orders in website list will now be ordered by sequence field
2026-02-21 16:37:55 +01:00
snt
cf9ea887c1 [REF] Code quality improvements and structure fixes
- Add mypy.ini configuration to exclude migration scripts
- Rename migration files to proper snake_case (post-migration.py → post_migration.py)
- Add __init__.py to migration directories for proper Python package structure
- Add new portal access tests for website_sale_aplicoop
- Code formatting improvements (black, isort)
- Update copilot instructions and project configuration

Related to previous code quality refactoring work.
2026-02-21 13:51:25 +01:00
snt
a1431d3521 website_sale_aplicoop: añadir settings, incluir data/groups.xml en manifest y limpiar vistas duplicadas 2026-02-20 20:44:58 +01:00
snt
6fbc7b9456 [FIX] website_sale_aplicoop: Remove redundant string= attributes and fix OCA linting warnings
- 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
2026-02-18 17:54:43 +01:00
snt
5c89795e30 [IMP] website_sale_aplicoop: Fix mandatory translation linting errors
- Added self.env._() translation to ValidationError in _check_company_groups
- Added self.env._() translation to ValidationError in _check_dates
- Replaced f-strings with .format() for proper lazy translation
2026-02-18 17:46:38 +01:00
snt
8b0a402ccf [FIX] website_sale_aplicoop: Critical date calculation fixes (v18.0.1.3.1)
- Fixed _compute_cutoff_date logic: Changed days_ahead <= 0 to days_ahead < 0 to allow cutoff_date same day as today
- Enabled store=True for delivery_date field to persist calculated values and enable database filtering
- Added constraint _check_cutoff_before_pickup to validate pickup_day >= cutoff_day in weekly orders
- Added @api.onchange methods for immediate UI feedback when changing cutoff_day or pickup_day
- Created daily cron job _cron_update_dates to automatically recalculate dates for active orders
- Added 'Calculated Dates' section in form view showing readonly cutoff_date, pickup_date, delivery_date
- Added 6 regression tests with @tagged('post_install', 'date_calculations')
- Updated documentation with comprehensive changelog

This is a more robust fix than v18.0.1.2.0, addressing edge cases in date calculations.
2026-02-18 17:45:45 +01:00
snt
9000e92324 [DOC] website_sale_aplicoop: Add lazy loading documentation and implement v18.0.1.3.0 feature
- 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
2026-02-16 18:39:39 +01:00
snt
115c9c0cc4 [ADD] website_sale_aplicoop: Configurable pricelist for Aplicoop orders 2026-02-14 18:55:54 +01:00
snt
7cff89e418 Aplicoop desde el repo de kidekoop 2026-02-11 15:32:11 +01:00