[REV] account: remove the ability for the automatic entries wizard to generate multiple entries at once

This reverts commit 7e3e99adb4.

Usability of that new wizard was too poor. We revert it for now; it'll make a comeback eventually.

closes odoo/odoo#63436

X-original-commit: 1d75786b8b45fd4f6b08d726165b60875b62b1e7
Signed-off-by: Quentin De Paoli (qdp) <qdp@openerp.com>
Signed-off-by: oco-odoo <oco-odoo@users.noreply.github.com>
This commit is contained in:
oco-odoo
2020-12-16 11:29:57 +00:00
parent 1a58bcce08
commit 71ebdcbf3c
8 changed files with 318 additions and 524 deletions
@@ -126,7 +126,6 @@ access_account_payment,account.payment,model_account_payment,account.group_accou
access_account_payment_register,access.account.payment.register,model_account_payment_register,account.group_account_invoice,1,1,1,0
access_account_bank_statement_closebalance,access.account.bank.statement.closebalance,model_account_bank_statement_closebalance,account.group_account_user,1,1,1,0
access_account_automatic_entry_wizard,access.account.automatic.entry.wizard,model_account_automatic_entry_wizard,account.group_account_user,1,1,1,0
access_account_automatic_entry_wizard_line,access.account.automatic.entry.wizard.line,model_account_automatic_entry_wizard_line,account.group_account_user,1,1,1,1
access_account_unreconcile,access.account.unreconcile,model_account_unreconcile,account.group_account_user,1,1,1,0
access_account_resequence,access.account.resequence.wizard,model_account_resequence_wizard,account.group_account_manager,1,1,1,0
access_validate_account_move,access.validate.account.move,model_validate_account_move,account.group_account_invoice,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
126 access_account_invoice_send access_account_analytic_default access.account.invoice.send account.analytic.default model_account_invoice_send model_account_analytic_default account.group_account_invoice account.group_account_readonly 1 1 0 1 0 0
127 access_account_analytic_default access_account_analytic_default_analytic account.analytic.default account.analytic.default analytic model_account_analytic_default account.group_account_readonly analytic.group_analytic_accounting 1 0 0 0
128 access_account_analytic_default_analytic access_account_analytic_default_invoice account.analytic.default analytic account.analytic.default invoice model_account_analytic_default analytic.group_analytic_accounting account.group_account_invoice 1 0 1 0 1 0 1
access_account_analytic_default_invoice account.analytic.default invoice model_account_analytic_default account.group_account_invoice 1 1 1 1
129 access_account_tour_upload_bill account.tour.upload.bill model_account_tour_upload_bill account.group_account_manager 1 1 1 0
130 access_account_tour_upload_bill_email_confirm account.tour.upload.bill.email.confirm model_account_tour_upload_bill_email_confirm account.group_account_manager 1 1 1 0
131
-1
View File
@@ -2,7 +2,6 @@
from . import test_account_move_reconcile
from . import test_account_move_payments_widget
from . import test_account_automatic_entry_wizard_period
from . import test_account_move_out_invoice
from . import test_account_move_out_refund
from . import test_account_move_in_invoice
@@ -1,204 +0,0 @@
# -*- coding: utf-8 -*-
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo import fields
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestAccountAutomaticEntryWizardPeriod(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
cls.invoice = cls.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2017-01-01',
'partner_id': cls.partner_a.id,
'invoice_date': '2017-01-01',
'invoice_line_ids': [
(0, 0, {
'name': "line1",
'quantity': 1,
'price_unit': 1000.0,
'account_id': cls.company_data['default_account_revenue'].id,
}),
(0, 0, {
'name': "line2",
'quantity': 1,
'price_unit': 200.0,
'account_id': cls.company_data['default_account_revenue'].id,
}),
]
})
cls.invoice.action_post()
cls.accrual_account = cls.env['account.account'].create({
'name': "test_accrual_account",
'code': "TEST",
'user_type_id': cls.env.ref('account.data_account_type_revenue').id,
'reconcile': True,
'company_id': cls.company_data['company'].id,
})
cls.income_account = cls.company_data['default_account_revenue']
cls.Wizard = cls.env['account.automatic.entry.wizard']\
.with_context(active_model='account.move.line', active_ids=cls.invoice.invoice_line_ids.ids)
def test_chg_period_100_percent_no_time_division(self):
''' Test smoothing the invoice in the period without the time division. '''
to_date = lambda string: fields.Date.from_string(string)
wizard = self.Wizard.create({
'action': 'change_period',
'journal_id': self.company_data['default_journal_misc'].id,
'revenue_accrual_account': self.accrual_account.id,
'chg_period_date_from': '2017-06-01',
'chg_period_date_to': '2017-12-31', # Large period to check the rounding issues.
'chg_period_percentage': 100.0,
'chg_period_time_division': False,
})
wizard_res = wizard.do_action()
lines = self.env['account.move'].browse(wizard_res['domain'][0][2]).line_ids.sorted(lambda line: (line.date, -abs(line.balance), -line.balance))
dest_lines = lines.filtered(lambda line: line.date == self.invoice.date)
accrual_lines = lines.filtered(lambda line: line.date != self.invoice.date)
self.assertRecordValues(dest_lines, [
{'debit': 1000.0, 'credit': 0.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-01-01')},
{'debit': 0.0, 'credit': 1000.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-01-01')},
{'debit': 200.0, 'credit': 0.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-01-01')},
{'debit': 0.0, 'credit': 200.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-01-01')},
])
self.assertRecordValues(accrual_lines, [
{'debit': 142.86, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-06-30')},
{'debit': 0.0, 'credit': 142.86, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-06-30')},
{'debit': 28.57, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-06-30')},
{'debit': 0.0, 'credit': 28.57, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-06-30')},
{'debit': 142.86, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-07-31')},
{'debit': 0.0, 'credit': 142.86, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-07-31')},
{'debit': 28.57, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-07-31')},
{'debit': 0.0, 'credit': 28.57, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-07-31')},
{'debit': 142.86, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-08-31')},
{'debit': 0.0, 'credit': 142.86, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-08-31')},
{'debit': 28.57, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-08-31')},
{'debit': 0.0, 'credit': 28.57, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-08-31')},
{'debit': 142.86, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-09-30')},
{'debit': 0.0, 'credit': 142.86, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-09-30')},
{'debit': 28.57, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-09-30')},
{'debit': 0.0, 'credit': 28.57, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-09-30')},
{'debit': 142.86, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-10-31')},
{'debit': 0.0, 'credit': 142.86, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-10-31')},
{'debit': 28.57, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-10-31')},
{'debit': 0.0, 'credit': 28.57, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-10-31')},
{'debit': 142.86, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-11-30')},
{'debit': 0.0, 'credit': 142.86, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-11-30')},
{'debit': 28.57, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-11-30')},
{'debit': 0.0, 'credit': 28.57, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-11-30')},
{'debit': 142.84, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-12-31')},
{'debit': 0.0, 'credit': 142.84, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-12-31')},
{'debit': 28.58, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-12-31')},
{'debit': 0.0, 'credit': 28.58, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-12-31')},
])
def test_chg_period_100_percent_time_division(self):
''' Same as test_chg_period_100_percent_no_time_division using the time division meaning the smoothing is made
to different months considering their number of days.
'''
to_date = lambda string: fields.Date.from_string(string)
wizard = self.Wizard.create({
'action': 'change_period',
'journal_id': self.company_data['default_journal_misc'].id,
'revenue_accrual_account': self.accrual_account.id,
'chg_period_date_from': '2017-06-01',
'chg_period_date_to': '2017-12-31', # Large period to check the rounding issues.
'chg_period_percentage': 100.0,
'chg_period_time_division': True,
})
wizard_res = wizard.do_action()
lines = self.env['account.move'].browse(wizard_res['domain'][0][2]).line_ids.sorted(lambda line: (line.date, -abs(line.balance), -line.balance))
dest_lines = lines.filtered(lambda line: line.date == self.invoice.date)
accrual_lines = lines.filtered(lambda line: line.date != self.invoice.date)
self.assertRecordValues(dest_lines, [
{'debit': 1000.0, 'credit': 0.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-01-01')},
{'debit': 0.0, 'credit': 1000.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-01-01')},
{'debit': 200.0, 'credit': 0.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-01-01')},
{'debit': 0.0, 'credit': 200.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-01-01')},
])
self.assertRecordValues(accrual_lines, [
{'debit': 140.1, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-06-30')},
{'debit': 0.0, 'credit': 140.1, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-06-30')},
{'debit': 28.02, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-06-30')},
{'debit': 0.0, 'credit': 28.02, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-06-30')},
{'debit': 144.93, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-07-31')},
{'debit': 0.0, 'credit': 144.93, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-07-31')},
{'debit': 28.99, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-07-31')},
{'debit': 0.0, 'credit': 28.99, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-07-31')},
{'debit': 144.93, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-08-31')},
{'debit': 0.0, 'credit': 144.93, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-08-31')},
{'debit': 28.99, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-08-31')},
{'debit': 0.0, 'credit': 28.99, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-08-31')},
{'debit': 140.1, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-09-30')},
{'debit': 0.0, 'credit': 140.1, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-09-30')},
{'debit': 28.02, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-09-30')},
{'debit': 0.0, 'credit': 28.02, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-09-30')},
{'debit': 144.93, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-10-31')},
{'debit': 0.0, 'credit': 144.93, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-10-31')},
{'debit': 28.99, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-10-31')},
{'debit': 0.0, 'credit': 28.99, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-10-31')},
{'debit': 140.1, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-11-30')},
{'debit': 0.0, 'credit': 140.1, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-11-30')},
{'debit': 28.02, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-11-30')},
{'debit': 0.0, 'credit': 28.02, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-11-30')},
{'debit': 144.91, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-12-31')},
{'debit': 0.0, 'credit': 144.91, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-12-31')},
{'debit': 28.97, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-12-31')},
{'debit': 0.0, 'credit': 28.97, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-12-31')},
])
def test_chg_period_manual_periods(self):
''' Test the smoothing by manual lines. '''
to_date = lambda string: fields.Date.from_string(string)
wizard = self.Wizard.create({
'action': 'change_period',
'journal_id': self.company_data['default_journal_misc'].id,
'revenue_accrual_account': self.accrual_account.id,
'chg_period_line_ids': [
(0, 0, {'date': '2017-06-01', 'balance': 120.0}),
(0, 0, {'date': '2017-07-01', 'balance': 300.0}),
(0, 0, {'date': '2017-08-01', 'balance': 700.0}),
(0, 0, {'date': '2017-09-01', 'balance': 80.0}),
],
})
wizard_res = wizard.do_action()
lines = self.env['account.move'].browse(wizard_res['domain'][0][2]).line_ids.sorted(lambda line: (line.date, -abs(line.balance), -line.balance))
dest_lines = lines.filtered(lambda line: line.date == self.invoice.date)
accrual_lines = lines.filtered(lambda line: line.date != self.invoice.date)
self.assertRecordValues(dest_lines, [
{'debit': 1000.0, 'credit': 0.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-01-01')},
{'debit': 0.0, 'credit': 1000.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-01-01')},
{'debit': 200.0, 'credit': 0.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-01-01')},
{'debit': 0.0, 'credit': 200.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-01-01')},
])
self.assertRecordValues(accrual_lines, [
{'debit': 100.0, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-06-01')},
{'debit': 0.0, 'credit': 100.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-06-01')},
{'debit': 20.0, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-06-01')},
{'debit': 0.0, 'credit': 20.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-06-01')},
{'debit': 250.0, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-07-01')},
{'debit': 0.0, 'credit': 250.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-07-01')},
{'debit': 50.0, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-07-01')},
{'debit': 0.0, 'credit': 50.0, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-07-01')},
{'debit': 583.33, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-08-01')},
{'debit': 0.0, 'credit': 583.33, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-08-01')},
{'debit': 116.67, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-08-01')},
{'debit': 0.0, 'credit': 116.67, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-08-01')},
{'debit': 66.67, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-09-01')},
{'debit': 0.0, 'credit': 66.67, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-09-01')},
{'debit': 13.33, 'credit': 0.0, 'account_id': self.accrual_account.id, 'reconciled': True, 'date': to_date('2017-09-01')},
{'debit': 0.0, 'credit': 13.33, 'account_id': self.income_account.id, 'reconciled': False, 'date': to_date('2017-09-01')},
])
@@ -1656,3 +1656,108 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon):
'amount_total' : self.move_vals['amount_total'],
'amount_untaxed' : self.move_vals['amount_untaxed'],
})
def test_in_invoice_change_period_accrual_1(self):
move = self.env['account.move'].create({
'move_type': 'in_invoice',
'date': '2017-01-01',
'partner_id': self.partner_a.id,
'invoice_date': fields.Date.from_string('2017-01-01'),
'currency_id': self.currency_data['currency'].id,
'invoice_payment_term_id': self.pay_terms_a.id,
'invoice_line_ids': [
(0, None, {
'name': self.product_line_vals_1['name'],
'product_id': self.product_line_vals_1['product_id'],
'product_uom_id': self.product_line_vals_1['product_uom_id'],
'quantity': self.product_line_vals_1['quantity'],
'price_unit': self.product_line_vals_1['price_unit'],
'tax_ids': self.product_line_vals_1['tax_ids'],
}),
(0, None, {
'name': self.product_line_vals_2['name'],
'product_id': self.product_line_vals_2['product_id'],
'product_uom_id': self.product_line_vals_2['product_uom_id'],
'quantity': self.product_line_vals_2['quantity'],
'price_unit': self.product_line_vals_2['price_unit'],
'tax_ids': self.product_line_vals_2['tax_ids'],
}),
]
})
move.action_post()
wizard = self.env['account.automatic.entry.wizard']\
.with_context(active_model='account.move.line', active_ids=move.invoice_line_ids.ids).create({
'action': 'change_period',
'date': '2018-01-01',
'percentage': 60,
'journal_id': self.company_data['default_journal_misc'].id,
'expense_accrual_account': 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,
}).id,
'revenue_accrual_account': 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,
}).id,
})
wizard_res = wizard.do_action()
self.assertInvoiceValues(move, [
{
**self.product_line_vals_1,
'currency_id': self.currency_data['currency'].id,
'amount_currency': 800.0,
'debit': 400.0,
'credit': 0.0,
},
{
**self.product_line_vals_2,
'currency_id': self.currency_data['currency'].id,
'amount_currency': 160.0,
'debit': 80.0,
'credit': 0.0,
},
{
**self.tax_line_vals_1,
'currency_id': self.currency_data['currency'].id,
'amount_currency': 144.0,
'debit': 72.0,
'credit': 0.0,
},
{
**self.tax_line_vals_2,
'currency_id': self.currency_data['currency'].id,
'amount_currency': 24.0,
'debit': 12.0,
'credit': 0.0,
},
{
**self.term_line_vals_1,
'currency_id': self.currency_data['currency'].id,
'amount_currency': -1128.0,
'debit': 0.0,
'credit': 564.0,
'date_maturity': fields.Date.from_string('2017-01-01'),
},
], {
**self.move_vals,
'currency_id': self.currency_data['currency'].id,
'date': fields.Date.from_string('2017-01-01'),
})
accrual_lines = self.env['account.move'].browse(wizard_res['domain'][0][2]).line_ids.sorted('date')
self.assertRecordValues(accrual_lines, [
{'amount_currency': -480.0, 'debit': 0.0, 'credit': 240.0, 'account_id': self.product_line_vals_1['account_id'], 'reconciled': False},
{'amount_currency': 480.0, 'debit': 240.0, 'credit': 0.0, 'account_id': wizard.expense_accrual_account.id, 'reconciled': True},
{'amount_currency': -96.0, 'debit': 0.0, 'credit': 48.0, 'account_id': self.product_line_vals_2['account_id'], 'reconciled': False},
{'amount_currency': 96.0, 'debit': 48.0, 'credit': 0.0, 'account_id': wizard.expense_accrual_account.id, 'reconciled': True},
{'amount_currency': 480.0, 'debit': 240.0, 'credit': 0.0, 'account_id': self.product_line_vals_1['account_id'], 'reconciled': False},
{'amount_currency': -480.0, 'debit': 0.0, 'credit': 240.0, 'account_id': wizard.expense_accrual_account.id, 'reconciled': True},
{'amount_currency': 96.0, 'debit': 48.0, 'credit': 0.0, 'account_id': self.product_line_vals_2['account_id'], 'reconciled': False},
{'amount_currency': -96.0, 'debit': 0.0, 'credit': 48.0, 'account_id': wizard.expense_accrual_account.id, 'reconciled': True},
])
@@ -2424,6 +2424,113 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
'amount_untaxed' : self.move_vals['amount_untaxed'],
})
def test_out_invoice_change_period_accrual_1(self):
move = self.env['account.move'].create({
'move_type': 'out_invoice',
'date': '2017-01-01',
'partner_id': self.partner_a.id,
'invoice_date': fields.Date.from_string('2017-01-01'),
'currency_id': self.currency_data['currency'].id,
'invoice_payment_term_id': self.pay_terms_a.id,
'invoice_line_ids': [
(0, None, {
'name': self.product_line_vals_1['name'],
'product_id': self.product_line_vals_1['product_id'],
'product_uom_id': self.product_line_vals_1['product_uom_id'],
'quantity': self.product_line_vals_1['quantity'],
'price_unit': self.product_line_vals_1['price_unit'],
'tax_ids': self.product_line_vals_1['tax_ids'],
}),
(0, None, {
'name': self.product_line_vals_2['name'],
'product_id': self.product_line_vals_2['product_id'],
'product_uom_id': self.product_line_vals_2['product_uom_id'],
'quantity': self.product_line_vals_2['quantity'],
'price_unit': self.product_line_vals_2['price_unit'],
'tax_ids': self.product_line_vals_2['tax_ids'],
}),
]
})
move.action_post()
wizard = self.env['account.automatic.entry.wizard']\
.with_context(active_model='account.move.line', active_ids=move.invoice_line_ids.ids).create({
'action': 'change_period',
'date': '2018-01-01',
'percentage': 60,
'journal_id': self.company_data['default_journal_misc'].id,
'expense_accrual_account': 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,
}).id,
'revenue_accrual_account': 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,
}).id,
})
wizard_res = wizard.do_action()
self.assertInvoiceValues(move, [
{
**self.product_line_vals_1,
'currency_id': self.currency_data['currency'].id,
'amount_currency': -1000.0,
'debit': 0.0,
'credit': 500.0,
},
{
**self.product_line_vals_2,
'currency_id': self.currency_data['currency'].id,
'amount_currency': -200.0,
'debit': 0.0,
'credit': 100.0,
},
{
**self.tax_line_vals_1,
'currency_id': self.currency_data['currency'].id,
'amount_currency': -180.0,
'debit': 0.0,
'credit': 90.0,
},
{
**self.tax_line_vals_2,
'currency_id': self.currency_data['currency'].id,
'amount_currency': -30.0,
'debit': 0.0,
'credit': 15.0,
},
{
**self.term_line_vals_1,
'currency_id': self.currency_data['currency'].id,
'name': 'INV/2017/01/0001',
'amount_currency': 1410.0,
'debit': 705.0,
'credit': 0.0,
'date_maturity': fields.Date.from_string('2017-01-01'),
},
], {
**self.move_vals,
'currency_id': self.currency_data['currency'].id,
'date': fields.Date.from_string('2017-01-01'),
'payment_reference': 'INV/2017/01/0001',
})
accrual_lines = self.env['account.move'].browse(wizard_res['domain'][0][2]).line_ids.sorted('date')
self.assertRecordValues(accrual_lines, [
{'amount_currency': 600.0, 'debit': 300.0, 'credit': 0.0, 'account_id': self.product_line_vals_1['account_id'], 'reconciled': False},
{'amount_currency': -600.0, 'debit': 0.0, 'credit': 300.0, 'account_id': wizard.revenue_accrual_account.id, 'reconciled': True},
{'amount_currency': 120.0, 'debit': 60.0, 'credit': 0.0, 'account_id': self.product_line_vals_2['account_id'], 'reconciled': False},
{'amount_currency': -120.0, 'debit': 0.0, 'credit': 60.0, 'account_id': wizard.revenue_accrual_account.id, 'reconciled': True},
{'amount_currency': -600.0, 'debit': 0.0, 'credit': 300.0, 'account_id': self.product_line_vals_1['account_id'], 'reconciled': False},
{'amount_currency': 600.0, 'debit': 300.0, 'credit': 0.0, 'account_id': wizard.revenue_accrual_account.id, 'reconciled': True},
{'amount_currency': -120.0, 'debit': 0.0, 'credit': 60.0, 'account_id': self.product_line_vals_2['account_id'], 'reconciled': False},
{'amount_currency': 120.0, 'debit': 60.0, 'credit': 0.0, 'account_id': wizard.revenue_accrual_account.id, 'reconciled': True},
])
def test_out_invoice_filter_zero_balance_lines(self):
zero_balance_payment_term = self.env['account.payment.term'].create({
'name': 'zero_balance_payment_term',
+1 -1
View File
@@ -1006,7 +1006,7 @@
<button name="action_automatic_entry"
type="object"
icon="fa-calendar"
string="Re-allocate"
string="Cut-Off"
aria-label="Change Period"
class="float-right"
attrs="{'invisible': [('account_internal_group', 'not in', ('income', 'expense'))], 'column_invisible': [('parent.move_type', '=', 'entry')]}"
@@ -5,10 +5,8 @@ from odoo.tools.misc import format_date, formatLang
from collections import defaultdict
from itertools import groupby
from dateutil.relativedelta import relativedelta
import json
class AutomaticEntryWizard(models.TransientModel):
_name = 'account.automatic.entry.wizard'
_description = 'Create Automatic Entries'
@@ -18,21 +16,18 @@ class AutomaticEntryWizard(models.TransientModel):
move_data = fields.Text(compute="_compute_move_data", help="JSON value of the moves to be created")
preview_move_data = fields.Text(compute="_compute_preview_move_data", help="JSON value of the data to be displayed in the previewer")
move_line_ids = fields.Many2many('account.move.line')
date = fields.Date(required=True, default=lambda self: fields.Date.context_today(self))
company_id = fields.Many2one('res.company', required=True, readonly=True)
company_currency_id = fields.Many2one('res.currency', related='company_id.currency_id')
total_amount = fields.Monetary(
compute='_compute_from_move_line_ids',
currency_field='company_currency_id',
help="Total amount impacted by the automatic entry.")
percentage = fields.Float("Percentage", compute='_compute_percentage', readonly=False, store=True, help="Percentage of each line to execute the action on.")
total_amount = fields.Monetary(compute='_compute_total_amount', store=True, readonly=False, currency_field='company_currency_id', help="Total amount impacted by the automatic entry.")
journal_id = fields.Many2one('account.journal', required=True, readonly=False, string="Journal",
domain="[('company_id', '=', company_id), ('type', '=', 'general')]",
related="company_id.automatic_entry_default_journal_id",
help="Journal where to create the entry.")
# change period
account_type = fields.Selection(
selection=[('income', 'Revenue'), ('expense', 'Expense')],
compute='_compute_from_move_line_ids')
account_type = fields.Selection([('income', 'Revenue'), ('expense', 'Expense')], compute='_compute_account_type', store=True)
expense_accrual_account = fields.Many2one('account.account', readonly=False,
domain="[('company_id', '=', company_id),"
"('internal_type', 'not in', ('receivable', 'payable')),"
@@ -43,105 +38,38 @@ class AutomaticEntryWizard(models.TransientModel):
"('internal_type', 'not in', ('receivable', 'payable')),"
"('is_off_balance', '=', False)]",
related="company_id.revenue_accrual_account_id")
chg_period_date_from = fields.Date(
string="Date from",
default=lambda self: fields.Date.context_today(self),
help="Date at which the smoothing of the balance will start.")
chg_period_date_to = fields.Date(
string="Date to",
default=lambda self: fields.Date.context_today(self),
help="Date at which the smoothing of the balance will end.")
chg_period_time_division = fields.Boolean(
string="Time Division",
help="Allocate the balance to different periods considering their number of days.")
chg_period_percentage = fields.Float(string="Percentage", default=100.0)
chg_period_line_ids = fields.One2many(
comodel_name='account.automatic.entry.wizard.line',
inverse_name='wizard_id',
string='Lines',
store=True, readonly=False,
compute='_compute_chg_period_line_ids')
chg_period_warning_message = fields.Text(
string="Warning",
compute='_compute_chg_period_warning_message')
# change account
date = fields.Date(string="Transfer Date", default=lambda self: fields.Date.context_today(self))
destination_account_id = fields.Many2one(string="To", comodel_name='account.account', help="Account to transfer to.")
display_currency_helper = fields.Boolean(string="Currency Conversion Helper", compute='_compute_display_currency_helper',
help="Technical field. Used to indicate whether or not to display the currency conversion tooltip. The tooltip informs a currency conversion will be performed with the transfer.")
def _get_total_balance(self):
self.ensure_one()
return sum(line.amount_residual if line.account_id.reconcile else line.balance for line in self.move_line_ids)
@api.constrains('percentage', 'action')
def _constraint_percentage(self):
for record in self:
if not (0.0 < record.percentage <= 100.0):
raise UserError(_("Percentage must be between 0 and 100"))
if record.percentage != 100 and record.action != 'change_period':
raise UserError(_("Percentage can only be set for Change Period method"))
@api.depends('chg_period_date_from', 'chg_period_date_to', 'chg_period_time_division', 'chg_period_percentage')
def _compute_chg_period_line_ids(self):
''' Create the lines representing the way the balance will be smoothed per period. '''
for wizard in self:
one2many_commands = [(5, 0)]
@api.depends('percentage', 'move_line_ids')
def _compute_total_amount(self):
for record in self:
record.total_amount = (record.percentage or 100) * sum(record.move_line_ids.mapped('balance')) / 100
date_from = wizard.chg_period_date_from
date_to = wizard.chg_period_date_to
percentage = (wizard.chg_period_percentage or 0.0) / 100.0
if date_from and date_to and percentage:
total_balance = wizard.company_currency_id.round(wizard._get_total_balance() * percentage)
total_days = 0.0
date_distribution = []
while date_from <= date_to:
next_month_date = (date_from + relativedelta(months=1)).replace(day=1)
period_date = next_month_date - relativedelta(days=1)
period_days = (period_date - date_from).days
date_distribution.append((period_date, period_days))
date_from = next_month_date
total_days += period_days
total_reported_balance = 0.0
for period_date, nb_days in date_distribution:
if wizard.chg_period_time_division:
period_balance = wizard.company_currency_id.round(total_balance * nb_days / total_days)
else:
period_balance = wizard.company_currency_id.round(total_balance / len(date_distribution))
one2many_commands.append((0, 0, {
'wizard_id': wizard.id,
'date': period_date,
'balance': period_balance,
}))
total_reported_balance += period_balance
# When the percentage is 100%, ensure the full balance is dispatched into the periods.
# To avoid a huge gap in the last line, we ensure the rounding error is also smoothed.
# For example: smoothing 100 into 12 months:
# 12 lines of 8.33 are generated at this point. Since 8.33 * 12 = 99.96, the error of 0.04 will be
# smoothed by adding 0.01 to the last 4 periods.
if wizard.chg_period_percentage == 100.0:
total_rounding_error = wizard.company_currency_id.round(total_balance - total_reported_balance)
nber_rounding_steps = int(abs(total_rounding_error / wizard.company_currency_id.rounding))
rounding_error = round(
nber_rounding_steps and total_rounding_error / nber_rounding_steps or 0.0,
wizard.company_currency_id.decimal_places,
)
nber_periods = len(one2many_commands) - 1
if len(one2many_commands) > nber_rounding_steps:
for i in range(nber_rounding_steps):
one2many_commands[nber_periods - i][2]['balance'] += rounding_error
wizard.chg_period_line_ids = one2many_commands
@api.depends('chg_period_date_from', 'chg_period_date_to')
def _compute_chg_period_warning_message(self):
for wizard in self:
if wizard.chg_period_date_from and wizard.chg_period_date_to and wizard.chg_period_date_from > wizard.chg_period_date_to:
wizard.chg_period_warning_message = _("Check the dates. The period cannot start later than its own end.")
@api.depends('total_amount', 'move_line_ids')
def _compute_percentage(self):
for record in self:
total = (sum(record.move_line_ids.mapped('balance')) or record.total_amount)
if total != 0:
record.percentage = (record.total_amount / total) * 100
else:
wizard.chg_period_warning_message = False
record.percentage = 100
@api.depends('move_line_ids.balance')
def _compute_from_move_line_ids(self):
for wizard in self:
wizard.total_amount = wizard._get_total_balance()
wizard.account_type = 'income' if wizard.total_amount < 0.0 else 'expense'
@api.depends('move_line_ids')
def _compute_account_type(self):
for record in self:
record.account_type = 'income' if sum(record.move_line_ids.mapped('balance')) < 0 else 'expense'
@api.depends('destination_account_id')
def _compute_display_currency_helper(self):
@@ -239,113 +167,80 @@ class AutomaticEntryWizard(models.TransientModel):
def _get_move_dict_vals_change_period(self):
# set the change_period account on the selected journal items
accrual_account = self.revenue_accrual_account if self.account_type == 'income' else self.expense_accrual_account
total_percentage = sum(self.chg_period_line_ids.mapped('percentage'))
move_data = {
'original_dates': {},
'new_dates': {},
}
# ==== Prepare journal entries (account.move) ====
for date, grouped_lines in groupby(self.move_line_ids, lambda line: line.date):
move_data = {'new_date': {
'currency_id': self.journal_id.currency_id.id or self.journal_id.company_id.currency_id.id,
'move_type': 'entry',
'line_ids': [],
'ref': _('Adjusting Entry'),
'date': fields.Date.to_string(self.date),
'journal_id': self.journal_id.id,
}}
# complete the account.move data
for date, grouped_lines in groupby(self.move_line_ids, lambda m: m.move_id.date):
grouped_lines = list(grouped_lines)
amount = sum(l.balance for l in grouped_lines)
move_data['original_dates'][date] = {
move_data[date] = {
'currency_id': self.journal_id.currency_id.id or self.journal_id.company_id.currency_id.id,
'move_type': 'entry',
'line_ids': [],
'ref': self._format_strings(_('Adjusting Entry of {date} ({percent:f}% recognized on {new_date})'), grouped_lines[0].move_id, amount),
'date': fields.Date.to_string(date),
'journal_id': self.journal_id.id,
'line_ids': [],
}
for line in self.chg_period_line_ids:
ref = _("Adjusting Entry made on {date} ({percent:f}%)").format(
date=format_date(self.env, line.date),
percent=line.percentage,
)
move_data['new_dates'][line.date] = {
'move_type': 'entry',
'ref': ref,
'date': fields.Date.to_string(line.date),
'journal_id': self.journal_id.id,
'line_ids': [],
}
# ==== Prepare journal items (account.move.line) ====
# compute the account.move.lines and the total amount per move
for aml in self.move_line_ids:
# account.move.line data
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)
reported_amount_currency = aml.currency_id.round((self.percentage / 100) * aml.amount_currency)
total_reported_balance = 0.0
total_reported_amount_currency = 0.0
# Avoid rounding issues with 100%.
if round(total_percentage, 2) == 100.0:
total_balance_to_report = aml.balance
total_amount_currency_to_report = aml.amount_currency
else:
total_balance_to_report = aml.company_currency_id.round((total_percentage / 100) * aml.balance)
total_amount_currency_to_report = aml.currency_id.round((total_percentage / 100) * aml.amount_currency)
for i, line in enumerate(self.chg_period_line_ids):
# Avoid rounding issue on the last line.
if i == len(self.chg_period_line_ids) - 1:
reported_balance = total_balance_to_report - total_reported_balance
reported_amount_currency = total_amount_currency_to_report - total_reported_amount_currency
else:
reported_balance = aml.company_currency_id.round((line.percentage / 100) * aml.balance)
reported_amount_currency = aml.currency_id.round((line.percentage / 100) * aml.amount_currency)
total_reported_balance += reported_balance
total_reported_amount_currency += reported_amount_currency
move_data['new_dates'][line.date]['line_ids'] += [
(0, 0, {
'name': aml.name or '',
'currency_id': aml.currency_id.id,
'account_id': aml.account_id.id,
'partner_id': aml.partner_id.id,
'debit': reported_balance if reported_balance > 0.0 else 0.0,
'credit': -reported_balance if reported_balance < 0.0 else 0.0,
'amount_currency': reported_amount_currency,
}),
(0, 0, {
'name': _('Adjusting Entry'),
'currency_id': aml.currency_id.id,
'account_id': accrual_account.id,
'partner_id': aml.partner_id.id,
'debit': -reported_balance if reported_balance < 0.0 else 0.0,
'credit': reported_balance if reported_balance > 0.0 else 0.0,
'amount_currency': -reported_amount_currency,
}),
]
move_data['original_dates'][aml.date]['line_ids'] += [
move_data['new_date']['line_ids'] += [
(0, 0, {
'name': aml.name or '',
'debit': reported_debit,
'credit': reported_credit,
'amount_currency': reported_amount_currency,
'currency_id': aml.currency_id.id,
'account_id': aml.account_id.id,
'partner_id': aml.partner_id.id,
'debit': -total_reported_balance if total_reported_balance < 0.0 else 0.0,
'credit': total_reported_balance if total_reported_balance > 0.0 else 0.0,
'amount_currency': -total_reported_amount_currency,
}),
(0, 0, {
'name': _('Adjusting Entry'),
'debit': reported_credit,
'credit': reported_debit,
'amount_currency': -reported_amount_currency,
'currency_id': aml.currency_id.id,
'account_id': accrual_account.id,
'partner_id': aml.partner_id.id,
}),
]
move_data[aml.move_id.date]['line_ids'] += [
(0, 0, {
'name': aml.name or '',
'debit': reported_credit,
'credit': reported_debit,
'amount_currency': -reported_amount_currency,
'currency_id': aml.currency_id.id,
'account_id': aml.account_id.id,
'partner_id': aml.partner_id.id,
}),
(0, 0, {
'name': _('Adjusting Entry'),
'debit': reported_debit,
'credit': reported_credit,
'amount_currency': reported_amount_currency,
'currency_id': aml.currency_id.id,
'account_id': accrual_account.id,
'partner_id': aml.partner_id.id,
'debit': total_reported_balance if total_reported_balance > 0.0 else 0.0,
'credit': -total_reported_balance if total_reported_balance < 0.0 else 0.0,
'amount_currency': total_reported_amount_currency,
}),
]
return list(move_data['original_dates'].values()) + list(move_data['new_dates'].values())
move_vals = [m for m in move_data.values()]
return move_vals
@api.depends('move_line_ids', 'journal_id', 'revenue_accrual_account', 'expense_accrual_account',
'date', 'account_type', 'action', 'destination_account_id',
'chg_period_line_ids')
@api.depends('move_line_ids', 'journal_id', 'revenue_accrual_account', 'expense_accrual_account', 'percentage', 'date', 'account_type', 'action', 'destination_account_id')
def _compute_move_data(self):
for record in self:
if record.action == 'change_period':
@@ -392,44 +287,28 @@ class AutomaticEntryWizard(models.TransientModel):
def _do_action_change_period(self, move_vals):
accrual_account = self.revenue_accrual_account if self.account_type == 'income' else self.expense_accrual_account
# ==== Create new journal entries ====
created_moves = self.env['account.move'].create(move_vals)
created_moves._post()
# ==== Manage chatters ====
destination_move = created_moves[0]
accrual_moves = created_moves[1:]
messages_from = [_("<li>%(link)s</li>", link=self._format_move_link(move)) for move in self.move_line_ids.move_id]
messages_from = ''.join([_("Adjusting Entry generated for these journal entries:<ul>")] + messages_from + ["</ul>"])
messages_to = [_("Adjusting Entries created:<ul>")]
messages_to.append(self._format_strings(
_("<li>%(link)s cancelling {percent:f}%% of {amount}</li>", link=self._format_move_link(destination_move)),
destination_move, self.total_amount,
))
for accrual_move in accrual_moves:
messages_to.append(self._format_strings(
_("<li>%(link)s postponing it to {new_date}</li>", link=self._format_move_link(accrual_move)),
accrual_move, 0.0,
))
messages_to = ''.join(messages_to + ["</ul>"])
destination_messages = []
for move in self.move_line_ids.move_id:
move.message_post(body=messages_to)
destination_move.message_post(body=messages_from)
for accrual_move in accrual_moves:
accrual_move.message_post(body=messages_from)
amount = sum((self.move_line_ids._origin & move.line_ids).mapped('balance'))
accrual_move = created_moves[1:].filtered(lambda m: m.date == move.date)
# ==== Reconcile ====
if accrual_account.reconcile and all(move.state == 'posted' for move in created_moves):
created_moves.line_ids.filtered(lambda line: line.account_id == accrual_account and not line.reconciled).reconcile()
# ==== Redirect ====
if accrual_account.reconcile:
to_reconcile = (accrual_move + destination_move).mapped('line_ids').filtered(lambda line: line.account_id == accrual_account)
to_reconcile.reconcile()
move.message_post(body=self._format_strings(_('Adjusting Entries have been created for this invoice:<ul><li>%(link1)s cancelling '
'{percent:f}%% of {amount}</li><li>%(link0)s postponing it to {new_date}</li></ul>',
link0=self._format_move_link(destination_move),
link1=self._format_move_link(accrual_move),
), move, amount))
destination_messages += [self._format_strings(_('Adjusting Entry {link}: {percent:f}% of {amount} recognized from {date}'), move, amount)]
accrual_move.message_post(body=self._format_strings(_('Adjusting Entry for {link}: {percent:f}% of {amount} recognized on {new_date}'), move, amount))
destination_move.message_post(body='<br/>\n'.join(destination_messages))
# open the generated entries
action = {
'name': _('Generated Entries'),
'domain': [('id', 'in', created_moves.ids)],
@@ -510,7 +389,7 @@ class AutomaticEntryWizard(models.TransientModel):
def _format_strings(self, string, move, amount):
return string.format(
percent=sum(self.chg_period_line_ids.mapped('percentage')),
percent=self.percentage,
name=move.name,
id=move.id,
amount=formatLang(self.env, abs(amount), currency_obj=self.company_id.currency_id),
@@ -520,43 +399,3 @@ class AutomaticEntryWizard(models.TransientModel):
new_date=self.date and format_date(self.env, self.date) or _('[Not set]'),
account_target_name=self.destination_account_id.display_name,
)
class AutomaticEntryWizardLine(models.TransientModel):
_name = "account.automatic.entry.wizard.line"
_description = "Create Automatic Entries Line"
wizard_id = fields.Many2one(
comodel_name='account.automatic.entry.wizard',
required=True, readonly=True, ondelete='cascade')
date = fields.Date(
string="Date",
required=True,
default=lambda self: fields.Date.context_today(self))
percentage = fields.Float(
string="Percentage",
store=True, readonly=False,
compute='_compute_percentage',
help="Percentage of each line to execute the action on.")
balance = fields.Monetary(
string="Amount",
store=True, readonly=False,
compute='_compute_balance',
currency_field='company_currency_id',
help="Total amount impacted by the automatic entry.")
# ==== Display purpose fields ====
company_currency_id = fields.Many2one(
comodel_name='res.currency',
related='wizard_id.company_id.currency_id')
@api.depends('balance')
def _compute_percentage(self):
for line in self:
total = abs(line.wizard_id._get_total_balance())
line.percentage = total and (abs(line.balance) / total) * 100.0 or 0.0
@api.depends('percentage')
def _compute_balance(self):
for line in self:
line.balance = line.company_currency_id.round((line.percentage / 100.0) * line.wizard_id._get_total_balance())
@@ -9,85 +9,34 @@
<field name="account_type" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="display_currency_helper" invisible="1"/>
<div attrs="{'invisible': [('display_currency_helper', '=', False)]}" class="alert alert-info text-center" role="status">
The selected destination account is set to use a specific currency. Every entry transferred to it will be converted into this currency, causing
the loss of any pre-existing foreign currency amount.
</div>
<div class="alert alert-warning"
role="alert"
style="margin-bottom:0px;"
attrs="{'invisible': ['|', ('action', '!=', 'change_period'), ('chg_period_warning_message', '=', False)]}">
<field name="chg_period_warning_message" nolabel="1"/>
</div>
<field name="action" invisible="context.get('hide_automatic_options')" widget="radio" options="{'horizontal': true}"/>
<group>
<group>
<field name="total_amount"/>
<field name="journal_id"/>
</group>
<group attrs="{'invisible': [('action', '!=', 'change_period')]}">
<field name="expense_accrual_account"
string="Accrued Account"
<field name="date" string="Recognition Date"/>
<field name="expense_accrual_account" string="Accrued Account"
attrs="{'invisible': [('account_type', '!=', 'expense')], 'required': [('account_type', '=', 'expense'), ('action', '=', 'change_period')]}"/>
<field name="revenue_accrual_account"
string="Accrued Account"
<field name="revenue_accrual_account" string="Accrued Account"
attrs="{'invisible': [('account_type', '!=', 'income')], 'required': [('account_type', '=', 'income'), ('action', '=', 'change_period')]}"/>
</group>
<group attrs="{'invisible': [('action', '!=', 'change_account')]}">
<field name="date"/>
<field name="destination_account_id"
attrs="{'required': [('action', '=', 'change_account')]}"
domain="[('company_id', '=', company_id)]"/>
<field name="date" string="Transfer Date"/>
<field name="destination_account_id" attrs="{'required': [('action', '=', 'change_account')]}" domain="[('company_id', '=', company_id)]"/>
</group>
<group>
<label for="total_amount" string="Adjusting Amount" attrs="{'invisible': [('action', '!=', 'change_period')]}"/>
<div attrs="{'invisible': [('action', '!=', 'change_period')]}">
<field name="percentage" style="width:40% !important" class="oe_inline" attrs="{'readonly': [('action', '!=', 'change_period')]}"/>%<span class="px-3"></span>(<field name="total_amount" class="oe_inline"/>)
</div>
<field name="total_amount" readonly="1" attrs="{'invisible': [('action', '=', 'change_period')]}"/>
<field name="journal_id"/>
</group>
</group>
<notebook>
<page string="Automatic re-allocation"
attrs="{'invisible': [('action', '!=', 'change_period')]}">
<span>Create one journal entry per month automatically</span>
<group>
<group>
<label for="chg_period_date_from" string="From"/>
<div class="d-flex">
<field name="chg_period_date_from"/>
<span class="oe_inline o_form_label mx-3"> to </span>
<field name="chg_period_date_to"/>
</div>
<field name="chg_period_time_division"/>
</group>
<group>
<label for="chg_period_percentage" string="Re-allocation percentage"/>
<div class="d-flex">
<field name="chg_period_percentage"/>
<span class="oe_inline o_form_label mx-3">%</span>
</div>
</group>
</group>
</page>
<page string="Manual re-allocation" attrs="{'invisible': [('action', '!=', 'change_period')]}">
<field name="chg_period_line_ids">
<tree editable="bottom" default_order="date desc">
<field name="company_currency_id" invisible="1"/>
<field name="date"/>
<field name="percentage" sum="Total Percentage"/>
<field name="balance" sum="Total Balance"/>
</tree>
</field>
</page>
<page string="Preview">
<label for="preview_move_data" string="The following Journal Entries will be generated"/>
<field name="preview_move_data" widget="grouped_view_widget"/>
</page>
</notebook>
<label for="preview_move_data" string="The following Journal Entries will be generated"/>
<field name="preview_move_data" widget="grouped_view_widget"/>
<footer>
<button string="Create Journal Entries" name="do_action" type="object" class="oe_highlight"/>
<button string="Cancel" class="btn btn-secondary" special="cancel"/>