payment.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. from odoo import _
  3. from odoo.exceptions import AccessError, MissingError, ValidationError
  4. from odoo.fields import Command
  5. from odoo.http import request, route
  6. from odoo.addons.payment import utils as payment_utils
  7. from odoo.addons.payment.controllers import portal as payment_portal
  8. class PaymentPortal(payment_portal.PaymentPortal):
  9. @route('/invoice/transaction/<int:invoice_id>', type='json', auth='public')
  10. def invoice_transaction(self, invoice_id, access_token, **kwargs):
  11. """ Create a draft transaction and return its processing values.
  12. :param int invoice_id: The invoice to pay, as an `account.move` id
  13. :param str access_token: The access token used to authenticate the request
  14. :param dict kwargs: Locally unused data passed to `_create_transaction`
  15. :return: The mandatory values for the processing of the transaction
  16. :rtype: dict
  17. :raise: ValidationError if the invoice id or the access token is invalid
  18. """
  19. # Check the invoice id and the access token
  20. try:
  21. invoice_sudo = self._document_check_access('account.move', invoice_id, access_token)
  22. except MissingError as error:
  23. raise error
  24. except AccessError:
  25. raise ValidationError(_("The access token is invalid."))
  26. kwargs['reference_prefix'] = None # Allow the reference to be computed based on the invoice
  27. logged_in = not request.env.user._is_public()
  28. partner = request.env.user.partner_id if logged_in else invoice_sudo.partner_id
  29. kwargs['partner_id'] = partner.id
  30. kwargs.pop('custom_create_values', None) # Don't allow passing arbitrary create values
  31. tx_sudo = self._create_transaction(
  32. custom_create_values={'invoice_ids': [Command.set([invoice_id])]}, **kwargs,
  33. )
  34. return tx_sudo._get_processing_values()
  35. # Payment overrides
  36. @route()
  37. def payment_pay(self, *args, amount=None, invoice_id=None, access_token=None, **kwargs):
  38. """ Override of `payment` to replace the missing transaction values by that of the invoice.
  39. This is necessary for the reconciliation as all transaction values, excepted the amount,
  40. need to match exactly that of the invoice.
  41. :param str amount: The (possibly partial) amount to pay used to check the access token.
  42. :param str invoice_id: The invoice for which a payment id made, as an `account.move` id.
  43. :param str access_token: The access token used to authenticate the partner.
  44. :return: The result of the parent method.
  45. :rtype: str
  46. :raise ValidationError: If the invoice id is invalid.
  47. """
  48. # Cast numeric parameters as int or float and void them if their str value is malformed.
  49. amount = self._cast_as_float(amount)
  50. invoice_id = self._cast_as_int(invoice_id)
  51. if invoice_id:
  52. invoice_sudo = request.env['account.move'].sudo().browse(invoice_id).exists()
  53. if not invoice_sudo:
  54. raise ValidationError(_("The provided parameters are invalid."))
  55. # Check the access token against the invoice values. Done after fetching the invoice
  56. # as we need the invoice fields to check the access token.
  57. if not payment_utils.check_access_token(
  58. access_token, invoice_sudo.partner_id.id, amount, invoice_sudo.currency_id.id
  59. ):
  60. raise ValidationError(_("The provided parameters are invalid."))
  61. kwargs.update({
  62. 'currency_id': invoice_sudo.currency_id.id,
  63. 'partner_id': invoice_sudo.partner_id.id,
  64. 'company_id': invoice_sudo.company_id.id,
  65. 'invoice_id': invoice_id,
  66. })
  67. return super().payment_pay(*args, amount=amount, access_token=access_token, **kwargs)
  68. def _get_custom_rendering_context_values(self, invoice_id=None, **kwargs):
  69. """ Override of `payment` to add the invoice id in the custom rendering context values.
  70. :param int invoice_id: The invoice for which a payment id made, as an `account.move` id.
  71. :param dict kwargs: Optional data. This parameter is not used here.
  72. :return: The extended rendering context values.
  73. :rtype: dict
  74. """
  75. rendering_context_values = super()._get_custom_rendering_context_values(
  76. invoice_id=invoice_id, **kwargs
  77. )
  78. if invoice_id:
  79. rendering_context_values['invoice_id'] = invoice_id
  80. # Interrupt the payment flow if the invoice has been canceled.
  81. invoice_sudo = request.env['account.move'].sudo().browse(invoice_id)
  82. if invoice_sudo.state == 'cancel':
  83. rendering_context_values['amount'] = 0.0
  84. return rendering_context_values
  85. def _create_transaction(self, *args, invoice_id=None, custom_create_values=None, **kwargs):
  86. """ Override of `payment` to add the invoice id in the custom create values.
  87. :param int invoice_id: The invoice for which a payment id made, as an `account.move` id.
  88. :param dict custom_create_values: Additional create values overwriting the default ones.
  89. :param dict kwargs: Optional data. This parameter is not used here.
  90. :return: The result of the parent method.
  91. :rtype: recordset of `payment.transaction`
  92. """
  93. if invoice_id:
  94. if custom_create_values is None:
  95. custom_create_values = {}
  96. custom_create_values['invoice_ids'] = [Command.set([int(invoice_id)])]
  97. return super()._create_transaction(
  98. *args, invoice_id=invoice_id, custom_create_values=custom_create_values, **kwargs
  99. )