details: https://code.tryton.org/tryton/commit/9cf089215d53
branch: default
user: Maxime Richez <[email protected]>
date: Mon Oct 05 12:54:17 2026 +0200
description:
Allow draft and staging moves to be created and modified in the closed
period
Closes #15056
diffstat:
modules/stock/move.py | 14 ++++++++++----
modules/stock/tests/scenario_stock_period.rst | 14 ++++++++++++--
modules/stock/tests/test_module.py | 26 --------------------------
3 files changed, 22 insertions(+), 32 deletions(-)
diffs (112 lines):
diff -r 41ca943f0f6b -r 9cf089215d53 modules/stock/move.py
--- a/modules/stock/move.py Sun Oct 04 16:48:54 2026 +0200
+++ b/modules/stock/move.py Mon Oct 05 12:54:17 2026 +0200
@@ -724,9 +724,15 @@
@classmethod
@without_check_access
- def check_period_closed(cls, moves):
- Period = Pool().get('stock.period')
- for company, moves in groupby(moves, lambda m: m.company):
+ def check_period_closed(cls, moves, state=None):
+ pool = Pool()
+ Period = pool.get('stock.period')
+
+ def exclude_draft_staging(move):
+ return (state if state else move.state) not in {'draft', 'staging'}
+
+ for company, moves in groupby(
+ filter(exclude_draft_staging, moves), lambda m: m.company):
periods = Period.search([
('state', '=', 'closed'),
('company', '=', company.id),
@@ -1068,7 +1074,7 @@
cls.check_period_closed(moves)
elif mode == 'write':
if values.keys() - cls._allow_modify_closed_period:
- cls.check_period_closed(moves)
+ cls.check_period_closed(moves, state=values.get('state'))
if values.keys() & cls._deny_modify_assigned:
for move in moves:
if move.state == 'assigned':
diff -r 41ca943f0f6b -r 9cf089215d53
modules/stock/tests/scenario_stock_period.rst
--- a/modules/stock/tests/scenario_stock_period.rst Sun Oct 04 16:48:54
2026 +0200
+++ b/modules/stock/tests/scenario_stock_period.rst Mon Oct 05 12:54:17
2026 +0200
@@ -71,7 +71,7 @@
>>> period, = Period.find([])
>>> assertEqual(period.state, 'closed')
-Try to create a move::
+Create a draft move in closed period::
>>> move = Move()
>>> move.product = product
@@ -82,6 +82,17 @@
>>> move.unit_price = Decimal('42.0000')
>>> move.currency = currency
>>> move.save()
+
+Update draft move in closed period::
+
+ >>> move.quantity = 2
+ >>> move.save()
+
+Try to update a draft move in closed period::
+
+ >>> Move.write(
+ ... [move], {'state': 'assigned'},
+ ... {**config._context, '_check_access': False})
Traceback (most recent call last):
...
AccessError: ...
@@ -94,7 +105,6 @@
Close the period with draft move::
- >>> move.save()
>>> period.click('close')
>>> period.state
'closed'
diff -r 41ca943f0f6b -r 9cf089215d53 modules/stock/tests/test_module.py
--- a/modules/stock/tests/test_module.py Sun Oct 04 16:48:54 2026 +0200
+++ b/modules/stock/tests/test_module.py Mon Oct 05 12:54:17 2026 +0200
@@ -8,7 +8,6 @@
from dateutil.relativedelta import relativedelta
-from trytond.model.exceptions import AccessError
from trytond.modules.company.tests import (
CompanyTestMixin, PartyCompanyCheckEraseMixin, create_company, set_company)
from trytond.modules.party.tests import PartyCheckReplaceMixin
@@ -974,31 +973,6 @@
}])
Move.do(moves)
- self.assertRaises(AccessError, Move.create, [{
- 'product': product.id,
- 'unit': unit.id,
- 'quantity': 10,
- 'from_location': supplier.id,
- 'to_location': storage.id,
- 'planned_date': today + relativedelta(days=-5),
- 'effective_date': today + relativedelta(days=-5),
- 'company': company.id,
- 'unit_price': Decimal('1'),
- 'currency': currency.id,
- }])
- self.assertRaises(AccessError, Move.create, [{
- 'product': product.id,
- 'unit': unit.id,
- 'quantity': 10,
- 'from_location': supplier.id,
- 'to_location': storage.id,
- 'planned_date': today + relativedelta(days=-3),
- 'effective_date': today + relativedelta(days=-3),
- 'company': company.id,
- 'unit_price': Decimal('1'),
- 'currency': currency.id,
- }])
-
# Test close period check
period, = Period.create([{
'date': today,