Allow order change

This commit is contained in:
Raphael Michel
2019-09-19 17:54:05 +02:00
parent e97ae04581
commit 9842fcf7da
4 changed files with 83 additions and 14 deletions

View File

@@ -61,6 +61,9 @@ class GiftCard(LoggedModel):
def value(self):
return self.transactions.aggregate(s=Sum('value'))['s'] or Decimal('0.00')
def accepted_by(self, organizer):
return self.issuer == organizer or GiftCardAcceptance.objects.filter(issuer=self.issuer, collector=organizer).exists()
class Meta:
unique_together = (('secret', 'issuer'),)

View File

@@ -899,26 +899,27 @@ class GiftCardPayment(BasePaymentProvider):
return super().is_allowed(request, total) and self.event.organizer.has_gift_cards
def order_change_allowed(self, order: Order) -> bool:
return False
def execute_payment(self, request: HttpRequest, payment: OrderPayment) -> str:
raise PaymentException("Invalid state, should never occur.")
return super().order_change_allowed(order) and self.event.organizer.has_gift_cards
def payment_form_render(self, request: HttpRequest, total: Decimal) -> str:
return get_template('pretixcontrol/giftcards/checkout.html').render({})
def checkout_confirm_render(self, request) -> str:
return get_template('pretixcontrol/giftcards/checkout_confirm.html').render({})
def payment_control_render(self, request, payment) -> str:
from .models import GiftCard
gc = GiftCard.objects.get(pk=payment.info_data.get('gift_card'))
template = get_template('pretixcontrol/giftcards/payment.html')
if 'gift_card' in payment.info_data:
gc = GiftCard.objects.get(pk=payment.info_data.get('gift_card'))
template = get_template('pretixcontrol/giftcards/payment.html')
ctx = {
'request': request,
'event': self.event,
'gc': gc,
}
return template.render(ctx)
ctx = {
'request': request,
'event': self.event,
'gc': gc,
}
return template.render(ctx)
def api_payment_details(self, payment: OrderPayment):
from .models import GiftCard
@@ -977,6 +978,60 @@ class GiftCardPayment(BasePaymentProvider):
except GiftCard.MultipleObjectsReturned:
messages.error(request, _("This gift card can not be redeemed since its code is not unique. Please contact the organizer of this event."))
def payment_prepare(self, request: HttpRequest, payment: OrderPayment) -> Union[bool, str, None]:
try:
gc = self.event.organizer.accepted_gift_cards.get(
secret=request.POST.get("giftcard")
)
if gc.currency != self.event.currency:
messages.error(request, _("This gift card does not support this currency."))
return
if gc.value <= Decimal("0.00"):
messages.error(request, _("All credit on this gift card has been used."))
return
payment.info_data = {
'gift_card': gc.pk,
'retry': True
}
payment.amount = min(payment.amount, gc.value)
payment.save()
return True
except GiftCard.DoesNotExist:
if self.event.vouchers.filter(code__iexact=request.POST.get("giftcard")).exists():
messages.warning(request, _("You entered a voucher instead of a gift card. Vouchers can only be entered on the first page of the shop below "
"the product selection."))
else:
messages.error(request, _("This gift card is not known."))
except GiftCard.MultipleObjectsReturned:
messages.error(request, _("This gift card can not be redeemed since its code is not unique. Please contact the organizer of this event."))
def execute_payment(self, request: HttpRequest, payment: OrderPayment) -> str:
gcpk = payment.info_data.get('gift_card')
if not gcpk or not payment.info_data.get('retry'):
raise PaymentException("Invalid state, should never occur.")
with transaction.atomic():
gc = GiftCard.objects.select_for_update().get(pk=gcpk)
if gc.currency != self.event.currency:
raise PaymentException(_("This gift card does not support this currency."))
if not gc.accepted_by(self.event.organizer):
raise PaymentException(_("This gift card is not accepted by this event organizer."))
if payment.amount > gc.value:
raise PaymentException(_("This gift card was used in the meantime. Please try again"))
trans = gc.transactions.create(
value=-1 * payment.amount,
order=payment.order,
payment=payment
)
payment.info_data = {
'gift_card': gc.pk,
'transaction_id': trans.pk,
}
payment.confirm()
def payment_is_valid_session(self, request: HttpRequest) -> bool:
return True
@transaction.atomic()
def execute_refund(self, refund: OrderRefund):
from .models import GiftCard

View File

@@ -595,9 +595,12 @@ def _create_order(event: Event, email: str, positions: List[CartPosition], now_d
with transaction.atomic():
checked_gift_cards = []
if gift_cards:
gc_qs = GiftCard.objects.select_for_update().filter(pk__in=gift_cards) # TODO: Make sure to prevent race conditions
gc_qs = GiftCard.objects.select_for_update().filter(pk__in=gift_cards)
for gc in gc_qs:
# TODO: Re-check acceptance
if gc.currency != event.currency:
raise OrderError(_("This gift card does not support this currency."))
if not gc.accepted_by(event.organizer):
raise OrderError(_("This gift card is not accepted by this event organizer."))
checked_gift_cards.append(gc)
fees, pf, gift_card_values = _get_fees(positions, payment_provider, address, meta_info, event, checked_gift_cards)

View File

@@ -0,0 +1,8 @@
{% load i18n %}
<p>
{% blocktrans %}
Your gift card will be used to pay for this order. If the credit on the gift card is lower than the order total, you will be able to pay the
difference with a different payment method. If the credit is higher than the order total, you will be able to re-use the gift card in the future.
{% endblocktrans %}
</p>