19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:30:07 +01:00
parent ba20ce7443
commit 768b70e05e
2357 changed files with 1057103 additions and 712486 deletions

View file

@ -11,7 +11,7 @@ from odoo.addons.payment.controllers import portal as payment_portal
class PaymentPortal(payment_portal.PaymentPortal):
@route('/invoice/transaction/<int:invoice_id>', type='json', auth='public')
@route('/invoice/transaction/<int:invoice_id>', type='jsonrpc', auth='public')
def invoice_transaction(self, invoice_id, access_token, **kwargs):
""" Create a draft transaction and return its processing values.
@ -30,13 +30,43 @@ class PaymentPortal(payment_portal.PaymentPortal):
except AccessError:
raise ValidationError(_("The access token is invalid."))
kwargs['reference_prefix'] = None # Allow the reference to be computed based on the invoice
logged_in = not request.env.user._is_public()
partner = request.env.user.partner_id if logged_in else invoice_sudo.partner_id
kwargs['partner_id'] = partner.id
kwargs.pop('custom_create_values', None) # Don't allow passing arbitrary create values
partner_sudo = request.env.user.partner_id if logged_in else invoice_sudo.partner_id
self._validate_transaction_kwargs(kwargs, additional_allowed_keys={'name_next_installment'})
return self._process_transaction(partner_sudo.id, invoice_sudo.currency_id.id, [invoice_id], False, **kwargs)
@route('/invoice/transaction/overdue', type='jsonrpc', auth='public')
def overdue_invoices_transaction(self, payment_reference, **kwargs):
""" Create a draft transaction for overdue invoices and return its processing values.
:param str payment_reference: The reference to the current payment
:param dict kwargs: Locally unused data passed to `_create_transaction`
:return: The mandatory values for the processing of the transaction
:rtype: dict
:raise: ValidationError if the user is not logged in, or all the overdue invoices don't share the same currency.
"""
logged_in = not request.env.user._is_public()
if not logged_in:
raise ValidationError(_("Please log in to pay your overdue invoices"))
partner = request.env.user.partner_id
overdue_invoices = request.env['account.move'].search(self._get_overdue_invoices_domain())
currencies = overdue_invoices.mapped('currency_id')
if not all(currency == currencies[0] for currency in currencies):
raise ValidationError(_("Impossible to pay all the overdue invoices if they don't share the same currency."))
self._validate_transaction_kwargs(kwargs)
return self._process_transaction(partner.id, currencies[0].id, overdue_invoices.ids, payment_reference, **kwargs)
def _process_transaction(self, partner_id, currency_id, invoice_ids, payment_reference, **kwargs):
kwargs.update({
'currency_id': currency_id,
'partner_id': partner_id,
'reference_prefix': payment_reference,
}) # Inject the create values taken from the invoice into the kwargs.
tx_sudo = self._create_transaction(
custom_create_values={'invoice_ids': [Command.set([invoice_id])]}, **kwargs,
custom_create_values={
'invoice_ids': [Command.set(invoice_ids)],
},
**kwargs,
)
return tx_sudo._get_processing_values()
@ -47,9 +77,6 @@ class PaymentPortal(payment_portal.PaymentPortal):
def payment_pay(self, *args, amount=None, invoice_id=None, access_token=None, **kwargs):
""" Override of `payment` to replace the missing transaction values by that of the invoice.
This is necessary for the reconciliation as all transaction values, excepted the amount,
need to match exactly that of the invoice.
:param str amount: The (possibly partial) amount to pay used to check the access token.
:param str invoice_id: The invoice for which a payment id made, as an `account.move` id.
:param str access_token: The access token used to authenticate the partner.
@ -73,48 +100,53 @@ class PaymentPortal(payment_portal.PaymentPortal):
raise ValidationError(_("The provided parameters are invalid."))
kwargs.update({
# To display on the payment form; will be later overwritten when creating the tx.
'reference': invoice_sudo.name,
# To fix the currency if incorrect and avoid mismatches when creating the tx.
'currency_id': invoice_sudo.currency_id.id,
# To fix the partner if incorrect and avoid mismatches when creating the tx.
'partner_id': invoice_sudo.partner_id.id,
'company_id': invoice_sudo.company_id.id,
'invoice_id': invoice_id,
})
return super().payment_pay(*args, amount=amount, access_token=access_token, **kwargs)
def _get_custom_rendering_context_values(self, invoice_id=None, **kwargs):
""" Override of `payment` to add the invoice id in the custom rendering context values.
def _get_extra_payment_form_values(self, invoice_id=None, access_token=None, **kwargs):
""" Override of `payment` to reroute the payment flow to the portal view of the invoice.
:param int invoice_id: The invoice for which a payment id made, as an `account.move` id.
:param dict kwargs: Optional data. This parameter is not used here.
:param str invoice_id: The invoice for which a payment id made, as an `account.move` id.
:param str access_token: The portal or payment access token, respectively if we are in a
portal or payment link flow.
:return: The extended rendering context values.
:rtype: dict
"""
rendering_context_values = super()._get_custom_rendering_context_values(
invoice_id=invoice_id, **kwargs
form_values = super()._get_extra_payment_form_values(
invoice_id=invoice_id, access_token=access_token, **kwargs
)
if invoice_id:
rendering_context_values['invoice_id'] = invoice_id
invoice_id = self._cast_as_int(invoice_id)
try: # Check document access against what could be a portal access token.
invoice_sudo = self._document_check_access('account.move', invoice_id, access_token)
except AccessError: # It is a payment access token computed on the payment context.
if not payment_utils.check_access_token(
access_token,
kwargs.get('partner_id'),
kwargs.get('amount'),
kwargs.get('currency_id'),
):
raise
invoice_sudo = request.env['account.move'].sudo().browse(invoice_id)
# Interrupt the payment flow if the invoice has been canceled.
invoice_sudo = request.env['account.move'].sudo().browse(invoice_id)
if invoice_sudo.state == 'cancel':
rendering_context_values['amount'] = 0.0
form_values['amount'] = 0.0
return rendering_context_values
def _create_transaction(self, *args, invoice_id=None, custom_create_values=None, **kwargs):
""" Override of `payment` to add the invoice id in the custom create values.
:param int invoice_id: The invoice for which a payment id made, as an `account.move` id.
:param dict custom_create_values: Additional create values overwriting the default ones.
:param dict kwargs: Optional data. This parameter is not used here.
:return: The result of the parent method.
:rtype: recordset of `payment.transaction`
"""
if invoice_id:
if custom_create_values is None:
custom_create_values = {}
custom_create_values['invoice_ids'] = [Command.set([int(invoice_id)])]
return super()._create_transaction(
*args, invoice_id=invoice_id, custom_create_values=custom_create_values, **kwargs
)
# Reroute the next steps of the payment flow to the portal view of the invoice.
form_values.update({
'transaction_route': f'/invoice/transaction/{invoice_id}',
'landing_route': f'{invoice_sudo.access_url}'
f'?access_token={invoice_sudo._portal_ensure_token()}',
'access_token': invoice_sudo.access_token,
})
return form_values