[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
This commit is contained in:
parent
d90f2cdc61
commit
c1226e720b
7 changed files with 413 additions and 1 deletions
|
|
@ -999,3 +999,308 @@ class TestSupplierBlacklist(TransactionCase):
|
|||
# Count should decrease by 1 (product_A excluded)
|
||||
new_count = self.group_order.available_products_count
|
||||
self.assertEqual(new_count, 3)
|
||||
|
||||
|
||||
class TestCategoryBlacklist(TransactionCase):
|
||||
"""Test category blacklist (excluded_category_ids) functionality.
|
||||
|
||||
The category blacklist filters out products in the excluded categories
|
||||
AND all their subcategories (recursive).
|
||||
|
||||
Blacklist has absolute priority over inclusion sources.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.group = self.env["res.partner"].create(
|
||||
{
|
||||
"name": "Test Group",
|
||||
"is_company": True,
|
||||
}
|
||||
)
|
||||
|
||||
# Create category hierarchy:
|
||||
# Parent Category
|
||||
# ├── Child Category A
|
||||
# │ └── Grandchild Category A1
|
||||
# └── Child Category B
|
||||
self.parent_category = self.env["product.category"].create(
|
||||
{
|
||||
"name": "Parent Category",
|
||||
}
|
||||
)
|
||||
|
||||
self.child_category_A = self.env["product.category"].create(
|
||||
{
|
||||
"name": "Child Category A",
|
||||
"parent_id": self.parent_category.id,
|
||||
}
|
||||
)
|
||||
|
||||
self.grandchild_category_A1 = self.env["product.category"].create(
|
||||
{
|
||||
"name": "Grandchild Category A1",
|
||||
"parent_id": self.child_category_A.id,
|
||||
}
|
||||
)
|
||||
|
||||
self.child_category_B = self.env["product.category"].create(
|
||||
{
|
||||
"name": "Child Category B",
|
||||
"parent_id": self.parent_category.id,
|
||||
}
|
||||
)
|
||||
|
||||
self.other_category = self.env["product.category"].create(
|
||||
{
|
||||
"name": "Other Category (not in hierarchy)",
|
||||
}
|
||||
)
|
||||
|
||||
# Create products in different categories
|
||||
# Product in parent category
|
||||
self.product_parent = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product in Parent Category",
|
||||
"type": "consu",
|
||||
"list_price": 10.0,
|
||||
"categ_id": self.parent_category.id,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
}
|
||||
)
|
||||
|
||||
# Product in Child A
|
||||
self.product_child_A = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product in Child A",
|
||||
"type": "consu",
|
||||
"list_price": 20.0,
|
||||
"categ_id": self.child_category_A.id,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
}
|
||||
)
|
||||
|
||||
# Product in Grandchild A1
|
||||
self.product_grandchild_A1 = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product in Grandchild A1",
|
||||
"type": "consu",
|
||||
"list_price": 30.0,
|
||||
"categ_id": self.grandchild_category_A1.id,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
}
|
||||
)
|
||||
|
||||
# Product in Child B
|
||||
self.product_child_B = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product in Child B",
|
||||
"type": "consu",
|
||||
"list_price": 40.0,
|
||||
"categ_id": self.child_category_B.id,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
}
|
||||
)
|
||||
|
||||
# Product in Other Category
|
||||
self.product_other = self.env["product.product"].create(
|
||||
{
|
||||
"name": "Product in Other Category",
|
||||
"type": "consu",
|
||||
"list_price": 50.0,
|
||||
"categ_id": self.other_category.id,
|
||||
"is_published": True,
|
||||
"sale_ok": True,
|
||||
}
|
||||
)
|
||||
|
||||
start_date = datetime.now().date()
|
||||
self.group_order = self.env["group.order"].create(
|
||||
{
|
||||
"name": "Test Category Blacklist Order",
|
||||
"group_ids": [(6, 0, [self.group.id])],
|
||||
"type": "regular",
|
||||
"start_date": start_date,
|
||||
"end_date": start_date + timedelta(days=7),
|
||||
"period": "weekly",
|
||||
"pickup_day": "3",
|
||||
"cutoff_day": "0",
|
||||
}
|
||||
)
|
||||
|
||||
def test_category_blacklist_excludes_single_category(self):
|
||||
"""Test that category blacklist excludes products in that category."""
|
||||
# Add parent category to inclusion (includes all products in hierarchy)
|
||||
self.group_order.category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
# All products should be discoverable initially
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
self.assertIn(self.product_parent, products)
|
||||
self.assertIn(self.product_child_A, products)
|
||||
self.assertIn(self.product_grandchild_A1, products)
|
||||
self.assertIn(self.product_child_B, products)
|
||||
|
||||
# Exclude Child Category B
|
||||
self.group_order.excluded_category_ids = [(4, self.child_category_B.id)]
|
||||
|
||||
# Product in Child B should NOT be discoverable
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
self.assertNotIn(self.product_child_B, products)
|
||||
# But others should still be there
|
||||
self.assertIn(self.product_parent, products)
|
||||
self.assertIn(self.product_child_A, products)
|
||||
self.assertIn(self.product_grandchild_A1, products)
|
||||
|
||||
def test_category_blacklist_excludes_with_subcategories(self):
|
||||
"""Test that excluding a category also excludes all its subcategories (recursive)."""
|
||||
# Add parent category to inclusion
|
||||
self.group_order.category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
# Exclude Child Category A (should also exclude Grandchild A1)
|
||||
self.group_order.excluded_category_ids = [(4, self.child_category_A.id)]
|
||||
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
|
||||
# Products in Child A and Grandchild A1 should NOT be discoverable
|
||||
self.assertNotIn(self.product_child_A, products)
|
||||
self.assertNotIn(self.product_grandchild_A1, products) # Recursive exclusion
|
||||
|
||||
# But products in parent and Child B should still be there
|
||||
self.assertIn(self.product_parent, products)
|
||||
self.assertIn(self.product_child_B, products)
|
||||
|
||||
def test_category_blacklist_excludes_parent_excludes_all_children(self):
|
||||
"""Test that excluding parent category excludes ALL descendants."""
|
||||
# Add parent category to inclusion (includes all)
|
||||
self.group_order.category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
# Exclude the parent category (should exclude ALL products in hierarchy)
|
||||
self.group_order.excluded_category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
|
||||
# ALL products in the hierarchy should be excluded
|
||||
self.assertNotIn(self.product_parent, products)
|
||||
self.assertNotIn(self.product_child_A, products)
|
||||
self.assertNotIn(self.product_grandchild_A1, products)
|
||||
self.assertNotIn(self.product_child_B, products)
|
||||
|
||||
# Result should be empty (no products available)
|
||||
self.assertEqual(len(products), 0)
|
||||
|
||||
def test_category_blacklist_with_direct_product_inclusion(self):
|
||||
"""Test that category blacklist affects even directly included products."""
|
||||
# Add product directly
|
||||
self.group_order.product_ids = [(4, self.product_child_A.id)]
|
||||
|
||||
# Product should be discoverable
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
self.assertIn(self.product_child_A, products)
|
||||
|
||||
# Exclude the category
|
||||
self.group_order.excluded_category_ids = [(4, self.child_category_A.id)]
|
||||
|
||||
# Product should NOT be discoverable anymore, even though directly included
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
self.assertNotIn(self.product_child_A, products)
|
||||
|
||||
def test_category_blacklist_does_not_affect_other_categories(self):
|
||||
"""Test that excluding a category doesn't affect products in unrelated categories."""
|
||||
# Add all categories to inclusion
|
||||
self.group_order.category_ids = [
|
||||
(4, self.parent_category.id),
|
||||
(4, self.other_category.id),
|
||||
]
|
||||
|
||||
# Exclude parent category
|
||||
self.group_order.excluded_category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
|
||||
# Products in parent hierarchy should NOT be there
|
||||
self.assertNotIn(self.product_parent, products)
|
||||
self.assertNotIn(self.product_child_A, products)
|
||||
self.assertNotIn(self.product_child_B, products)
|
||||
|
||||
# But product in other category should still be there
|
||||
self.assertIn(self.product_other, products)
|
||||
|
||||
def test_empty_category_blacklist_no_effect(self):
|
||||
"""Test that empty excluded_category_ids doesn't affect discovery."""
|
||||
# Add parent category
|
||||
self.group_order.category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
# All products should be discoverable
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
self.assertIn(self.product_parent, products)
|
||||
self.assertIn(self.product_child_A, products)
|
||||
self.assertIn(self.product_grandchild_A1, products)
|
||||
self.assertIn(self.product_child_B, products)
|
||||
|
||||
# Excluded category list is empty - should have no effect
|
||||
self.assertEqual(len(self.group_order.excluded_category_ids), 0)
|
||||
|
||||
def test_multiple_category_exclusions(self):
|
||||
"""Test excluding multiple categories at once."""
|
||||
# Add parent category
|
||||
self.group_order.category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
# Exclude both child categories
|
||||
self.group_order.excluded_category_ids = [
|
||||
(4, self.child_category_A.id),
|
||||
(4, self.child_category_B.id),
|
||||
]
|
||||
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
|
||||
# Products in both child categories (+ grandchild) should NOT be there
|
||||
self.assertNotIn(self.product_child_A, products)
|
||||
self.assertNotIn(self.product_grandchild_A1, products)
|
||||
self.assertNotIn(self.product_child_B, products)
|
||||
|
||||
# But product in parent category should still be there
|
||||
self.assertIn(self.product_parent, products)
|
||||
|
||||
def test_category_blacklist_combined_with_other_blacklists(self):
|
||||
"""Test that category blacklist works together with product and supplier blacklists."""
|
||||
# Add parent category
|
||||
self.group_order.category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
# Exclude Child A category (affects product_child_A and product_grandchild_A1)
|
||||
self.group_order.excluded_category_ids = [(4, self.child_category_A.id)]
|
||||
|
||||
# Also exclude product_child_B directly
|
||||
self.group_order.excluded_product_ids = [(4, self.product_child_B.id)]
|
||||
|
||||
products = self.group_order._get_products_for_group_order(self.group_order.id)
|
||||
|
||||
# Products excluded by category blacklist
|
||||
self.assertNotIn(self.product_child_A, products)
|
||||
self.assertNotIn(self.product_grandchild_A1, products)
|
||||
|
||||
# Product excluded by product blacklist
|
||||
self.assertNotIn(self.product_child_B, products)
|
||||
|
||||
# Only product_parent should be available
|
||||
self.assertIn(self.product_parent, products)
|
||||
self.assertEqual(len(products), 1)
|
||||
|
||||
def test_category_blacklist_available_products_count(self):
|
||||
"""Test that available_products_count reflects category blacklist."""
|
||||
# Add parent category (4 products in hierarchy)
|
||||
self.group_order.category_ids = [(4, self.parent_category.id)]
|
||||
|
||||
# Count should include all 4 products
|
||||
initial_count = self.group_order.available_products_count
|
||||
self.assertEqual(initial_count, 4)
|
||||
|
||||
# Exclude Child Category A (should exclude 2 products: child_A + grandchild_A1)
|
||||
self.group_order.excluded_category_ids = [(4, self.child_category_A.id)]
|
||||
|
||||
# Count should decrease by 2
|
||||
new_count = self.group_order.available_products_count
|
||||
self.assertEqual(new_count, 2)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue