From 5721687488f1a797ae0ff55bf900b74ce75f8665 Mon Sep 17 00:00:00 2001
From: snt
Date: Mon, 16 Feb 2026 23:28:36 +0100
Subject: [PATCH] [FIX] website_sale_aplicoop: Move template logic to
controller for QWeb compatibility
This fixes the persistent 'TypeError: NoneType object is not callable' error
by moving all complex conditional logic out of the template and into the
Python controller.
QWeb has strict parsing limitations - it fails on:
- Complex nested conditionals in t-set
- Chained 'or' operators in t-attf-* attributes
- Deep object attribute chains (uom_id.category_id.name)
Solution: Pre-process all display values in controller via _prepare_product_display_info()
which creates product_display_info dict with safe values ready for template.
Template now uses simple dict.get() calls without any conditional logic.
---
.../controllers/website_sale.py | 53 +++++++++++++++++++
.../views/website_templates.xml | 12 +----
2 files changed, 55 insertions(+), 10 deletions(-)
diff --git a/website_sale_aplicoop/controllers/website_sale.py b/website_sale_aplicoop/controllers/website_sale.py
index 262d0ee..d28e379 100644
--- a/website_sale_aplicoop/controllers/website_sale.py
+++ b/website_sale_aplicoop/controllers/website_sale.py
@@ -388,6 +388,40 @@ class AplicoopWebsiteSale(WebsiteSale):
)
return False
+ def _prepare_product_display_info(self, product, product_price_info):
+ """Prepare all display information for a product in a QWeb-safe way.
+
+ This function pre-processes all values that might be None or require
+ conditional logic, so the template can use simple variable references
+ without complex expressions that confuse QWeb's parser.
+
+ Args:
+ product: product.template record
+ product_price_info: dict with 'price', 'list_price', etc.
+
+ Returns:
+ dict with all pre-processed display values ready for template
+ """
+ # Safety: Get price, ensure it's a float
+ price_data = product_price_info.get(product.id, {})
+ price = (
+ price_data.get("price", product.list_price)
+ if price_data
+ else product.list_price
+ )
+ price_safe = float(price) if price else 0.0
+
+ # Safety: Get UoM category name
+ uom_category_name = ""
+ if product.uom_id:
+ if product.uom_id.category_id:
+ uom_category_name = product.uom_id.category_id.name or ""
+
+ return {
+ "display_price": price_safe,
+ "safe_uom_category": uom_category_name,
+ }
+
def _validate_confirm_request(self, data):
"""Validate all requirements for confirm order request.
@@ -1029,6 +1063,15 @@ class AplicoopWebsiteSale(WebsiteSale):
"tax_included": False,
}
+ # Prepare display info for each product (QWeb-safe: all values pre-processed)
+ # This ensures the template can use simple variable references without complex conditionals
+ product_display_info = {}
+ for product in products:
+ display_info = self._prepare_product_display_info(
+ product, product_price_info
+ )
+ product_display_info[product.id] = display_info
+
# Calculate available tags with product count (only show tags that are actually used and visible)
# Build a dict: {tag_id: {'id': tag_id, 'name': tag_name, 'count': num_products}}
available_tags_dict = {}
@@ -1099,6 +1142,7 @@ class AplicoopWebsiteSale(WebsiteSale):
"day_names": self._get_day_names(env=request.env),
"product_supplier_info": product_supplier_info,
"product_price_info": product_price_info,
+ "product_display_info": product_display_info,
"labels": labels,
"labels_json": json.dumps(labels, ensure_ascii=False),
"lazy_loading_enabled": lazy_loading_enabled,
@@ -1225,6 +1269,14 @@ class AplicoopWebsiteSale(WebsiteSale):
"published_tags": published_tags,
}
+ # Prepare display info for each product (QWeb-safe: all values pre-processed)
+ product_display_info = {}
+ for product in products_page:
+ display_info = self._prepare_product_display_info(
+ product, product_price_info
+ )
+ product_display_info[product.id] = display_info
+
# Get labels
labels = self.get_checkout_labels()
@@ -1236,6 +1288,7 @@ class AplicoopWebsiteSale(WebsiteSale):
"filtered_product_tags": filtered_products,
"product_supplier_info": product_supplier_info,
"product_price_info": product_price_info,
+ "product_display_info": product_display_info,
"labels": labels,
"has_next": has_next,
"next_page": page + 1,
diff --git a/website_sale_aplicoop/views/website_templates.xml b/website_sale_aplicoop/views/website_templates.xml
index e0de944..4635ab5 100644
--- a/website_sale_aplicoop/views/website_templates.xml
+++ b/website_sale_aplicoop/views/website_templates.xml
@@ -1161,17 +1161,9 @@
-
-