From 9e432ed2432416e09b341adb8a3e374e6b325081 Mon Sep 17 00:00:00 2001 From: "Nicolas (vin)" Date: Fri, 16 Jul 2021 15:52:41 +0000 Subject: [PATCH] [FIX] account, payment: Various fixes for account payments/method lines There is an issue when computing the suitable payment token ids making it impossible to open a payment for a user without access to payment acquirers. Also, the default computation of payment token was wrong and would never set it correctly. The compute for the method lines in payment would not filter unavailable acquirers line and thus select them by default if they were first in line. Also fix an issue with the ordering of payment method lines X-original-commit: 73410a0fd76a70e1730883d35b79fc603741b59c --- addons/account/models/account_payment.py | 11 ++++----- .../wizard/account_payment_register.py | 9 +++---- addons/payment/models/account_journal.py | 2 +- addons/payment/models/account_payment.py | 24 +++++++++++++------ .../payment/models/account_payment_method.py | 11 ++++++++- .../wizards/account_payment_register.py | 21 +++++++++++----- 6 files changed, 50 insertions(+), 28 deletions(-) diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py index 89320a1a3ef..89ed6cac6f6 100644 --- a/addons/account/models/account_payment.py +++ b/addons/account/models/account_payment.py @@ -383,16 +383,13 @@ class AccountPayment(models.Model): This field is not computed in '_compute_payment_method_fields' because it's a stored editable one. ''' for pay in self: - if pay.payment_type == 'inbound': - available_payment_methods = pay.journal_id.inbound_payment_method_line_ids - else: - available_payment_methods = pay.journal_id.outbound_payment_method_line_ids + available_payment_method_lines = pay.journal_id._get_available_payment_method_lines(pay.payment_type) # Select the first available one by default. - if pay.payment_method_line_id in available_payment_methods: + if pay.payment_method_line_id in available_payment_method_lines: pay.payment_method_line_id = pay.payment_method_line_id - elif available_payment_methods: - pay.payment_method_line_id = available_payment_methods[0]._origin + elif available_payment_method_lines: + pay.payment_method_line_id = available_payment_method_lines[0]._origin else: pay.payment_method_line_id = False diff --git a/addons/account/wizard/account_payment_register.py b/addons/account/wizard/account_payment_register.py index 5adf8e3876d..dccfdb9c6dd 100644 --- a/addons/account/wizard/account_payment_register.py +++ b/addons/account/wizard/account_payment_register.py @@ -304,14 +304,11 @@ class AccountPaymentRegister(models.TransientModel): @api.depends('payment_type', 'journal_id') def _compute_payment_method_line_id(self): for wizard in self: - if wizard.payment_type == 'inbound': - available_payment_methods = wizard.journal_id.inbound_payment_method_line_ids - else: - available_payment_methods = wizard.journal_id.outbound_payment_method_line_ids + available_payment_method_lines = wizard.journal_id._get_available_payment_method_lines(wizard.payment_type) # Select the first available one by default. - if available_payment_methods: - wizard.payment_method_line_id = available_payment_methods[0]._origin + if available_payment_method_lines: + wizard.payment_method_line_id = available_payment_method_lines[0]._origin else: wizard.payment_method_line_id = False diff --git a/addons/payment/models/account_journal.py b/addons/payment/models/account_journal.py index b4cbeb29d3a..284c75fd078 100644 --- a/addons/payment/models/account_journal.py +++ b/addons/payment/models/account_journal.py @@ -24,7 +24,7 @@ class AccountJournal(models.Model): SELECT acquirer.id FROM payment_acquirer acquirer JOIN account_payment_method apm ON apm.code = acquirer.provider - LEFT JOIN account_payment_method_line apml ON apm.id = apml.payment_method_id + LEFT JOIN account_payment_method_line apml ON apm.id = apml.payment_method_id AND apml.journal_id IS NOT NULL WHERE acquirer.state IN ('enabled', 'test') AND apm.payment_type = 'inbound' AND apml.id IS NULL AND acquirer.company_id IN %(company_ids)s diff --git a/addons/payment/models/account_payment.py b/addons/payment/models/account_payment.py index f25647c041d..0a61a0c21e9 100644 --- a/addons/payment/models/account_payment.py +++ b/addons/payment/models/account_payment.py @@ -36,11 +36,12 @@ class AccountPayment(models.Model): )._origin if payment.use_electronic_payment_method: - payment.suitable_payment_token_ids = self.env['payment.token'].search([ + payment.suitable_payment_token_ids = self.env['payment.token'].sudo().search([ ('company_id', '=', payment.company_id.id), ('acquirer_id.capture_manually', '=', False), ('partner_id', 'in', related_partner_ids.ids), - ]).filtered(lambda t: t.acquirer_id.journal_id == payment.journal_id.id) + ('acquirer_id.journal_id', '=', payment.journal_id.id), + ]) else: payment.suitable_payment_token_ids = [Command.clear()] @@ -50,17 +51,24 @@ class AccountPayment(models.Model): # Get a list of all electronic payment method codes. # These codes are comprised of 'electronic' and the providers of each payment acquirer. codes = [key for key in dict(self.env['payment.acquirer']._fields['provider']._description_selection(self.env))] - codes.append('electronic') payment.use_electronic_payment_method = payment.payment_method_code in codes @api.onchange('partner_id', 'payment_method_line_id', 'journal_id') def _onchange_set_payment_token_id(self): - if not (self.payment_method_code == 'electronic' and self.partner_id and self.journal_id): + codes = [key for key in dict(self.env['payment.acquirer']._fields['provider']._description_selection(self.env))] + if not (self.payment_method_code in codes and self.partner_id and self.journal_id): self.payment_token_id = False return - self.payment_token_id = self.env['payment.token'].search([ - ('partner_id', 'in', self.related_partner_ids.ids), + related_partner_ids = ( + self.partner_id + | self.partner_id.commercial_partner_id + | self.partner_id.commercial_partner_id.child_ids + )._origin + + self.payment_token_id = self.env['payment.token'].sudo().search([ + ('company_id', '=', self.company_id.id), + ('partner_id', 'in', related_partner_ids.ids), ('acquirer_id.capture_manually', '=', False), ('acquirer_id.journal_id', '=', self.journal_id.id), ], limit=1) @@ -108,7 +116,9 @@ class AccountPayment(models.Model): payments_need_tx = self.filtered( lambda p: p.payment_token_id and not p.payment_transaction_id ) - transactions = payments_need_tx._create_payment_transaction() + # creating the transaction require to access data on payment acquirers, not always accessible to users + # able to create payments + transactions = payments_need_tx.sudo()._create_payment_transaction() res = super(AccountPayment, self - payments_need_tx).action_post() diff --git a/addons/payment/models/account_payment_method.py b/addons/payment/models/account_payment_method.py index 9e24c957f89..d38fa2b5424 100644 --- a/addons/payment/models/account_payment_method.py +++ b/addons/payment/models/account_payment_method.py @@ -23,7 +23,16 @@ class AccountPaymentMethodLine(models.Model): ('provider', 'in', self.mapped('code')), ('company_id', 'in', self.journal_id.company_id.ids), ]) - acquirers_map = {(x.provider, x.company_id): x for x in acquirers} + + # Make sure to pick the active acquirer, if any. + acquirers_map = dict() + for acquirer in acquirers: + current_value = acquirers_map.get((acquirer.provider, acquirer.company_id), False) + if current_value and current_value.state != 'disabled': + continue + + acquirers_map[(acquirer.provider, acquirer.company_id)] = acquirer + for line in self: code = line.payment_method_id.code company = line.journal_id.company_id diff --git a/addons/payment/wizards/account_payment_register.py b/addons/payment/wizards/account_payment_register.py index b47fedca8d8..2fffb2180b0 100644 --- a/addons/payment/wizards/account_payment_register.py +++ b/addons/payment/wizards/account_payment_register.py @@ -42,11 +42,12 @@ class AccountPaymentRegister(models.TransientModel): | wizard.partner_id.commercial_partner_id.child_ids )._origin - wizard.suitable_payment_token_ids = self.env['payment.token'].search([ + wizard.suitable_payment_token_ids = self.env['payment.token'].sudo().search([ ('company_id', '=', wizard.company_id.id), ('acquirer_id.capture_manually', '=', False), ('partner_id', 'in', related_partner_ids.ids), - ]).filtered(lambda t: t.acquirer_id.journal_id == wizard.journal_id.id) + ('acquirer_id.journal_id', '=', wizard.journal_id.id), + ]) else: wizard.suitable_payment_token_ids = [Command.clear()] @@ -60,13 +61,21 @@ class AccountPaymentRegister(models.TransientModel): @api.onchange('can_edit_wizard', 'payment_method_line_id', 'journal_id') def _compute_payment_token_id(self): + codes = [key for key in dict(self.env['payment.acquirer']._fields['provider']._description_selection(self.env))] for wizard in self: + related_partner_ids = ( + wizard.partner_id + | wizard.partner_id.commercial_partner_id + | wizard.partner_id.commercial_partner_id.child_ids + )._origin if wizard.can_edit_wizard \ - and wizard.payment_method_line_id.code == 'electronic' \ + and wizard.payment_method_line_id.code in codes \ and wizard.journal_id \ - and wizard.suitable_payment_token_partner_ids: - wizard.payment_token_id = self.env['payment.token'].search([ - ('partner_id', 'in', wizard.suitable_payment_token_partner_ids.ids), + and related_partner_ids: + + wizard.payment_token_id = self.env['payment.token'].sudo().search([ + ('company_id', '=', wizard.company_id.id), + ('partner_id', 'in', related_partner_ids.ids), ('acquirer_id.capture_manually', '=', False), ('acquirer_id.journal_id', '=', wizard.journal_id.id), ], limit=1)