diff --git a/addons/account/tests/test_account_move_out_invoice.py b/addons/account/tests/test_account_move_out_invoice.py index bf3e320ca17..7dd8316c30b 100644 --- a/addons/account/tests/test_account_move_out_invoice.py +++ b/addons/account/tests/test_account_move_out_invoice.py @@ -2813,6 +2813,140 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): {'amount_currency': 120.0, 'debit': 60.0, 'credit': 0.0, 'account_id': wizard.revenue_accrual_account.id, 'reconciled': True}, ]) + def test_out_invoice_multi_date_change_period_accrual(self): + dates = ['2017-01-01', '2017-01-01', '2017-02-01'] + values = [] + for date in dates: + values.append({ + 'move_type': 'out_invoice', + 'date': date, + 'partner_id': self.partner_a.id, + 'invoice_date': fields.Date.from_string(date), + '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'], + }), + ] + }) + + moves = self.env['account.move'].create(values) + moves.action_post() + + wizard = self.env['account.automatic.entry.wizard'].with_context( + active_model='account.move.line', + active_ids=moves.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() + + for date, move, ref in zip(dates, moves, ['INV/2017/00001', 'INV/2017/00002', 'INV/2017/00003']): + 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': ref, + 'amount_currency': 1410.0, + 'debit': 705.0, + 'credit': 0.0, + 'date_maturity': fields.Date.from_string(date), + }, + ], { + **self.move_vals, + 'currency_id': self.currency_data['currency'].id, + 'date': fields.Date.from_string(date), + 'payment_reference': ref, + }) + + moves = self.env['account.move'].browse(wizard_res['domain'][0][2]) + + accrual_lines = moves.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': 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': 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}, + {'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}, + {'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', diff --git a/addons/account/wizard/account_automatic_entry_wizard.py b/addons/account/wizard/account_automatic_entry_wizard.py index e4b4682bdfd..6632c64f1b5 100644 --- a/addons/account/wizard/account_automatic_entry_wizard.py +++ b/addons/account/wizard/account_automatic_entry_wizard.py @@ -321,22 +321,31 @@ class AutomaticEntryWizard(models.TransientModel): created_moves._post() destination_move = created_moves[0] + destination_move_offset = 0 destination_messages = [] + accrual_move_messages = defaultdict(lambda: []) + accrual_move_offsets = defaultdict(int) for move in self.move_line_ids.move_id: amount = sum((self.move_line_ids._origin & move.line_ids).mapped('balance')) accrual_move = created_moves[1:].filtered(lambda m: m.date == move.date) if accrual_account.reconcile: - to_reconcile = (accrual_move + destination_move).mapped('line_ids').filtered(lambda line: line.account_id == accrual_account) - to_reconcile.reconcile() + destination_move_lines = destination_move.mapped('line_ids').filtered(lambda line: line.account_id == accrual_account)[destination_move_offset:destination_move_offset+2] + destination_move_offset += 2 + accrual_move_lines = accrual_move.mapped('line_ids').filtered(lambda line: line.account_id == accrual_account)[accrual_move_offsets[accrual_move]:accrual_move_offsets[accrual_move]+2] + accrual_move_offsets[accrual_move] += 2 + (accrual_move_lines + destination_move_lines).reconcile() move.message_post(body=self._format_strings(_('Adjusting Entries have been created for this invoice: