From bd5c6d6ff00cfea0f9e0993db815dd2f7cf13e20 Mon Sep 17 00:00:00 2001 From: wan Date: Tue, 8 Oct 2019 15:15:04 +0000 Subject: [PATCH] [IMP] account: avoid draft entries for closed fiscal years Task 2076182 It makes no sense to allow creating draft entries for closed periods as it will never be allowed to post them! Directly warn the user seems smart. At the same time, we should be able to duplicate entries from closed fiscal years without any errors. So, if we duplicate an entry from a closed period, we should replace the accounting date by the first "open" accounting date. In order to keep the audit trails, we should keep the history in the chatter. closes odoo/odoo#38699 Signed-off-by: Quentin De Paoli (qdp) --- addons/account/models/account_move.py | 17 +++++++++++------ addons/account/models/company.py | 10 +++++++++- addons/account/tests/test_account_move_entry.py | 17 +++++------------ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 2543ee1b5cc..c970b42e2e2 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -1375,11 +1375,9 @@ class AccountMove(models.Model): raise UserError(_("Cannot create unbalanced journal entry. Ids: %s\nDifferences debit - credit: %s") % (ids, sums)) def _check_fiscalyear_lock_date(self): - for move in self.filtered(lambda move: move.state == 'posted'): - lock_date = max(move.company_id.period_lock_date or date.min, move.company_id.fiscalyear_lock_date or date.min) - if self.user_has_groups('account.group_account_manager'): - lock_date = move.company_id.fiscalyear_lock_date - if move.date <= (lock_date or date.min): + for move in self: + lock_date = move.company_id._get_user_fiscal_lock_date() + if move.date <= lock_date: if self.user_has_groups('account.group_account_manager'): message = _("You cannot add/modify entries prior to and inclusive of the lock date %s.") % format_date(self.env, lock_date) else: @@ -1496,6 +1494,13 @@ class AccountMove(models.Model): invoice.write(values) return True + @api.returns('self', lambda value: value.id) + def copy(self, default=None): + default = dict(default or {}) + if (fields.Date.to_date(default.get('date')) or self.date) <= self.company_id._get_user_fiscal_lock_date(): + default['date'] = self.company_id._get_user_fiscal_lock_date() + timedelta(days=1) + return super(AccountMove, self).copy(default) + @api.model_create_multi def create(self, vals_list): # OVERRIDE @@ -4133,6 +4138,6 @@ class AccountFullReconcile(models.Model): # The move date should be the maximum date between payment and invoice # (in case of payment in advance). However, we should make sure the # move date is not recorded after the end of year closing. - if move_date > (company.fiscalyear_lock_date or date.min): + if move_date > company._get_user_fiscal_lock_date(): res['date'] = move_date return res diff --git a/addons/account/models/company.py b/addons/account/models/company.py index 0c1e652b775..21f12239532 100644 --- a/addons/account/models/company.py +++ b/addons/account/models/company.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from datetime import timedelta, datetime +from datetime import timedelta, datetime, date import calendar from dateutil.relativedelta import relativedelta @@ -232,6 +232,14 @@ class ResCompany(models.Model): if nb_draft_entries: raise ValidationError(_('There are still unposted entries in the period you want to lock. You should either post or delete them.')) + def _get_user_fiscal_lock_date(self): + """Get the fiscal lock date for this company depending on the user""" + self.ensure_one() + lock_date = max(self.period_lock_date or date.min, self.fiscalyear_lock_date or date.min) + if self.user_has_groups('account.group_account_manager'): + lock_date = self.fiscalyear_lock_date or date.min + return lock_date + def write(self, values): #restrict the closing of FY if there are still unposted entries self._validate_fiscalyear_lock(values) diff --git a/addons/account/tests/test_account_move_entry.py b/addons/account/tests/test_account_move_entry.py index 841f97f5276..d10bbab526d 100644 --- a/addons/account/tests/test_account_move_entry.py +++ b/addons/account/tests/test_account_move_entry.py @@ -4,6 +4,8 @@ from odoo.tests import tagged, new_test_user from odoo import fields from odoo.exceptions import ValidationError, UserError +from dateutil.relativedelta import relativedelta + @tagged('post_install', '-at_install') class TestAccountMove(InvoiceTestCommon): @@ -113,19 +115,10 @@ class TestAccountMove(InvoiceTestCommon): with self.assertRaises(UserError), self.cr.savepoint(): self.test_move.button_draft() - copy_move = self.test_move.copy() - # Try to add a new journal entry prior to the lock date. - with self.assertRaises(UserError), self.cr.savepoint(): - copy_move.post() - - # You can change the date as the journal entry is not posted. - copy_move.date = fields.Date.from_string('2018-01-01') - copy_move.post() - - # You can't change the date to one being in a locked period. - with self.assertRaises(UserError), self.cr.savepoint(): - copy_move.date = fields.Date.from_string('2017-01-01') + copy_move = self.test_move.copy({'date': '2017-01-01'}) + # The date has been changed to the first valid date. + self.assertEqual(copy_move.date, copy_move.company_id.fiscalyear_lock_date + relativedelta(days=1)) def test_misc_tax_lock_date_1(self): self.test_move.post()