From ab7ff3eea5c7b3cce0980132b1e1031a2c16b124 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Mon, 18 May 2026 00:13:33 -0400 Subject: [PATCH] =?UTF-8?q?fix(portal):=20/my/orders=20500=20=E2=80=94=20Q?= =?UTF-8?q?Web=20t-value=20is=20Python=20not=20Jinja,=20|length=20is=20bit?= =?UTF-8?q?wise=20OR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit orders|length in t-value parses as orders | length, not as a Jinja length filter. orders is a sale.order recordset; the `length` identifier resolves to None; Python evaluates recordset | None and raises TypeError. Use len(orders) instead. Also documents the gotcha in CLAUDE.md (rule 19) so future templates don't reach for Jinja-style filters in t-value. Co-Authored-By: Claude Opus 4.7 (1M context) --- fusion_plating/CLAUDE.md | 1 + .../fusion_plating_portal/views/fp_sale_order_portal.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fusion_plating/CLAUDE.md b/fusion_plating/CLAUDE.md index 2d1386c1..d5549f3d 100644 --- a/fusion_plating/CLAUDE.md +++ b/fusion_plating/CLAUDE.md @@ -179,6 +179,7 @@ These modules have **source code in this repo** but are **intentionally NOT inst - `fusion_plating_invoicing` blocks `action_post()` when `invoice_payment_term_id` is unset. Bypass: pass `'invoice_payment_term_id': self.env.ref('account.account_payment_term_immediate').id` in the create vals. Both are test-data scaffolding; neither weakens assertions and neither must appear in production code paths. 18. **Portal list pages — no pagination, 500-record cap**: All FP portal list routes (quote requests, jobs, certifications, deliveries) load up to 500 records and rely on client-side JS filtering. Do NOT re-add `portal_pager` to these routes. The `fp_portal_list_controls` macro + `fp_portal_list_search.js` handle filtering, counting, and the sort dropdown. Hidden `` cells inside each row carry extra searchable text (part number, customer PO, contact) that isn't displayed but is matched by the JS. +19. **QWeb `t-value` is Python, not Jinja**: `t-value="orders|length"` does NOT call a filter — Python parses `|` as bitwise/recordset OR, so on a non-empty recordset it tries `recordset | length_var` and raises `TypeError: unsupported operand types in: sale.order(…) | None` (when `length` is undefined) or returns a merged recordset (when `length` happens to be another recordset). Use `len(orders)` or `bool(orders)` or `(orders and orders[0]) or False` — explicit Python. Same trap applies to `|default`, `|first`, `|join`, etc. — none of these Jinja filters exist in QWeb. Bit us 2026-05-18 on `fp_sale_order_portal.xml` injecting `result_total` into the list-controls macro. ## Naming - **New custom models** (post-2026-04): `fp.*` prefix (e.g. `fp.part.catalog`, `fp.certificate`) diff --git a/fusion_plating/fusion_plating_portal/views/fp_sale_order_portal.xml b/fusion_plating/fusion_plating_portal/views/fp_sale_order_portal.xml index be3d6e3b..a7846abd 100644 --- a/fusion_plating/fusion_plating_portal/views/fp_sale_order_portal.xml +++ b/fusion_plating/fusion_plating_portal/views/fp_sale_order_portal.xml @@ -39,7 +39,7 @@ - +