Before this commit, it was not possible to refund a payment from Odoo. Users had to go through the payment acquirer's backend and update the payment accordingly in Odoo. With this commit, refunds are made available in Odoo directly from the payment form, for acquirers that support them. Acquirer can either only support full refunds or also support partial refunds. As of now, the only acquirer allowing refunds is Adyen, with partial refund support. task-2527891 closes odoo/odoo#70881 Related: odoo/upgrade#2689 Related: odoo/enterprise#19829 Signed-off-by: Antoine Vandevenne (anv) <AntoineVDV@users.noreply.github.com>
93 lines
3.6 KiB
Python
93 lines
3.6 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo.tests import tagged
|
|
|
|
from odoo.addons.payment.tests.common import PaymentCommon
|
|
|
|
|
|
@tagged('-at_install', 'post_install')
|
|
class TestTransactions(PaymentCommon):
|
|
|
|
def test_refunds_count(self):
|
|
self.acquirer.support_refund = 'full_only' # Should simply not be False
|
|
tx = self.create_transaction('redirect', state='done')
|
|
tx._reconcile_after_done() # Create the payment
|
|
for reference_index, operation in enumerate(
|
|
('online_redirect', 'online_direct', 'online_token', 'validation', 'refund')
|
|
):
|
|
self.create_transaction(
|
|
'dummy',
|
|
reference=f'R-{tx.reference}-{reference_index + 1}',
|
|
state='done',
|
|
operation=operation, # Override the computed flow
|
|
source_transaction_id=tx.id,
|
|
)._reconcile_after_done()
|
|
|
|
self.assertEqual(
|
|
tx.refunds_count,
|
|
1,
|
|
msg="The refunds count should only consider transactions with operation 'refund'."
|
|
)
|
|
|
|
def test_refund_transaction_values(self):
|
|
self.acquirer.support_refund = 'partial'
|
|
tx = self.create_transaction('redirect', state='done')
|
|
tx._reconcile_after_done() # Create the payment
|
|
|
|
# Test the default values of a full refund transaction
|
|
refund_tx = tx._create_refund_transaction()
|
|
self.assertEqual(
|
|
refund_tx.reference,
|
|
f'R-{tx.reference}',
|
|
msg="The reference of the refund transaction should be the prefixed reference of the "
|
|
"source transaction."
|
|
)
|
|
self.assertLess(
|
|
refund_tx.amount, 0, msg="The amount of a refund transaction should always be negative."
|
|
)
|
|
self.assertAlmostEqual(
|
|
refund_tx.amount,
|
|
-tx.amount,
|
|
places=2,
|
|
msg="The amount of the refund transaction should be taken from the amount of the "
|
|
"source transaction."
|
|
)
|
|
self.assertEqual(
|
|
refund_tx.currency_id,
|
|
tx.currency_id,
|
|
msg="The currency of the refund transaction should that of the source transaction."
|
|
)
|
|
self.assertEqual(
|
|
refund_tx.operation,
|
|
'refund',
|
|
msg="The operation of the refund transaction should be 'refund'."
|
|
)
|
|
self.assertEqual(
|
|
tx,
|
|
refund_tx.source_transaction_id,
|
|
msg="The refund transaction should be linked to the source transaction."
|
|
)
|
|
self.assertEqual(
|
|
refund_tx.partner_id,
|
|
tx.partner_id,
|
|
msg="The partner of the refund transaction should that of the source transaction."
|
|
)
|
|
|
|
# Test the values of a partial refund transaction with custom refund amount
|
|
partial_refund_tx = tx._create_refund_transaction(refund_amount=11.11)
|
|
self.assertAlmostEqual(
|
|
partial_refund_tx.amount,
|
|
-11.11,
|
|
places=2,
|
|
msg="The amount of the refund transaction should be the negative value of the amount "
|
|
"to refund."
|
|
)
|
|
|
|
def test_no_payment_for_validations(self):
|
|
tx = self.create_transaction(flow='dummy', operation='validation') # Overwrite the flow
|
|
tx._reconcile_after_done()
|
|
payment_count = self.env['account.payment'].search_count(
|
|
[('payment_transaction_id', '=', tx.id)]
|
|
)
|
|
self.assertEqual(payment_count, 0, msg="validation transactions should not create payments")
|