diff --git a/addons/account/__manifest__.py b/addons/account/__manifest__.py index c1951b19666..1670fd3bc62 100644 --- a/addons/account/__manifest__.py +++ b/addons/account/__manifest__.py @@ -24,6 +24,7 @@ You could use this simplified accounting in case you work with an (external) acc 'data/digest_data.xml', 'views/account_menuitem.xml', 'views/account_payment_view.xml', + 'wizard/account_accrual_accounting_view.xml', 'wizard/account_unreconcile_view.xml', 'wizard/account_move_reversal_view.xml', 'views/account_move_views.xml', diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 69af644a794..c162b869d25 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -3568,6 +3568,11 @@ class AccountMoveLine(models.Model): action['domain'] = [('id', 'in', ids)] return action + def action_accrual_entry(self): + [action] = self.env.ref('account.account_accrual_accounting_wizard_action').read() + action['context'] = self.env.context + return action + @api.model def _get_suspense_moves_domain(self): return [ diff --git a/addons/account/models/company.py b/addons/account/models/company.py index 95980862702..a2d71f8645d 100644 --- a/addons/account/models/company.py +++ b/addons/account/models/company.py @@ -107,6 +107,11 @@ Best Regards,''')) # Needed in the Point of Sale account_default_pos_receivable_account_id = fields.Many2one('account.account', string="Default PoS Receivable Account") + # Accrual Accounting + expense_accrual_account_id = fields.Many2one('account.account', help="Account used to move the period of an expense", domain=[('internal_group', '=', 'liability'), ('reconcile', '=', True)]) + revenue_accrual_account_id = fields.Many2one('account.account', help="Account used to move the period of a revenue", domain=[('internal_group', '=', 'asset'), ('reconcile', '=', True)]) + accrual_default_journal_id = fields.Many2one('account.journal', help="Journal used by default for moving the period of an entry", domain="[('type', '=', 'general')]") + @api.constrains('account_opening_move_id', 'fiscalyear_last_day', 'fiscalyear_last_month') def _check_fiscalyear_last_day(self): # if the user explicitly chooses the 29th of February we allow it: diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml index 3e704a282cb..89d3103898c 100644 --- a/addons/account/views/account_move_views.xml +++ b/addons/account/views/account_move_views.xml @@ -983,6 +983,14 @@ manual_reconciliation_view + + Change Period + + + code + action = records.action_accrual_entry() + + {name}').format( + percent=self.percentage, + 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 + 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({ + 'date': aml.move_id.date, + 'ref': ref, + 'journal_id': self.journal_id.id, + 'line_ids': [ + (0, 0, { + 'name': aml.name, + 'debit': aml.debit - reported_debit, + 'credit': aml.credit - reported_credit, + 'account_id': origin_accounts[aml.id], + 'partner_id': aml.partner_id.id, + }), + (0, 0, { + 'name': ref, + 'debit': aml.credit - reported_credit, + 'credit': aml.debit - reported_debit, + 'account_id': (self.revenue_accrual_account if self.account_type == 'income' else self.expense_accrual_account).id, + 'partner_id': aml.partner_id.id, + }), + ], + }) + message_data.append((_('Accrual Adjusting Entry ({percent}% recognized) for invoice:') + ' {name}').format( + percent=self.percentage, + id=aml.move_id.id, + name=aml.move_id.name, + )) + + created_ids = self.env['account.move'].create(move_data) + created_ids.post() + for move, msg in zip(created_ids, message_data): + move.message_post(body=msg) + + #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 + action = { + 'name': _('Generated Entries'), + 'domain': [('id', 'in', created_ids.ids)], + 'res_model': 'account.move', + 'view_mode': 'tree,form', + 'type': 'ir.actions.act_window', + 'views': [(self.env.ref('account.view_move_tree').id, 'tree'), (False, 'form')], + } + if len(created_ids) == 1: + action.update({'view_mode': 'form', 'res_id': created_ids.id}) + return action diff --git a/addons/account/wizard/account_accrual_accounting_view.xml b/addons/account/wizard/account_accrual_accounting_view.xml new file mode 100644 index 00000000000..62d3a7a377f --- /dev/null +++ b/addons/account/wizard/account_accrual_accounting_view.xml @@ -0,0 +1,38 @@ + + + + + account.accrual.accounting.wizard.form + account.accrual.accounting.wizard + +
+ + + + + + + + + + + + + + +
+
+ +
+
+ + + Change Period for the expense/revenue recognition + account.accrual.accounting.wizard + form + new + +
+