diff --git a/addons/account/models/account_reconcile_model.py b/addons/account/models/account_reconcile_model.py index b22aa22a9e9..757702a1612 100644 --- a/addons/account/models/account_reconcile_model.py +++ b/addons/account/models/account_reconcile_model.py @@ -2,6 +2,7 @@ from odoo import api, fields, models, _ from odoo.tools import float_compare, float_is_zero +from odoo.osv.expression import get_unaccent_wrapper from odoo.exceptions import UserError, ValidationError import re from math import copysign @@ -582,6 +583,8 @@ class AccountReconcileModel(models.Model): if self.rule_type != 'invoice_matching': raise UserError(_('Programmation Error: Can\'t call _get_invoice_matching_query() for different rules than \'invoice_matching\'')) + unaccent = get_unaccent_wrapper(self._cr) + # N.B: 'communication_flag' is there to distinguish invoice matching through the number/reference # (higher priority) from invoice matching using the partner (lower priority). query = r''' @@ -641,7 +644,10 @@ class AccountReconcileModel(models.Model): within the payment_ref, in any order, with any characters between them. */ aml_partner.name IS NOT NULL - AND st_line.payment_ref ~* concat('(?=.*', array_to_string(regexp_split_to_array(lower(aml_partner.name), ' '),'.*)(?=.*'), '.*)') + AND """ + unaccent("st_line.payment_ref") + r""" ~* ('^' || ( + SELECT string_agg(concat('(?=.*\m', chunk[1], '\M)'), '') + FROM regexp_matches(""" + unaccent("aml_partner.name") + r""", '\w{3,}', 'g') AS chunk + )) ) """ diff --git a/addons/account/tests/test_reconciliation_matching_rules.py b/addons/account/tests/test_reconciliation_matching_rules.py index b31e40eab5c..cc9e9d73d7c 100644 --- a/addons/account/tests/test_reconciliation_matching_rules.py +++ b/addons/account/tests/test_reconciliation_matching_rules.py @@ -678,6 +678,18 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon): self.bank_line_2.id: {'aml_ids': []}, }, self.bank_st) + def test_partner_name_with_regexp_chars(self): + self.invoice_line_1.partner_id.write({'name': "Archibald + Haddock"}) + self.bank_line_1.write({'partner_id': None, 'payment_ref': '1234//HADDOCK+Archibald'}) + self.bank_line_2.write({'partner_id': None}) + self.rule_1.write({'match_partner': False}) + + # The query should still work + self._check_statement_matching(self.rule_1, { + self.bank_line_1.id: {'aml_ids': [self.invoice_line_1.id], 'model': self.rule_1, 'partner': self.bank_line_1.partner_id}, + self.bank_line_2.id: {'aml_ids': []}, + }, self.bank_st) + def test_match_multi_currencies(self): ''' Ensure the matching of candidates is made using the right statement line currency.