test_account_payment.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. from unittest.mock import patch
  3. from odoo.exceptions import UserError
  4. from odoo.tests import tagged
  5. from odoo.addons.account_payment.tests.common import AccountPaymentCommon
  6. @tagged('-at_install', 'post_install')
  7. class TestAccountPayment(AccountPaymentCommon):
  8. def test_no_amount_available_for_refund_when_not_supported(self):
  9. self.provider.support_refund = False
  10. tx = self._create_transaction('redirect', state='done')
  11. tx._reconcile_after_done() # Create the payment
  12. self.assertEqual(
  13. tx.payment_id.amount_available_for_refund,
  14. 0,
  15. msg="The value of `amount_available_for_refund` should be 0 when the provider doesn't "
  16. "support refunds."
  17. )
  18. def test_full_amount_available_for_refund_when_not_yet_refunded(self):
  19. self.provider.support_refund = 'full_only' # Should simply not be False
  20. tx = self._create_transaction('redirect', state='done')
  21. tx._reconcile_after_done() # Create the payment
  22. self.assertAlmostEqual(
  23. tx.payment_id.amount_available_for_refund,
  24. tx.amount,
  25. places=2,
  26. msg="The value of `amount_available_for_refund` should be that of `total` when there "
  27. "are no linked refunds."
  28. )
  29. def test_full_amount_available_for_refund_when_refunds_are_pending(self):
  30. self.provider.write({
  31. 'support_refund': 'full_only', # Should simply not be False
  32. 'support_manual_capture': True, # To create transaction in the 'authorized' state
  33. })
  34. tx = self._create_transaction('redirect', state='done')
  35. tx._reconcile_after_done() # Create the payment
  36. for reference_index, state in enumerate(('draft', 'pending', 'authorized')):
  37. self._create_transaction(
  38. 'dummy',
  39. amount=-tx.amount,
  40. reference=f'R-{tx.reference}-{reference_index + 1}',
  41. state=state,
  42. operation='refund', # Override the computed flow
  43. source_transaction_id=tx.id,
  44. )
  45. self.assertAlmostEqual(
  46. tx.payment_id.amount_available_for_refund,
  47. tx.payment_id.amount,
  48. places=2,
  49. msg="The value of `amount_available_for_refund` should be that of `total` when all the "
  50. "linked refunds are pending (not in the state 'done')."
  51. )
  52. def test_no_amount_available_for_refund_when_fully_refunded(self):
  53. self.provider.support_refund = 'full_only' # Should simply not be False
  54. tx = self._create_transaction('redirect', state='done')
  55. tx._reconcile_after_done() # Create the payment
  56. self._create_transaction(
  57. 'dummy',
  58. amount=-tx.amount,
  59. reference=f'R-{tx.reference}',
  60. state='done',
  61. operation='refund', # Override the computed flow
  62. source_transaction_id=tx.id,
  63. )._reconcile_after_done()
  64. self.assertEqual(
  65. tx.payment_id.amount_available_for_refund,
  66. 0,
  67. msg="The value of `amount_available_for_refund` should be 0 when there is a linked "
  68. "refund of the full amount that is confirmed (state 'done')."
  69. )
  70. def test_no_full_amount_available_for_refund_when_partially_refunded(self):
  71. self.provider.support_refund = 'partial'
  72. tx = self._create_transaction('redirect', state='done')
  73. tx._reconcile_after_done() # Create the payment
  74. self._create_transaction(
  75. 'dummy',
  76. amount=-(tx.amount / 10),
  77. reference=f'R-{tx.reference}',
  78. state='done',
  79. operation='refund', # Override the computed flow
  80. source_transaction_id=tx.id,
  81. )._reconcile_after_done()
  82. self.assertAlmostEqual(
  83. tx.payment_id.amount_available_for_refund,
  84. tx.payment_id.amount - (tx.amount / 10),
  85. places=2,
  86. msg="The value of `amount_available_for_refund` should be equal to the total amount "
  87. "minus the sum of the absolute amount of the refunds that are confirmed (state "
  88. "'done')."
  89. )
  90. def test_refunds_count(self):
  91. self.provider.support_refund = 'full_only' # Should simply not be False
  92. tx = self._create_transaction('redirect', state='done')
  93. tx._reconcile_after_done() # Create the payment
  94. for reference_index, operation in enumerate(
  95. ('online_redirect', 'online_direct', 'online_token', 'validation', 'refund')
  96. ):
  97. self._create_transaction(
  98. 'dummy',
  99. reference=f'R-{tx.reference}-{reference_index + 1}',
  100. state='done',
  101. operation=operation, # Override the computed flow
  102. source_transaction_id=tx.id,
  103. )._reconcile_after_done()
  104. self.assertEqual(
  105. tx.payment_id.refunds_count,
  106. 1,
  107. msg="The refunds count should only consider transactions with operation 'refund'."
  108. )
  109. def test_action_post_calls_send_payment_request_only_once(self):
  110. payment_token = self._create_token()
  111. payment_without_token = self.env['account.payment'].create({
  112. 'payment_type': 'inbound',
  113. 'partner_type': 'customer',
  114. 'amount': 2000.0,
  115. 'date': '2019-01-01',
  116. 'currency_id': self.currency.id,
  117. 'partner_id': self.partner.id,
  118. 'journal_id': self.provider.journal_id.id,
  119. 'payment_method_line_id': self.inbound_payment_method_line.id,
  120. })
  121. payment_with_token = payment_without_token.copy()
  122. payment_with_token.payment_token_id = payment_token.id
  123. with patch(
  124. 'odoo.addons.payment.models.payment_transaction.PaymentTransaction'
  125. '._send_payment_request'
  126. ) as patched:
  127. payment_without_token.action_post()
  128. patched.assert_not_called()
  129. payment_with_token.action_post()
  130. patched.assert_called_once()
  131. def test_no_payment_for_validations(self):
  132. tx = self._create_transaction(flow='dummy', operation='validation') # Overwrite the flow
  133. tx._reconcile_after_done()
  134. payment_count = self.env['account.payment'].search_count(
  135. [('payment_transaction_id', '=', tx.id)]
  136. )
  137. self.assertEqual(payment_count, 0, msg="validation transactions should not create payments")
  138. def test_prevent_unlink_apml_with_active_provider(self):
  139. """ Deleting an account.payment.method.line that is related to a provider in 'test' or 'enabled' state
  140. should raise an error.
  141. """
  142. self.assertEqual(self.dummy_provider.state, 'test')
  143. with self.assertRaises(UserError):
  144. self.dummy_provider.journal_id.inbound_payment_method_line_ids.unlink()