[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
This commit is contained in:
snt 2026-02-22 20:41:11 +01:00
parent 4a4639f13a
commit 75ebb7b907
7 changed files with 4765 additions and 7222 deletions

View file

@ -188,6 +188,14 @@ class GroupOrder(models.Model):
tracking=True,
help="Products in these categories will be available",
)
excluded_product_ids = fields.Many2many(
"product.product",
"group_order_excluded_product_rel",
"order_id",
"product_id",
tracking=True,
help="Products explicitly excluded from this order (blacklist has absolute priority)",
)
# === Estado ===
state = fields.Selection(
@ -233,7 +241,7 @@ class GroupOrder(models.Model):
help="Total count of available products from all sources",
)
@api.depends("product_ids", "category_ids", "supplier_ids")
@api.depends("product_ids", "category_ids", "supplier_ids", "excluded_product_ids")
def _compute_available_products_count(self):
"""Count all available products from all sources."""
for record in self:
@ -387,6 +395,17 @@ class GroupOrder(models.Model):
).filtered("active")
products |= supplier_products
# 4) Apply blacklist filter (absolute priority)
if order.excluded_product_ids:
excluded_count = len(products & order.excluded_product_ids)
products = products - order.excluded_product_ids
_logger.info(
"Group order %d: Excluded %d products from blacklist (total available: %d)",
order.id,
excluded_count,
len(products),
)
return products
def _get_products_paginated(self, order_id, page=1, per_page=20):