Add definitive lock of period and fiscal year
issue6339 review28201002
This commit is contained in:
1 parent
c3e41c2147
commit
b1e320e204
15 files changed
+224
-243
No files matched your search
@@ -1,3 +1,5 @@
|
||||
* Add definitive lock of period and fiscal year
|
||||
|
||||
Version 4.2.0 - 2016-11-28
|
||||
* Bug fixes (see mercurial logs for details)
|
||||
* Add test wizard for taxes
|
||||
|
||||
@@ -18,7 +18,6 @@ def register():
|
||||
FiscalYear,
|
||||
FiscalYearLine,
|
||||
BalanceNonDeferralStart,
|
||||
CloseFiscalYearStart,
|
||||
TypeTemplate,
|
||||
Type,
|
||||
AccountTemplate,
|
||||
@@ -83,14 +82,9 @@ def register():
|
||||
Pool.register(
|
||||
OpenType,
|
||||
BalanceNonDeferral,
|
||||
CloseFiscalYear,
|
||||
OpenChartAccount,
|
||||
CreateChart,
|
||||
UpdateChart,
|
||||
ClosePeriod,
|
||||
ReOpenPeriod,
|
||||
CloseJournalPeriod,
|
||||
ReOpenJournalPeriod,
|
||||
OpenJournal,
|
||||
OpenAccount,
|
||||
ReconcileLines,
|
||||
|
||||
+5
-4
@@ -8,15 +8,16 @@ Fiscal Year
|
||||
***********
|
||||
|
||||
A fiscal year aggregates a set of periods that are included between
|
||||
two dates. A Fiscal year can be *Open* or *Closed*. Closing a fiscal
|
||||
year will close all the corresponding periods.
|
||||
two dates. A Fiscal year can be *Open*, *Closed* or *Locked*. Closing a fiscal
|
||||
year will close all the corresponding periods. A *Locked* fiscal can not be
|
||||
re-open.
|
||||
|
||||
- Name: The name of the fiscal year.
|
||||
- Code: The code, useful for fast data entry and searching.
|
||||
- Starting and Ending Date: The dates in which the periods should be
|
||||
included.
|
||||
- Company: The company for which the fiscal year is defined.
|
||||
- State: Can be *Open* or *Closed*.
|
||||
- State: Can be *Open*, *Closed* or *Locked*.
|
||||
- Periods: The list of periods.
|
||||
- Post Move Sequence: The sequence to use for numbering moves in this
|
||||
fiscal year.
|
||||
@@ -30,7 +31,7 @@ Period
|
||||
******
|
||||
|
||||
A period is mainly defined by a Starting and an Ending date, a Fiscal
|
||||
Year, a Type and a State (*Open* or *Closed* ).
|
||||
Year, a Type and a State (*Open*, *Closed* or *Locked*).
|
||||
|
||||
The type can be *Standard* or *Adjustement*: Periods of type
|
||||
*Standard* on the same fiscal year can not overlap. Period of type
|
||||
|
||||
+44
-43
@@ -1,25 +1,23 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.wizard import Wizard, StateView, StateTransition, StateAction, \
|
||||
Button
|
||||
from trytond.model import ModelView, ModelSQL, Workflow, fields
|
||||
from trytond.wizard import Wizard, StateView, StateAction, Button
|
||||
from trytond.tools import datetime_strftime
|
||||
from trytond.pyson import Eval, If, PYSONEncoder
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
__all__ = ['FiscalYear', 'FiscalYearLine',
|
||||
'BalanceNonDeferralStart', 'BalanceNonDeferral',
|
||||
'CloseFiscalYearStart', 'CloseFiscalYear']
|
||||
'BalanceNonDeferralStart', 'BalanceNonDeferral']
|
||||
|
||||
STATES = {
|
||||
'readonly': Eval('state') == 'close',
|
||||
'readonly': Eval('state') != 'open',
|
||||
}
|
||||
DEPENDS = ['state']
|
||||
|
||||
|
||||
class FiscalYear(ModelSQL, ModelView):
|
||||
class FiscalYear(Workflow, ModelSQL, ModelView):
|
||||
'Fiscal Year'
|
||||
__name__ = 'account.fiscalyear'
|
||||
name = fields.Char('Name', size=None, required=True, depends=DEPENDS)
|
||||
@@ -32,9 +30,10 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
periods = fields.One2Many('account.period', 'fiscalyear', 'Periods',
|
||||
states=STATES, depends=DEPENDS)
|
||||
state = fields.Selection([
|
||||
('open', 'Open'),
|
||||
('close', 'Close'),
|
||||
], 'State', readonly=True, required=True)
|
||||
('open', 'Open'),
|
||||
('close', 'Close'),
|
||||
('locked', 'Locked'),
|
||||
], 'State', readonly=True, required=True)
|
||||
post_move_sequence = fields.Many2One('ir.sequence', 'Post Move Sequence',
|
||||
required=True, domain=[('code', '=', 'account.move'),
|
||||
['OR',
|
||||
@@ -53,6 +52,7 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
], select=True)
|
||||
close_lines = fields.Many2Many('account.fiscalyear-account.move.line',
|
||||
'fiscalyear', 'line', 'Close Lines')
|
||||
icon = fields.Function(fields.Char("Icon"), 'get_icon')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
@@ -73,6 +73,11 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
'reopen_error': ('You can not reopen fiscal year "%s" until '
|
||||
'you reopen all later fiscal years.'),
|
||||
})
|
||||
cls._transitions |= set((
|
||||
('open', 'close'),
|
||||
('close', 'locked'),
|
||||
('close', 'open'),
|
||||
))
|
||||
cls._buttons.update({
|
||||
'create_period': {
|
||||
'invisible': ((Eval('state') != 'open')
|
||||
@@ -88,6 +93,9 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
'reopen': {
|
||||
'invisible': Eval('state') != 'close',
|
||||
},
|
||||
'lock': {
|
||||
'invisible': Eval('state') != 'close',
|
||||
},
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
@@ -98,6 +106,13 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
|
||||
def get_icon(self, name):
|
||||
return {
|
||||
'open': 'tryton-open',
|
||||
'close': 'tryton-close',
|
||||
'locked': 'tryton-readonly',
|
||||
}.get(self.state)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, years):
|
||||
super(FiscalYear, cls).validate(years)
|
||||
@@ -258,6 +273,7 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('close')
|
||||
def close(cls, fiscalyears):
|
||||
'''
|
||||
Close a fiscal year
|
||||
@@ -266,6 +282,12 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
Period = pool.get('account.period')
|
||||
Account = pool.get('account.account')
|
||||
Deferral = pool.get('account.account.deferral')
|
||||
transaction = Transaction()
|
||||
database = transaction.database
|
||||
connection = transaction.connection
|
||||
|
||||
# Lock period to be sure no new period will be created in between.
|
||||
database.lock(connection, Period._table)
|
||||
|
||||
deferrals = []
|
||||
for fiscalyear in fiscalyears:
|
||||
@@ -276,11 +298,6 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
]):
|
||||
cls.raise_user_error('close_error', (fiscalyear.rec_name,))
|
||||
|
||||
# First close the fiscalyear to be sure
|
||||
# it will not have new period created between.
|
||||
cls.write([fiscalyear], {
|
||||
'state': 'close',
|
||||
})
|
||||
periods = Period.search([
|
||||
('fiscalyear', '=', fiscalyear.id),
|
||||
])
|
||||
@@ -297,6 +314,7 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('open')
|
||||
def reopen(cls, fiscalyears):
|
||||
'''
|
||||
Re-open a fiscal year
|
||||
@@ -306,7 +324,7 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
for fiscalyear in fiscalyears:
|
||||
if cls.search([
|
||||
('start_date', '>=', fiscalyear.end_date),
|
||||
('state', '=', 'close'),
|
||||
('state', '!=', 'open'),
|
||||
('company', '=', fiscalyear.company.id),
|
||||
]):
|
||||
cls.raise_user_error('reopen_error')
|
||||
@@ -316,9 +334,16 @@ class FiscalYear(ModelSQL, ModelView):
|
||||
])
|
||||
Deferral.delete(deferrals)
|
||||
|
||||
cls.write([fiscalyear], {
|
||||
'state': 'open',
|
||||
})
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('locked')
|
||||
def lock(cls, fiscalyears):
|
||||
pool = Pool()
|
||||
Period = pool.get('account.period')
|
||||
periods = Period.search([
|
||||
('fiscalyear', 'in', [f.id for f in fiscalyears]),
|
||||
])
|
||||
Period.lock(periods)
|
||||
|
||||
|
||||
class FiscalYearLine(ModelSQL):
|
||||
@@ -453,27 +478,3 @@ class BalanceNonDeferral(Wizard):
|
||||
('origin', '=', str(self.start.fiscalyear)),
|
||||
])
|
||||
return action, {}
|
||||
|
||||
|
||||
class CloseFiscalYearStart(ModelView):
|
||||
'Close Fiscal Year'
|
||||
__name__ = 'account.fiscalyear.close.start'
|
||||
close_fiscalyear = fields.Many2One('account.fiscalyear',
|
||||
'Fiscal Year to close', required=True,
|
||||
domain=[('state', '!=', 'close')])
|
||||
|
||||
|
||||
class CloseFiscalYear(Wizard):
|
||||
'Close Fiscal Year'
|
||||
__name__ = 'account.fiscalyear.close'
|
||||
start = StateView('account.fiscalyear.close.start',
|
||||
'account.fiscalyear_close_start_view_form', [
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Close', 'close', 'tryton-ok', default=True),
|
||||
])
|
||||
close = StateTransition()
|
||||
|
||||
def transition_close(self):
|
||||
Fiscalyear = Pool().get('account.fiscalyear')
|
||||
Fiscalyear.close([self.start.close_fiscalyear])
|
||||
return 'end'
|
||||
+22
-13
@@ -15,6 +15,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type">tree</field>
|
||||
<field name="name">fiscalyear_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="fiscalyear_view_list_close">
|
||||
<field name="model">account.fiscalyear</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">fiscalyear_list_close</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_fiscalyear_form">
|
||||
<field name="name">Fiscal Years</field>
|
||||
<field name="res_model">account.fiscalyear</field>
|
||||
@@ -59,6 +65,22 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="rule_group" ref="rule_group_fiscalyear"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_fiscalyear_form_close">
|
||||
<field name="name">Close Fiscal Years</field>
|
||||
<field name="res_model">account.fiscalyear</field>
|
||||
<field name="search_value"
|
||||
eval="[('state', '=', 'open')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_fiscalyear_form_close_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="fiscalyear_view_list_close"/>
|
||||
<field name="act_window" ref="act_fiscalyear_form_close"/>
|
||||
</record>
|
||||
|
||||
<menuitem parent="menu_processing" sequence="40"
|
||||
action="act_fiscalyear_form_close" id="menu_close_fiscalyear"/>
|
||||
|
||||
<record model="ir.ui.view"
|
||||
id="fiscalyear_balance_non_deferral_start_view_form">
|
||||
<field
|
||||
@@ -76,18 +98,5 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<menuitem parent="menu_processing" sequence="10"
|
||||
action="act_balance_non_deferral"
|
||||
id="menu_balance_non_deferral"/>
|
||||
|
||||
<record model="ir.ui.view" id="fiscalyear_close_start_view_form">
|
||||
<field name="model">account.fiscalyear.close.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">fiscalyear_close_start_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="act_close_fiscalyear">
|
||||
<field name="name">Close Fiscal Year</field>
|
||||
<field name="wiz_name">account.fiscalyear.close</field>
|
||||
</record>
|
||||
<menuitem parent="menu_processing" sequence="20"
|
||||
action="act_close_fiscalyear" id="menu_close_fiscalyear"/>
|
||||
</data>
|
||||
</tryton>
|
||||
+28
-45
@@ -5,8 +5,7 @@ from decimal import Decimal
|
||||
from sql import Null
|
||||
from sql.aggregate import Sum
|
||||
|
||||
from trytond.model import ModelView, ModelSQL, fields, Unique
|
||||
from trytond.wizard import Wizard, StateTransition
|
||||
from trytond.model import ModelView, ModelSQL, Workflow, fields, Unique
|
||||
from trytond import backend
|
||||
from trytond.pyson import Eval, Bool
|
||||
from trytond.transaction import Transaction
|
||||
@@ -18,18 +17,13 @@ from trytond.modules.company.model import (
|
||||
|
||||
__all__ = ['JournalType', 'Journal', 'JournalSequence', 'JournalAccount',
|
||||
'JournalCashContext',
|
||||
'JournalPeriod', 'CloseJournalPeriod', 'ReOpenJournalPeriod']
|
||||
'JournalPeriod']
|
||||
|
||||
STATES = {
|
||||
'readonly': Eval('state') == 'close',
|
||||
}
|
||||
DEPENDS = ['state']
|
||||
|
||||
_ICONS = {
|
||||
'open': 'tryton-open',
|
||||
'close': 'tryton-readonly',
|
||||
}
|
||||
|
||||
|
||||
class JournalType(ModelSQL, ModelView):
|
||||
'Journal Type'
|
||||
@@ -312,7 +306,7 @@ class JournalCashContext(ModelView):
|
||||
default_end_date = default_start_date
|
||||
|
||||
|
||||
class JournalPeriod(ModelSQL, ModelView):
|
||||
class JournalPeriod(Workflow, ModelSQL, ModelView):
|
||||
'Journal - Period'
|
||||
__name__ = 'account.journal.period'
|
||||
journal = fields.Many2One('account.journal', 'Journal', required=True,
|
||||
@@ -345,6 +339,18 @@ class JournalPeriod(ModelSQL, ModelView):
|
||||
'journal - period "%(journal_period)s" because period '
|
||||
'"%(period)s" is closed.'),
|
||||
})
|
||||
cls._transitions |= set((
|
||||
('open', 'close'),
|
||||
('close', 'open'),
|
||||
))
|
||||
cls._buttons.update({
|
||||
'close': {
|
||||
'invisible': Eval('state') != 'open',
|
||||
},
|
||||
'reopen': {
|
||||
'invisible': Eval('state') != 'close',
|
||||
},
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
@@ -379,7 +385,10 @@ class JournalPeriod(ModelSQL, ModelView):
|
||||
]
|
||||
|
||||
def get_icon(self, name):
|
||||
return _ICONS.get(self.state, '')
|
||||
return {
|
||||
'open': 'tryton-open',
|
||||
'close': 'tryton-close',
|
||||
}.get(self.state)
|
||||
|
||||
@classmethod
|
||||
def _check(cls, periods):
|
||||
@@ -399,7 +408,7 @@ class JournalPeriod(ModelSQL, ModelView):
|
||||
for vals in vlist:
|
||||
if vals.get('period'):
|
||||
period = Period(vals['period'])
|
||||
if period.state == 'close':
|
||||
if period.state != 'open':
|
||||
cls.raise_user_error('create_journal_period', (
|
||||
period.rec_name,))
|
||||
return super(JournalPeriod, cls).create(vlist)
|
||||
@@ -413,7 +422,7 @@ class JournalPeriod(ModelSQL, ModelView):
|
||||
cls._check(journal_periods)
|
||||
if values.get('state') == 'open':
|
||||
for journal_period in journal_periods:
|
||||
if journal_period.period.state == 'close':
|
||||
if journal_period.period.state != 'open':
|
||||
cls.raise_user_error('open_journal_period', {
|
||||
'journal_period': journal_period.rec_name,
|
||||
'period': journal_period.period.rec_name,
|
||||
@@ -426,43 +435,17 @@ class JournalPeriod(ModelSQL, ModelView):
|
||||
super(JournalPeriod, cls).delete(periods)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('close')
|
||||
def close(cls, periods):
|
||||
'''
|
||||
Close journal - period
|
||||
'''
|
||||
cls.write(periods, {
|
||||
'state': 'close',
|
||||
})
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def open_(cls, periods):
|
||||
@ModelView.button
|
||||
@Workflow.transition('open')
|
||||
def reopen(cls, periods):
|
||||
"Open journal - period"
|
||||
cls.write(periods, {
|
||||
'state': 'open',
|
||||
})
|
||||
|
||||
|
||||
class CloseJournalPeriod(Wizard):
|
||||
'Close Journal - Period'
|
||||
__name__ = 'account.journal.period.close'
|
||||
start_state = 'close'
|
||||
close = StateTransition()
|
||||
|
||||
def transition_close(self):
|
||||
JournalPeriod = Pool().get('account.journal.period')
|
||||
JournalPeriod.close(
|
||||
JournalPeriod.browse(Transaction().context['active_ids']))
|
||||
return 'end'
|
||||
|
||||
|
||||
class ReOpenJournalPeriod(Wizard):
|
||||
'Re-Open Journal - Period'
|
||||
__name__ = 'account.journal.period.reopen'
|
||||
start_state = 'reopen'
|
||||
reopen = StateTransition()
|
||||
|
||||
def transition_reopen(self):
|
||||
JournalPeriod = Pool().get('account.journal.period')
|
||||
JournalPeriod.open_(
|
||||
JournalPeriod.browse(Transaction().context['active_ids']))
|
||||
return 'end'
|
||||
pass
|
||||
+17
-37
@@ -172,6 +172,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type">tree</field>
|
||||
<field name="name">journal_period_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="journal_period_view_list_close">
|
||||
<field name="model">account.journal.period</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">journal_period_list_close</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_journal_period_tree">
|
||||
<field name="name">Journals - Periods</field>
|
||||
<field name="res_model">account.journal.period</field>
|
||||
@@ -186,11 +192,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</record>
|
||||
<menuitem parent="menu_reporting" action="act_journal_period_tree"
|
||||
id="menu_journal_period_tree"/>
|
||||
|
||||
<record model="ir.action.act_window" id="act_journal_period_tree2">
|
||||
<field name="name">Journals - Periods</field>
|
||||
<field name="res_model">account.journal.period</field>
|
||||
<field name="domain"
|
||||
eval="[('state', '!=', 'close'), ('period.fiscalyear.company.id', '=', Eval('context', {}).get('company', -1))]"
|
||||
eval="[('state', '=', 'open'), ('period.fiscalyear.company.id', '=', Eval('context', {}).get('company', -1))]"
|
||||
pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_journal_period_tree2_view1">
|
||||
@@ -201,47 +208,20 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<menuitem parent="menu_entries" action="act_journal_period_tree2"
|
||||
id="menu_journal_period_tree2"/>
|
||||
|
||||
<record model="ir.action.wizard" id="act_journal_period_close">
|
||||
<record model="ir.action.act_window" id="act_journal_period_form_close">
|
||||
<field name="name">Close Journals - Periods</field>
|
||||
<field name="wiz_name">account.journal.period.close</field>
|
||||
<field name="model">account.journal.period</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_journal_period_close_keyword">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">account.journal.period,-1</field>
|
||||
<field name="action" ref="act_journal_period_close"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="act_journal_period_reopen">
|
||||
<field name="name">Re-Open Journals - Periods</field>
|
||||
<field name="wiz_name">account.journal.period.reopen</field>
|
||||
<field name="model">account.journal.period</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_journal_period_reopen_keyword">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">account.journal.period,-1</field>
|
||||
<field name="action" ref="act_journal_period_reopen"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_journal_period_form">
|
||||
<field name="name">Journals - Periods</field>
|
||||
<field name="res_model">account.journal.period</field>
|
||||
<field name="domain"
|
||||
eval="[('period.fiscalyear.company.id', '=', Eval('context', {}).get('company', -1))]"
|
||||
pyson="1"/>
|
||||
<field name="search_value"
|
||||
eval="[('state', '=', 'open')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_journal_period_form_view1">
|
||||
<record model="ir.action.act_window.view" id="act_journal_period_form_close_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="journal_period_view_tree"/>
|
||||
<field name="act_window" ref="act_journal_period_form"/>
|
||||
<field name="view" ref="journal_period_view_list_close"/>
|
||||
<field name="act_window" ref="act_journal_period_form_close"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_journal_period_form_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="journal_period_view_form"/>
|
||||
<field name="act_window" ref="act_journal_period_form"/>
|
||||
</record>
|
||||
<menuitem parent="menu_processing" action="act_journal_period_form"
|
||||
id="menu_journal_period_form" name="Close Journals - Periods"/>
|
||||
|
||||
<menuitem parent="menu_processing" sequence="20"
|
||||
action="act_journal_period_form_close" id="menu_close_journal_period"/>
|
||||
|
||||
<record model="ir.model.access" id="access_journal_period">
|
||||
<field name="model" search="[('model', '=', 'account.journal.period')]"/>
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.wizard import Wizard, StateTransition
|
||||
from trytond.model import ModelView, ModelSQL, Workflow, fields
|
||||
from trytond.pyson import Eval
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.const import OPERATORS
|
||||
from trytond import backend
|
||||
|
||||
__all__ = ['Period', 'ClosePeriod', 'ReOpenPeriod']
|
||||
__all__ = ['Period']
|
||||
|
||||
_STATES = {
|
||||
'readonly': Eval('state') == 'close',
|
||||
'readonly': Eval('state') != 'open',
|
||||
}
|
||||
_DEPENDS = ['state']
|
||||
|
||||
|
||||
class Period(ModelSQL, ModelView):
|
||||
class Period(Workflow, ModelSQL, ModelView):
|
||||
'Period'
|
||||
__name__ = 'account.period'
|
||||
name = fields.Char('Name', required=True)
|
||||
@@ -29,9 +28,10 @@ class Period(ModelSQL, ModelView):
|
||||
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
|
||||
required=True, states=_STATES, depends=_DEPENDS, select=True)
|
||||
state = fields.Selection([
|
||||
('open', 'Open'),
|
||||
('close', 'Close'),
|
||||
], 'State', readonly=True, required=True)
|
||||
('open', 'Open'),
|
||||
('close', 'Close'),
|
||||
('locked', 'Locked'),
|
||||
], 'State', readonly=True, required=True)
|
||||
post_move_sequence = fields.Many2One('ir.sequence', 'Post Move Sequence',
|
||||
domain=[
|
||||
('code', '=', 'account.move'),
|
||||
@@ -48,6 +48,7 @@ class Period(ModelSQL, ModelView):
|
||||
states=_STATES, depends=_DEPENDS, select=True)
|
||||
company = fields.Function(fields.Many2One('company.company', 'Company',),
|
||||
'on_change_with_company', searcher='search_company')
|
||||
icon = fields.Function(fields.Char("Icon"), 'get_icon')
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
@@ -85,6 +86,22 @@ class Period(ModelSQL, ModelView):
|
||||
'fiscalyear_dates': ('Dates of period "%s" are outside '
|
||||
'are outside it\'s fiscal year dates.'),
|
||||
})
|
||||
cls._transitions |= set((
|
||||
('open', 'close'),
|
||||
('close', 'locked'),
|
||||
('close', 'open'),
|
||||
))
|
||||
cls._buttons.update({
|
||||
'close': {
|
||||
'invisible': Eval('state') != 'open',
|
||||
},
|
||||
'reopen': {
|
||||
'invisible': Eval('state') != 'close',
|
||||
},
|
||||
'lock': {
|
||||
'invisible': Eval('state') != 'close',
|
||||
},
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
def default_state():
|
||||
@@ -103,6 +120,13 @@ class Period(ModelSQL, ModelView):
|
||||
def search_company(cls, name, clause):
|
||||
return [('fiscalyear.%s' % name,) + tuple(clause[1:])]
|
||||
|
||||
def get_icon(self, name):
|
||||
return {
|
||||
'open': 'tryton-open',
|
||||
'close': 'tryton-close',
|
||||
'locked': 'tryton-readonly',
|
||||
}.get(self.state)
|
||||
|
||||
@classmethod
|
||||
def validate(cls, periods):
|
||||
super(Period, cls).validate(periods)
|
||||
@@ -177,7 +201,7 @@ class Period(ModelSQL, ModelView):
|
||||
('type', '=', 'standard'),
|
||||
]
|
||||
if test_state:
|
||||
clause.append(('state', '!=', 'close'))
|
||||
clause.append(('state', '=', 'open'))
|
||||
periods = cls.search(clause, order=[('start_date', 'DESC')], limit=1)
|
||||
if not periods:
|
||||
if exception:
|
||||
@@ -237,7 +261,7 @@ class Period(ModelSQL, ModelView):
|
||||
for vals in vlist:
|
||||
if vals.get('fiscalyear'):
|
||||
fiscalyear = FiscalYear(vals['fiscalyear'])
|
||||
if fiscalyear.state == 'close':
|
||||
if fiscalyear.state != 'open':
|
||||
cls.raise_user_error('create_period_closed_fiscalyear',
|
||||
(fiscalyear.rec_name,))
|
||||
if not vals.get('post_move_sequence'):
|
||||
@@ -262,7 +286,7 @@ class Period(ModelSQL, ModelView):
|
||||
break
|
||||
if values.get('state') == 'open':
|
||||
for period in periods:
|
||||
if period.fiscalyear.state == 'close':
|
||||
if period.fiscalyear.state != 'open':
|
||||
cls.raise_user_error('open_period_closed_fiscalyear', {
|
||||
'period': period.rec_name,
|
||||
'fiscalyear': period.fiscalyear.rec_name,
|
||||
@@ -287,10 +311,18 @@ class Period(ModelSQL, ModelView):
|
||||
super(Period, cls).delete(periods)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('close')
|
||||
def close(cls, periods):
|
||||
pool = Pool()
|
||||
JournalPeriod = pool.get('account.journal.period')
|
||||
Move = pool.get('account.move')
|
||||
transaction = Transaction()
|
||||
database = transaction.database
|
||||
connection = transaction.connection
|
||||
|
||||
# Lock period to be sure no new period will be created in between.
|
||||
database.lock(connection, JournalPeriod._table)
|
||||
|
||||
unposted_moves = Move.search([
|
||||
('period', 'in', [p.id for p in periods]),
|
||||
@@ -302,47 +334,24 @@ class Period(ModelSQL, ModelView):
|
||||
'period': unposted_move.period.rec_name,
|
||||
'move': unposted_move.rec_name,
|
||||
})
|
||||
# First close the period to be sure
|
||||
# it will not have new journal.period created between.
|
||||
cls.write(periods, {
|
||||
'state': 'close',
|
||||
})
|
||||
journal_periods = JournalPeriod.search([
|
||||
('period', 'in', [p.id for p in periods]),
|
||||
])
|
||||
JournalPeriod.close(journal_periods)
|
||||
|
||||
@classmethod
|
||||
def open_(cls, periods):
|
||||
"Open Journal"
|
||||
cls.write(periods, {
|
||||
'state': 'open',
|
||||
})
|
||||
@ModelView.button
|
||||
@Workflow.transition('open')
|
||||
def reopen(cls, periods):
|
||||
"Re-open period"
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('locked')
|
||||
def lock(cls, periods):
|
||||
pass
|
||||
|
||||
@property
|
||||
def post_move_sequence_used(self):
|
||||
return self.post_move_sequence or self.fiscalyear.post_move_sequence
|
||||
|
||||
|
||||
class ClosePeriod(Wizard):
|
||||
'Close Period'
|
||||
__name__ = 'account.period.close'
|
||||
start_state = 'close'
|
||||
close = StateTransition()
|
||||
|
||||
def transition_close(self):
|
||||
Period = Pool().get('account.period')
|
||||
Period.close(Period.browse(Transaction().context['active_ids']))
|
||||
return 'end'
|
||||
|
||||
|
||||
class ReOpenPeriod(Wizard):
|
||||
'Re-Open Period'
|
||||
__name__ = 'account.period.reopen'
|
||||
start_state = 'reopen'
|
||||
reopen = StateTransition()
|
||||
|
||||
def transition_reopen(self):
|
||||
Period = Pool().get('account.period')
|
||||
Period.open_(Period.browse(Transaction().context['active_ids']))
|
||||
return 'end'
|
||||
+16
-34
@@ -13,6 +13,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type">tree</field>
|
||||
<field name="name">period_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="period_view_list_close">
|
||||
<field name="model">account.period</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">period_list_close</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_period_form">
|
||||
<field name="name">Periods</field>
|
||||
<field name="res_model">account.period</field>
|
||||
@@ -50,45 +56,21 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="act_period_close">
|
||||
<record model="ir.action.act_window" id="act_period_form_close">
|
||||
<field name="name">Close Periods</field>
|
||||
<field name="wiz_name">account.period.close</field>
|
||||
<field name="model">account.period</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_period_close_keyword">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">account.period,-1</field>
|
||||
<field name="action" ref="act_period_close"/>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="act_period_reopen">
|
||||
<field name="name">Re-Open Periods</field>
|
||||
<field name="wiz_name">account.period.reopen</field>
|
||||
<field name="model">account.period</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_period_reopen_keyword">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">account.period,-1</field>
|
||||
<field name="action" ref="act_period_reopen"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window" id="act_period_form2">
|
||||
<field name="name">Periods</field>
|
||||
<field name="res_model">account.period</field>
|
||||
<field name="domain"
|
||||
eval="[('state', 'in', ['open']), ('fiscalyear.company.id', '=', Eval('context', {}).get('company', -1))]"
|
||||
pyson="1"/>
|
||||
<field name="search_value"
|
||||
eval="[('state', '=', 'open')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_period_form2_view1">
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_period_form_close_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="period_view_tree"/>
|
||||
<field name="act_window" ref="act_period_form2"/>
|
||||
<field name="view" ref="period_view_list_close"/>
|
||||
<field name="act_window" ref="act_period_form_close"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_period_form2_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="period_view_form"/>
|
||||
<field name="act_window" ref="act_period_form2"/>
|
||||
</record>
|
||||
<menuitem parent="menu_processing" action="act_period_form2"
|
||||
id="menu_period_form2" name="Close Periods"/>
|
||||
|
||||
<menuitem parent="menu_processing" sequence="30"
|
||||
action="act_period_form_close" id="menu_close_period"/>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_period">
|
||||
<field name="model" search="[('model', '=', 'account.period')]"/>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<form>
|
||||
<label name="close_fiscalyear"/>
|
||||
<field name="close_fiscalyear"/>
|
||||
</form>
|
||||
@@ -27,12 +27,4 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="post_move_sequence"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<label string="" colspan="2" id="empty"/>
|
||||
<group col="-1" colspan="2" id="buttons">
|
||||
<button name="close" string="Close Fiscal Year"
|
||||
icon="tryton-readonly"
|
||||
confirm="Are you sure to close fiscal year?"/>
|
||||
<button name="reopen" string="Re-Open Fiscal Year"
|
||||
icon="tryton-clear"/>
|
||||
</group>
|
||||
</form>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree>
|
||||
<field name="name" icon="icon"/>
|
||||
<field name="company"/>
|
||||
<button name="reopen" string="Re-Open"/>
|
||||
<button name="close" string="Close"/>
|
||||
<button name="lock" string="Lock"
|
||||
confirm="Are you sure to lock the fiscal year?"/>
|
||||
<field name="state" tree_invisible="1"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree>
|
||||
<field name="journal" icon="icon"/>
|
||||
<field name="period"/>
|
||||
<button name="reopen" string="Re-Open"/>
|
||||
<button name="close" string="Close"/>
|
||||
<field name="state" tree_invisible="1"/>
|
||||
</tree>
|
||||
@@ -2,7 +2,6 @@
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree keyword_open="1">
|
||||
<field name="rec_name" icon="icon"/>
|
||||
<field name="journal"/>
|
||||
<field name="period"/>
|
||||
<field name="state"/>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree>
|
||||
<field name="name" icon="icon"/>
|
||||
<field name="company"/>
|
||||
<field name="fiscalyear"/>
|
||||
<field name="type"/>
|
||||
<button name="reopen" string="Re-Open"/>
|
||||
<button name="close" string="Close"/>
|
||||
<button name="lock" string="Lock"
|
||||
confirm="Are you sure to lock the period?"/>
|
||||
<field name="state" tree_invisible="1"/>
|
||||
</tree>
|
||||
Reference in new issue
Block a user