diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py index 23797c0b7bc..f6c81bb076a 100644 --- a/addons/account/models/account_bank_statement.py +++ b/addons/account/models/account_bank_statement.py @@ -1250,13 +1250,14 @@ class AccountBankStatementLine(models.Model): # ------------------------------------------------------------------------- def _find_or_create_bank_account(self): - bank_account = self.env['res.partner.bank'].search( - [('company_id', '=', self.company_id.id), ('acc_number', '=', self.account_number)]) + bank_account = self.env['res.partner.bank'].search([ + ('acc_number', '=', self.account_number), + ('partner_id', '=', self.partner_id.id), + ]) if not bank_account: bank_account = self.env['res.partner.bank'].create({ 'acc_number': self.account_number, 'partner_id': self.partner_id.id, - 'company_id': self.company_id.id, }) return bank_account diff --git a/addons/account/models/account_journal.py b/addons/account/models/account_journal.py index 18497f07161..e4520976c7f 100644 --- a/addons/account/models/account_journal.py +++ b/addons/account/models/account_journal.py @@ -659,15 +659,16 @@ class AccountJournal(models.Model): def set_bank_account(self, acc_number, bank_id=None): """ Create a res.partner.bank (if not exists) and set it as value of the field bank_account_id """ self.ensure_one() - res_partner_bank = self.env['res.partner.bank'].search([('sanitized_acc_number', '=', sanitize_account_number(acc_number)), - ('company_id', '=', self.company_id.id)], limit=1) + res_partner_bank = self.env['res.partner.bank'].search([ + ('sanitized_acc_number', '=', sanitize_account_number(acc_number)), + ('partner_id', '=', self.company_id.partner_id.id), + ], limit=1) if res_partner_bank: self.bank_account_id = res_partner_bank.id else: self.bank_account_id = self.env['res.partner.bank'].create({ 'acc_number': acc_number, 'bank_id': bank_id, - 'company_id': self.company_id.id, 'currency_id': self.currency_id.id, 'partner_id': self.company_id.partner_id.id, }).id diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 6035aa5d466..d3dbda2ec68 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -521,7 +521,7 @@ class AccountMove(models.Model): line.account_id = new_term_account self._compute_bank_partner_id() - bank_ids = self.bank_partner_id.bank_ids.filtered(lambda bank: bank.company_id is False or bank.company_id == self.company_id) + bank_ids = self.bank_partner_id.bank_ids.filtered(lambda bank: not bank.company_id or bank.company_id == self.company_id) self.partner_bank_id = bank_ids and bank_ids[0] # Find the new fiscal position. diff --git a/addons/account/models/partner.py b/addons/account/models/partner.py index 56510f2d2c5..91372bb06d3 100644 --- a/addons/account/models/partner.py +++ b/addons/account/models/partner.py @@ -7,6 +7,7 @@ import logging from psycopg2 import sql, DatabaseError from odoo import api, fields, models, _ +from odoo.osv import expression from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT from odoo.exceptions import ValidationError from odoo.addons.base.models.res_partner import WARNING_MESSAGE, WARNING_HELP @@ -483,6 +484,11 @@ class ResPartner(models.Model): supplier_rank = fields.Integer(default=0) customer_rank = fields.Integer(default=0) + duplicated_bank_account_partners_count = fields.Integer( + compute='_compute_duplicated_bank_account_partners_count', + help='Technical field holding the amount partners that share the same account number as any set on this partner.', + ) + def _get_name_search_order_by_fields(self): res = super()._get_name_search_order_by_fields() partner_search_mode = self.env.context.get('res_partner_search_mode') @@ -503,6 +509,24 @@ class ResPartner(models.Model): for partner in self: partner.bank_account_count = mapped_data.get(partner.id, 0) + def _get_duplicated_bank_accounts(self): + self.ensure_one() + if not self.bank_ids: + return self.env['res.partner.bank'] + domains = [] + for bank in self.bank_ids: + domains.append([('acc_number', '=', bank.acc_number), ('bank_id', '=', bank.bank_id.id)]) + domain = expression.OR(domains) + if self.company_id: + domain = expression.AND([domain, [('company_id', 'in', (False, self.company_id.id))]]) + domain = expression.AND([domain, [('partner_id', '!=', self._origin.id)]]) + return self.env['res.partner.bank'].search(domain) + + @api.depends('bank_ids') + def _compute_duplicated_bank_account_partners_count(self): + for partner in self: + partner.duplicated_bank_account_partners_count = len(partner._get_duplicated_bank_accounts()) + def _find_accounting_partner(self, partner): ''' Find the partner for which the accounting entries will be created ''' return partner.commercial_partner_id @@ -523,6 +547,30 @@ class ResPartner(models.Model): action['context'] = {'default_move_type':'out_invoice', 'move_type':'out_invoice', 'journal_type': 'sale', 'search_default_open': 1} return action + def action_view_partner_with_same_bank(self): + self.ensure_one() + partners = self._get_duplicated_bank_accounts() + # Open a list view or form view of the partner(s) with the same bank accounts + if self.duplicated_bank_account_partners_count == 1: + action_vals = { + 'type': 'ir.actions.act_window', + 'res_model': 'res.partner', + 'view_mode': 'form', + 'res_id': partners.id, + 'views': [(False, 'form')], + } + else: + action_vals = { + 'name': _("Partners"), + 'type': 'ir.actions.act_window', + 'res_model': 'res.partner', + 'view_mode': 'tree,form', + 'views': [(False, 'list'), (False, 'form')], + 'domain': [('id', 'in', partners.ids)], + } + + return action_vals + def can_edit_vat(self): ''' Can't edit `vat` if there is (non draft) issued invoices. ''' can_edit_vat = super(ResPartner, self).can_edit_vat() diff --git a/addons/account/views/partner_view.xml b/addons/account/views/partner_view.xml index 9876efeff9e..a93beab0110 100644 --- a/addons/account/views/partner_view.xml +++ b/addons/account/views/partner_view.xml @@ -194,11 +194,18 @@ + + + One or more Bank Accounts set on this partner are also used by other . Please make sure that this is a wanted behavior. + + + - + diff --git a/addons/l10n_it_edi/models/account_edi_format.py b/addons/l10n_it_edi/models/account_edi_format.py index 577b8e077e5..2320ef24158 100644 --- a/addons/l10n_it_edi/models/account_edi_format.py +++ b/addons/l10n_it_edi/models/account_edi_format.py @@ -423,7 +423,12 @@ class AccountEdiFormat(models.Model): ('partner_id.id', '=', invoice_form.partner_id.commercial_partner_id.id) ]) else: - bank = self.env['res.partner.bank'].search([('acc_number', '=', elements[0].text)]) + bank = self.env['res.partner.bank'].search([ + ('acc_number', '=', elements[0].text), + ('company_id', '=', invoice_form.company_id.id), + ]) + if len(bank) > 1: + bank = None if bank: invoice_form.partner_bank_id = bank else: diff --git a/odoo/addons/base/models/res_bank.py b/odoo/addons/base/models/res_bank.py index 885ffb7acb0..f0fb7dd6a63 100644 --- a/odoo/addons/base/models/res_bank.py +++ b/odoo/addons/base/models/res_bank.py @@ -83,11 +83,13 @@ class ResPartnerBank(models.Model): bank_bic = fields.Char(related='bank_id.bic', readonly=False) sequence = fields.Integer(default=10) currency_id = fields.Many2one('res.currency', string='Currency') - company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company, ondelete='cascade', readonly=True) + company_id = fields.Many2one('res.company', 'Company', related='partner_id.company_id', store=True, readonly=True) - _sql_constraints = [ - ('unique_number', 'unique(sanitized_acc_number, company_id)', 'Account Number must be unique'), - ] + _sql_constraints = [( + 'unique_number', + 'unique(sanitized_acc_number, partner_id)', + 'The combination Account Number/Partner must be unique.' + )] @api.depends('acc_number') def _compute_sanitized_acc_number(self):