mirror of
https://github.com/pretix/pretix.git
synced 2026-05-04 15:04:03 +00:00
Allow customers to choose to receive their refund as a gift card (#1626)
* Minor text adjustments * Allow users to receive their cancellation as a gift card
This commit is contained in:
@@ -1210,6 +1210,7 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
)
|
||||
refund.info_data = {
|
||||
'gift_card': gc.pk,
|
||||
'gift_card_code': gc.secret,
|
||||
'transaction_id': trans.pk,
|
||||
}
|
||||
refund.done()
|
||||
|
||||
@@ -1888,7 +1888,8 @@ def perform_order(self, event: Event, payment_provider: str, positions: List[str
|
||||
raise OrderError(str(error_messages['busy']))
|
||||
|
||||
|
||||
def _try_auto_refund(order, manual_refund=False, allow_partial=False, source=OrderRefund.REFUND_SOURCE_BUYER):
|
||||
def _try_auto_refund(order, manual_refund=False, allow_partial=False, source=OrderRefund.REFUND_SOURCE_BUYER,
|
||||
refund_as_giftcard=False):
|
||||
notify_admin = False
|
||||
error = False
|
||||
if isinstance(order, int):
|
||||
@@ -1897,9 +1898,49 @@ def _try_auto_refund(order, manual_refund=False, allow_partial=False, source=Ord
|
||||
if refund_amount <= Decimal('0.00'):
|
||||
return
|
||||
|
||||
proposals = order.propose_auto_refunds(refund_amount)
|
||||
can_auto_refund_sum = sum(proposals.values())
|
||||
can_auto_refund = (allow_partial and can_auto_refund_sum) or can_auto_refund_sum == refund_amount
|
||||
if refund_as_giftcard:
|
||||
proposals = {}
|
||||
can_auto_refund = True
|
||||
can_auto_refund_sum = refund_amount
|
||||
with transaction.atomic():
|
||||
giftcard = order.event.organizer.issued_gift_cards.create(
|
||||
currency=order.event.currency,
|
||||
testmode=order.testmode
|
||||
)
|
||||
giftcard.log_action('pretix.giftcards.created', data={})
|
||||
r = order.refunds.create(
|
||||
order=order,
|
||||
payment=None,
|
||||
source=source,
|
||||
state=OrderRefund.REFUND_STATE_CREATED,
|
||||
execution_date=now(),
|
||||
amount=can_auto_refund_sum,
|
||||
provider='giftcard',
|
||||
info=json.dumps({
|
||||
'gift_card': giftcard.pk
|
||||
})
|
||||
)
|
||||
try:
|
||||
r.payment_provider.execute_refund(r)
|
||||
except PaymentException as e:
|
||||
with transaction.atomic():
|
||||
r.state = OrderRefund.REFUND_STATE_FAILED
|
||||
r.save()
|
||||
order.log_action('pretix.event.order.refund.failed', {
|
||||
'local_id': r.local_id,
|
||||
'provider': r.provider,
|
||||
'error': str(e)
|
||||
})
|
||||
error = True
|
||||
notify_admin = True
|
||||
else:
|
||||
if r.state != OrderRefund.REFUND_STATE_DONE:
|
||||
notify_admin = True
|
||||
|
||||
else:
|
||||
proposals = order.propose_auto_refunds(refund_amount)
|
||||
can_auto_refund_sum = sum(proposals.values())
|
||||
can_auto_refund = (allow_partial and can_auto_refund_sum) or can_auto_refund_sum == refund_amount
|
||||
if can_auto_refund:
|
||||
for p, value in proposals.items():
|
||||
with transaction.atomic():
|
||||
@@ -1961,13 +2002,13 @@ def _try_auto_refund(order, manual_refund=False, allow_partial=False, source=Ord
|
||||
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
|
||||
@scopes_disabled()
|
||||
def cancel_order(self, order: int, user: int=None, send_mail: bool=True, api_token=None, oauth_application=None,
|
||||
device=None, cancellation_fee=None, try_auto_refund=False):
|
||||
device=None, cancellation_fee=None, try_auto_refund=False, refund_as_giftcard=False):
|
||||
try:
|
||||
try:
|
||||
ret = _cancel_order(order, user, send_mail, api_token, device, oauth_application,
|
||||
cancellation_fee)
|
||||
if try_auto_refund:
|
||||
_try_auto_refund(order)
|
||||
_try_auto_refund(order, refund_as_giftcard=refund_as_giftcard)
|
||||
return ret
|
||||
except LockTimeoutException:
|
||||
self.retry()
|
||||
|
||||
@@ -917,6 +917,29 @@ DEFAULTS = {
|
||||
help_text=_("With this option enabled, your customers can choose to get a smaller refund to support you.")
|
||||
)
|
||||
},
|
||||
'cancel_allow_user_paid_refund_as_giftcard': {
|
||||
'default': 'off',
|
||||
'type': str,
|
||||
'serializer_class': serializers.ChoiceField,
|
||||
'serializer_kwargs': dict(
|
||||
choices=[
|
||||
('off', _('All refunds are issued to the original payment method')),
|
||||
('option', _('Customers can choose between a gift card and a refund to their payment method')),
|
||||
('force', _('All refunds are issued as gift cards')),
|
||||
],
|
||||
),
|
||||
'form_class': forms.ChoiceField,
|
||||
'form_kwargs': dict(
|
||||
label=_('Refund method'),
|
||||
choices=[
|
||||
('off', _('All refunds are issued to the original payment method')),
|
||||
('option', _('Customers can choose between a gift card and a refund to their payment method')),
|
||||
('force', _('All refunds are issued as gift cards')),
|
||||
],
|
||||
widget=forms.RadioSelect,
|
||||
# When adding a new ordering, remember to also define it in the event model
|
||||
)
|
||||
},
|
||||
'cancel_allow_user_paid_until': {
|
||||
'default': None,
|
||||
'type': RelativeDateWrapper,
|
||||
|
||||
Reference in New Issue
Block a user