diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index b8a478cfef8..113980d1306 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -546,6 +546,7 @@ class AccountBankStatementLine(models.Model): - 'account_id' - (optional) 'tax_ids' - (optional) Other account.move.line fields like analytic_account_id or analytics_id + - (optional) 'reconcile_model_id' :returns: The journal entries with which the transaction was matched. If there was at least an entry in counterpart_aml_dicts or new_aml_dicts, this list contains the move created by the reconciliation, containing entries for the statement.line (1), the counterpart move lines (0..*) and the new move lines (0..*). diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index b19485674a4..23e22efba3f 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -61,6 +61,23 @@ class AccountMove(models.Model): move.matched_percentage = 1.0 else: move.matched_percentage = total_reconciled / total_amount + + @api.multi + @api.depends('line_ids.reconcile_model_id') + def _compute_reconcile_model(self): + for move in self: + move.reconcile_model_id = move.line_ids.mapped('reconcile_model_id') + + @api.model + @api.depends('reconcile_model_id') + def _search_reconcile_model(self, operator, operand): + if operand: + rmi = self.search([('line_ids.reconcile_model_id', operator, operand)]) + else: + rmi = self.search([('line_ids', operator, operand)]) + if rmi: + return [('id', 'in', rmi.ids)] + return [('id', '=', False)] @api.one @api.depends('company_id') @@ -106,6 +123,7 @@ class AccountMove(models.Model): narration = fields.Text(string='Internal Note') company_id = fields.Many2one('res.company', related='journal_id.company_id', string='Company', store=True, readonly=True) matched_percentage = fields.Float('Percentage Matched', compute='_compute_matched_percentage', digits=0, store=True, readonly=True, help="Technical field used in cash basis method") + reconcile_model_id = fields.Many2many('account.reconcile.model', compute='_compute_reconcile_model', search='_search_reconcile_model', string="Reconciliation Model", readonly=True) # Dummy Account field to search on account.move by account_id dummy_account_id = fields.Many2one('account.account', related='line_ids.account_id', string='Account', store=False, readonly=True) tax_cash_basis_rec_id = fields.Many2one( @@ -609,6 +627,7 @@ class AccountMoveLine(models.Model): statement_id = fields.Many2one('account.bank.statement', related='statement_line_id.statement_id', string='Statement', store=True, help="The bank statement used for bank reconciliation", index=True, copy=False) reconciled = fields.Boolean(compute='_amount_residual', store=True) + reconcile_model_id = fields.Many2one('account.reconcile.model', string="Reconciliation Model", copy=False) full_reconcile_id = fields.Many2one('account.full.reconcile', string="Matching Number", copy=False, index=True) matched_debit_ids = fields.One2many('account.partial.reconcile', 'credit_move_id', String='Matched Debits', help='Debit journal items that are matched with this journal item.') @@ -1019,6 +1038,7 @@ class AccountMoveLine(models.Model): return True rec_move_ids = self.env['account.partial.reconcile'] for account_move_line in self: + account_move_line.reconcile_model_id = False for invoice in account_move_line.payment_id.invoice_ids: if invoice.id == self.env.context.get('invoice_id') and account_move_line in invoice.payment_move_line_ids: account_move_line.payment_id.write({'invoice_ids': [(3, invoice.id, None)]}) diff --git a/addons/account/models/account_reconcile_model.py b/addons/account/models/account_reconcile_model.py index 621b49e6a54..7fc1ef93ad3 100644 --- a/addons/account/models/account_reconcile_model.py +++ b/addons/account/models/account_reconcile_model.py @@ -107,6 +107,24 @@ class AccountReconcileModel(models.Model): second_analytic_account_id = fields.Many2one('account.analytic.account', string='Second Analytic Account', ondelete='set null') second_analytic_tag_ids = fields.Many2many('account.analytic.tag', string='Second Analytic Tags', relation='account_reconcile_model_second_analytic_tag_rel') + + number_entries = fields.Integer(string='Number of entries related to this model', compute='_compute_number_entries') + + @api.multi + def action_reconcile_stat(self): + action = self.env.ref('account.action_move_journal_line').read()[0] + action.update({ + 'context': {'search_default_reconcile_model_id': self.name}, + 'help': """
{}
""".format(_('No move from this reconciliation model')), + }) + return action + + @api.multi + def _compute_number_entries(self): + data = self.env['account.move.line'].read_group([('reconcile_model_id', 'in', self.ids)], ['reconcile_model_ids'], 'reconcile_model_id') + mapped_data = dict([(d['reconcile_model_id'][0], d['reconcile_model_id_count']) for d in data]) + for model in self: + model.number_entries = mapped_data.get(model.id, 0) @api.onchange('name') def onchange_name(self): diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py index 8d7a48424fe..1b4f3dc45f8 100644 --- a/addons/account/models/chart_template.py +++ b/addons/account/models/chart_template.py @@ -1054,3 +1054,5 @@ class AccountReconcileModelTemplate(models.Model): force_second_tax_included = fields.Boolean(string='Second Tax Included in Price', help='Force the second tax to be managed as a price included tax.') second_tax_id = fields.Many2one('account.tax.template', string='Second Tax', ondelete='restrict', domain=[('type_tax_use', '=', 'purchase')]) + + number_entries = fields.Integer(string='Number of entries related to this model', compute='_compute_number_entries') diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index 5e756f28247..2a0148acbe8 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -1228,6 +1228,7 @@ var StatementModel = BasicModel.extend({ if (prop.analytic_account_id) result.analytic_account_id = prop.analytic_account_id.id; if (prop.tax_id && !prop.is_tax) result.tax_ids = [[4, prop.tax_id.id, null]]; if (prop.tax_id && prop.is_tax) result.tax_line_id = prop.tax_id.id; + if (prop.reconcileModelId) result.reconcile_model_id = prop.reconcileModelId return result; }, }); diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index 970989a970f..6e2fde895ed 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -387,7 +387,7 @@ class TestReconciliation(AccountingTestCase): self.assertEquals(invoice.state, 'paid', 'The invoice should be paid by now') reconcile = None for payment in invoice.payment_ids: - reconcile = payment.reconcile_id + reconcile = payment.reconcile_model_id break # The invoice should be reconciled (entirely, not a partial reconciliation) self.assertTrue(reconcile, 'The invoice should be totally reconciled') diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml index 2e3a86da034..0377d9adf15 100644 --- a/addons/account/views/account_view.xml +++ b/addons/account/views/account_view.xml @@ -811,6 +811,12 @@