[FIX] payment: avoid a mismatch between partner's and acquirer's company
In a multi-company environment, a partner of company A should not be able to make payments for company B. With this commit, if we detect a mismatch between the companies, a UserError is raised. Task - 2627751 closes odoo/odoo#91189 X-original-commit: 6064cf2e98f16b42f516dcd1b0793a62436bab33 Related: odoo/enterprise#27245 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com> Signed-off-by: Horacio Tellez Perez (hote) <hote@odoo.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
from odoo.http import request
|
||||
|
||||
from odoo.addons.account.controllers import portal
|
||||
from odoo.addons.payment.controllers.portal import PaymentPortal
|
||||
from odoo.addons.portal.controllers.portal import _build_url_w_params
|
||||
|
||||
|
||||
@@ -15,14 +16,17 @@ class PortalAccount(portal.PortalAccount):
|
||||
# We set partner_id to the partner id of the current user if logged in, otherwise we set it
|
||||
# to the invoice partner id. We do this to ensure that payment tokens are assigned to the
|
||||
# correct partner and to avoid linking tokens to the public user.
|
||||
partner_id = request.env.user.partner_id.id if logged_in else invoice.partner_id.id
|
||||
partner = request.env.user.partner_id if logged_in else invoice.partner_id
|
||||
|
||||
# Make sure that the partner's company matches the invoice's company.
|
||||
invoice_company = invoice.company_id or request.env.company
|
||||
PaymentPortal.ensure_matching_companies(partner, invoice_company)
|
||||
|
||||
acquirers_sudo = request.env['payment.acquirer'].sudo()._get_compatible_acquirers(
|
||||
invoice.company_id.id or request.env.company.id,
|
||||
partner_id,
|
||||
currency_id=invoice.currency_id.id,
|
||||
invoice_company.id, partner.id, currency_id=invoice.currency_id.id
|
||||
) # In sudo mode to read the fields of acquirers and partner (if not logged in)
|
||||
tokens = request.env['payment.token'].search(
|
||||
[('acquirer_id', 'in', acquirers_sudo.ids), ('partner_id', '=', partner_id)]
|
||||
[('acquirer_id', 'in', acquirers_sudo.ids), ('partner_id', '=', partner.id)]
|
||||
) # Tokens are cleared at the end if the user is not logged in
|
||||
fees_by_acquirer = {
|
||||
acq_sudo: acq_sudo._compute_fees(
|
||||
@@ -36,7 +40,7 @@ class PortalAccount(portal.PortalAccount):
|
||||
'show_tokenize_input': logged_in, # Prevent public partner from saving payment methods
|
||||
'amount': invoice.amount_residual,
|
||||
'currency': invoice.currency_id,
|
||||
'partner_id': partner_id,
|
||||
'partner_id': partner.id,
|
||||
'access_token': access_token,
|
||||
'transaction_route': f'/invoice/transaction/{invoice.id}/',
|
||||
'landing_route': _build_url_w_params(invoice.access_url, {'access_token': access_token})
|
||||
|
||||
@@ -103,6 +103,9 @@ class PaymentPortal(portal.CustomerPortal):
|
||||
company = request.env['res.company'].sudo().browse(company_id)
|
||||
currency_id = currency_id or company.currency_id.id
|
||||
|
||||
# Make sure that the company passed as parameter matches the partner's company.
|
||||
PaymentPortal.ensure_matching_companies(partner_sudo, company)
|
||||
|
||||
# Make sure that the currency exists and is active
|
||||
currency = request.env['res.currency'].browse(currency_id).exists()
|
||||
if not currency or not currency.active:
|
||||
@@ -429,3 +432,22 @@ class PaymentPortal(portal.CustomerPortal):
|
||||
return float(str_value)
|
||||
except (TypeError, ValueError, OverflowError):
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def ensure_matching_companies(partner, document_company):
|
||||
""" Check that the partner's company is the same as the document's company.
|
||||
|
||||
If the partner company is not set, the check passes. If the companies don't match, a
|
||||
`UserError` is raised.
|
||||
|
||||
:param recordset partner: The partner on behalf on which the payment is made, as a
|
||||
`res.partner` record.
|
||||
:param recordset document_company: The company of the document being paid, as a
|
||||
`res.company` record.
|
||||
:return: None
|
||||
:raise UserError: If the companies don't match.
|
||||
"""
|
||||
if partner.company_id and partner.company_id != document_company:
|
||||
raise UserError(
|
||||
_("Please switch to company '%s' to make this payment.", document_company.name)
|
||||
)
|
||||
|
||||
@@ -1399,6 +1399,12 @@ msgstr ""
|
||||
msgid "Please set an amount smaller than %s."
|
||||
msgstr ""
|
||||
|
||||
#. module: payment
|
||||
#: code:addons/payment/controllers/portal.py:0
|
||||
#, python-format
|
||||
msgid "Please switch to company '%s' to make this payment."
|
||||
msgstr ""
|
||||
|
||||
#. module: payment
|
||||
#: model_terms:payment.acquirer,pending_msg:payment.payment_acquirer_transfer
|
||||
msgid "Please use the following transfer details"
|
||||
|
||||
@@ -152,6 +152,12 @@ class CustomerPortal(portal.CustomerPortal):
|
||||
# Payment values
|
||||
if order_sudo.has_to_be_paid():
|
||||
logged_in = not request.env.user._is_public()
|
||||
|
||||
# Make sure that the partner's company matches the sales order's company.
|
||||
payment_portal.PaymentPortal.ensure_matching_companies(
|
||||
order_sudo.partner_id, order_sudo.company_id
|
||||
)
|
||||
|
||||
acquirers_sudo = request.env['payment.acquirer'].sudo()._get_compatible_acquirers(
|
||||
order_sudo.company_id.id,
|
||||
order_sudo.partner_id.id,
|
||||
|
||||
Reference in New Issue
Block a user