Files
tryton/modules/account/fiscalyear.py
T

717 lines
26 KiB
Python
Raw Normal View History

2014-12-02 12:54:29 +01:00
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
2017-09-28 11:37:00 +02:00
2010-08-19 22:02:00 +02:00
from dateutil.relativedelta import relativedelta
from sql import Null
from sql.conditionals import Case
from sql.operators import Equal, NotEqual
2018-12-29 14:20:28 +01:00
from trytond.cache import Cache
2018-12-29 14:20:28 +01:00
from trytond.i18n import gettext
from trytond.model import (
Exclude, ModelSQL, ModelView, Unique, Workflow, fields)
2018-12-29 14:20:28 +01:00
from trytond.model.exceptions import AccessError
2011-07-03 13:18:40 +02:00
from trytond.pool import Pool
2021-07-24 09:42:06 +02:00
from trytond.pyson import Eval, Id
from trytond.rpc import RPC
from trytond.sql.functions import DateRange
from trytond.sql.operators import RangeOverlap
from trytond.transaction import Transaction
from trytond.wizard import (
2021-12-11 17:58:41 +01:00
Button, StateAction, StateTransition, StateView, Wizard)
2021-12-11 17:58:41 +01:00
from .exceptions import (
FiscalYearCloseError, FiscalYearNotFoundError, FiscalYearReOpenError)
2018-12-29 14:20:28 +01:00
2008-03-13 23:22:59 +01:00
STATES = {
'readonly': Eval('state') != 'open',
2008-03-13 23:22:59 +01:00
}
class FiscalYear(Workflow, ModelSQL, ModelView):
2012-09-24 22:17:29 +02:00
__name__ = 'account.fiscalyear'
name = fields.Char('Name', size=None, required=True)
start_date = fields.Date(
"Start Date", required=True, states=STATES,
domain=[('start_date', '<=', Eval('end_date', None))])
end_date = fields.Date(
"End Date", required=True, states=STATES,
domain=[('end_date', '>=', Eval('start_date', None))])
2008-03-13 23:22:59 +01:00
periods = fields.One2Many('account.period', 'fiscalyear', 'Periods',
2019-09-28 23:59:08 +02:00
states=STATES,
domain=[
('company', '=', Eval('company', -1)),
2019-09-28 23:59:08 +02:00
],
order=[('start_date', 'ASC'), ('id', 'ASC')])
2008-03-13 23:22:59 +01:00
state = fields.Selection([
('open', 'Open'),
2023-06-20 10:13:56 +02:00
('closed', 'Closed'),
('locked', 'Locked'),
2022-02-15 00:08:46 +01:00
], 'State', readonly=True, required=True, sort=False)
2025-02-11 12:04:55 +01:00
move_sequence = fields.Many2One(
'ir.sequence.strict', "Move Sequence", required=True,
2021-03-11 23:00:09 +01:00
domain=[
('sequence_type', '=',
Id('account', 'sequence_type_account_move')),
('company', '=', Eval('company', -1)),
2025-02-11 12:04:55 +01:00
],
help="Used to generate the move number when posting "
"if the period has no sequence.")
2021-04-20 09:18:57 +02:00
company = fields.Many2One(
'company.company', "Company", required=True)
icon = fields.Function(fields.Char("Icon"), 'get_icon')
_find_cache = Cache(__name__ + '.find', context=False)
2008-03-13 23:22:59 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def __setup__(cls):
2025-04-04 00:45:18 +02:00
super().__setup__()
t = cls.__table__()
cls._sql_constraints += [
('dates_overlap',
Exclude(t,
(t.company, Equal),
(DateRange(t.start_date, t.end_date, '[]'), RangeOverlap),
),
'account.msg_fiscalyear_overlap'),
('open_earlier',
Exclude(t,
(t.company, Equal),
(DateRange(
Case(
(t.state == 'open', t.start_date), else_=Null),
t.end_date), RangeOverlap),
(Case((t.state == 'open', t.id), else_=-1), NotEqual)),
'account.msg_open_fiscalyear_earlier'),
2025-02-11 12:04:55 +01:00
('move_sequence_unique', Unique(t, t.move_sequence),
'account.msg_fiscalyear_move_sequence_unique'),
]
cls._order.insert(0, ('start_date', 'DESC'))
cls._transitions |= set((
2023-06-20 10:13:56 +02:00
('open', 'closed'),
('closed', 'locked'),
('closed', 'open'),
))
2012-09-24 22:17:29 +02:00
cls._buttons.update({
'create_periods': {
2012-03-25 00:17:23 +01:00
'invisible': ((Eval('state') != 'open')
| Eval('periods', [0])),
2018-02-19 11:36:13 +01:00
'depends': ['state'],
2012-03-25 00:17:23 +01:00
},
'close': {
'invisible': Eval('state') != 'open',
2018-02-19 11:36:13 +01:00
'depends': ['state'],
2012-03-25 00:17:23 +01:00
},
'reopen': {
2023-06-20 10:13:56 +02:00
'invisible': Eval('state') != 'closed',
2018-02-19 11:36:13 +01:00
'depends': ['state'],
2012-03-25 00:17:23 +01:00
},
2021-10-03 00:35:25 +02:00
'lock_': {
2023-06-20 10:13:56 +02:00
'invisible': Eval('state') != 'closed',
2018-02-19 11:36:13 +01:00
'depends': ['state'],
},
2012-03-25 00:17:23 +01:00
})
cls.__rpc__.update({
'create_period': RPC(readonly=False, instantiate=0),
})
2008-03-13 23:22:59 +01:00
2023-06-20 10:13:56 +02:00
@classmethod
def __register__(cls, module):
2025-02-11 12:04:55 +01:00
pool = Pool()
Period = pool.get('account.period')
Sequence = pool.get('ir.sequence')
SequenceStrict = pool.get('ir.sequence.strict')
table_h = cls.__table_handler__(module)
2023-06-20 10:13:56 +02:00
cursor = Transaction().connection.cursor()
t = cls.__table__()
2025-02-11 12:04:55 +01:00
migrate_move_sequence = not table_h.column_exist('move_sequence')
2023-06-20 10:13:56 +02:00
super().__register__(module)
# Migration from 6.8: rename state close to closed
cursor.execute(
*t.update([t.state], ['closed'], where=t.state == 'close'))
2025-02-11 12:04:55 +01:00
# Migrationn from 7.4: use strict sequence
if (table_h.column_exist('post_move_sequence')
and migrate_move_sequence):
table_h.not_null_action('post_move_sequence', 'remove')
period_h = Period.__table_handler__(module)
period = Period.__table__()
old2new = {}
period_migrated = (
period_h.column_exist('post_move_sequence')
and period_h.column_exist('move_sequence'))
if period_migrated:
cursor.execute(*period.select(
period.post_move_sequence, period.move_sequence))
old2new.update(cursor)
cursor.execute(*t.select(t.post_move_sequence, distinct=True))
for sequence_id, in cursor:
if sequence_id not in old2new:
sequence = Sequence(sequence_id)
new_sequence = SequenceStrict(
name=sequence.name,
sequence_type=sequence.sequence_type,
prefix=sequence.prefix,
suffix=sequence.suffix,
type=sequence.type,
number_next=sequence.number_next,
2025-02-11 12:04:55 +01:00
number_increment=sequence.number_increment,
padding=sequence.padding,
timestamp_rounding=sequence.timestamp_rounding,
timestamp_offset=sequence.timestamp_offset,
last_timestamp=sequence.last_timestamp,
company=sequence.company)
2025-02-11 12:04:55 +01:00
new_sequence.save()
old2new[sequence_id] = new_sequence.id
for old_id, new_id in old2new.items():
cursor.execute(*t.update(
[t.move_sequence], [new_id],
where=t.post_move_sequence == old_id))
if period_migrated:
table_h.drop_column('post_move_sequence')
period_h.drop_column('post_move_sequence')
2012-09-24 22:17:29 +02:00
@staticmethod
def default_state():
2008-03-13 23:22:59 +01:00
return 'open'
2012-09-24 22:17:29 +02:00
@staticmethod
def default_company():
2012-03-27 10:43:03 +02:00
return Transaction().context.get('company')
def get_icon(self, name):
return {
'open': 'tryton-account-open',
2023-06-20 10:13:56 +02:00
'closed': 'tryton-account-close',
'locked': 'tryton-account-block',
}.get(self.state)
@classmethod
2022-04-11 23:24:20 +02:00
def validate_fields(cls, fiscalyears, field_names):
super().validate_fields(fiscalyears, field_names)
cls.check_period_dates(fiscalyears, field_names)
@classmethod
def check_period_dates(cls, fiscalyears, field_names=None):
pool = Pool()
Period = pool.get('account.period')
if field_names and not (field_names & {'start_date', 'end_date'}):
return
periods = [p for f in fiscalyears for p in f.periods]
Period.check_fiscalyear_dates(periods, field_names={'fiscalyear'})
@classmethod
def check_modification(
cls, mode, fiscalyears, values=None, external=False):
2018-12-29 14:20:28 +01:00
pool = Pool()
Move = pool.get('account.move')
super().check_modification(
mode, fiscalyears, values=values, external=external)
if mode == 'write' and 'move_sequence' in values:
for fiscalyear in fiscalyears:
if sequence := fiscalyear.move_sequence:
if sequence.id != values['move_sequence']:
2018-12-29 14:20:28 +01:00
if Move.search([
('period.fiscalyear', '=', fiscalyear.id),
('state', '=', 'posted'),
], limit=1):
2018-12-29 14:20:28 +01:00
raise AccessError(
gettext('account.'
2025-02-11 12:04:55 +01:00
'msg_change_fiscalyear_move_sequence',
2018-12-29 14:20:28 +01:00
fiscalyear=fiscalyear.rec_name))
2008-10-07 12:25:54 +02:00
2012-09-24 22:17:29 +02:00
@classmethod
def on_modification(cls, mode, records, field_names=None):
super().on_modification(mode, records, field_names=field_names)
cls._find_cache.clear()
2012-09-24 22:17:29 +02:00
@classmethod
def create_period(cls, fiscalyears, interval=1, end_day=31):
2008-03-13 23:22:59 +01:00
'''
Create periods for the fiscal years with month interval
'''
2012-09-24 22:17:29 +02:00
Period = Pool().get('account.period')
2013-01-06 22:18:13 +01:00
to_create = []
2012-09-24 22:17:29 +02:00
for fiscalyear in fiscalyears:
period_start_date = fiscalyear.start_date
while period_start_date < fiscalyear.end_date:
month_offset = 1 if period_start_date.day < end_day else 0
period_end_date = (period_start_date
+ relativedelta(months=interval - month_offset)
+ relativedelta(day=end_day))
if period_end_date > fiscalyear.end_date:
period_end_date = fiscalyear.end_date
2018-10-31 18:15:57 +01:00
name = period_start_date.strftime('%Y-%m')
if name != period_end_date.strftime('%Y-%m'):
name += ' - ' + period_end_date.strftime('%Y-%m')
2013-01-06 22:18:13 +01:00
to_create.append({
2008-11-22 14:53:02 +01:00
'name': name,
'start_date': period_start_date,
'end_date': period_end_date,
2008-03-13 23:22:59 +01:00
'fiscalyear': fiscalyear.id,
2008-09-16 19:43:07 +02:00
'type': 'standard',
2010-08-19 22:02:00 +02:00
})
period_start_date = period_end_date + relativedelta(days=1)
2013-01-06 22:18:13 +01:00
if to_create:
Period.create(to_create)
2008-03-13 23:22:59 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
@ModelView.button_action('account.act_create_periods')
def create_periods(cls, fiscalyears):
pass
2008-03-13 23:22:59 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
def find(cls, company, date=None, test_state=True):
2008-03-13 23:22:59 +01:00
'''
Return the fiscal year for the company at the date or the current date
or raise FiscalYearNotFoundError.
If test_state is true, it searches on non-closed fiscal years
2008-03-13 23:22:59 +01:00
'''
pool = Pool()
Lang = pool.get('ir.lang')
Date = pool.get('ir.date')
Company = pool.get('company.company')
2008-10-08 12:17:47 +02:00
company_id = int(company) if company is not None else None
2008-03-13 23:22:59 +01:00
if not date:
with Transaction().set_context(company=company_id):
date = Date.today()
key = (company_id, date)
fiscalyear = cls._find_cache.get(key, -1)
if fiscalyear is not None and fiscalyear < 0:
clause = [
('start_date', '<=', date),
('end_date', '>=', date),
('company', '=', company_id),
]
fiscalyears = cls.search(
clause, order=[('start_date', 'DESC')], limit=1)
if fiscalyears:
fiscalyear, = fiscalyears
2008-03-13 23:22:59 +01:00
else:
fiscalyear = None
cls._find_cache.set(key, int(fiscalyear) if fiscalyear else None)
elif fiscalyear is not None:
fiscalyear = cls(fiscalyear)
found = fiscalyear and (not test_state or fiscalyear.state == 'open')
if not found:
lang = Lang.get()
if company is not None and not isinstance(company, Company):
company = Company(company)
if not fiscalyear:
raise FiscalYearNotFoundError(
gettext('account.msg_no_fiscalyear_date',
date=lang.strftime(date),
company=company.rec_name if company else ''))
else:
raise FiscalYearNotFoundError(
gettext('account.msg_no_open_fiscalyear_date',
date=lang.strftime(date),
fiscalyear=fiscalyear.rec_name,
company=company.rec_name if company else ''))
else:
return fiscalyear
2008-03-13 23:22:59 +01:00
2015-01-21 19:40:24 +01:00
def get_deferral(self, account):
'Computes deferrals for accounts'
pool = Pool()
Currency = pool.get('currency.currency')
Deferral = pool.get('account.account.deferral')
2008-09-19 15:00:26 +02:00
2019-03-24 18:00:01 +01:00
if not account.type:
2008-09-19 15:00:26 +02:00
return
2012-09-25 11:26:00 +02:00
if not account.deferral:
2012-09-24 22:17:29 +02:00
if not Currency.is_zero(self.company.currency, account.balance):
2018-12-29 14:20:28 +01:00
raise FiscalYearCloseError(
gettext('account'
'.msg_close_fiscalyear_account_balance_not_zero',
account=account.rec_name))
2008-09-19 15:00:26 +02:00
else:
2015-01-21 19:40:24 +01:00
deferral = Deferral()
deferral.account = account
deferral.fiscalyear = self
deferral.debit = account.debit
deferral.credit = account.credit
deferral.line_count = account.line_count
deferral.amount_second_currency = account.amount_second_currency
2015-01-21 19:40:24 +01:00
return deferral
2008-09-19 15:00:26 +02:00
2012-09-24 22:17:29 +02:00
@classmethod
2012-03-25 00:17:23 +01:00
@ModelView.button
2023-06-20 10:13:56 +02:00
@Workflow.transition('closed')
2012-09-24 22:17:29 +02:00
def close(cls, fiscalyears):
2008-09-19 15:00:26 +02:00
'''
Close a fiscal year
'''
2012-09-24 22:17:29 +02:00
pool = Pool()
Period = pool.get('account.period')
Account = pool.get('account.account')
2015-01-21 19:40:24 +01:00
Deferral = pool.get('account.account.deferral')
# Prevent create new fiscal year or period
cls.lock()
2021-10-18 01:22:26 +02:00
Period.lock()
2008-09-19 15:00:26 +02:00
2015-01-21 19:40:24 +01:00
deferrals = []
2012-09-24 22:17:29 +02:00
for fiscalyear in fiscalyears:
if cls.search([
2013-02-16 18:54:35 +01:00
('end_date', '<=', fiscalyear.start_date),
('state', '=', 'open'),
('company', '=', fiscalyear.company.id),
]):
2018-12-29 14:20:28 +01:00
raise FiscalYearCloseError(
gettext('account.msg_close_fiscalyear_earlier',
fiscalyear=fiscalyear.rec_name))
2008-09-19 15:00:26 +02:00
2012-09-24 22:17:29 +02:00
periods = Period.search([
('fiscalyear', '=', fiscalyear.id),
])
Period.close(periods)
2012-03-25 00:17:23 +01:00
with Transaction().set_context(fiscalyear=fiscalyear.id,
2021-01-04 21:33:28 +01:00
date=None, cumulate=True, journal=None):
2012-09-24 22:17:29 +02:00
accounts = Account.search([
('company', '=', fiscalyear.company.id),
])
2021-12-08 10:37:04 +01:00
for account in accounts:
deferral = fiscalyear.get_deferral(account)
if deferral:
deferrals.append(deferral)
2015-01-21 19:40:24 +01:00
Deferral.save(deferrals)
2012-03-25 00:17:23 +01:00
2012-09-24 22:17:29 +02:00
@classmethod
2012-03-25 00:17:23 +01:00
@ModelView.button
@Workflow.transition('open')
2012-09-24 22:17:29 +02:00
def reopen(cls, fiscalyears):
2008-09-19 15:00:26 +02:00
'''
2024-07-13 19:54:41 +02:00
Reopen a fiscal year
2008-09-19 15:00:26 +02:00
'''
2012-09-24 22:17:29 +02:00
Deferral = Pool().get('account.account.deferral')
2008-09-19 15:00:26 +02:00
2012-09-24 22:17:29 +02:00
for fiscalyear in fiscalyears:
if cls.search([
2013-02-16 18:54:35 +01:00
('start_date', '>=', fiscalyear.end_date),
('state', '!=', 'open'),
2013-02-16 18:54:35 +01:00
('company', '=', fiscalyear.company.id),
]):
2018-12-29 14:20:28 +01:00
raise FiscalYearReOpenError(
gettext('account.msg_reopen_fiscalyear_later',
fiscalyear=fiscalyear.rec_name))
2008-09-19 15:00:26 +02:00
2012-09-24 22:17:29 +02:00
deferrals = Deferral.search([
2012-03-25 00:17:23 +01:00
('fiscalyear', '=', fiscalyear.id),
])
2012-09-24 22:17:29 +02:00
Deferral.delete(deferrals)
2008-09-19 15:00:26 +02:00
@classmethod
@ModelView.button
@Workflow.transition('locked')
2021-10-03 00:35:25 +02:00
def lock_(cls, fiscalyears):
pool = Pool()
Period = pool.get('account.period')
periods = Period.search([
('fiscalyear', 'in', [f.id for f in fiscalyears]),
])
2021-10-03 00:35:25 +02:00
Period.lock_(periods)
2008-09-19 15:00:26 +02:00
2013-09-16 11:33:24 +02:00
class BalanceNonDeferralStart(ModelView):
__name__ = 'account.fiscalyear.balance_non_deferral.start'
fiscalyear = fields.Many2One('account.fiscalyear', 'Fiscal Year',
required=True, domain=[('state', '=', 'open')])
2014-12-03 16:13:08 +01:00
company = fields.Function(fields.Many2One('company.company', 'Company'),
'on_change_with_company')
2013-09-16 11:33:24 +02:00
journal = fields.Many2One('account.journal', 'Journal', required=True,
domain=[
('type', '=', 'situation'),
],
context={
'company': Eval('company', -1),
},
depends={'company'})
2013-09-16 11:33:24 +02:00
period = fields.Many2One('account.period', 'Period', required=True,
domain=[
('fiscalyear', '=', Eval('fiscalyear', -1)),
2013-09-16 11:33:24 +02:00
('type', '=', 'adjustment'),
])
2013-09-16 11:33:24 +02:00
credit_account = fields.Many2One('account.account', 'Credit Account',
required=True,
domain=[
2019-03-24 18:00:01 +01:00
('type', '!=', None),
('closed', '!=', True),
2014-12-03 16:13:08 +01:00
('company', '=', Eval('company', -1)),
2013-09-16 11:33:24 +02:00
('deferral', '=', True),
])
2013-09-16 11:33:24 +02:00
debit_account = fields.Many2One('account.account', 'Debit Account',
required=True,
domain=[
2019-03-24 18:00:01 +01:00
('type', '!=', None),
('closed', '!=', True),
2014-12-03 16:13:08 +01:00
('company', '=', Eval('company', -1)),
2013-09-16 11:33:24 +02:00
('deferral', '=', True),
])
2014-12-03 16:13:08 +01:00
@fields.depends('fiscalyear')
def on_change_with_company(self, name=None):
2023-03-26 09:49:00 +02:00
return self.fiscalyear.company if self.fiscalyear else None
2013-09-16 11:33:24 +02:00
class BalanceNonDeferral(Wizard):
__name__ = 'account.fiscalyear.balance_non_deferral'
start = StateView('account.fiscalyear.balance_non_deferral.start',
'account.fiscalyear_balance_non_deferral_start_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
2015-03-10 18:27:06 +01:00
Button('OK', 'balance', 'tryton-ok', default=True),
2013-09-16 11:33:24 +02:00
])
2021-07-02 11:49:14 +02:00
balance = StateAction('account.act_move_form')
2013-09-16 11:33:24 +02:00
def get_move_line(self, account):
pool = Pool()
Line = pool.get('account.move.line')
# Don't use account.balance because we need the non-commulated balance
balance = account.debit - account.credit
if account.company.currency.is_zero(balance):
2013-09-16 11:33:24 +02:00
return
line = Line()
line.account = account
if balance >= 0:
line.credit = abs(balance)
2013-09-16 11:33:24 +02:00
line.debit = 0
else:
line.credit = 0
line.debit = abs(balance)
2013-09-16 11:33:24 +02:00
return line
def get_counterpart_line(self, amount):
pool = Pool()
Line = pool.get('account.move.line')
if self.start.fiscalyear.company.currency.is_zero(amount):
return
line = Line()
if amount >= 0:
line.credit = abs(amount)
line.debit = 0
line.account = self.start.credit_account
else:
line.credit = 0
line.debit = abs(amount)
line.account = self.start.debit_account
return line
def create_move(self):
pool = Pool()
Account = pool.get('account.account')
Move = pool.get('account.move')
with Transaction().set_context(fiscalyear=self.start.fiscalyear.id,
date=None, cumulate=False):
accounts = Account.search([
('company', '=', self.start.fiscalyear.company.id),
('deferral', '=', False),
2019-03-24 18:00:01 +01:00
('type', '!=', None),
('closed', '!=', True),
2013-09-16 11:33:24 +02:00
])
lines = []
for account in accounts:
line = self.get_move_line(account)
if line:
lines.append(line)
if not lines:
return
amount = sum(l.debit - l.credit for l in lines)
counter_part_line = self.get_counterpart_line(amount)
if counter_part_line:
lines.append(counter_part_line)
move = Move()
move.period = self.start.period
move.journal = self.start.journal
move.date = self.start.period.start_date
move.origin = self.start.fiscalyear
move.lines = lines
move.save()
return move
def do_balance(self, action):
move = self.create_move()
2022-01-20 18:56:17 +01:00
if move:
action['views'].reverse()
return action, {'res_id': move.id if move else None}
2017-09-28 11:37:00 +02:00
class CreatePeriodsStart(ModelView):
__name__ = 'account.fiscalyear.create_periods.start'
frequency = fields.Selection([
('monthly', "Monthly"),
('quarterly', "Quarterly"),
('other', "Other"),
], "Frequency", sort=False, required=True)
interval = fields.Integer("Interval", required=True,
states={
'invisible': Eval('frequency') != 'other',
},
help="The length of each period, in months.")
end_day = fields.Integer("End Day", required=True,
help="The day of the month on which periods end.\n"
"Months with fewer days will end on the last day.")
@classmethod
def default_frequency(cls):
return 'monthly'
@classmethod
def default_end_day(cls):
return 31
@classmethod
def frequency_intervals(cls):
return {
'monthly': 1,
'quarterly': 3,
'other': None,
}
@fields.depends('frequency', 'interval')
def on_change_frequency(self):
if self.frequency:
self.interval = self.frequency_intervals()[self.frequency]
class CreatePeriods(Wizard):
__name__ = 'account.fiscalyear.create_periods'
start = StateView('account.fiscalyear.create_periods.start',
'account.fiscalyear_create_periods_start_view_form', [
Button("Cancel", 'end', 'tryton-cancel'),
Button("Create", 'create_periods', 'tryton-ok', default=True),
])
create_periods = StateTransition()
def transition_create_periods(self):
self.model.create_period(
[self.record], self.start.interval, self.start.end_day)
return 'end'
2017-09-28 11:37:00 +02:00
def month_delta(d1, d2):
month_offset = 1 if d1.day < d2.day else 0
return (d1.year - d2.year) * 12 + d1.month - d2.month - month_offset
2017-09-28 11:37:00 +02:00
class RenewFiscalYearStart(ModelView):
__name__ = 'account.fiscalyear.renew.start'
name = fields.Char("Name", required=True)
company = fields.Many2One('company.company', "Company", required=True)
previous_fiscalyear = fields.Many2One(
'account.fiscalyear', "Previous Fiscalyear", required=True,
domain=[
('company', '=', Eval('company', -1)),
2017-09-28 11:37:00 +02:00
],
help="Used as reference for fiscalyear configuration.")
start_date = fields.Date("Start Date", required=True)
end_date = fields.Date("End Date", required=True)
reset_sequences = fields.Boolean("Reset Sequences",
help="If checked, new sequences will be created.")
@classmethod
def default_company(cls):
return Transaction().context.get('company')
@classmethod
def default_previous_fiscalyear(cls):
pool = Pool()
FiscalYear = pool.get('account.fiscalyear')
fiscalyears = FiscalYear.search([
('company', '=', cls.default_company() or -1),
],
order=[('end_date', 'DESC')], limit=1)
if fiscalyears:
fiscalyear, = fiscalyears
return fiscalyear.id
@classmethod
def default_reset_sequences(cls):
return True
@fields.depends('previous_fiscalyear')
def on_change_previous_fiscalyear(self):
if self.previous_fiscalyear:
fiscalyear = self.previous_fiscalyear
months = month_delta(
fiscalyear.end_date, fiscalyear.start_date) + 1
self.start_date = fiscalyear.start_date + relativedelta(
months=months, day=fiscalyear.start_date.day)
self.end_date = fiscalyear.end_date + relativedelta(
months=months, day=fiscalyear.end_date.day)
self.name = fiscalyear.name.replace(
str(fiscalyear.end_date.year),
str(self.end_date.year)).replace(
str(fiscalyear.start_date.year),
str(self.start_date.year))
class RenewFiscalYear(Wizard):
__name__ = 'account.fiscalyear.renew'
start = StateView('account.fiscalyear.renew.start',
'account.fiscalyear_renew_start_view_form', [
Button("Cancel", 'end', 'tryton-cancel'),
Button("Create", 'create_', 'tryton-ok', default=True),
])
create_ = StateAction('account.act_fiscalyear_form')
def fiscalyear_defaults(self):
pool = Pool()
2025-02-11 12:04:55 +01:00
Sequence = pool.get('ir.sequence.strict')
2017-09-28 11:37:00 +02:00
defaults = {
'name': self.start.name,
'start_date': self.start.start_date,
'end_date': self.start.end_date,
'periods': [],
}
2025-02-11 12:04:55 +01:00
previous_sequence = self.start.previous_fiscalyear.move_sequence
2019-07-26 09:39:29 +02:00
sequence, = Sequence.copy([previous_sequence],
default={
'name': lambda data: data['name'].replace(
self.start.previous_fiscalyear.name,
self.start.name)
})
2017-09-28 11:37:00 +02:00
if self.start.reset_sequences:
sequence.number_next = 1
else:
sequence.number_next = previous_sequence.number_next
sequence.save()
2025-02-11 12:04:55 +01:00
defaults['move_sequence'] = sequence.id
2017-09-28 11:37:00 +02:00
return defaults
def create_fiscalyear(self):
pool = Pool()
FiscalYear = pool.get('account.fiscalyear')
fiscalyear, = FiscalYear.copy(
[self.start.previous_fiscalyear],
default=self.fiscalyear_defaults())
periods = [
p for p in self.start.previous_fiscalyear.periods
2017-09-28 11:37:00 +02:00
if p.type == 'standard']
if periods:
months = month_delta(fiscalyear.end_date, fiscalyear.start_date)
months += 1
interval = months / len(periods)
end_day = max(
p.end_date.day
for p in self.start.previous_fiscalyear.periods
if p.type == 'standard')
if interval.is_integer():
FiscalYear.create_period([fiscalyear], interval, end_day)
2017-09-28 11:37:00 +02:00
return fiscalyear
def do_create_(self, action):
fiscalyear = self.create_fiscalyear()
2023-04-08 18:40:27 +02:00
fiscalyear.save()
2017-09-28 11:37:00 +02:00
action['views'].reverse()
return action, {'res_id': fiscalyear.id}