If a user has the portal access, when going to his documents, if one of
them belongs to an archived partner, it will raise a 403 error.
To reproduce the error:
1. Go to Settings > Invoicing > Customer Payments
2. Enable "Invoice Online Payment"
3. Create a customer C
- Set a name
- In Contacts & Addresses, add two contacts C_01 and C_02
- Both are "Invoice Address"
- Add a valid email for C_01
4. Go to Customers > C_01, Action, Grand portal acess
- Check "In Portal", Apply
5. Go to Settings > Users & Companies > Users
6. Remove the search filter, Select C_01, Add a password
7. Create an invoice INV
- Customer: C_02
8. Connect to C_01's account
9. Click on "Invoices & Bills"
- The invoice INV is listed
10. Connect to admin's account
11. Go to Customers, Archive C_02
12. Repeat steps 8-9
=> A 403-Forbidden page is displayed with a traceback.
For a user to have access to the "Invoices & Bills", one of the
followers of each invoice must be part of the same commercial partner:
`('message_partner_ids','child_of',[user.commercial_partner_id.id])`.
Here is the issue: if archived, the partner will not be in the
`message_partner_ids` list. This is the reason why, in our case, C_01
can no longer access the documents.
This commit allows the archived partners to be listed when getting the
portal transactions.
OPW-2417275
closes odoo/odoo#63790
X-original-commit: ad36feae0a1ee6fe0bdfbb622685a6b143ea4f2a
Signed-off-by: Adrien Widart <adwid@users.noreply.github.com>
95 lines
4.1 KiB
Python
95 lines
4.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class AccountMove(models.Model):
|
|
_inherit = 'account.move'
|
|
|
|
transaction_ids = fields.Many2many('payment.transaction', 'account_invoice_transaction_rel', 'invoice_id', 'transaction_id',
|
|
string='Transactions', copy=False, readonly=True)
|
|
authorized_transaction_ids = fields.Many2many('payment.transaction', compute='_compute_authorized_transaction_ids',
|
|
string='Authorized Transactions', copy=False, readonly=True)
|
|
|
|
@api.depends('transaction_ids')
|
|
def _compute_authorized_transaction_ids(self):
|
|
for trans in self:
|
|
trans.authorized_transaction_ids = trans.transaction_ids.filtered(lambda t: t.state == 'authorized')
|
|
|
|
def get_portal_last_transaction(self):
|
|
self.ensure_one()
|
|
return self.with_context(active_test=False).transaction_ids.get_last_transaction()
|
|
|
|
def _create_payment_transaction(self, vals):
|
|
'''Similar to self.env['payment.transaction'].create(vals) but the values are filled with the
|
|
current invoices fields (e.g. the partner or the currency).
|
|
:param vals: The values to create a new payment.transaction.
|
|
:return: The newly created payment.transaction record.
|
|
'''
|
|
# Ensure the currencies are the same.
|
|
currency = self[0].currency_id
|
|
if any(inv.currency_id != currency for inv in self):
|
|
raise ValidationError(_('A transaction can\'t be linked to invoices having different currencies.'))
|
|
|
|
# Ensure the partner are the same.
|
|
partner = self[0].partner_id
|
|
if any(inv.partner_id != partner for inv in self):
|
|
raise ValidationError(_('A transaction can\'t be linked to invoices having different partners.'))
|
|
|
|
# Try to retrieve the acquirer. However, fallback to the token's acquirer.
|
|
acquirer_id = vals.get('acquirer_id')
|
|
acquirer = None
|
|
payment_token_id = vals.get('payment_token_id')
|
|
|
|
if payment_token_id:
|
|
payment_token = self.env['payment.token'].sudo().browse(payment_token_id)
|
|
|
|
# Check payment_token/acquirer matching or take the acquirer from token
|
|
if acquirer_id:
|
|
acquirer = self.env['payment.acquirer'].browse(acquirer_id)
|
|
if payment_token and payment_token.acquirer_id != acquirer:
|
|
raise ValidationError(_('Invalid token found! Token acquirer %s != %s') % (
|
|
payment_token.acquirer_id.name, acquirer.name))
|
|
if payment_token and payment_token.partner_id != partner:
|
|
raise ValidationError(_('Invalid token found! Token partner %s != %s') % (
|
|
payment_token.partner.name, partner.name))
|
|
else:
|
|
acquirer = payment_token.acquirer_id
|
|
|
|
# Check an acquirer is there.
|
|
if not acquirer_id and not acquirer:
|
|
raise ValidationError(_('A payment acquirer is required to create a transaction.'))
|
|
|
|
if not acquirer:
|
|
acquirer = self.env['payment.acquirer'].browse(acquirer_id)
|
|
|
|
# Check a journal is set on acquirer.
|
|
if not acquirer.journal_id:
|
|
raise ValidationError(_('A journal must be specified for the acquirer %s.', acquirer.name))
|
|
|
|
if not acquirer_id and acquirer:
|
|
vals['acquirer_id'] = acquirer.id
|
|
|
|
vals.update({
|
|
'amount': sum(self.mapped('amount_residual')),
|
|
'currency_id': currency.id,
|
|
'partner_id': partner.id,
|
|
'invoice_ids': [(6, 0, self.ids)],
|
|
})
|
|
|
|
transaction = self.env['payment.transaction'].create(vals)
|
|
|
|
# Process directly if payment_token
|
|
if transaction.payment_token_id:
|
|
transaction.s2s_do_transaction()
|
|
|
|
return transaction
|
|
|
|
def payment_action_capture(self):
|
|
self.authorized_transaction_ids.s2s_capture_transaction()
|
|
|
|
def payment_action_void(self):
|
|
self.authorized_transaction_ids.s2s_void_transaction()
|