From a11fb2ecb9cd471f7b49913534eaeb84085bfb94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 25 Jun 2018 22:57:00 +0200 Subject: [PATCH] Check no move when modify product of lot issue7516 review42241003 --- CHANGELOG | 2 ++ stock.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 5c7072ceaa..9b9e8f6f05 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Check no move when modify product of lot + Version 4.8.0 - 2018-04-23 * Bug fixes (see mercurial logs for details) diff --git a/stock.py b/stock.py index d1372e7e6d..105d14c06b 100644 --- a/stock.py +++ b/stock.py @@ -2,10 +2,12 @@ # this repository contains the full copyright notices and license terms. import datetime from collections import defaultdict +from functools import wraps from trytond.model import ModelView, ModelSQL, fields from trytond.pyson import Eval from trytond.pool import Pool, PoolMeta +from trytond.tools import grouped_slice from trytond.transaction import Transaction from trytond.modules.stock import StockMixin @@ -15,6 +17,38 @@ __all__ = ['Lot', 'LotType', 'Move', 'ShipmentIn', 'ShipmentOut', 'Inventory', 'InventoryLine', 'LotByLocationContext'] +def check_no_move(func): + def find_moves(cls, records, state=None): + pool = Pool() + Move = pool.get('stock.move') + for sub_records in grouped_slice(records): + domain = [ + ('lot', 'in', [r.id for r in sub_records]) + ] + if state: + domain.append(('state', '=', state)) + moves = Move.search(domain, limit=1, order=[]) + if moves: + return True + return False + + @wraps(func) + def decorator(cls, *args): + transaction = Transaction() + if (transaction.user != 0 + and transaction.context.get('_check_access')): + actions = iter(args) + for records, values in zip(actions, actions): + for field, state, error in cls._modify_no_move: + if field in values: + if find_moves(cls, records, state): + cls.raise_user_error(error) + # No moves for those records + break + func(*args) + return decorator + + class Lot(ModelSQL, ModelView, StockMixin): "Stock Lot" __name__ = 'stock.lot' @@ -26,6 +60,17 @@ class Lot(ModelSQL, ModelView, StockMixin): forecast_quantity = fields.Function(fields.Float('Forecast Quantity'), 'get_quantity', searcher='search_quantity') + @classmethod + def __setup__(cls): + super(Lot, cls).__setup__() + cls._error_messages.update({ + 'change_product': ("You cannot change the product of a lot " + "which is associated to stock moves."), + }) + cls._modify_no_move = [ + ('product', None, 'change_product'), + ] + @classmethod def get_quantity(cls, lots, name): location_ids = Transaction().context.get('locations') @@ -39,6 +84,11 @@ class Lot(ModelSQL, ModelView, StockMixin): return cls._search_quantity(name, location_ids, domain, grouping=('product', 'lot')) + @classmethod + @check_no_move + def write(cls, *args): + super(Lot, cls).write(*args) + class LotByLocationContext(ModelView): 'Lot by Location'