From a706cb676d35e6ec7b81268a5bc9f95a0dddec0f Mon Sep 17 00:00:00 2001 From: wan Date: Fri, 16 Nov 2018 10:28:14 +0100 Subject: [PATCH] [IMP] Improve reconciliation rule activity tracking --- addons/account/models/account_bank_statement.py | 12 ++++++++---- addons/account/models/account_move.py | 2 ++ .../account/models/account_reconcile_model.py | 17 +++++++++++++++++ addons/account/models/reconciliation_widget.py | 14 ++++++++++---- .../js/reconciliation/reconciliation_model.js | 6 ++++-- .../reconciliation/reconciliation_renderer.js | 2 ++ addons/account/views/account_view.xml | 7 +++++++ 7 files changed, 50 insertions(+), 10 deletions(-) diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 46db7c5c8e7a7..86ce1794a9c7e 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -482,7 +482,7 @@ def fast_counterpart_creation(self): def _get_communication(self, payment_method_id): return self.name or '' - def process_reconciliation(self, counterpart_aml_dicts=None, payment_aml_rec=None, new_aml_dicts=None): + def process_reconciliation(self, model, counterpart_aml_dicts=None, payment_aml_rec=None, new_aml_dicts=None): """ Match statement lines with existing payments (eg. checks) and/or payables/receivables (eg. invoices and credit notes) and/or new move lines (eg. write-offs). If any new journal item needs to be created (via new_aml_dicts or counterpart_aml_dicts), a new journal entry will be created and will contain those items, as well as a journal item for the bank statement line. @@ -541,7 +541,7 @@ def process_reconciliation(self, counterpart_aml_dicts=None, payment_aml_rec=Non total = self.amount for aml_rec in payment_aml_rec: total -= aml_rec.debit - aml_rec.credit - aml_rec.with_context(check_move_validity=False).write({'statement_line_id': self.id}) + aml_rec.with_context(check_move_validity=False).write({'statement_line_id': self.id, 'reconcile_id' : model.id}) counterpart_moves = (counterpart_moves | aml_rec.move_id) if aml_rec.journal_id.post_at_bank_rec and aml_rec.payment_id and aml_rec.move_id.state == 'draft': # In case the journal is set to only post payments when performing bank @@ -597,6 +597,7 @@ def process_reconciliation(self, counterpart_aml_dicts=None, payment_aml_rec=Non company = self.company_id date = self.date or fields.Date.today() for aml_dict in to_create: + aml_dict['reconcile_id'] = model.id aml_dict['move_id'] = move.id aml_dict['partner_id'] = self.partner_id.id aml_dict['statement_line_id'] = self.id @@ -624,16 +625,18 @@ def process_reconciliation(self, counterpart_aml_dicts=None, payment_aml_rec=Non # Create write-offs for aml_dict in new_aml_dicts: aml_dict['payment_id'] = payment and payment.id or False + aml_dict['reconcile_id'] = model.id aml_obj.with_context(check_move_validity=False).create(aml_dict) # Create counterpart move lines and reconcile them for aml_dict in counterpart_aml_dicts: if aml_dict['move_line'].payment_id: - aml_dict['move_line'].write({'statement_line_id': self.id}) + aml_dict['move_line'].write({'statement_line_id': self.id, 'reconcile_id' : model.id}) if aml_dict['move_line'].partner_id.id: aml_dict['partner_id'] = aml_dict['move_line'].partner_id.id aml_dict['account_id'] = aml_dict['move_line'].account_id.id aml_dict['payment_id'] = payment and payment.id or False + aml_dict['reconcile_id'] = model.id counterpart_move_line = aml_dict.pop('move_line') new_aml = aml_obj.with_context(check_move_validity=False).create(aml_dict) @@ -646,11 +649,12 @@ def process_reconciliation(self, counterpart_aml_dicts=None, payment_aml_rec=Non st_line_amount = -sum([x.balance for x in move.line_ids]) aml_dict = self._prepare_reconciliation_move_line(move, st_line_amount) aml_dict['payment_id'] = payment and payment.id or False + aml_dict['reconcile_id'] = model.id aml_obj.with_context(check_move_validity=False).create(aml_dict) move.post() #record the move name on the statement line to be able to retrieve it in case of unreconciliation - self.write({'move_name': move.name}) + self.write({'move_name': move.name, 'reconcile_id': model.id}) payment and payment.write({'payment_reference': move.name}) elif self.move_name: raise UserError(_('Operation not allowed. Since your statement line already received a number (%s), you cannot reconcile it entirely with existing journal entries otherwise it would make a gap in the numbering. You should book an entry and make a regular revert of it in case you want to cancel it.') % (self.move_name)) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index dc4c37f54db80..1f2c4f0ef04ad 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -618,6 +618,7 @@ def _get_counterpart(self): 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_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.') @@ -1028,6 +1029,7 @@ def remove_move_reconcile(self): """ Undo a reconciliation """ if not self: return True + self.write({'reconcile_id':False}) rec_move_ids = self.env['account.partial.reconcile'] for account_move_line in self: for invoice in account_move_line.payment_id.invoice_ids: diff --git a/addons/account/models/account_reconcile_model.py b/addons/account/models/account_reconcile_model.py index bd89394733dc4..63c29f3eb4996 100644 --- a/addons/account/models/account_reconcile_model.py +++ b/addons/account/models/account_reconcile_model.py @@ -106,6 +106,21 @@ 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') + @api.multi + def action_reconcile_stat(self): + search_view_id = self.env.ref('account.view_account_move_line_filter').id + return {'name': 'Stat', + 'type': 'ir.actions.act_window', + 'view_type': 'form', + 'view_mode': 'tree', + 'res_model': 'account.move.line', + 'search_view_id': search_view_id, + 'context': {'search_default_reconcile_id': self.id}, + 'help': """

+ No move from this reconciliation model +

""", + } + @api.onchange('name') def onchange_name(self): self.label = self.name @@ -680,6 +695,7 @@ def _apply_rules(self, st_lines, excluded_ids=None, partner_map=None): counterpart_aml_dicts=reconciliation_results['counterpart_aml_dicts'], payment_aml_rec=reconciliation_results['payment_aml_rec'], new_aml_dicts=new_aml_dicts, + model=model, ) results[line.id]['status'] = 'reconciled' results[line.id]['reconciled_lines'] = counterpart_moves.mapped('line_ids') @@ -711,6 +727,7 @@ def _apply_rules(self, st_lines, excluded_ids=None, partner_map=None): counterpart_aml_dicts=reconciliation_results['counterpart_aml_dicts'], payment_aml_rec=reconciliation_results['payment_aml_rec'], new_aml_dicts=new_aml_dicts, + model=model, ) results[line.id]['status'] = 'reconciled' results[line.id]['reconciled_lines'] = counterpart_moves.mapped('line_ids') diff --git a/addons/account/models/reconciliation_widget.py b/addons/account/models/reconciliation_widget.py index 934272c1c81f1..58a61a91c7ee4 100644 --- a/addons/account/models/reconciliation_widget.py +++ b/addons/account/models/reconciliation_widget.py @@ -16,7 +16,7 @@ class AccountReconciliation(models.AbstractModel): #################################################### @api.model - def process_bank_statement_line(self, st_line_ids, data): + def process_bank_statement_line(self, st_line_ids, data, reconcile_id): """ Handles data sent from the bank statement reconciliation widget (and can otherwise serve as an old-API bridge) @@ -27,6 +27,7 @@ def process_bank_statement_line(self, st_line_ids, data): except that ids are used instead of recordsets. """ st_lines = self.env['account.bank.statement.line'].browse(st_line_ids) + account_reconcile_model = self.env['account.reconcile.model'].browse(reconcile_id) AccountMoveLine = self.env['account.move.line'] ctx = dict(self._context, force_price_include=False) @@ -41,9 +42,11 @@ def process_bank_statement_line(self, st_line_ids, data): st_line.write({'partner_id': datum['partner_id']}) st_line.with_context(ctx).process_reconciliation( + account_reconcile_model, datum.get('counterpart_aml_dicts', []), payment_aml_rec, - datum.get('new_aml_dicts', [])) + datum.get('new_aml_dicts', []), + ) @api.model def get_move_lines_for_bank_statement_line(self, st_line_id, partner_id=None, excluded_ids=None, search_str=False, offset=0, limit=None): @@ -148,6 +151,7 @@ def get_bank_statement_line_data(self, st_line_ids, excluded_ids=None): 'reconciliation_proposition': aml_ids and self._prepare_move_lines(amls) or [], 'model_id': matching_amls[line.id].get('model') and matching_amls[line.id]['model'].id, 'write_off': matching_amls[line.id].get('status') == 'write_off', + 'reconcile_id' : matching_amls[line.id].get('reconcile_id') }) return results @@ -349,7 +353,7 @@ def process_move_lines(self, data): for datum in data: if len(datum['mv_line_ids']) >= 1 or len(datum['mv_line_ids']) + len(datum['new_mv_line_dicts']) >= 2: - self._process_move_lines(datum['mv_line_ids'], datum['new_mv_line_dicts']) + self._process_move_lines(datum['mv_line_ids'], datum['new_mv_line_dicts'], datum.get('reconcile_id',0)) if datum['type'] == 'partner': partners = Partner.browse(datum['id']) @@ -514,6 +518,7 @@ def _prepare_move_lines(self, move_lines, target_currency=False, target_date=Fal 'partner_id': line.partner_id.id, 'partner_name': line.partner_id.name, 'currency_id': line_currency.id, + 'reconcile_id' : line.reconcile_id.id, } debit = line.debit @@ -672,7 +677,7 @@ def _get_move_line_reconciliation_proposition(self, account_id, partner_id=None) return Account_move_line @api.model - def _process_move_lines(self, move_line_ids, new_mv_line_dicts): + def _process_move_lines(self, move_line_ids, new_mv_line_dicts, model): """ Create new move lines from new_mv_line_dicts (if not empty) then call reconcile_partial on self and new move lines :param new_mv_line_dicts: list of dicts containing values suitable for account_move_line.create() @@ -681,6 +686,7 @@ def _process_move_lines(self, move_line_ids, new_mv_line_dicts): raise UserError(_('A reconciliation must involve at least 2 move lines.')) account_move_line = self.env['account.move.line'].browse(move_line_ids) + account_move_line.write({'reconcile_id':model}) writeoff_lines = self.env['account.move.line'] # Create writeoff move lines diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index b9504bd6ee62d..67d20dbfa7a64 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -716,6 +716,7 @@ var StatementModel = BasicModel.extend({ values_dict['new_aml_dicts'].push(unreconciled_amount_dict); } values.push(values_dict); + values['reconcile_id'] = self._reconcile_id; line.reconciled = true; self.valuenow++; }); @@ -723,7 +724,7 @@ var StatementModel = BasicModel.extend({ return this._rpc({ model: 'account.reconciliation.widget', method: 'process_bank_statement_line', - args: [ids, values], + args: [ids, values, self._reconcile_id], }) .then(function () { return {handles: handles}; @@ -1374,7 +1375,8 @@ var ManualModel = StatementModel.extend({ id: null, type: null, mv_line_ids: mv_line_ids, - new_mv_line_dicts: new_mv_line_dicts + new_mv_line_dicts: new_mv_line_dicts, + reconcile_id: self._reconcile_id, }); } line.reconciliation_proposition = []; diff --git a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js index 7d572bc74b36f..b5e216c5749ab 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js @@ -739,6 +739,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, { _onSelectProposition: function (event) { var $el = $(event.target); this._destroyPopover($el); + this.model._reconcile_id = null; var moveLineId = $el.closest('.mv_line').data('line-id'); this.trigger_up('remove_proposition', {'data': moveLineId}); }, @@ -748,6 +749,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, { */ _onQuickCreateProposition: function (event) { document.activeElement && document.activeElement.blur(); + this.model._reconcile_id = $(event.target).data('reconcile-model-id'); this.trigger_up('quick_create_proposition', {'data': $(event.target).data('reconcile-model-id')}); }, /** diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml index 3d15d0976c3cc..0dadba55940a4 100644 --- a/addons/account/views/account_view.xml +++ b/addons/account/views/account_view.xml @@ -864,6 +864,11 @@
+
+ +