Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
periods
: Stored periods¶
The lino.modlib.periods
plugin adds the notions of “stored” years and
periods, often called fiscal year and accounting period. But
these designations can be customized e.g. into “academic years”, “semesters”,
“trimesters”, or “quarters”.
Table of contents:
Examples in this document use the lino_book.projects.cosi1
demo project.
>>> from lino import startup
>>> startup('lino_book.projects.cosi1.settings')
>>> from lino.api.doctest import *
>>> ses = rt.login("robin")
>>> translation.activate('en')
Overview¶
- accounting period¶
The smallest time slice to be observed in accounting reports. It usually corresponds to one month, but you can choose to report per quarter, per trimester or per semester. See Accounting periods below.
- fiscal year¶
Usually a calendar year, but there can be situations where a company reports a shorter fiscal year. See Fiscal years below.
The plugin defines two models: StoredYear
and StoredPeriod
.
Fiscal years¶
Lino has a table of fiscal years. A fiscal year often corresponds to the calendar year, but not necessarily.
If lino_xl.lib.sheets
is installed, the detail window of a fiscal
year object shows the financial reports (balance sheet and income statement)
for this year.
The std
fixture of the lino.modlib.periods
plugins fills
StoredYear
with 5 years starting from periods.start_year
.
>>> settings.SITE.the_demo_date
datetime.date(2015, 3, 12)
>>> dd.plugins.periods.start_year
2014
>>> dd.today()
datetime.date(2015, 3, 12)
>>> dd.today().year + 5
2020
>>> rt.show(periods.StoredYears)
...
=========== ============ ============ =======
Reference Start date End date State
----------- ------------ ------------ -------
2014 01/01/2014 31/12/2014 Open
2015 01/01/2015 31/12/2015 Open
2016 01/01/2016 31/12/2016 Open
2017 01/01/2017 31/12/2017 Open
2018 01/01/2018 31/12/2018 Open
2019 01/01/2019 31/12/2019 Open
2020 01/01/2020 31/12/2020 Open
=========== ============ ============ =======
Accounting periods¶
For each period it is possible to specify the dates during which it is allowed to register vouchers into this period, and also its “state”: whether it is “closed” or not.
Each ledger movement happens in a given accounting period. An accounting period usually corresponds to a month of the calendar.
Accounting periods are automatically created the first time they are needed by some operation.
>>> rt.show(periods.StoredPeriods)
...
=========== ============ ============ ============= ======= ========
Reference Start date End date Fiscal year State Remark
----------- ------------ ------------ ------------- ------- --------
2014-01 01/01/2014 31/01/2014 2014 Open
2014-02 01/02/2014 28/02/2014 2014 Open
2014-03 01/03/2014 31/03/2014 2014 Open
2014-04 01/04/2014 30/04/2014 2014 Open
2014-05 01/05/2014 31/05/2014 2014 Open
2014-06 01/06/2014 30/06/2014 2014 Open
2014-07 01/07/2014 31/07/2014 2014 Open
2014-08 01/08/2014 31/08/2014 2014 Open
2014-09 01/09/2014 30/09/2014 2014 Open
2014-10 01/10/2014 31/10/2014 2014 Open
2014-11 01/11/2014 30/11/2014 2014 Open
2014-12 01/12/2014 31/12/2014 2014 Open
2015-01 01/01/2015 31/01/2015 2015 Open
2015-02 01/02/2015 28/02/2015 2015 Open
2015-03 01/03/2015 31/03/2015 2015 Open
2015-12 01/12/2015 31/12/2015 2015 Open
=========== ============ ============ ============= ======= ========
The reference of a new accounting period is computed by applying the
voucher’s entry date to the template defined in the date_to_period_tpl
attribute of the accounting
plugin. The default implementation leads to the following references:
>>> from lino.modlib.periods.models import date2ref
>>> date2ref(i2d(19940202))
'1994-02'
>>> date2ref(i2d(20150228))
'2015-02'
>>> date2ref(i2d(20150401))
'2015-04'
Special accounting periods¶
You may manually create additional accounting periods. For example
2015-00 might stand for a fictive “opening” period before January 2015 and after December 2014.
2015-13 might stand for January 2016 in a company that is changing their fiscal year from “January-December” to “July-June”.
in certain public administrations “January 2024” can be considered as the “Thirteenth month of 2023” for operations that are bound to the fiscal year 2023. We call this overlapping periods.
Filtering the list of stored periods¶
The parameter panel of the StoredPeriods
table has two fields,
start_date
and end_date
.
>>> ses = rt.login("robin")
>>> pv = dict(start_date=i2d(20140212))
>>> ses.show(periods.StoredPeriods, param_values=pv)
...
=========== ============ ============ ============= ======= ========
Reference Start date End date Fiscal year State Remark
----------- ------------ ------------ ------------- ------- --------
2014-02 01/02/2014 28/02/2014 2014 Open
=========== ============ ============ ============= ======= ========
>>> pv = dict(start_date=i2d(20140212), end_date=i2d(20140312))
>>> ses.show(periods.StoredPeriods, param_values=pv)
...
=========== ============ ============ ============= ======= ========
Reference Start date End date Fiscal year State Remark
----------- ------------ ------------ ------------- ------- --------
2014-02 01/02/2014 28/02/2014 2014 Open
2014-03 01/03/2014 31/03/2014 2014 Open
=========== ============ ============ ============= ======= ========
>>> dd.today()
datetime.date(2015, 3, 12)
>>> pv = dict(start_date=i2d(20141118), end_date=i2d(20160312))
>>> ses.show(periods.StoredPeriods, param_values=pv, display_mode="summary")
...
`2014-11 <…>`__, `2014-12 <…>`__, `2015-01 <…>`__, `2015-02 <…>`__, `2015-03 <…>`__, `2015-12 <…>`__
Test examples¶
>>> TEST_DATES = list(map(i2d, [
... 19850203, 19990901, 20000101, 20150427, 20240324,
... 20590601, 29970123]))
>>> Y, P = periods.StoredYear, periods.StoredPeriod
>>> from lino.modlib.periods.mixins import get_range_for_date
>>> def run_test():
... headers = ["Date", "year", "period", "ref", "start date", "end date"]
... rows = []
... for d in TEST_DATES:
... sd, ed = get_range_for_date(d)
... rows.append([str(d), Y.get_ref_for_date(d), P.get_ref_for_date(d),
... date2ref(d), str(sd), str(ed)])
... print(table(headers, rows))
>>> run_test()
============ ====== ======== ========= ============ ============
Date year period ref start date end date
------------ ------ -------- --------- ------------ ------------
1985-02-03 1985 02 1985-02 1985-02-01 1985-02-28
1999-09-01 1999 09 1999-09 1999-09-01 1999-09-30
2000-01-01 2000 01 2000-01 2000-01-01 2000-01-31
2015-04-27 2015 04 2015-04 2015-04-01 2015-04-30
2024-03-24 2024 03 2024-03 2024-03-01 2024-03-31
2059-06-01 2059 06 2059-06 2059-06-01 2059-06-30
2997-01-23 2997 01 2997-01 2997-01-01 2997-01-31
============ ====== ======== ========= ============ ============
Period types¶
Some organizations subdivide their years in periods other than months. You can
customize this by setting periods.period_type
, which contains one of
the choices defined in PeriodTypes
.
>>> rt.show(periods.PeriodTypes)
=========== =========== ========== ========================
value text Duration Template for reference
----------- ----------- ---------- ------------------------
month Month 1 {month:0>2}
quarter Quarter 3 Q{period}
trimester Trimester 4 T{period}
semester Semester 6 S{period}
=========== =========== ========== ========================
>>> dd.plugins.periods.period_type = periods.PeriodTypes.quarter
>>> run_test()
============ ====== ======== ========= ============ ============
Date year period ref start date end date
------------ ------ -------- --------- ------------ ------------
1985-02-03 1985 Q1 1985-Q1 1985-01-01 1985-03-31
1999-09-01 1999 Q3 1999-Q3 1999-07-01 1999-09-30
2000-01-01 2000 Q1 2000-Q1 2000-01-01 2000-03-31
2015-04-27 2015 Q2 2015-Q2 2015-04-01 2015-06-30
2024-03-24 2024 Q1 2024-Q1 2024-01-01 2024-03-31
2059-06-01 2059 Q2 2059-Q2 2059-04-01 2059-06-30
2997-01-23 2997 Q1 2997-Q1 2997-01-01 2997-03-31
============ ====== ======== ========= ============ ============
>>> dd.plugins.periods.period_type = periods.PeriodTypes.trimester
>>> run_test()
============ ====== ======== ========= ============ ============
Date year period ref start date end date
------------ ------ -------- --------- ------------ ------------
1985-02-03 1985 T1 1985-T1 1985-01-01 1985-04-30
1999-09-01 1999 T3 1999-T3 1999-09-01 1999-12-31
2000-01-01 2000 T1 2000-T1 2000-01-01 2000-04-30
2015-04-27 2015 T1 2015-T1 2015-01-01 2015-04-30
2024-03-24 2024 T1 2024-T1 2024-01-01 2024-04-30
2059-06-01 2059 T2 2059-T2 2059-05-01 2059-08-31
2997-01-23 2997 T1 2997-T1 2997-01-01 2997-04-30
============ ====== ======== ========= ============ ============
>>> dd.plugins.periods.period_type = periods.PeriodTypes.month # restore default
Short references¶
Lino usually represents a fiscal year using 4 digits. You can set
periods.short_ref
to use a two-letter code.
>>> dd.plugins.periods.short_ref = True
>>> run_test()
============ ====== ======== ======= ============ ============
Date year period ref start date end date
------------ ------ -------- ------- ------------ ------------
1985-02-03 85 02 85-02 1985-02-01 1985-02-28
1999-09-01 99 09 99-09 1999-09-01 1999-09-30
2000-01-01 00 01 00-01 2000-01-01 2000-01-31
2015-04-27 15 04 15-04 2015-04-01 2015-04-30
2024-03-24 24 03 24-03 2024-03-01 2024-03-31
2059-06-01 59 06 59-06 2059-06-01 2059-06-30
2997-01-23 97 01 97-01 2997-01-01 2997-01-31
============ ====== ======== ======= ============ ============
>>> dd.plugins.periods.short_ref = False # restore default
The Y2K problem¶
There are legacy systems where the year was internally
represented using a two-letter code. That’s why we have a setting periods.fix_y2k
, which
is either True or False. Default is False. If you want to represent years
using only two digits and remain y2k-proof, set periods.fix_y2k
to
True and Lino will give different reference names:
>>> dd.plugins.periods.fix_y2k = True
>>> run_test()
============ ====== ======== ======= ============ ============
Date year period ref start date end date
------------ ------ -------- ------- ------------ ------------
1985-02-03 85 02 85-02 1985-02-01 1985-02-28
1999-09-01 99 09 99-09 1999-09-01 1999-09-30
2000-01-01 A0 01 A0-01 2000-01-01 2000-01-31
2015-04-27 B5 04 B5-04 2015-04-01 2015-04-30
2024-03-24 C4 03 C4-03 2024-03-01 2024-03-31
2059-06-01 F9 06 F9-06 2059-06-01 2059-06-30
2997-01-23 ¤7 01 ¤7-01 2997-01-01 2997-01-31
============ ====== ======== ======= ============ ============
This system works only for the next two hundred years, more precisely until 2259. After this the short references will look silly:
>>> print(date2ref(i2d(22591231)))
Z9-12
>>> print(date2ref(i2d(22600101)))
[0-01
>>> dd.plugins.periods.fix_y2k = False # Restore default value
Shifted years¶
When your fiscal or academic year starts in another month than January, you set
periods.start_month
to the number of the first month of your fiscal
year.
On a site with shifted year, Lino represents the stored year as “YEAR/YEAR+1”
>>> dd.plugins.periods.start_month = 9
>>> run_test()
============ ========= ======== ============ ============ ============
Date year period ref start date end date
------------ --------- -------- ------------ ------------ ------------
1985-02-03 1984/85 02 1984/85-02 1985-02-01 1985-02-28
1999-09-01 1999/00 09 1999/00-09 1999-09-01 1999-09-30
2000-01-01 1999/00 01 1999/00-01 2000-01-01 2000-01-31
2015-04-27 2014/15 04 2014/15-04 2015-04-01 2015-04-30
2024-03-24 2023/24 03 2023/24-03 2024-03-01 2024-03-31
2059-06-01 2058/59 06 2058/59-06 2059-06-01 2059-06-30
2997-01-23 2996/97 01 2996/97-01 2997-01-01 2997-01-31
============ ========= ======== ============ ============ ============
>>> dd.plugins.periods.start_month = 1 # Restore default value
School years¶
A school year in Belgium starts in September and has two periods called “semesters”:
>>> dd.plugins.periods.year_name = "Year"
>>> dd.plugins.periods.period_name = "Period"
>>> dd.plugins.periods.short_ref = True
>>> dd.plugins.periods.start_month = 9
>>> dd.plugins.periods.period_type = periods.PeriodTypes.semester
>>> run_test()
============ ======= ======== ========== ============ ============
Date year period ref start date end date
------------ ------- -------- ---------- ------------ ------------
1985-02-03 84/85 S1 84/85-S1 1984-09-01 1985-02-28
1999-09-01 99/00 S1 99/00-S1 1999-09-01 2000-02-29
2000-01-01 99/00 S1 99/00-S1 1999-09-01 2000-02-29
2015-04-27 14/15 S2 14/15-S2 2015-03-01 2015-08-31
2024-03-24 23/24 S2 23/24-S2 2024-03-01 2024-08-31
2059-06-01 58/59 S2 58/59-S2 2059-03-01 2059-08-31
2997-01-23 96/97 S1 96/97-S1 2996-09-01 2997-02-28
============ ======= ======== ========== ============ ============
You can customize the format used to represent a period
>>> dd.plugins.periods.period_type.ref_template
'S{period}'
>>> dd.plugins.periods.period_type.ref_template = 'P{period}'
>>> run_test()
============ ======= ======== ========== ============ ============
Date year period ref start date end date
------------ ------- -------- ---------- ------------ ------------
1985-02-03 84/85 P1 84/85-P1 1984-09-01 1985-02-28
1999-09-01 99/00 P1 99/00-P1 1999-09-01 2000-02-29
2000-01-01 99/00 P1 99/00-P1 1999-09-01 2000-02-29
2015-04-27 14/15 P2 14/15-P2 2015-03-01 2015-08-31
2024-03-24 23/24 P2 23/24-P2 2024-03-01 2024-08-31
2059-06-01 58/59 P2 58/59-P2 2059-03-01 2059-08-31
2997-01-23 96/97 P1 96/97-P1 2996-09-01 2997-02-28
============ ======= ======== ========== ============ ============
>>> dd.plugins.periods.start_month = 1 # Restore default value
>>> dd.plugins.periods.short_ref = False
>>> dd.plugins.periods.period_type.ref_template = 'S{period}'
Plugin configuration settings¶
Here is a list of the plugin settings for this plugin.
- periods.period_name¶
- periods.period_name_plural¶
- periods.year_name¶
- periods.year_name_plural¶
The end-user designation of a “stored period” and a “stored year”, respectively.
- periods.start_year¶
An integer with the calendar year in which this site starts working.
This is used by the
std
fixture to fill the default list ofStoredYears
, and by certaindemo
fixtures for generating demo invoices.
- periods.fix_y2k¶
Whether to use a Y2K compatible representation for fiscal years. See The Y2K problem
- periods.start_month¶
The number of the first month of your fiscal year. Allowed values are 1 to 12. Default value is 1 (January). See Shifted years.
- periods.period_type¶
A string that specifies into what kinds of periods to subdivide a years. Default value is ‘month’. See Period types.
Class reference¶
- class lino.modlib.periods.StoredYear¶
The Django model used to store a fiscal year.
- class lino.modlib.periods.StoredPeriod¶
The Django model used to store an accounting period.
- start_date¶
- end_date¶
- state¶
- year¶
- ref¶
- class lino.modlib.periods.StoredYears¶
The fiscal years defined in this database.
- class lino.modlib.periods.StoredPeriods¶
The accounting periods defined in this database.
- class lino.modlib.periods.PeriodTypes¶
A list of choices for the values allowed as
periods.period_type
.
- class lino.modlib.periods.PeriodRange¶
Model mixin for objects that cover a range of accounting periods.
- start_period¶
The first period of the range to cover.
- end_period¶
The last period of the range to cover.
Leave empty if you want only one period (specified in
start_period
). If this is non-empty, all periods between and including these two are covered.
- get_period_filter(self, voucher_prefix, **kwargs)¶
- class lino.modlib.periods.PeriodRangeObservable¶
Model mixin for objects that can be filtered by a range of accounting periods. This adds two parameter fields
start_period
andend_period
to every table on this model.Class attribute:
- observable_period_field = 'accounting_period'
The name of the database field on the observed model to use for filtering.