forked from CGM_Public/pretix_original
Add testmode for gift cards
This commit is contained in:
@@ -46,4 +46,4 @@ class GiftCardSerializer(I18nAwareModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GiftCard
|
||||
fields = ('id', 'secret', 'issuance', 'value', 'currency')
|
||||
fields = ('id', 'secret', 'issuance', 'value', 'currency', 'testmode')
|
||||
|
||||
@@ -117,7 +117,8 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
GiftCard.objects.select_for_update().get(pk=self.get_object().pk)
|
||||
old_value = serializer.instance.value
|
||||
value = serializer.validated_data.pop('value')
|
||||
inst = serializer.save(secret=serializer.instance.secret, currency=serializer.instance.currency)
|
||||
inst = serializer.save(secret=serializer.instance.secret, currency=serializer.instance.currency,
|
||||
testmode=serializer.instance.testmode)
|
||||
diff = value - old_value
|
||||
inst.transactions.create(value=diff)
|
||||
inst.log_action(
|
||||
|
||||
@@ -32,6 +32,7 @@ class Migration(migrations.Migration):
|
||||
('issuer',
|
||||
models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='issued_gift_cards',
|
||||
to='pretixbase.Organizer')),
|
||||
('testmode', django.db.models.BooleanField(default=False)),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('secret', 'issuer')},
|
||||
|
||||
@@ -52,6 +52,10 @@ class GiftCard(LoggedModel):
|
||||
db_index=True,
|
||||
verbose_name=_('Gift card code'),
|
||||
)
|
||||
testmode = models.BooleanField(
|
||||
verbose_name=_('Test mode card'),
|
||||
default=False
|
||||
)
|
||||
CURRENCY_CHOICES = [(c.alpha_3, c.alpha_3 + " - " + c.name) for c in settings.CURRENCIES]
|
||||
currency = models.CharField(max_length=10, choices=CURRENCY_CHOICES)
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ class Order(LockModel, LoggedModel):
|
||||
return self.full_code
|
||||
|
||||
def gracefully_delete(self, user=None, auth=None):
|
||||
from . import Voucher
|
||||
from . import Voucher, GiftCard, GiftCardTransaction
|
||||
|
||||
if not self.testmode:
|
||||
raise TypeError("Only test mode orders can be deleted.")
|
||||
@@ -217,6 +217,10 @@ class Order(LockModel, LoggedModel):
|
||||
if position.voucher:
|
||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
||||
|
||||
GiftCardTransaction.objects.filter(payment__in=self.payments.all()).update(payment=None)
|
||||
GiftCardTransaction.objects.filter(refund__in=self.refunds.all()).update(refund=None)
|
||||
GiftCardTransaction.objects.filter(order=self).update(order=None)
|
||||
GiftCard.objects.filter(issued_in__in=self.positions.all()).update(issued_in=None)
|
||||
OrderPosition.all.filter(order=self, addon_to__isnull=False).delete()
|
||||
OrderPosition.all.filter(order=self).delete()
|
||||
OrderFee.all.filter(order=self).delete()
|
||||
|
||||
@@ -906,6 +906,10 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
del f['_invoice_text']
|
||||
return f
|
||||
|
||||
@property
|
||||
def test_mode_message(self) -> str:
|
||||
return _("In test mode, only test cards will work.")
|
||||
|
||||
def is_allowed(self, request: HttpRequest, total: Decimal=None) -> bool:
|
||||
return super().is_allowed(request, total) and self.event.organizer.has_gift_cards
|
||||
|
||||
@@ -958,6 +962,12 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
if gc.currency != self.event.currency:
|
||||
messages.error(request, _("This gift card does not support this currency."))
|
||||
return
|
||||
if gc.testmode and not self.event.testmode:
|
||||
messages.error(request, _("This gift card can only be used in test mode."))
|
||||
return
|
||||
if not gc.testmode and self.event.testmode:
|
||||
messages.error(request, _("Only test gifts cards can be used in test mode."))
|
||||
return
|
||||
if gc.value <= Decimal("0.00"):
|
||||
messages.error(request, _("All credit on this gift card has been used."))
|
||||
return
|
||||
@@ -997,6 +1007,12 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
if gc.currency != self.event.currency:
|
||||
messages.error(request, _("This gift card does not support this currency."))
|
||||
return
|
||||
if gc.testmode and not self.event.testmode:
|
||||
messages.error(request, _("This gift card can only be used in test mode."))
|
||||
return
|
||||
if not gc.testmode and self.event.testmode:
|
||||
messages.error(request, _("Only test gift cards can be used in test mode."))
|
||||
return
|
||||
if gc.value <= Decimal("0.00"):
|
||||
messages.error(request, _("All credit on this gift card has been used."))
|
||||
return
|
||||
@@ -1027,6 +1043,8 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
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 gc.testmode != payment.order.testmode:
|
||||
raise PaymentException(_("Only the gift card or only the order are created in test mode."))
|
||||
if payment.amount > gc.value:
|
||||
raise PaymentException(_("This gift card was used in the meantime. Please try again"))
|
||||
trans = gc.transactions.create(
|
||||
|
||||
@@ -971,9 +971,13 @@ def get_fees(event, request, total, invoice_address, provider):
|
||||
|
||||
cs = cart_session(request)
|
||||
if cs.get('gift_cards'):
|
||||
gcs = cs['gift_cards']
|
||||
gc_qs = event.organizer.accepted_gift_cards.filter(pk__in=cs.get('gift_cards'), currency=event.currency)
|
||||
summed = 0
|
||||
for gc in gc_qs:
|
||||
if gc.testmode != event.testmode:
|
||||
gcs.remove(gc.pk)
|
||||
continue
|
||||
fval = Decimal(gc.value) # TODO: don't require an extra query
|
||||
fval = min(fval, total - summed)
|
||||
if fval > 0:
|
||||
@@ -988,6 +992,7 @@ def get_fees(event, request, total, invoice_address, provider):
|
||||
tax_value=Decimal('0.00'),
|
||||
tax_rule=TaxRule.zero()
|
||||
))
|
||||
cs['gift_cards'] = gcs
|
||||
|
||||
if provider and total != 0:
|
||||
provider = event.get_payment_providers().get(provider)
|
||||
|
||||
@@ -600,6 +600,10 @@ def _create_order(event: Event, email: str, positions: List[CartPosition], now_d
|
||||
for gc in gc_qs:
|
||||
if gc.currency != event.currency:
|
||||
raise OrderError(_("This gift card does not support this currency."))
|
||||
if gc.testmode and not event.testmode:
|
||||
raise OrderError(_("This gift card can only be used in test mode."))
|
||||
if not gc.testmode and event.testmode:
|
||||
raise OrderError(_("Only test gift cards can be used in test mode."))
|
||||
if not gc.accepted_by(event.organizer):
|
||||
raise OrderError(_("This gift card is not accepted by this event organizer."))
|
||||
checked_gift_cards.append(gc)
|
||||
@@ -1687,7 +1691,7 @@ def signal_listener_issue_giftcards(sender: Event, order: Order, **kwargs):
|
||||
for p in order.positions.all():
|
||||
if p.item.issue_giftcard:
|
||||
gc = sender.organizer.issued_gift_cards.create(
|
||||
currency=sender.currency, issued_in=p
|
||||
currency=sender.currency, issued_in=p, testmode=order.testmode
|
||||
)
|
||||
gc.transactions.create(value=p.price, order=order)
|
||||
any_giftcards = True
|
||||
|
||||
@@ -355,4 +355,4 @@ class GiftCardCreateForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = GiftCard
|
||||
fields = ['secret', 'currency']
|
||||
fields = ['secret', 'currency', 'testmode']
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
{% blocktrans trimmed with card=card.secret %}
|
||||
Gift card: {{ card }}
|
||||
{% endblocktrans %}
|
||||
{% if card.testmode %}
|
||||
<span class="label label-warning">{% trans "TEST MODE" %}</span>
|
||||
{% endif %}
|
||||
</h1>
|
||||
<div class="panel panel-primary items">
|
||||
<div class="panel-heading">
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
{% bootstrap_field form.secret layout="control" %}
|
||||
{% bootstrap_field form.value layout="control" %}
|
||||
{% bootstrap_field form.currency layout="control" %}
|
||||
{% bootstrap_field form.testmode layout="control" %}
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
|
||||
@@ -54,6 +54,9 @@
|
||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=g.id %}">
|
||||
<strong>{{ g.secret }}</strong>
|
||||
</a>
|
||||
{% if g.testmode %}
|
||||
<span class="label label-warning">{% trans "TEST MODE" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ g.issuance|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td class="text-right">
|
||||
|
||||
@@ -18,6 +18,7 @@ TEST_GC_RES = {
|
||||
"id": 1,
|
||||
"secret": "ABCDEF",
|
||||
"value": "23.00",
|
||||
"testmode": False,
|
||||
"currency": "EUR"
|
||||
}
|
||||
|
||||
@@ -46,6 +47,7 @@ def test_giftcard_detail(token_client, organizer, event, giftcard):
|
||||
TEST_GIFTCARD_CREATE_PAYLOAD = {
|
||||
"secret": "DEFABC",
|
||||
"value": "12.00",
|
||||
"testmode": False,
|
||||
"currency": "EUR",
|
||||
}
|
||||
|
||||
@@ -84,6 +86,7 @@ def test_giftcard_patch(token_client, organizer, event, giftcard):
|
||||
{
|
||||
'secret': 'foo',
|
||||
'value': '10.00',
|
||||
'testmode': True,
|
||||
'currency': 'USD'
|
||||
},
|
||||
format='json'
|
||||
@@ -93,6 +96,7 @@ def test_giftcard_patch(token_client, organizer, event, giftcard):
|
||||
assert giftcard.value == Decimal('10.00')
|
||||
assert giftcard.secret == "ABCDEF"
|
||||
assert giftcard.currency == "EUR"
|
||||
assert not giftcard.testmode
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
Reference in New Issue
Block a user