details: https://code.tryton.org/tryton/commit/792812104ec9
branch: 7.8
user: Cédric Krier <[email protected]>
date: Thu Jun 11 15:30:11 2026 +0200
description:
Aggregate product by locations before applying filter when searching by
quantity
Closes #14887
(grafted from d7abce5cd10ccba9852f26c7b1aef465e20b4585)
diffstat:
modules/stock/move.py | 17 ++++++++---------
modules/stock/tests/test_module.py | 19 +++++++++++++++++++
2 files changed, 27 insertions(+), 9 deletions(-)
diffs (63 lines):
diff -r 9edf756cdbf5 -r 792812104ec9 modules/stock/move.py
--- a/modules/stock/move.py Thu Jun 18 14:37:36 2026 +0200
+++ b/modules/stock/move.py Thu Jun 11 15:30:11 2026 +0200
@@ -153,6 +153,12 @@
pbl = Product.products_by_location(
location_ids, with_childs=with_childs, grouping=grouping)
+ quantities = defaultdict(float)
+ for key, quantity in pbl.items():
+ # pbl could return None in some keys
+ if key[position] is not None:
+ quantities[key[position]] += quantity
+
operator_ = {
'=': operator.eq,
'>=': operator.ge,
@@ -163,15 +169,8 @@
'in': lambda v, l: v in l,
'not in': lambda v, l: v not in l,
}.get(operator_, lambda v, l: False)
- record_ids = []
- for key, quantity in pbl.items():
- if (quantity is not None and operand is not None
- and operator_(quantity, operand)):
- # pbl could return None in some keys
- if key[position] is not None:
- record_ids.append(key[position])
-
- return [('id', 'in', record_ids)]
+ return [('id', 'in',
+ [k for k, v in quantities.items() if operator_(v, operand)])]
class Move(Workflow, ModelSQL, ModelView):
diff -r 9edf756cdbf5 -r 792812104ec9 modules/stock/tests/test_module.py
--- a/modules/stock/tests/test_module.py Thu Jun 18 14:37:36 2026 +0200
+++ b/modules/stock/tests/test_module.py Thu Jun 11 15:30:11 2026 +0200
@@ -335,6 +335,25 @@
test_products_by_location()
+ with transaction.set_context(
+ locations=[supplier.id, customer.id, storage.id]):
+ for domain, found in [
+ ([('quantity', '=', 0)], True),
+ ([('quantity', '>=', 0)], True),
+ ([('quantity', '>', 0)], False),
+ ([('quantity', '<=', 0)], True),
+ ([('quantity', '<', 0)], False),
+ ([('quantity', '!=', 0)], False),
+ ([('quantity', 'in', [0])], True),
+ ([('quantity', 'in', [1])], False),
+ ([('quantity', 'not in', [0])], False),
+ ([('quantity', 'not in', [1])], True),
+ ]:
+ with self.subTest(domain=domain):
+ self.assertEqual(
+ Product.search(domain),
+ [product] if found else [])
+
periods = [
today + relativedelta(days=-6),
today + relativedelta(days=-5),