payment_token.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. import logging
  3. from odoo import _, api, fields, models
  4. from odoo.exceptions import UserError
  5. class PaymentToken(models.Model):
  6. _name = 'payment.token'
  7. _order = 'partner_id, id desc'
  8. _description = 'Payment Token'
  9. provider_id = fields.Many2one(string="Provider", comodel_name='payment.provider', required=True)
  10. provider_code = fields.Selection(related='provider_id.code')
  11. payment_details = fields.Char(
  12. string="Payment Details", help="The clear part of the payment method's payment details.",
  13. )
  14. partner_id = fields.Many2one(string="Partner", comodel_name='res.partner', required=True)
  15. company_id = fields.Many2one( # Indexed to speed-up ORM searches (from ir_rule or others)
  16. related='provider_id.company_id', store=True, index=True)
  17. provider_ref = fields.Char(
  18. string="Provider Reference", help="The provider reference of the token of the transaction",
  19. required=True) # This is not the same thing as the provider reference of the transaction.
  20. transaction_ids = fields.One2many(
  21. string="Payment Transactions", comodel_name='payment.transaction', inverse_name='token_id')
  22. verified = fields.Boolean(string="Verified")
  23. active = fields.Boolean(string="Active", default=True)
  24. #=== CRUD METHODS ===#
  25. @api.model_create_multi
  26. def create(self, values_list):
  27. for values in values_list:
  28. if 'provider_id' in values:
  29. provider = self.env['payment.provider'].browse(values['provider_id'])
  30. # Include provider-specific create values
  31. values.update(self._get_specific_create_values(provider.code, values))
  32. else:
  33. pass # Let psycopg warn about the missing required field.
  34. return super().create(values_list)
  35. @api.model
  36. def _get_specific_create_values(self, provider_code, values):
  37. """ Complete the values of the `create` method with provider-specific values.
  38. For a provider to add its own create values, it must overwrite this method and return a
  39. dict of values. Provider-specific values take precedence over those of the dict of generic
  40. create values.
  41. :param str provider_code: The code of the provider managing the token.
  42. :param dict values: The original create values.
  43. :return: The dict of provider-specific create values.
  44. :rtype: dict
  45. """
  46. return dict()
  47. def write(self, values):
  48. """ Prevent unarchiving tokens and handle their archiving.
  49. :return: The result of the call to the parent method.
  50. :rtype: bool
  51. :raise UserError: If at least one token is being unarchived.
  52. """
  53. if 'active' in values:
  54. if values['active']:
  55. if any(not token.active for token in self):
  56. raise UserError(_("A token cannot be unarchived once it has been archived."))
  57. else:
  58. # Call the handlers in sudo mode because this method might have been called by RPC.
  59. self.filtered('active').sudo()._handle_archiving()
  60. return super().write(values)
  61. def _handle_archiving(self):
  62. """ Handle the archiving of tokens.
  63. For a module to perform additional operations when a token is archived, it must override
  64. this method.
  65. :return: None
  66. """
  67. return
  68. def name_get(self):
  69. return [(token.id, token._build_display_name()) for token in self]
  70. #=== BUSINESS METHODS ===#
  71. def _build_display_name(self, *args, max_length=34, should_pad=True, **kwargs):
  72. """ Build a token name of the desired maximum length with the format `•••• 1234`.
  73. The payment details are padded on the left with up to four padding characters. The padding
  74. is only added if there is enough room for it. If not, it is either reduced or not added at
  75. all. If there is not enough room for the payment details either, they are trimmed from the
  76. left.
  77. For a module to customize the display name of a token, it must override this method and
  78. return the customized display name.
  79. Note: `self.ensure_one()`
  80. :param list args: The arguments passed by QWeb when calling this method.
  81. :param int max_length: The desired maximum length of the token name. The default is `34` to
  82. fit the largest IBANs.
  83. :param bool should_pad: Whether the token should be padded.
  84. :param dict kwargs: Optional data used in overrides of this method.
  85. :return: The padded token name.
  86. :rtype: str
  87. """
  88. self.ensure_one()
  89. padding_length = max_length - len(self.payment_details or '')
  90. if not self.payment_details:
  91. create_date_str = self.create_date.strftime('%Y/%m/%d')
  92. display_name = _("Payment details saved on %(date)s", date=create_date_str)
  93. elif padding_length >= 2: # Enough room for padding.
  94. padding = '•' * min(padding_length - 1, 4) + ' ' if should_pad else ''
  95. display_name = ''.join([padding, self.payment_details])
  96. elif padding_length > 0: # Not enough room for padding.
  97. display_name = self.payment_details
  98. else: # Not enough room for neither padding nor the payment details.
  99. display_name = self.payment_details[-max_length:] if max_length > 0 else ''
  100. return display_name
  101. def get_linked_records_info(self):
  102. """ Return a list of information about records linked to the current token.
  103. For a module to implement payments and link documents to a token, it must override this
  104. method and add information about linked document records to the returned list.
  105. The information must be structured as a dict with the following keys:
  106. - `description`: The description of the record's model (e.g. "Subscription").
  107. - `id`: The id of the record.
  108. - `name`: The name of the record.
  109. - `url`: The url to access the record.
  110. Note: `self.ensure_one()`
  111. :return: The list of information about the linked document records.
  112. :rtype: list
  113. """
  114. self.ensure_one()
  115. return []