Skip to content

Commit

Permalink
[IMP] Improve reconciliation rule activity tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
william-andre committed Nov 16, 2018
1 parent 1e4b3d0 commit a706cb6
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 10 deletions.
12 changes: 8 additions & 4 deletions addons/account/models/account_bank_statement.py
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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))
Expand Down
2 changes: 2 additions & 0 deletions addons/account/models/account_move.py
Expand Up @@ -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.')
Expand Down Expand Up @@ -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:
Expand Down
17 changes: 17 additions & 0 deletions addons/account/models/account_reconcile_model.py
Expand Up @@ -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': """<p class="o_view_nocontent_empty_folder">
No move from this reconciliation model
</p>""",
}

@api.onchange('name')
def onchange_name(self):
self.label = self.name
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down
14 changes: 10 additions & 4 deletions addons/account/models/reconciliation_widget.py
Expand Up @@ -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)
Expand All @@ -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)

Expand All @@ -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):
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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'])
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down
Expand Up @@ -716,14 +716,15 @@ 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++;
});

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};
Expand Down Expand Up @@ -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 = [];
Expand Down
Expand Up @@ -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});
},
Expand All @@ -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')});
},
/**
Expand Down
7 changes: 7 additions & 0 deletions addons/account/views/account_view.xml
Expand Up @@ -864,6 +864,11 @@
<field name="arch" type="xml">
<form string="Operation Templates">
<sheet>
<div class="oe_button_box" name="button_box">
<button type="object" name="action_reconcile_stat"
string="Stat" class="oe_stat_button" icon="fa-info-circle">
</button>
</div>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name" placeholder="e.g. Bank Fees"/></h1>
Expand Down Expand Up @@ -1413,6 +1418,7 @@
<field name="analytic_tag_ids" widget="many2many_tags" groups="analytic.group_analytic_tags"/>
<field name="reconciled" invisible="1"/>
<field name="full_reconcile_id"/>
<field name="reconcile_id"/>
<field name="debit" sum="Total Debit"/>
<field name="credit" sum="Total Credit"/>
<field name="amount_currency" readonly="True" groups="base.group_multi_currency"/>
Expand Down Expand Up @@ -1488,6 +1494,7 @@
<field name="move_id" string="Number (Move)"/>
<field name="tax_line_id"/>
<field name="tax_ids" />
<field name="reconcile_id"/>
<group expand="0" string="Group By">
<filter string="Partner" name="partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Journal" name="journal" domain="[]" context="{'group_by':'journal_id'}"/>
Expand Down

0 comments on commit a706cb6

Please sign in to comment.