details: https://code.tryton.org/tryton/commit/9539955e9deb
branch: default
user: Cédric Krier <[email protected]>
date: Wed Aug 19 00:14:21 2026 +0200
description:
Add scheduled task to create stock period automatically
diffstat:
modules/stock/CHANGELOG | 1 +
modules/stock/configuration.py | 25 +++++++++++++++++++++-
modules/stock/doc/usage/period.inc.rst | 7 ++++++
modules/stock/ir.py | 2 +
modules/stock/period.py | 30 +++++++++++++++++++++++++++
modules/stock/period.xml | 7 ++++++
modules/stock/tests/scenario_stock_period.rst | 23 ++++++++++++++++----
modules/stock/tryton.cfg | 1 +
modules/stock/view/configuration_form.xml | 3 ++
9 files changed, 93 insertions(+), 6 deletions(-)
diffs (217 lines):
diff -r 532babdb004e -r 9539955e9deb modules/stock/CHANGELOG
--- a/modules/stock/CHANGELOG Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/CHANGELOG Wed Aug 19 00:14:21 2026 +0200
@@ -1,3 +1,4 @@
+* Add scheduled task to create period automatically
Version 8.0.0 - 2026-04-20
--------------------------
diff -r 532babdb004e -r 9539955e9deb modules/stock/configuration.py
--- a/modules/stock/configuration.py Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/configuration.py Wed Aug 19 00:14:21 2026 +0200
@@ -5,7 +5,7 @@
from trytond.modules.company.model import (
CompanyMultiValueMixin, CompanyValueMixin)
from trytond.pool import Pool
-from trytond.pyson import Eval, Id
+from trytond.pyson import Eval, Id, TimeDelta
sequences = ['shipment_in_sequence', 'shipment_in_return_sequence',
'shipment_out_sequence', 'shipment_out_return_sequence',
@@ -104,6 +104,16 @@
help="Used to generate the number given to inventories."))
shipment_internal_transit = fields.MultiValue(shipment_internal_transit)
+ period_creation_interval = fields.MultiValue(
+ fields.TimeDelta(
+ "Period Creation Interval",
+ domain=['OR',
+ ('period_creation_interval', '=', None),
+ ('period_creation_interval', '>=', TimeDelta(days=1)),
+ ],
+ help="Leave it empty to prevent periods "
+ "from being created automatically."))
+
@classmethod
def multivalue_model(cls, field):
pool = Pool()
@@ -111,6 +121,8 @@
return pool.get('stock.configuration.sequence')
if field == 'shipment_internal_transit':
return pool.get('stock.configuration.location')
+ if field == 'period_creation_interval':
+ return pool.get('stock.configuration.period')
return super().multivalue_model(field)
default_shipment_in_sequence = default_func('shipment_in_sequence')
@@ -194,3 +206,14 @@
return ModelData.get_id('stock', 'location_transit')
except KeyError:
return None
+
+
+class Period(ModelSQL, CompanyValueMixin):
+ __name__ = 'stock.configuration.period'
+
+ period_creation_interval = fields.TimeDelta(
+ "Period Creation Interval",
+ domain=['OR',
+ ('period_creation_interval', '=', None),
+ ('period_creation_interval', '>=', TimeDelta(days=1)),
+ ])
diff -r 532babdb004e -r 9539955e9deb modules/stock/doc/usage/period.inc.rst
--- a/modules/stock/doc/usage/period.inc.rst Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/doc/usage/period.inc.rst Wed Aug 19 00:14:21 2026 +0200
@@ -14,3 +14,10 @@
`Company <company:model-company.company>` generates you may find it useful
to create new stock periods as part of your accounting period end, or
fiscal year end, processes.
+
+.. tip::
+
+ You can set a :guilabel:`Period Creation Interval` on the `stock
+ configuration <model-stock.configuration>` and add the `company
+ <company:model-company.company>` to the `scheduled task
+ <trytond:model-ir.cron>` to create periods automatically.
diff -r 532babdb004e -r 9539955e9deb modules/stock/ir.py
--- a/modules/stock/ir.py Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/ir.py Wed Aug 19 00:14:21 2026 +0200
@@ -26,10 +26,12 @@
('stock.shipment.internal|reschedule',
"Reschedule Internal Shipments"),
('ir.cron|stock_shipment_assign_try', "Assign Shipments"),
+ ('stock.period|auto_create', "Create Stock Periods"),
])
cls.methods_company_needed.update({
'product.product|recompute_cost_price_from_moves',
'ir.cron|stock_shipment_assign_try',
+ 'stock.period|auto_create',
})
@classmethod
diff -r 532babdb004e -r 9539955e9deb modules/stock/period.py
--- a/modules/stock/period.py Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/period.py Wed Aug 19 00:14:21 2026 +0200
@@ -172,6 +172,36 @@
if to_create:
Cache.create(to_create)
+ @classmethod
+ def auto_create(cls):
+ pool = Pool()
+ Date = pool.get('ir.date')
+ Configuration = pool.get('stock.configuration')
+
+ company = Transaction().context.get('company')
+ if company is None:
+ return
+ config = Configuration(1)
+ interval = config.get_multivalue(
+ 'period_creation_interval', company=company)
+ if interval is None:
+ return
+ today = Date.today()
+ last_period = cls.search([
+ ('company', '=', company),
+ ],
+ limit=1, order=[('date', 'DESC')])
+ if last_period:
+ next_date = last_period.date + interval
+ else:
+ next_date = today - interval
+ if next_date >= today:
+ return
+ return cls.create([{
+ 'date': next_date,
+ 'company': company,
+ }])[0]
+
class Cache(ModelSQL, ModelView):
"It is used to store cached computation of stock quantities"
diff -r 532babdb004e -r 9539955e9deb modules/stock/period.xml
--- a/modules/stock/period.xml Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/period.xml Wed Aug 19 00:14:21 2026 +0200
@@ -117,4 +117,11 @@
<field name="perm_delete" eval="True"/>
</record>
</data>
+ <data noupdate="1">
+ <record model="ir.cron" id="cron_create_period">
+ <field name="method">stock.period|auto_create</field>
+ <field name="interval_number" eval="1"/>
+ <field name="interval_type">days</field>
+ </record>
+ </data>
</tryton>
diff -r 532babdb004e -r 9539955e9deb
modules/stock/tests/scenario_stock_period.rst
--- a/modules/stock/tests/scenario_stock_period.rst Mon Jul 13 17:36:10
2026 +0200
+++ b/modules/stock/tests/scenario_stock_period.rst Wed Aug 19 00:14:21
2026 +0200
@@ -8,9 +8,9 @@
>>> from decimal import Decimal
>>> from proteus import Model
- >>> from trytond.modules.company.tests.tools import create_company
+ >>> from trytond.modules.company.tests.tools import create_company,
get_company
>>> from trytond.modules.currency.tests.tools import get_currency
- >>> from trytond.tests.tools import activate_modules
+ >>> from trytond.tests.tools import activate_modules, assertEqual
>>> today = dt.date.today()
>>> yesterday = today - dt.timedelta(days=1)
@@ -19,6 +19,8 @@
>>> config = activate_modules('stock', create_company)
+ >>> Configuration = Model.get('stock.configuration')
+ >>> Cron = Model.get('ir.cron')
>>> Location = Model.get('stock.location')
>>> Move = Model.get('stock.move')
>>> Period = Model.get('stock.period')
@@ -43,10 +45,21 @@
>>> storage_loc, = Location.find([('code', '=', 'STO')])
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
-Create a period::
+Setup period configuration::
+
+ >>> configuration = Configuration(1)
+ >>> configuration.period_creation_interval = dt.timedelta(days=1)
+ >>> configuration.save()
+
+Create periods::
- >>> period = Period(date=yesterday)
- >>> period.save()
+ >>> cron, = Cron.find([('method', '=', 'stock.period|auto_create')],
limit=1)
+ >>> cron.companies.append(get_company())
+ >>> cron.click('run_once')
+
+ >>> period, = Period.find([])
+ >>> assertEqual(period.date, yesterday)
+ >>> assertEqual(period.state, 'draft')
Close the period::
diff -r 532babdb004e -r 9539955e9deb modules/stock/tryton.cfg
--- a/modules/stock/tryton.cfg Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/tryton.cfg Wed Aug 19 00:14:21 2026 +0200
@@ -43,6 +43,7 @@
configuration.Configuration
configuration.ConfigurationSequence
configuration.ConfigurationLocation
+ configuration.Period
location.Location
location.WarehouseWasteLocation
location.ProductsByLocationsContext
diff -r 532babdb004e -r 9539955e9deb modules/stock/view/configuration_form.xml
--- a/modules/stock/view/configuration_form.xml Mon Jul 13 17:36:10 2026 +0200
+++ b/modules/stock/view/configuration_form.xml Wed Aug 19 00:14:21 2026 +0200
@@ -18,4 +18,7 @@
<separator id="inventory" colspan="4" string="Inventory"/>
<label name="inventory_sequence" string="Sequence"/>
<field name="inventory_sequence"/>
+ <separator id="period" colspan="4" string="Period"/>
+ <label name="period_creation_interval"/>
+ <field name="period_creation_interval"/>
</form>