Files
odoo_source/addons/payment/wizards/payment_refund_wizard.py
T
Demesmaeker e0233a1010 [IMP] payment(_adyen): allow to refund confirmed transactions
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>
2021-08-23 10:54:17 +00:00

67 lines
2.9 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class PaymentRefundWizard(models.TransientModel):
_name = 'payment.refund.wizard'
_description = "Payment Refund Wizard"
payment_id = fields.Many2one(
string="Payment",
comodel_name='account.payment',
readonly=True,
default=lambda self: self.env.context.get('active_id'),
)
transaction_id = fields.Many2one(
string="Payment Transaction", related='payment_id.payment_transaction_id'
)
payment_amount = fields.Monetary(string="Payment Amount", related='payment_id.amount')
refunded_amount = fields.Monetary(string="Refunded Amount", compute='_compute_refunded_amount')
amount_available_for_refund = fields.Monetary(
string="Maximum Refund Allowed", related='payment_id.amount_available_for_refund'
)
amount_to_refund = fields.Monetary(
string="Refund Amount", compute='_compute_amount_to_refund', store=True, readonly=False
)
currency_id = fields.Many2one(string="Currency", related='transaction_id.currency_id')
support_refund = fields.Selection(related='transaction_id.acquirer_id.support_refund')
has_pending_refund = fields.Boolean(
string="Has a pending refund", compute='_compute_has_pending_refund'
)
@api.constrains('amount_to_refund')
def _check_amount_to_refund_within_boundaries(self):
for wizard in self:
if not 0 < wizard.amount_to_refund <= wizard.amount_available_for_refund:
raise ValidationError(_(
"The amount to be refunded must be positive and cannot be superior to %s.",
wizard.amount_available_for_refund
))
@api.depends('amount_available_for_refund')
def _compute_refunded_amount(self):
for wizard in self:
wizard.refunded_amount = wizard.payment_amount - wizard.amount_available_for_refund
@api.depends('amount_available_for_refund')
def _compute_amount_to_refund(self):
""" Set the default amount to refund to the amount available for refund. """
for wizard in self:
wizard.amount_to_refund = wizard.amount_available_for_refund
@api.depends('payment_id') # To always trigger the compute
def _compute_has_pending_refund(self):
for wizard in self:
pending_refunds_count = self.env['payment.transaction'].search_count([
('source_transaction_id', '=', wizard.payment_id.payment_transaction_id.id),
('operation', '=', 'refund'),
('state', 'in', ['draft', 'pending', 'authorized']),
])
wizard.has_pending_refund = pending_refunds_count > 0
def action_refund(self):
for wizard in self:
wizard.transaction_id.action_refund(amount_to_refund=wizard.amount_to_refund)