Remove grouped_slice per IN_MAX
The usage of ``grouped_slice`` without size is deprecated since `= ANY(ARRAY[%s])` is used for PostgreSQL and SQLite is used only for tests. The ``Database.IN_MAX`` is replaced by ``backend.MAX_QUERY_PARAMS`` which is a more accurate limit of the backend. The SQLite limits is indeed SQLITE_MAX_EXPR_DEPTH so we use a empirical value.
This commit is contained in:
@@ -11,7 +11,7 @@ from trytond.model import (
|
||||
from trytond.model.exceptions import AccessError
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Bool, Eval, If
|
||||
from trytond.tools import grouped_slice, is_full_text, lstrip_wildcard
|
||||
from trytond.tools import is_full_text, lstrip_wildcard
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Button, StateTransition, StateView, Wizard
|
||||
|
||||
@@ -257,11 +257,10 @@ class Inventory(Workflow, ModelSQL, ModelView, ChatMixin):
|
||||
else:
|
||||
product_ids = [l.product.id for l in inventory.lines]
|
||||
pbl = defaultdict(int)
|
||||
for product_ids in grouped_slice(product_ids):
|
||||
pbl.update(Product.products_by_location(
|
||||
[inventory.location.id],
|
||||
grouping=grouping,
|
||||
grouping_filter=(list(product_ids),)))
|
||||
pbl.update(Product.products_by_location(
|
||||
[inventory.location.id],
|
||||
grouping=grouping,
|
||||
grouping_filter=(list(product_ids),)))
|
||||
|
||||
# Update existing lines
|
||||
for line in inventory.lines:
|
||||
|
||||
+17
-22
@@ -14,7 +14,6 @@ from trytond.model import (
|
||||
from trytond.modules.product import price_digits, round_price
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If, TimeDelta
|
||||
from trytond.tools import grouped_slice
|
||||
from trytond.transaction import (
|
||||
Transaction, inactive_records, without_check_access)
|
||||
|
||||
@@ -314,18 +313,16 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
|
||||
for (location_id, product), quantity in quantities.items():
|
||||
if quantity and product not in consumables:
|
||||
empty.discard(location_id)
|
||||
for sub_ids in grouped_slice(list(empty)):
|
||||
sub_ids = list(sub_ids)
|
||||
moves = Move.search([
|
||||
('state', 'not in', ['done', 'cancelled']),
|
||||
['OR',
|
||||
('from_location', 'in', sub_ids),
|
||||
('to_location', 'in', sub_ids),
|
||||
],
|
||||
])
|
||||
for move in moves:
|
||||
for location in [move.from_location, move.to_location]:
|
||||
empty.discard(location.id)
|
||||
moves = Move.search([
|
||||
('state', 'not in', ['done', 'cancelled']),
|
||||
['OR',
|
||||
('from_location', 'in', empty),
|
||||
('to_location', 'in', empty),
|
||||
],
|
||||
])
|
||||
for move in moves:
|
||||
for location in [move.from_location, move.to_location]:
|
||||
empty.discard(location.id)
|
||||
return cls.browse(empty)
|
||||
|
||||
@staticmethod
|
||||
@@ -434,15 +431,13 @@ class Location(DeactivableMixin, tree(), ModelSQL, ModelView):
|
||||
if not grouping:
|
||||
return {loc.id: None for loc in locations}
|
||||
|
||||
pbl = {}
|
||||
for sub_locations in grouped_slice(locations):
|
||||
location_ids = [l.id for l in sub_locations]
|
||||
with Transaction().set_context(context):
|
||||
pbl.update(Product.products_by_location(
|
||||
location_ids,
|
||||
grouping=grouping,
|
||||
grouping_filter=grouping_filter,
|
||||
with_childs=trans_context.get('with_childs', True)))
|
||||
location_ids = [l.id for l in locations]
|
||||
with Transaction().set_context(context):
|
||||
pbl = Product.products_by_location(
|
||||
location_ids,
|
||||
grouping=grouping,
|
||||
grouping_filter=grouping_filter,
|
||||
with_childs=trans_context.get('with_childs', True))
|
||||
|
||||
return dict((loc.id, pbl.get((loc.id,) + key, 0)) for loc in locations)
|
||||
|
||||
|
||||
@@ -13,9 +13,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="text">You cannot change the cost price of a product which is associated with stock moves.
|
||||
You must use the "Modify Cost Price" wizard.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_product_quantities_max">
|
||||
<field name="text">You cannot select more than %(max)s products to compute quantities.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_invalid_cost_price">
|
||||
<field name="text">Invalid cost price "%(cost_price)s" for product "%(product)s" with exception "%(exception)s".</field>
|
||||
</record>
|
||||
|
||||
+16
-19
@@ -19,7 +19,7 @@ from trytond.model.exceptions import AccessError
|
||||
from trytond.modules.product import price_digits, round_price
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Bool, Eval, Id, If, TimeDelta
|
||||
from trytond.tools import cached_property, grouped_slice
|
||||
from trytond.tools import cached_property
|
||||
from trytond.transaction import Transaction, without_check_access
|
||||
|
||||
from .exceptions import MoveFutureWarning, MoveOriginWarning
|
||||
@@ -1314,7 +1314,6 @@ class Move(Workflow, ModelSQL, ModelView):
|
||||
connection = transaction.connection
|
||||
|
||||
if database.has_select_for():
|
||||
count = database.IN_MAX // 2
|
||||
PeriodCache = Period.get_cache(grouping)
|
||||
with connection.cursor() as cursor:
|
||||
for company_id in company_ids:
|
||||
@@ -1327,24 +1326,22 @@ class Move(Workflow, ModelSQL, ModelView):
|
||||
], order=[('date', 'DESC')], limit=1)
|
||||
if periods:
|
||||
period, = periods
|
||||
for sub_location_ids in grouped_slice(location_ids, count):
|
||||
sub_location_ids = list(sub_location_ids)
|
||||
table = cls.__table__()
|
||||
query = table.select(Literal(1),
|
||||
where=(fields.SQL_OPERATORS['in'](
|
||||
table.to_location, sub_location_ids)
|
||||
| fields.SQL_OPERATORS['in'](
|
||||
table.from_location, sub_location_ids))
|
||||
& table.product.in_(product_ids)
|
||||
& (table.company == company_id),
|
||||
for_=For('UPDATE', nowait=True))
|
||||
table = cls.__table__()
|
||||
query = table.select(Literal(1),
|
||||
where=(fields.SQL_OPERATORS['in'](
|
||||
table.to_location, location_ids)
|
||||
| fields.SQL_OPERATORS['in'](
|
||||
table.from_location, location_ids))
|
||||
& table.product.in_(product_ids)
|
||||
& (table.company == company_id),
|
||||
for_=For('UPDATE', nowait=True))
|
||||
|
||||
if period:
|
||||
query.where &= Coalesce(
|
||||
table.effective_date,
|
||||
table.planned_date,
|
||||
datetime.date.max) > period.date
|
||||
cursor.execute(*query)
|
||||
if period:
|
||||
query.where &= Coalesce(
|
||||
table.effective_date,
|
||||
table.planned_date,
|
||||
datetime.date.max) > period.date
|
||||
cursor.execute(*query)
|
||||
else:
|
||||
cls.lock()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from itertools import chain, groupby
|
||||
from itertools import groupby
|
||||
|
||||
from sql import For, Literal
|
||||
|
||||
@@ -8,7 +8,6 @@ from trytond.i18n import gettext
|
||||
from trytond.model import Index, ModelSQL, ModelView, Workflow, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.tools import grouped_slice
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .exceptions import PeriodCloseError
|
||||
@@ -89,13 +88,10 @@ class Period(Workflow, ModelSQL, ModelView):
|
||||
def draft(cls, periods):
|
||||
for grouping in cls.groupings():
|
||||
Cache = cls.get_cache(grouping)
|
||||
caches = []
|
||||
for sub_periods in grouped_slice(periods):
|
||||
caches.append(Cache.search([
|
||||
('period', 'in',
|
||||
[p.id for p in sub_periods]),
|
||||
], order=[]))
|
||||
Cache.delete(list(chain(*caches)))
|
||||
caches = Cache.search([
|
||||
('period', 'in', periods),
|
||||
], order=[])
|
||||
Cache.delete(caches)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
|
||||
+32
-56
@@ -17,7 +17,7 @@ from trytond.model.exceptions import AccessError
|
||||
from trytond.modules.product import price_digits, round_price
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Bool, Eval, If, PYSONEncoder
|
||||
from trytond.tools import decistmt, grouped_slice
|
||||
from trytond.tools import decistmt
|
||||
from trytond.tools import timezone as tz
|
||||
from trytond.transaction import Transaction, without_check_access
|
||||
from trytond.wizard import (
|
||||
@@ -35,14 +35,11 @@ def _find_moves(cls, records):
|
||||
field = 'product.template'
|
||||
else:
|
||||
field = 'product'
|
||||
for sub_records in grouped_slice(records):
|
||||
moves = Move.search([
|
||||
(field, 'in', list(map(int, sub_records))),
|
||||
],
|
||||
limit=1, order=[])
|
||||
if moves:
|
||||
return moves
|
||||
return False
|
||||
moves = Move.search([
|
||||
(field, 'in', list(map(int, records))),
|
||||
],
|
||||
limit=1, order=[])
|
||||
return bool(moves)
|
||||
|
||||
|
||||
def _check_no_stock(cls, records):
|
||||
@@ -91,10 +88,9 @@ def _check_no_stock(cls, records):
|
||||
locations = Location.search([('type', '=', 'storage')])
|
||||
location_ids = list(map(int, locations))
|
||||
for company in Company.search([]):
|
||||
for sub_records in grouped_slice(records):
|
||||
record2locations = get_record_locations(
|
||||
company, location_ids, sub_records, grouping)
|
||||
raise_warning(cls, company, record2locations)
|
||||
record2locations = get_record_locations(
|
||||
company, location_ids, records, grouping)
|
||||
raise_warning(cls, company, record2locations)
|
||||
|
||||
|
||||
class Template(metaclass=PoolMeta):
|
||||
@@ -279,12 +275,11 @@ class Product(StockMixin, object, metaclass=PoolMeta):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
deactivated = super().deactivate_replaced(products=products)
|
||||
for sub_products in grouped_slice(deactivated):
|
||||
moves = Move.search([
|
||||
('product', 'in', list(map(int, sub_products))),
|
||||
('state', 'in', ['staging', 'draft']),
|
||||
])
|
||||
Move.delete(moves)
|
||||
moves = Move.search([
|
||||
('product', 'in', list(map(int, products))),
|
||||
('state', 'in', ['staging', 'draft']),
|
||||
])
|
||||
Move.delete(moves)
|
||||
return deactivated
|
||||
|
||||
@classmethod
|
||||
@@ -367,16 +362,14 @@ class Product(StockMixin, object, metaclass=PoolMeta):
|
||||
cost = round_price(cost)
|
||||
costs[cost].append(product)
|
||||
|
||||
updated = []
|
||||
for sub_products in grouped_slice(products):
|
||||
domain = [
|
||||
('unit_price_updated', '=', True),
|
||||
cls._domain_moves_cost(),
|
||||
('product', 'in', [p.id for p in sub_products]),
|
||||
]
|
||||
if start:
|
||||
domain.append(('effective_date', '>=', start))
|
||||
updated += Move.search(domain, order=[])
|
||||
domain = [
|
||||
('unit_price_updated', '=', True),
|
||||
cls._domain_moves_cost(),
|
||||
('product', 'in', products),
|
||||
]
|
||||
if start:
|
||||
domain.append(('effective_date', '>=', start))
|
||||
updated = Move.search(domain, order=[])
|
||||
if updated:
|
||||
Move.write(updated, {'unit_price_updated': False})
|
||||
|
||||
@@ -675,10 +668,6 @@ class ProductQuantitiesByWarehouse(ModelSQL, ModelView):
|
||||
product = Product.__table__()
|
||||
from_ = move.join(product, condition=move.product == product.id)
|
||||
if product_template:
|
||||
if len(product_template) > transaction.database.IN_MAX:
|
||||
raise AccessError(gettext(
|
||||
'stock.msg_product_quantities_max',
|
||||
max=transaction.database.IN_MAX))
|
||||
product_clause = fields.SQL_OPERATORS['in'](
|
||||
product.template, product_template)
|
||||
else:
|
||||
@@ -692,10 +681,6 @@ class ProductQuantitiesByWarehouse(ModelSQL, ModelView):
|
||||
if isinstance(product, int):
|
||||
product = [product]
|
||||
if product:
|
||||
if len(product) > transaction.database.IN_MAX:
|
||||
raise AccessError(gettext(
|
||||
'stock.msg_product_quantities_max',
|
||||
max=transaction.database.IN_MAX))
|
||||
product_clause = fields.SQL_OPERATORS['in'](
|
||||
move.product, product)
|
||||
else:
|
||||
@@ -943,10 +928,6 @@ class ProductQuantitiesByWarehouseMove(ModelSQL, ModelView):
|
||||
product = Product.__table__()
|
||||
from_ = move.join(product, condition=move.product == product.id)
|
||||
if product_template:
|
||||
if len(product_template) > transaction.database.IN_MAX:
|
||||
raise AccessError(gettext(
|
||||
'stock.msg_product_quantities_max',
|
||||
max=transaction.database.IN_MAX))
|
||||
product_clause = fields.SQL_OPERATORS['in'](
|
||||
product.template, product_template)
|
||||
else:
|
||||
@@ -959,10 +940,6 @@ class ProductQuantitiesByWarehouseMove(ModelSQL, ModelView):
|
||||
if isinstance(product, int):
|
||||
product = [product]
|
||||
if product:
|
||||
if len(product) > transaction.database.IN_MAX:
|
||||
raise AccessError(gettext(
|
||||
'stock.msg_product_quantities_max',
|
||||
max=transaction.database.IN_MAX))
|
||||
product_clause = fields.SQL_OPERATORS['in'](
|
||||
move.product, product)
|
||||
else:
|
||||
@@ -1139,17 +1116,16 @@ class RecomputeCostPrice(Wizard):
|
||||
products = []
|
||||
|
||||
from_ = None
|
||||
for sub_products in grouped_slice(products):
|
||||
moves = Move.search([
|
||||
('unit_price_updated', '=', True),
|
||||
Product._domain_moves_cost(),
|
||||
('product', 'in', [p.id for p in sub_products]),
|
||||
],
|
||||
order=[('effective_date', 'ASC')],
|
||||
limit=1)
|
||||
if moves:
|
||||
move, = moves
|
||||
from_ = min(from_ or datetime.date.max, move.effective_date)
|
||||
moves = Move.search([
|
||||
('unit_price_updated', '=', True),
|
||||
Product._domain_moves_cost(),
|
||||
('product', 'in', products),
|
||||
],
|
||||
order=[('effective_date', 'ASC')],
|
||||
limit=1)
|
||||
if moves:
|
||||
move, = moves
|
||||
from_ = min(from_ or datetime.date.max, move.effective_date)
|
||||
return {'from_': from_}
|
||||
|
||||
def transition_recompute(self):
|
||||
|
||||
@@ -15,7 +15,7 @@ from trytond.model import ModelSQL, ModelView, fields, sum_tree
|
||||
from trytond.modules.currency.fields import Monetary
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.tools import grouped_slice, pairwise_longest
|
||||
from trytond.tools import pairwise_longest
|
||||
from trytond.tools.chart import sparkline
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
@@ -592,15 +592,11 @@ class CategoryTree(ModelSQL, ModelView):
|
||||
categories = cls.search([
|
||||
('parent', 'child_of', [c.id for c in categories]),
|
||||
])
|
||||
ids = [c.id for c in categories]
|
||||
reporting_categories = []
|
||||
for sub_ids in grouped_slice(ids):
|
||||
sub_ids = list(sub_ids)
|
||||
where = fields.SQL_OPERATORS['in'](
|
||||
reporting_category.id, sub_ids)
|
||||
cursor.execute(
|
||||
*reporting_category.select(reporting_category.id, where=where))
|
||||
reporting_categories.extend(r for r, in cursor)
|
||||
cursor.execute(*reporting_category.select(
|
||||
reporting_category.id,
|
||||
where=fields.SQL_OPERATORS['in'](
|
||||
reporting_category.id, map(int, categories))))
|
||||
reporting_categories = [r for r, in cursor]
|
||||
|
||||
result = {}
|
||||
reporting_categories = ReportingCategory.browse(reporting_categories)
|
||||
|
||||
Reference in New Issue
Block a user