Fix #1111 -- Duplicate voucher warning (#1142)

Adds a new method to Voucher that selects all distinct orders containing
a position where the Voucher has been used, and changes the Voucher
detail view to use this method for the warning.
This commit is contained in:
Maarten van den Berg
2019-01-21 08:52:31 +01:00
committed by Raphael Michel
parent 350df2a3cc
commit bf1e9d47d0
3 changed files with 51 additions and 4 deletions

View File

@@ -13,6 +13,7 @@ from ..decimal import round_decimal
from .base import LoggedModel from .base import LoggedModel
from .event import Event, SubEvent from .event import Event, SubEvent
from .items import Item, ItemVariation, Quota from .items import Item, ItemVariation, Quota
from .orders import Order
def _generate_random_code(prefix=None): def _generate_random_code(prefix=None):
@@ -380,3 +381,11 @@ class Voucher(LoggedModel):
return p.quantize(Decimal('1') / 10 ** places, ROUND_HALF_UP) return p.quantize(Decimal('1') / 10 ** places, ROUND_HALF_UP)
return p return p
return original_price return original_price
def distinct_orders(self):
"""
Return the list of orders where this voucher has been used.
Each order will appear at most once.
"""
return Order.objects.filter(all_positions__voucher__in=[self]).distinct()

View File

@@ -9,9 +9,9 @@
<div class="alert alert-warning"> <div class="alert alert-warning">
{% trans "This voucher already has been used. It is not recommended to modify it." %} {% trans "This voucher already has been used. It is not recommended to modify it." %}
<ul> <ul>
{% for op in voucher.orderposition_set.all %} {% for order in voucher.distinct_orders %}
<li><a href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=op.order.code %}"> <li><a href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
{% blocktrans with code=op.order.code %}Order {{ code }}{% endblocktrans %} {% blocktrans with code=order.code %}Order {{ code }}{% endblocktrans %}
</a></li> </a></li>
{% endfor %} {% endfor %}
</ul> </ul>

View File

@@ -1,11 +1,13 @@
import datetime import datetime
import decimal
import json import json
from django.utils.timezone import now from django.utils.timezone import now
from tests.base import SoupTest, extract_form_fields from tests.base import SoupTest, extract_form_fields
from pretix.base.models import ( from pretix.base.models import (
Event, Item, ItemVariation, Organizer, Quota, Team, User, Voucher, Event, Item, ItemVariation, Order, OrderPosition, Organizer, Quota, Team,
User, Voucher,
) )
@@ -517,3 +519,39 @@ class VoucherFormTest(SoupTest):
'block_quota': 'on', 'block_quota': 'on',
'subevent': se1.pk 'subevent': se1.pk
}, expected_failure=True) }, expected_failure=True)
def test_order_warning_deduplication(self):
shirt_voucher = Voucher.objects.create(
event=self.event, item=self.shirt, price_mode='set', value=0.0, max_usages=100
)
shirt_order = Order.objects.create(
code='DEDUP', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PAID,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=0, locale='en'
)
OrderPosition.objects.create(
order=shirt_order,
item=self.shirt,
variation=self.shirt_red,
price=decimal.Decimal("0"),
voucher=shirt_voucher
)
OrderPosition.objects.create(
order=shirt_order,
item=self.shirt,
variation=self.shirt_blue,
price=decimal.Decimal("0"),
voucher=shirt_voucher
)
shirt_voucher.redeemed = 2
shirt_voucher.save()
doc = self.get_doc('/control/event/%s/%s/vouchers/%s/' % (self.orga.slug, self.event.slug, shirt_voucher.pk))
assert len(doc.select('.alert-warning ul li')) == 1 # Check that there's exactly 1 item in the warning list
assert doc.text.count('Order DEDUP') == 1 # Check that the order is listed exactly once