This commit changes the way transactions linked to a document (sales order, invoice...) are created in a payment flow. Rather than receiving and trusting the transaction values from the controller, they are now read from the linked document, and the payment flow is rerouted to use the document's module's controllers instead of that of `payment`. This ensures that no unexpected value can be passed to the `create` method of a transaction, and simplifies the implementation of the payment flows of linked documents. task-3136240 closes odoo/odoo#126425 Related: odoo/enterprise#43212 Related: odoo/upgrade#5124 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
86 lines
3.4 KiB
Python
86 lines
3.4 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from werkzeug import urls
|
|
|
|
from odoo import _, api, fields, models
|
|
|
|
from odoo.addons.payment import utils as payment_utils
|
|
|
|
|
|
class PaymentLinkWizard(models.TransientModel):
|
|
_name = 'payment.link.wizard'
|
|
_description = "Generate Payment Link"
|
|
|
|
@api.model
|
|
def default_get(self, fields_list):
|
|
res = super().default_get(fields_list)
|
|
res_id = self.env.context.get('active_id')
|
|
res_model = self.env.context.get('active_model')
|
|
if res_id and res_model:
|
|
res.update({'res_model': res_model, 'res_id': res_id})
|
|
res.update(
|
|
self.env[res_model].browse(res_id)._get_default_payment_link_values()
|
|
)
|
|
return res
|
|
|
|
res_model = fields.Char("Related Document Model", required=True)
|
|
res_id = fields.Integer("Related Document ID", required=True)
|
|
amount = fields.Monetary(currency_field='currency_id', required=True)
|
|
amount_max = fields.Monetary(currency_field='currency_id')
|
|
currency_id = fields.Many2one('res.currency')
|
|
partner_id = fields.Many2one('res.partner')
|
|
partner_email = fields.Char(related='partner_id.email')
|
|
link = fields.Char(string="Payment Link", compute='_compute_link')
|
|
company_id = fields.Many2one('res.company', compute='_compute_company_id')
|
|
warning_message = fields.Char(compute='_compute_warning_message')
|
|
|
|
@api.depends('amount', 'amount_max')
|
|
def _compute_warning_message(self):
|
|
self.warning_message = ''
|
|
for wizard in self:
|
|
if wizard.amount_max <= 0:
|
|
wizard.warning_message = _("There is nothing to be paid.")
|
|
elif wizard.amount <= 0:
|
|
wizard.warning_message = _("Please set a positive amount.")
|
|
elif wizard.amount > wizard.amount_max:
|
|
wizard.warning_message = _("Please set an amount lower than %s.", wizard.amount_max)
|
|
|
|
@api.depends('res_model', 'res_id')
|
|
def _compute_company_id(self):
|
|
for link in self:
|
|
record = self.env[link.res_model].browse(link.res_id)
|
|
link.company_id = record.company_id if 'company_id' in record else False
|
|
|
|
def _get_access_token(self):
|
|
self.ensure_one()
|
|
return payment_utils.generate_access_token(
|
|
self.partner_id.id, self.amount, self.currency_id.id
|
|
)
|
|
|
|
@api.depends('amount', 'currency_id', 'partner_id', 'company_id')
|
|
def _compute_link(self):
|
|
for payment_link in self:
|
|
related_document = self.env[payment_link.res_model].browse(payment_link.res_id)
|
|
base_url = related_document.get_base_url() # Don't generate links for the wrong website
|
|
url_params = {
|
|
'amount': self.amount,
|
|
'access_token': self._get_access_token(),
|
|
**self._get_additional_link_values(),
|
|
}
|
|
payment_link.link = f'{base_url}/payment/pay?{urls.url_encode(url_params)}'
|
|
|
|
def _get_additional_link_values(self):
|
|
""" Return the additional values to append to the payment link.
|
|
|
|
Note: self.ensure_one()
|
|
|
|
:return: The additional payment link values.
|
|
:rtype: dict
|
|
"""
|
|
self.ensure_one()
|
|
return {
|
|
'currency_id': self.currency_id.id,
|
|
'partner_id': self.partner_id.id,
|
|
'company_id': self.company_id.id,
|
|
}
|