diff --git a/move.py b/move.py index b32014553d..b46d0085fd 100644 --- a/move.py +++ b/move.py @@ -7,7 +7,7 @@ from functools import partial from collections import OrderedDict, defaultdict from itertools import groupby -from sql import Literal, Union, Column, Null +from sql import Literal, Union, Column, Null, For from sql.aggregate import Sum from sql.conditionals import Coalesce from sql.operators import Concat @@ -778,8 +778,10 @@ class Move(Workflow, ModelSQL, ModelView): Uom = pool.get('product.uom') Date = pool.get('ir.date') Location = pool.get('stock.location') - - Transaction().database.lock(Transaction().connection, cls._table) + Period = pool.get('stock.period') + transaction = Transaction() + database = transaction.database + connection = transaction.connection if with_childs: locations = Location.search([ @@ -788,12 +790,42 @@ class Move(Workflow, ModelSQL, ModelView): ]) else: locations = list(set((m.from_location for m in moves))) + location_ids = [l.id for l in locations] + product_ids = list(set((m.product.id for m in moves))) + stock_date_end = Date.today() + + if database.has_select_for(): + table = cls.__table__() + query = table.select(Literal(1), + where=(table.to_location.in_(location_ids) + | table.from_location.in_(location_ids)) + & table.product.in_(product_ids), + for_=For('UPDATE', nowait=True)) + + PeriodCache = Period.get_cache(grouping) + if PeriodCache: + periods = Period.search([ + ('date', '<', stock_date_end), + ('state', '=', 'closed'), + ], order=[('date', 'DESC')], limit=1) + if periods: + period, = periods + query.where &= Coalesce( + table.effective_date, + table.planned_date, + datetime.date.max) > period.date + + with connection.cursor() as cursor: + cursor.execute(*query) + else: + database.lock(connection, cls._table) + with Transaction().set_context( - stock_date_end=Date.today(), + stock_date_end=stock_date_end, stock_assign=True): pbl = Product.products_by_location( - location_ids=[l.id for l in locations], - product_ids=[m.product.id for m in moves], + location_ids=location_ids, + product_ids=product_ids, grouping=grouping) def get_key(move, location): diff --git a/period.py b/period.py index 5b9b8028d5..34bf713ebe 100644 --- a/period.py +++ b/period.py @@ -1,6 +1,9 @@ # 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 + +from sql import Literal, For + from trytond.model import Workflow, ModelView, ModelSQL, fields from trytond.pyson import Eval, If from trytond.transaction import Transaction @@ -93,6 +96,20 @@ class Period(Workflow, ModelSQL, ModelView): Location = pool.get('stock.location') Move = pool.get('stock.move') Date = pool.get('ir.date') + transaction = Transaction() + connection = transaction.connection + database = transaction.database + + # XXX: A move in the period could be inserted before the lock + # from a different transaction. It will not be taken in the pbl + # computation but it is quite rare because only past periods are + # closed. + database.lock(connection, Move._table) + if database.has_select_for(): + move = Move.__table__() + query = move.select(Literal(1), for_=For('UPDATE', nowait=True)) + with connection.cursor() as cursor: + cursor.execute(*query) locations = Location.search([ ('type', 'not in', ['warehouse', 'view']),