[FIX] account: manage multi-company for accrual wizard

Before, it was possible to select lines from different companies and create a line from a yet different company. This is now forbidden.
Also, add tests to ensure only the account is changed when creating an accrual entry.

closes odoo/odoo#36751

Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
This commit is contained in:
wan
2019-09-12 09:31:53 +00:00
parent 4926f03e6f
commit 956338f28a
3 changed files with 99 additions and 12 deletions
@@ -1193,3 +1193,47 @@ class TestAccountMoveInInvoiceOnchanges(InvoiceTestCommon):
'amount_total' : self.move_vals['amount_total'],
'amount_untaxed' : self.move_vals['amount_untaxed'],
})
def test_in_invoice_accrual(self):
self.env.company.accrual_default_journal_id = self.company_data['default_journal_misc']
self.env.company.expense_accrual_account_id = self.env['account.account'].create({
'name': 'Accrual Expense Account',
'code': '234567',
'user_type_id': self.env.ref('account.data_account_type_expenses').id,
'reconcile': True,
})
self.env.company.revenue_accrual_account_id = self.env['account.account'].create({
'name': 'Accrual Revenue Account',
'code': '765432',
'user_type_id': self.env.ref('account.data_account_type_expenses').id,
'reconcile': True,
})
invoice_line = self.invoice.line_ids.filtered(lambda l: l.account_id == self.product_a.property_account_expense_id)
self.env['account.accrual.accounting.wizard'].with_context(
active_model='account.move.line',
active_ids=invoice_line.ids
).create({
'date': '2016-01-01',
'percentage': 60,
}).amend_entries()
# Nothing changed except the account
self.assertInvoiceValues(self.invoice, [
{
**self.product_line_vals_1,
'account_id': self.env.company.expense_accrual_account_id.id,
},
self.product_line_vals_2,
self.tax_line_vals_1,
self.tax_line_vals_2,
self.term_line_vals_1,
], self.move_vals)
accrual_moves = self.env['account.move'].search([('journal_id', '=', self.env.company.accrual_default_journal_id.id)])
accrual_other_date = accrual_moves.filtered(lambda m: m.date == fields.Date.to_date('2016-01-01'))
accrual_same_date = accrual_moves.filtered(lambda m: m.date == invoice_line.date)
self.assertEqual(accrual_same_date.amount_total, 0.4 * invoice_line.balance)
self.assertEqual(accrual_other_date.amount_total, 0.6 * invoice_line.balance)
self.assertTrue(accrual_other_date.line_ids.full_reconcile_id)
@@ -1267,4 +1267,48 @@ class TestAccountMoveOutInvoiceOnchanges(InvoiceTestCommon):
'amount_tax' : self.move_vals['amount_tax'],
'amount_total' : self.move_vals['amount_total'],
'amount_untaxed' : self.move_vals['amount_untaxed'],
})
})
def test_out_invoice_accrual(self):
self.env.company.accrual_default_journal_id = self.company_data['default_journal_misc']
self.env.company.expense_accrual_account_id = self.env['account.account'].create({
'name': 'Accrual Expense Account',
'code': '234567',
'user_type_id': self.env.ref('account.data_account_type_expenses').id,
'reconcile': True,
})
self.env.company.revenue_accrual_account_id = self.env['account.account'].create({
'name': 'Accrual Revenue Account',
'code': '765432',
'user_type_id': self.env.ref('account.data_account_type_expenses').id,
'reconcile': True,
})
invoice_line = self.invoice.line_ids.filtered(lambda l: l.account_id == self.product_a.property_account_income_id)
self.env['account.accrual.accounting.wizard'].with_context(
active_model='account.move.line',
active_ids=invoice_line.ids
).create({
'date': '2016-01-01',
'percentage': 60,
}).amend_entries()
# Nothing changed except the account
self.assertInvoiceValues(self.invoice, [
{
**self.product_line_vals_1,
'account_id': self.env.company.revenue_accrual_account_id.id,
},
self.product_line_vals_2,
self.tax_line_vals_1,
self.tax_line_vals_2,
self.term_line_vals_1,
], self.move_vals)
accrual_moves = self.env['account.move'].search([('journal_id', '=', self.env.company.accrual_default_journal_id.id)])
accrual_other_date = accrual_moves.filtered(lambda m: m.date == fields.Date.to_date('2016-01-01'))
accrual_same_date = accrual_moves.filtered(lambda m: m.date == invoice_line.date)
self.assertEqual(accrual_same_date.amount_total, 0.4 * -invoice_line.balance)
self.assertEqual(accrual_other_date.amount_total, 0.6 * -invoice_line.balance)
self.assertTrue(accrual_other_date.line_ids.full_reconcile_id)
@@ -8,7 +8,7 @@ class AccrualAccountingWizard(models.TransientModel):
_description = 'Create accrual entry.'
date = fields.Date(required=True)
company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company)
company_id = fields.Many2one('res.company', required=True)
account_type = fields.Selection([('income', 'Revenue'), ('expense', 'Expense')])
active_move_line_ids = fields.Many2many('account.move.line')
journal_id = fields.Many2one('account.journal', required=True, related="company_id.accrual_default_journal_id", readonly=False)
@@ -41,6 +41,9 @@ class AccrualAccountingWizard(models.TransientModel):
raise UserError(_('You can only change the period for items that are not yet reconciled.'))
if any(line.account_id.user_type_id != active_move_line_ids[0].account_id.user_type_id for line in active_move_line_ids):
raise UserError(_('All accounts on the lines must be from the same type.'))
if any(line.company_id != active_move_line_ids[0].company_id for line in active_move_line_ids):
raise UserError(_('All lines must be from the same company.'))
rec['company_id'] = active_move_line_ids[0].company_id.id
account_types_allowed = self.env.ref('account.data_account_type_expenses') + self.env.ref('account.data_account_type_revenue') + self.env.ref('account.data_account_type_other_income')
if active_move_line_ids[0].account_id.user_type_id not in account_types_allowed:
raise UserError(_('You can only change the period for items in these types of accounts: ') + ", ".join(account_types_allowed.mapped('name')))
@@ -48,19 +51,15 @@ class AccrualAccountingWizard(models.TransientModel):
return rec
def amend_entries(self):
move_data = []
to_reconcile = []
message_data = []
#gather the origin account on seleced journal items
# gather the origin account on seleced journal items
origin_accounts = {}
for aml in self.active_move_line_ids:
origin_accounts[aml.id] = aml.account_id.id
#set the accrual account on the selected journal items
# set the accrual account on the selected journal items
self.active_move_line_ids.write({'account_id': (self.revenue_accrual_account if self.account_type == 'income' else self.expense_accrual_account).id})
#create the accrual move(s) and reconcile accrual items together
# create the accrual move(s) and reconcile accrual items together
for aml in self.active_move_line_ids:
reported_debit = aml.company_id.currency_id.round((self.percentage / 100) * aml.debit)
reported_credit = aml.company_id.currency_id.round((self.percentage / 100) * aml.credit)
@@ -91,7 +90,7 @@ class AccrualAccountingWizard(models.TransientModel):
id=aml.move_id.id,
name=aml.move_id.name,
)]
#in case the percentage to recognize is not 100%, another entry is created to keep the remaining balance in the same account at the original date
# in case the percentage to recognize is not 100%, another entry is created to keep the remaining balance in the same account at the original date
if self.percentage < 100:
ref = _('Accrual Adjusting Entry ({percent}% recognized) for invoice: {name}').format(percent=100 - self.percentage, name=aml.move_id.name)
move_data.append({
@@ -126,11 +125,11 @@ class AccrualAccountingWizard(models.TransientModel):
for move, msg in zip(created_ids, message_data):
move.message_post(body=msg)
#reconcile journal items on the accrual account
# reconcile journal items on the accrual account
to_reconcile = created_ids.line_ids.filtered(lambda line: line.account_id in (self.revenue_accrual_account + self.expense_accrual_account)) + aml
to_reconcile.reconcile()
#open the generated entries
# open the generated entries
action = {
'name': _('Generated Entries'),
'domain': [('id', 'in', created_ids.ids)],