[FIX] account: reconciliation widget: make invoice matching reconciliation models work with write-off lines

Use case:

1) Create an invoice matching reconciliation model, matching 90% percent of the amount, with a write-off line applying a 100% write-off of the remaining amount.

2) Create a 100€ invoice

3) Create a bank statement with a 90€ statement line whose payment reference corresponds to the one of the invoice

4) Click 'reconcile' on the bank statement

On enterprise, this crashes when preparing the data to give to the reconciliation widget, as the write_off_vals key is not set properly by the call to _apply_rules.

OPW 2367754

closes odoo/odoo#61265

X-original-commit: 1dd6199519b4ad5b5b17dfa17965ededcecb6da4
Related: odoo/enterprise#14563
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
Signed-off-by: oco-odoo <oco-odoo@users.noreply.github.com>
This commit is contained in:
oco-odoo
2020-11-03 13:23:08 +00:00
parent 8dcb312650
commit b66c4fd0f7
2 changed files with 38 additions and 2 deletions
@@ -317,7 +317,7 @@ class AccountReconcileModel(models.Model):
lines_vals_list = []
for line in self.line_ids:
currency_id = st_line.currency_id or st_line.journal_id.currency_id or self.company_id.currency_id
currency_id = st_line.currency_id or st_line.journal_id.currency_id or self.company_id.currency_id
if not line.account_id or currency_id.is_zero(residual_balance):
return []
@@ -795,8 +795,10 @@ class AccountReconcileModel(models.Model):
lines_vals_list = self._prepare_reconciliation(st_line, aml_ids=rslt['aml_ids'], partner=partner)
# A write-off must be applied if there are some 'new' lines to propose.
if not lines_vals_list or any(not line_vals.get('id') for line_vals in lines_vals_list):
write_off_lines_vals = list(filter(lambda x: 'id' not in x, lines_vals_list))
if not lines_vals_list or write_off_lines_vals:
rslt['status'] = 'write_off'
rslt['write_off_vals'] = write_off_lines_vals
# Process auto-reconciliation. We only do that for the first two priorities, if they are not matched elsewhere.
if lines_vals_list and priorities & {1, 3} and self.auto_reconcile:
@@ -712,3 +712,37 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
self._check_statement_matching(matching_rule, {
statement_line.id: {'aml_ids': (move_line_1 + move_line_2).ids, 'model': matching_rule, 'partner': statement_line.partner_id}
}, statements=statement)
def test_inv_matching_with_write_off(self):
self.rule_1.match_total_amount_param = 90
self.bank_st.line_ids[1].unlink() # We don't need this one here
statement_line = self.bank_st.line_ids[0]
statement_line.write({
'payment_ref': self.invoice_line_1.move_id.payment_reference,
'amount': 90,
})
# Test the invoice-matching part
self._check_statement_matching(self.rule_1, {
statement_line.id: {'aml_ids': self.invoice_line_1.ids, 'model': self.rule_1, 'partner': self.invoice_line_1.partner_id, 'status': 'write_off'},
}, self.bank_st)
# Test the write-off part
expected_write_off = {
'balance': 10,
'currency_id': False,
'reconcile_model_id': self.rule_1.id,
'account_id': self.current_assets_account.id,
}
matching_result = self.rule_1._apply_rules(statement_line)
self.assertEqual(len(matching_result[statement_line.id].get('write_off_vals', [])), 1, "Exactly one write-off line should be proposed.")
full_write_off_dict = matching_result[statement_line.id]['write_off_vals'][0]
to_compare = {
key: full_write_off_dict[key]
for key in expected_write_off.keys()
}
self.assertDictEqual(expected_write_off, to_compare)