[IMP] account_*, l10n_*: allows the same bank account on multiple partners
Some use cases require the use of the same account number on multiple partners. This will relax the constraints to allows such use cases, and adapt to avoid setting the partner or bank when we cannot be sure of the one we should take (on bank statement line, and during reconciliation) Task id #2692025 closes odoo/odoo#81362 Related: odoo/enterprise#22881 Signed-off-by: Laurent Smet <las@odoo.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -194,11 +194,18 @@
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="groups_id" eval="[(5,)]"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//sheet" position="before">
|
||||
<div groups="account.group_account_invoice,account.group_account_readonly" class="alert alert-warning" role="alert" style="margin-bottom:0px;"
|
||||
attrs="{'invisible': [('duplicated_bank_account_partners_count', '=', 0)]}">
|
||||
One or more Bank Accounts set on this partner are also used by other <bold><button class="alert-link" type="object" name="action_view_partner_with_same_bank" role="button" string="Partners" style="padding: 0;vertical-align: baseline;"/></bold>. Please make sure that this is a wanted behavior.
|
||||
</div>
|
||||
</xpath>
|
||||
<page name="sales_purchases" position="after">
|
||||
<page string="Invoicing" name="accounting" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}" groups="account.group_account_invoice,account.group_account_readonly">
|
||||
<field name="duplicated_bank_account_partners_count" invisible="1"/>
|
||||
<group>
|
||||
<group string="Bank Accounts" name="banks" groups="account.group_account_invoice,account.group_account_readonly">
|
||||
<field name="bank_ids" nolabel="1">
|
||||
<field name="bank_ids" nolabel="1" colspan="2">
|
||||
<tree editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="bank_id"/>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user