changeset fa9e653fb9db in modules/stock:default
details: https://hg.tryton.org/modules/stock?cmd=changeset;node=fa9e653fb9db
description:
        Prevent doing moves in the future

        issue9355
        review327351002
diffstat:

 CHANGELOG                               |   1 +
 exceptions.py                           |   4 +
 message.xml                             |   3 +
 move.py                                 |  25 +++++++++++-
 tests/scenario_stock_move_in_future.rst |  71 +++++++++++++++++++++++++++++++++
 tests/test_stock.py                     |   5 ++
 6 files changed, 108 insertions(+), 1 deletions(-)

diffs (163 lines):

diff -r 139297ec4faa -r fa9e653fb9db CHANGELOG
--- a/CHANGELOG Sat Oct 03 23:47:19 2020 +0200
+++ b/CHANGELOG Sun Oct 04 23:57:37 2020 +0200
@@ -1,3 +1,4 @@
+* Add warning to prevent move in the future
 * Add relate to open inventory lines
 * Use simplified view for moves list on shipments
 * Add a relate from product to its moves
diff -r 139297ec4faa -r fa9e653fb9db exceptions.py
--- a/exceptions.py     Sat Oct 03 23:47:19 2020 +0200
+++ b/exceptions.py     Sun Oct 04 23:57:37 2020 +0200
@@ -28,5 +28,9 @@
     pass
 
 
+class MoveFutureWarning(UserWarning):
+    pass
+
+
 class ProductCostPriceError(ValidationError):
     pass
diff -r 139297ec4faa -r fa9e653fb9db message.xml
--- a/message.xml       Sat Oct 03 23:47:19 2020 +0200
+++ b/message.xml       Sun Oct 04 23:57:37 2020 +0200
@@ -86,5 +86,8 @@
         <record model="ir.message" id="msg_move_from_to_location">
             <field name="text">The source and destination of stock move must 
be different.</field>
         </record>
+        <record model="ir.message" id="msg_effective_date_in_the_future">
+            <field name="text">The moves "%(moves)s" have effective dates in 
the future.</field>
+        </record>
     </data>
 </tryton>
diff -r 139297ec4faa -r fa9e653fb9db move.py
--- a/move.py   Sat Oct 03 23:47:19 2020 +0200
+++ b/move.py   Sun Oct 04 23:57:37 2020 +0200
@@ -21,7 +21,7 @@
 
 from trytond.modules.product import price_digits, round_price
 
-from .exceptions import MoveOriginWarning
+from .exceptions import MoveOriginWarning, MoveFutureWarning
 
 STATES = {
     'readonly': Eval('state').in_(['cancelled', 'assigned', 'done']),
@@ -616,6 +616,29 @@
     def do(cls, moves):
         pool = Pool()
         Product = pool.get('product.product')
+        Date = pool.get('ir.date')
+        Warning = pool.get('res.user.warning')
+        today_cache = {}
+
+        def in_future(move):
+            if move.company not in today_cache:
+                with Transaction().set_context(company=move.company.id):
+                    today_cache[move.company] = Date.today()
+            today = today_cache[move.company]
+            if move.effective_date and move.effective_date > today:
+                return move
+        future_moves = list(filter(in_future, moves))
+        if future_moves:
+            names = ', '.join(m.rec_name for m in future_moves[:5])
+            if len(future_moves) > 5:
+                names += '...'
+            warning_name = (
+                    '%s.effective_date_future' % hashlib.md5(
+                        str(future_moves).encode('utf-8')).hexdigest())
+            if Warning.check(warning_name):
+                raise MoveFutureWarning(warning_name,
+                    gettext('stock.msg_effective_date_in_the_future',
+                        moves=names))
 
         def set_cost_values(cost_values):
             Value = Product.multivalue_model('cost_price')
diff -r 139297ec4faa -r fa9e653fb9db tests/scenario_stock_move_in_future.rst
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_stock_move_in_future.rst   Sun Oct 04 23:57:37 2020 +0200
@@ -0,0 +1,71 @@
+=============================
+Stock Move In Future Scenario
+=============================
+
+Imports::
+
+    >>> import datetime
+    >>> from dateutil.relativedelta import relativedelta
+    >>> from decimal import Decimal
+    >>> from proteus import Model
+    >>> from trytond.tests.tools import activate_modules
+    >>> from trytond.modules.company.tests.tools import (
+    ...     create_company, get_company)
+    >>> today = datetime.date.today()
+    >>> tomorrow = today + relativedelta(days=1)
+
+Activate modules::
+
+    >>> config = activate_modules('stock')
+
+Create company::
+
+    >>> _ = create_company()
+    >>> company = get_company()
+
+Create product::
+
+    >>> ProductUom = Model.get('product.uom')
+    >>> ProductTemplate = Model.get('product.template')
+    >>> Product = Model.get('product.product')
+    >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+    >>> template = ProductTemplate()
+    >>> template.name = 'Product'
+    >>> template.default_uom = unit
+    >>> template.type = 'goods'
+    >>> template.list_price = Decimal('20')
+    >>> template.save()
+    >>> product, = template.products
+    >>> product.cost_price = Decimal('1')
+    >>> product.save()
+
+Get stock locations::
+
+    >>> Location = Model.get('stock.location')
+    >>> supplier_loc, = Location.find([('code', '=', 'SUP')])
+    >>> storage_loc, = Location.find([('code', '=', 'STO')])
+
+A warning is raised when doing a move in the future::
+
+    >>> Move = Model.get('stock.move')
+    >>> move = Move()
+    >>> move.product = product
+    >>> move.quantity = 1
+    >>> move.from_location = supplier_loc
+    >>> move.to_location = storage_loc
+    >>> move.currency = company.currency
+    >>> move.effective_date = tomorrow
+    >>> move.quantity = 2
+    >>> move.unit_price = Decimal('1')
+    >>> move.save()
+    >>> move.click('do')  # doctest: +IGNORE_EXCEPTION_DETAIL
+    Traceback (most recent call last):
+        ...
+    MoveFutureWarning: ...
+
+But it can be done for today::
+
+    >>> move.effective_date = today
+    >>> move.click('do')
+    >>> move.state
+    'done'
diff -r 139297ec4faa -r fa9e653fb9db tests/test_stock.py
--- a/tests/test_stock.py       Sat Oct 03 23:47:19 2020 +0200
+++ b/tests/test_stock.py       Sun Oct 04 23:57:37 2020 +0200
@@ -1552,4 +1552,9 @@
             tearDown=doctest_teardown, encoding='utf-8',
             checker=doctest_checker,
             optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
+    suite.addTests(doctest.DocFileSuite(
+            'scenario_stock_move_in_future.rst',
+            tearDown=doctest_teardown, encoding='utf-8',
+            checker=doctest_checker,
+            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
     return suite

Reply via email to