mirror of
https://github.com/pretix/pretix.git
synced 2026-11-13 01:47:07 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
addf94afe2 | ||
|
|
0d828e439e | ||
|
|
69108a1c20 |
No files matched your search
@@ -197,8 +197,6 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
||||
'linked_giftcard',
|
||||
'info',
|
||||
'notes',
|
||||
# When adding fields, check if they should be hidden in ReusableMediaViewSet
|
||||
# for cross-organizer lookups
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1282,7 +1282,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
raise ValidationError(
|
||||
'Orders cannot have more than %(max)s positions.' % {'max': settings.PRETIX_MAX_ORDER_SIZE}
|
||||
)
|
||||
errs = [{} for p in data]
|
||||
errs = defaultdict(dict)
|
||||
if any([p.get('positionid') for p in data]):
|
||||
if not all([p.get('positionid') for p in data]):
|
||||
for i, p in enumerate(data):
|
||||
@@ -1311,16 +1311,16 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
last_posid = p['positionid']
|
||||
|
||||
elif any([p.get('addon_to') for p in data]):
|
||||
errs = [
|
||||
{'positionid': ["If you set addon_to on any position, you need to specify position IDs manually."]}
|
||||
for p in data
|
||||
]
|
||||
errs = {
|
||||
i: {'positionid': ["If you set addon_to on any position, you need to specify position IDs manually."]}
|
||||
for i, p in enumerate(data)
|
||||
}
|
||||
else:
|
||||
for i, p in enumerate(data):
|
||||
p['positionid'] = i + 1
|
||||
|
||||
if any(errs):
|
||||
raise ValidationError(errs)
|
||||
if errs:
|
||||
raise ValidationError(dict(errs))
|
||||
return data
|
||||
|
||||
def create(self, validated_data):
|
||||
@@ -1437,7 +1437,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
# use further down
|
||||
del quota_diff_for_locking, voucher_diff_for_locking, seat_diff_for_locking
|
||||
|
||||
errs = [{} for p in positions_data]
|
||||
errs = defaultdict(dict)
|
||||
|
||||
for i, pos_data in enumerate(positions_data):
|
||||
if pos_data.get('voucher'):
|
||||
@@ -1566,7 +1566,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
)
|
||||
]
|
||||
|
||||
if any(errs):
|
||||
if errs:
|
||||
raise ValidationError({'positions': errs})
|
||||
|
||||
if validated_data.get('locale', None) is None:
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
|
||||
from rest_framework import serializers
|
||||
@@ -38,23 +39,20 @@ class VoucherListSerializer(serializers.ListSerializer):
|
||||
|
||||
codes = set()
|
||||
seats = set()
|
||||
errs = []
|
||||
err = False
|
||||
for voucher_data in validated_data:
|
||||
errs = defaultdict(dict)
|
||||
for i, voucher_data in enumerate(validated_data):
|
||||
if voucher_data.get('seat') and (voucher_data.get('seat'), voucher_data.get('subevent')) in seats:
|
||||
err = True
|
||||
errs.append({'code': ['Duplicate seat ID in request.']})
|
||||
errs[i] = {'code': ['Duplicate seat ID in request.']}
|
||||
continue
|
||||
else:
|
||||
seats.add((voucher_data.get('seat'), voucher_data.get('subevent')))
|
||||
|
||||
if voucher_data['code'] in codes:
|
||||
err = True
|
||||
errs.append({'code': ['Duplicate voucher code in request.']})
|
||||
errs[i] = {'code': ['Duplicate voucher code in request.']}
|
||||
else:
|
||||
codes.add(voucher_data['code'])
|
||||
errs.append({})
|
||||
if err:
|
||||
|
||||
if errs:
|
||||
raise ValidationError(errs)
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
@@ -183,18 +183,9 @@ class ReusableMediaViewSet(viewsets.ModelViewSet):
|
||||
type=s.validated_data["type"],
|
||||
identifier=s.validated_data["identifier"],
|
||||
)
|
||||
m.customer = None # not relevant for cross-organizer
|
||||
s = self.get_serializer(m)
|
||||
data = s.data
|
||||
# Remove fields that are not relevant for cross-organizer usage
|
||||
data["customer"] = None
|
||||
data["linked_orderposition"] = None
|
||||
data["linked_orderpositions"] = []
|
||||
data["info"] = {}
|
||||
data["notes"] = None
|
||||
data["claim_token"] = None
|
||||
data["label"] = None
|
||||
|
||||
return Response({"result": data})
|
||||
return Response({"result": s.data})
|
||||
except ReusableMedium.DoesNotExist:
|
||||
mt = MEDIA_TYPES.get(s.validated_data["type"])
|
||||
if mt:
|
||||
|
||||
@@ -75,7 +75,6 @@ class AuthenticationForm(forms.Form):
|
||||
'unverified': _("You have not yet activated your account and set a password. Please click the link in the "
|
||||
"email we sent you. In case you cannot find it, click \"Forgot your password?\" to receive "
|
||||
"a new email."),
|
||||
'rate_limit': _("For security reasons, please wait 5 minutes before you try again."),
|
||||
}
|
||||
|
||||
def __init__(self, request=None, *args, **kwargs):
|
||||
@@ -94,12 +93,6 @@ class AuthenticationForm(forms.Form):
|
||||
email = self.cleaned_data.get('email')
|
||||
password = self.cleaned_data.get('password')
|
||||
|
||||
if rate_limit("customer_login", include_ip_from_request=self.request, max_num=10, expire_time=300):
|
||||
raise forms.ValidationError(
|
||||
self.error_messages['rate_limit'],
|
||||
code='rate_limit',
|
||||
)
|
||||
|
||||
if email is not None and password:
|
||||
try:
|
||||
u = self.request.organizer.customers.get(email=email.lower(), provider__isnull=True)
|
||||
|
||||
@@ -507,7 +507,6 @@ REST_FRAMEWORK = {
|
||||
],
|
||||
'EXCEPTION_HANDLER': 'pretix.api.exception.custom_exception_handler',
|
||||
'UNICODE_JSON': False,
|
||||
'LIST_SERIALIZER_ERRORS_AS_DICT': False
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ filterwarnings =
|
||||
ignore:teardown:pytest.PytestWarning
|
||||
ignore:avoid running initialization queries:RuntimeWarning
|
||||
ignore:.*The 'strip_cdata' option of HTMLParser.*:DeprecationWarning:
|
||||
ignore:The list-based error format for `ListSerializer`:rest_framework.deprecation.RemovedInDRF320Warning
|
||||
|
||||
|
||||
[coverage:run]
|
||||
|
||||
+16
-13
@@ -424,7 +424,7 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'answers': [{'question': ['The specified question does not belong to this event.']}]}
|
||||
assert resp.data == {'answers': {0: {'question': ['The specified question does not belong to this event.']}}}
|
||||
|
||||
res['answers'][0]['question'] = question.pk
|
||||
res['answers'][0]['options'] = [question.options.first().pk]
|
||||
@@ -434,8 +434,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'answers': [{'non_field_errors': ['You should not specify options if the question is not of a choice type.']}]}
|
||||
assert resp.data == {'answers': {
|
||||
0: {'non_field_errors': ['You should not specify options if the question is not of a choice type.']}
|
||||
}}
|
||||
|
||||
question.type = Question.TYPE_CHOICE
|
||||
question.save()
|
||||
@@ -447,7 +448,7 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'answers': [{'non_field_errors': ['You need to specify options if the question is of a choice type.']}]}
|
||||
'answers': {0: {'non_field_errors': ['You need to specify options if the question is of a choice type.']}}}
|
||||
|
||||
with scopes_disabled():
|
||||
question.options.create(answer="L")
|
||||
@@ -461,7 +462,8 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'answers': [{'non_field_errors': ['You can specify at most one option for this question.']}]}
|
||||
assert resp.data == {
|
||||
'answers': {0: {'non_field_errors': ['You can specify at most one option for this question.']}}}
|
||||
|
||||
r = token_client.post(
|
||||
'/api/v1/upload',
|
||||
@@ -533,7 +535,7 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'answers': [{'non_field_errors': ['A valid number is required.']}]}
|
||||
assert resp.data == {'answers': {0: {'non_field_errors': ['A valid number is required.']}}}
|
||||
|
||||
question.type = Question.TYPE_BOOLEAN
|
||||
question.save()
|
||||
@@ -573,7 +575,8 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'answers': [{'non_field_errors': ['Please specify "true" or "false" for boolean questions.']}]}
|
||||
assert resp.data == {
|
||||
'answers': {0: {'non_field_errors': ['Please specify "true" or "false" for boolean questions.']}}}
|
||||
|
||||
question.type = Question.TYPE_DATE
|
||||
question.save()
|
||||
@@ -599,7 +602,7 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'answers': [{'non_field_errors': ['Date has wrong format. Use one of these formats instead: YYYY-MM-DD.']}]}
|
||||
'answers': {0: {'non_field_errors': ['Date has wrong format. Use one of these formats instead: YYYY-MM-DD.']}}}
|
||||
|
||||
question.type = Question.TYPE_DATETIME
|
||||
question.save()
|
||||
@@ -624,9 +627,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'answers': [{'non_field_errors': [
|
||||
assert resp.data == {'answers': {0: {'non_field_errors': [
|
||||
'Datetime has wrong format. Use one of these formats instead: '
|
||||
'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].']}]}
|
||||
'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].']}}}
|
||||
|
||||
question.type = Question.TYPE_TIME
|
||||
question.save()
|
||||
@@ -651,8 +654,8 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'answers': [
|
||||
{'non_field_errors': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].']}]}
|
||||
assert resp.data == {'answers': {0: {'non_field_errors': [
|
||||
'Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1387,7 +1390,7 @@ def test_cartpos_create_bulk_validation_error_in_addon(token_client, organizer,
|
||||
'data': None,
|
||||
'success': False,
|
||||
'errors': {
|
||||
'addons': [{'item': ['Invalid pk "-1" - object does not exist.']}]
|
||||
'addons': {0: {'item': ['Invalid pk "-1" - object does not exist.']}}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -958,9 +958,9 @@ def test_item_create_with_addon(token_client, organizer, event, item, category,
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() in [
|
||||
'{"addons":["The minimum count needs to be equal to or greater than zero."]}',
|
||||
'{"addons":[{"min_count":["Ensure this value is greater than or equal to 0."]}]}',
|
||||
assert resp.data in [
|
||||
{"addons": {0: "The minimum count needs to be equal to or greater than zero."}},
|
||||
{"addons": {0: {"min_count": ["Ensure this value is greater than or equal to 0."]}}},
|
||||
]
|
||||
with scopes_disabled():
|
||||
assert 2 == Item.objects.all().count()
|
||||
|
||||
@@ -978,7 +978,7 @@ def test_order_create_position_secret_optional(token_client, organizer, event, i
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
assert resp.data == {'positions': [{'secret': ['You cannot assign a position secret that already exists.']}]}
|
||||
assert resp.data == {'positions': {0: {'secret': ['You cannot assign a position secret that already exists.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1024,7 +1024,7 @@ def test_order_create_fee_type_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'fees': [{'fee_type': ['"unknown" is not a valid choice.']}]}
|
||||
assert resp.data == {'fees': {0: {'fee_type': ['"unknown" is not a valid choice.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1143,7 +1143,7 @@ def test_order_create_tax_rule_wrong_event(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'fees': [{'tax_rule': ['The specified tax rate does not belong to this event.']}]}
|
||||
assert resp.data == {'fees': {0: {'tax_rule': ['The specified tax rate does not belong to this event.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1158,7 +1158,7 @@ def test_order_create_subevent_not_allowed(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'subevent': ['You cannot set a subevent for this event.']}]}
|
||||
assert resp.data == {'positions': {0: {'subevent': ['You cannot set a subevent for this event.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1185,7 +1185,7 @@ def test_order_create_subevent_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'subevent': ['You need to set a subevent.']}]}
|
||||
assert resp.data == {'positions': {0: {'subevent': ['You need to set a subevent.']}}}
|
||||
|
||||
res['positions'][0]['subevent'] = subevent2.pk
|
||||
resp = token_client.post(
|
||||
@@ -1194,7 +1194,7 @@ def test_order_create_subevent_validation(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'subevent': ['The specified subevent does not belong to this event.']}]}
|
||||
assert resp.data == {'positions': {0: {'subevent': ['The specified subevent does not belong to this event.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1210,7 +1210,7 @@ def test_order_create_item_validation(token_client, organizer, event, item, item
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'item': ['The specified item is not active.']}]}
|
||||
assert resp.data == {'positions': {0: {'item': ['The specified item is not active.']}}}
|
||||
item.active = True
|
||||
item.save()
|
||||
|
||||
@@ -1222,7 +1222,7 @@ def test_order_create_item_validation(token_client, organizer, event, item, item
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'item': ['The specified item does not belong to this event.']}]}
|
||||
assert resp.data == {'positions': {0: {'item': ['The specified item does not belong to this event.']}}}
|
||||
|
||||
with scopes_disabled():
|
||||
var2 = item2.variations.create(value="A")
|
||||
@@ -1236,7 +1236,7 @@ def test_order_create_item_validation(token_client, organizer, event, item, item
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'variation': ['You cannot specify a variation for this item.']}]}
|
||||
assert resp.data == {'positions': {0: {'variation': ['You cannot specify a variation for this item.']}}}
|
||||
|
||||
with scopes_disabled():
|
||||
var1 = item.variations.create(value="A")
|
||||
@@ -1248,7 +1248,7 @@ def test_order_create_item_validation(token_client, organizer, event, item, item
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'item': ['The product "Budget Ticket" is not assigned to a quota.']}]}
|
||||
assert resp.data == {'positions': {0: {'item': ['The product "Budget Ticket" is not assigned to a quota.']}}}
|
||||
|
||||
with scopes_disabled():
|
||||
quota.variations.add(var1)
|
||||
@@ -1267,7 +1267,7 @@ def test_order_create_item_validation(token_client, organizer, event, item, item
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [{'variation': ['The specified variation does not belong to the specified item.']}]}
|
||||
'positions': {0: {'variation': ['The specified variation does not belong to the specified item.']}}}
|
||||
|
||||
res['positions'][0]['variation'] = None
|
||||
resp = token_client.post(
|
||||
@@ -1276,7 +1276,7 @@ def test_order_create_item_validation(token_client, organizer, event, item, item
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'variation': ['You should specify a variation for this item.']}]}
|
||||
assert resp.data == {'positions': {0: {'variation': ['You should specify a variation for this item.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1294,7 +1294,7 @@ def test_order_create_subevent_disabled(token_client, organizer, event, item, su
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'item': ['The product "Budget Ticket" is not available on this date.']}]}
|
||||
assert resp.data == {'positions': {0: {'item': ['The product "Budget Ticket" is not available on this date.']}}}
|
||||
|
||||
s.delete()
|
||||
resp = token_client.post(
|
||||
@@ -1326,7 +1326,7 @@ def test_order_create_subevent_variation_disabled(token_client, organizer, event
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'item': ['The product "Budget Ticket" is not available on this date.']}]}
|
||||
assert resp.data == {'positions': {0: {'item': ['The product "Budget Ticket" is not available on this date.']}}}
|
||||
|
||||
s.delete()
|
||||
resp = token_client.post(
|
||||
@@ -1453,16 +1453,15 @@ def test_order_create_positionid_validation(token_client, organizer, event, item
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{},
|
||||
{
|
||||
'positions': {
|
||||
1: {
|
||||
'addon_to': [
|
||||
'If you set addon_to, you need to make sure that the '
|
||||
'referenced position ID exists and is transmitted directly '
|
||||
'before its add-ons.'
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
res['positions'] = [
|
||||
@@ -1493,10 +1492,14 @@ def test_order_create_positionid_validation(token_client, organizer, event, item
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [
|
||||
{'positionid': ["If you set addon_to on any position, you need to specify position IDs manually."]},
|
||||
{'positionid': ["If you set addon_to on any position, you need to specify position IDs manually."]}
|
||||
]}
|
||||
assert resp.data == {'positions': {
|
||||
0:
|
||||
{'positionid': [
|
||||
"If you set addon_to on any position, you need to specify position IDs manually."]},
|
||||
1:
|
||||
{'positionid': [
|
||||
"If you set addon_to on any position, you need to specify position IDs manually."]}
|
||||
}}
|
||||
|
||||
res['positions'] = [
|
||||
{
|
||||
@@ -1526,12 +1529,11 @@ def test_order_create_positionid_validation(token_client, organizer, event, item
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{},
|
||||
{
|
||||
'positions': {
|
||||
1: {
|
||||
'positionid': ['If you set position IDs manually, you need to do so for all positions.']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
res['positions'] = [
|
||||
@@ -1563,12 +1565,11 @@ def test_order_create_positionid_validation(token_client, organizer, event, item
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{},
|
||||
{
|
||||
'positions': {
|
||||
1: {
|
||||
'positionid': ['Position IDs need to be consecutive.']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
res['positions'] = [
|
||||
@@ -1615,7 +1616,7 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [{'answers': [{'question': ['The specified question does not belong to this event.']}]}]}
|
||||
'positions': {0: {'answers': {0: {'question': ['The specified question does not belong to this event.']}}}}}
|
||||
|
||||
res['positions'][0]['answers'][0]['question'] = question.pk
|
||||
res['positions'][0]['answers'][0]['options'] = [question.options.first().pk]
|
||||
@@ -1625,8 +1626,8 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'answers': [
|
||||
{'non_field_errors': ['You should not specify options if the question is not of a choice type.']}]}]}
|
||||
assert resp.data == {'positions': {0: {'answers': {
|
||||
0: {'non_field_errors': ['You should not specify options if the question is not of a choice type.']}}}}}
|
||||
|
||||
question.type = Question.TYPE_CHOICE
|
||||
question.save()
|
||||
@@ -1637,8 +1638,8 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [
|
||||
{'answers': [{'non_field_errors': ['You need to specify options if the question is of a choice type.']}]}]}
|
||||
assert resp.data == {'positions': {0: {
|
||||
'answers': {0: {'non_field_errors': ['You need to specify options if the question is of a choice type.']}}}}}
|
||||
|
||||
with scopes_disabled():
|
||||
question2.options.create(answer="L")
|
||||
@@ -1653,7 +1654,8 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [{'answers': [{'non_field_errors': ['The specified option does not belong to this question.']}]}]}
|
||||
'positions': {
|
||||
0: {'answers': {0: {'non_field_errors': ['The specified option does not belong to this question.']}}}}}
|
||||
|
||||
with scopes_disabled():
|
||||
question.options.create(answer="L")
|
||||
@@ -1669,7 +1671,8 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [{'answers': [{'non_field_errors': ['You can specify at most one option for this question.']}]}]}
|
||||
'positions': {
|
||||
0: {'answers': {0: {'non_field_errors': ['You can specify at most one option for this question.']}}}}}
|
||||
|
||||
r = token_client.post(
|
||||
'/api/v1/upload',
|
||||
@@ -1745,7 +1748,7 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'answers': [{'non_field_errors': ['A valid number is required.']}]}]}
|
||||
assert resp.data == {'positions': {0: {'answers': {0: {'non_field_errors': ['A valid number is required.']}}}}}
|
||||
|
||||
question.type = Question.TYPE_BOOLEAN
|
||||
question.save()
|
||||
@@ -1787,8 +1790,8 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [{'answers': [{'non_field_errors': ['Please specify "true" or "false" for boolean questions.']}]}]}
|
||||
assert resp.data == {'positions': {
|
||||
0: {'answers': {0: {'non_field_errors': ['Please specify "true" or "false" for boolean questions.']}}}}}
|
||||
|
||||
question.type = Question.TYPE_DATE
|
||||
question.save()
|
||||
@@ -1814,8 +1817,8 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'answers': [
|
||||
{'non_field_errors': ['Date has wrong format. Use one of these formats instead: YYYY-MM-DD.']}]}]}
|
||||
assert resp.data == {'positions': {0: {'answers': {
|
||||
0: {'non_field_errors': ['Date has wrong format. Use one of these formats instead: YYYY-MM-DD.']}}}}}
|
||||
|
||||
question.type = Question.TYPE_DATETIME
|
||||
question.save()
|
||||
@@ -1841,9 +1844,9 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'answers': [{'non_field_errors': [
|
||||
assert resp.data == {'positions': {0: {'answers': {0: {'non_field_errors': [
|
||||
'Datetime has wrong format. Use one of these formats instead: '
|
||||
'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].']}]}]}
|
||||
'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].']}}}}}
|
||||
|
||||
question.type = Question.TYPE_TIME
|
||||
question.save()
|
||||
@@ -1869,8 +1872,8 @@ def test_order_create_answer_validation(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'answers': [
|
||||
{'non_field_errors': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].']}]}]}
|
||||
assert resp.data == {'positions': {0: {'answers': {
|
||||
0: {'non_field_errors': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].']}}}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -1910,10 +1913,10 @@ def test_order_create_quota_validation(token_client, organizer, event, item, quo
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']},
|
||||
{'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']},
|
||||
]
|
||||
'positions': {
|
||||
0: {'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']},
|
||||
1: {'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']},
|
||||
}
|
||||
}
|
||||
|
||||
quota.size = 1
|
||||
@@ -1924,12 +1927,8 @@ def test_order_create_quota_validation(token_client, organizer, event, item, quo
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{},
|
||||
{'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {
|
||||
1: {'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']}}}
|
||||
|
||||
res['force'] = True
|
||||
resp = token_client.post(
|
||||
@@ -1961,11 +1960,8 @@ def test_order_create_quota_consume_cart(token_client, organizer, event, item, q
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {
|
||||
0: {'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']}}}
|
||||
|
||||
res['consume_carts'] = [cr.cart_id]
|
||||
resp = token_client.post(
|
||||
@@ -2000,11 +1996,8 @@ def test_order_create_quota_consume_cart_expired(token_client, organizer, event,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {
|
||||
0: {'item': ['There is not enough quota available on quota "Budget Quota" to perform the operation.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2176,11 +2169,7 @@ def test_order_create_with_blocked_seat(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'seat': ['The selected seat "Seat A1" is not available.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {0: {'seat': ['The selected seat "Seat A1" is not available.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2199,11 +2188,7 @@ def test_order_create_with_used_seat(token_client, organizer, event, item, quota
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'seat': ['The selected seat "Seat A1" is not available.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {0: {'seat': ['The selected seat "Seat A1" is not available.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2218,11 +2203,7 @@ def test_order_create_with_unknown_seat(token_client, organizer, event, item, qu
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'seat': ['The specified seat does not exist.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {0: {'seat': ['The specified seat does not exist.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2236,11 +2217,7 @@ def test_order_create_require_seat(token_client, organizer, event, item, quota,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'seat': ['The specified product requires to choose a seat.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {0: {'seat': ['The specified product requires to choose a seat.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2258,11 +2235,7 @@ def test_order_create_unseated(token_client, organizer, event, item, quota, seat
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'seat': ['The specified product does not allow to choose a seat.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {0: {'seat': ['The specified product does not allow to choose a seat.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2300,12 +2273,7 @@ def test_order_create_with_duplicate_seat(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{},
|
||||
{'seat': ['The selected seat "Seat A1" is not available.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {1: {'seat': ['The selected seat "Seat A1" is not available.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2810,8 +2778,8 @@ def test_order_create_autopricing_voucher_budget_full(token_client, organizer, e
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{}, {'voucher': ['The voucher has a remaining budget of 0.00, therefore a '
|
||||
'discount of 1.50 can not be given.']}]}
|
||||
assert resp.data == {'positions': {1: {'voucher': ['The voucher has a remaining budget of 0.00, therefore a '
|
||||
'discount of 1.50 can not be given.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2832,8 +2800,8 @@ def test_order_create_voucher_budget_exceeded(token_client, organizer, event, it
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {'positions': [{'voucher': ['The voucher has a remaining budget of 3.00, therefore a '
|
||||
'discount of 4.00 can not be given.']}]}
|
||||
assert resp.data == {'positions': {0: {'voucher': ['The voucher has a remaining budget of 3.00, therefore a '
|
||||
'discount of 4.00 can not be given.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2876,11 +2844,7 @@ def test_order_create_voucher_unknown_code(token_client, organizer, event, item,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'voucher': ['Object with code=FOOBAR does not exist.']},
|
||||
]
|
||||
}
|
||||
assert resp.data == {'positions': {0: {'voucher': ['Object with code=FOOBAR does not exist.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2899,9 +2863,7 @@ def test_order_create_voucher_redeemed(token_client, organizer, event, item, quo
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'voucher': ['The voucher has already been used the maximum number of times.']},
|
||||
]
|
||||
'positions': {0: {'voucher': ['The voucher has already been used the maximum number of times.']}}
|
||||
}
|
||||
|
||||
|
||||
@@ -2924,11 +2886,10 @@ def test_order_create_voucher_redeemed_partially(token_client, organizer, event,
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{},
|
||||
{'voucher': ['The voucher has already been used the maximum number of times.']},
|
||||
{'voucher': ['The voucher has already been used the maximum number of times.']},
|
||||
]
|
||||
'positions': {
|
||||
1: {'voucher': ['The voucher has already been used the maximum number of times.']},
|
||||
2: {'voucher': ['The voucher has already been used the maximum number of times.']},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2949,10 +2910,7 @@ def test_order_create_voucher_item_mismatch(token_client, organizer, event, item
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'voucher': ['This voucher is not valid for this product.']},
|
||||
]
|
||||
}
|
||||
'positions': {0: {'voucher': ['This voucher is not valid for this product.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -2972,10 +2930,7 @@ def test_order_create_voucher_expired(token_client, organizer, event, item, quot
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{'voucher': ['This voucher is expired.']},
|
||||
]
|
||||
}
|
||||
'positions': {0: {'voucher': ['This voucher is expired.']}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -3103,10 +3058,8 @@ def test_create_cart_and_consume_cart_with_addons(token_client, organizer, event
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'positions': [
|
||||
{},
|
||||
{'item': ['There is not enough quota available on quota "Addon Quota" to perform the operation.']},
|
||||
]
|
||||
'positions': {
|
||||
1: {'item': ['There is not enough quota available on quota "Addon Quota" to perform the operation.']}}
|
||||
}
|
||||
|
||||
res['consume_carts'] = ['aaa@api']
|
||||
@@ -3214,12 +3167,7 @@ def test_order_create_use_medium_other_organizer(token_client, organizer, event,
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.data == {
|
||||
"positions": [
|
||||
{
|
||||
"use_reusable_medium": ["The specified medium does not belong to this organizer."]
|
||||
}
|
||||
]
|
||||
}
|
||||
"positions": {0: {"use_reusable_medium": ["The specified medium does not belong to this organizer."]}}}
|
||||
assert resp.status_code == 400
|
||||
|
||||
|
||||
@@ -3361,14 +3309,8 @@ def test_order_create_auto_pricing_explicit_discount_not_allowed(token_client, o
|
||||
), format='json', data=res
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
"positions": [
|
||||
{},
|
||||
{
|
||||
"discount": ["You can only specify a discount if you do the price computation, but price is not set."]
|
||||
}
|
||||
]
|
||||
}
|
||||
assert resp.data == {"positions": {
|
||||
1: {"discount": ["You can only specify a discount if you do the price computation, but price is not set."]}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
@@ -696,7 +696,7 @@ def test_medium_autocreate_giftcard(token_client, organizer, team):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_medium_lookup_cross_organizer(token_client, organizer, customer, organizer2, org2_event, medium2, giftcard2):
|
||||
def test_medium_lookup_cross_organizer(token_client, organizer, organizer2, org2_event, medium2, giftcard2):
|
||||
with scopes_disabled():
|
||||
o = Order.objects.create(
|
||||
code='FOO', event=org2_event, email='dummy@dummy.test',
|
||||
@@ -708,12 +708,7 @@ def test_medium_lookup_cross_organizer(token_client, organizer, customer, organi
|
||||
personalized=True)
|
||||
op = o.positions.create(item=ticket, price=Decimal("14"))
|
||||
medium2.linked_orderpositions.add(op)
|
||||
medium2.customer = customer
|
||||
medium2.linked_giftcard = giftcard2
|
||||
medium2.claim_token = "1234"
|
||||
medium2.info = {"foo": "bar"}
|
||||
medium2.notes = "Internal notes"
|
||||
medium2.label = "Max Muster"
|
||||
medium2.save()
|
||||
|
||||
resp = token_client.post(
|
||||
@@ -760,9 +755,3 @@ def test_medium_lookup_cross_organizer(token_client, organizer, customer, organi
|
||||
assert resp.data["result"]["organizer"] == "partner"
|
||||
assert resp.data["result"]["linked_giftcard"] is not None
|
||||
assert resp.data["result"]["linked_orderposition"] is None
|
||||
assert resp.data["result"]["linked_orderpositions"] == []
|
||||
assert resp.data["result"]["customer"] is None
|
||||
assert resp.data["result"]["info"] == {}
|
||||
assert resp.data["result"]["notes"] is None
|
||||
assert resp.data["result"]["claim_token"] is None
|
||||
assert resp.data["result"]["label"] is None
|
||||
@@ -409,7 +409,7 @@ def test_subevent_create(team, token_client, organizer, event, subevent, meta_pr
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"555\\" - object does not exist."]}]}'
|
||||
assert resp.data == {"item_price_overrides": {0: {"item": ["Invalid pk \"555\" - object does not exist."]}}}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -580,7 +580,7 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"item_price_overrides":[{"item":["Invalid pk \\"123\\" - object does not exist."]}]}'
|
||||
assert resp.data == {"item_price_overrides": {0: {"item": ["Invalid pk \"123\" - object does not exist."]}}}
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
@@ -686,7 +686,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.content.decode() == '{"variation_price_overrides":[{"variation":["Invalid pk \\"123\\" - object does not exist."]}]}'
|
||||
assert resp.data == {
|
||||
"variation_price_overrides": {0: {"variation": ["Invalid pk \"123\" - object does not exist."]}}}
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
|
||||
|
||||
@@ -1061,7 +1061,7 @@ def test_create_multiple_vouchers_one_invalid(token_client, organizer, event, it
|
||||
], format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == [{}, {'code': ['Ensure this field has at least 5 characters.']}]
|
||||
assert resp.data == {1: {'code': ['Ensure this field has at least 5 characters.']}}
|
||||
with scopes_disabled():
|
||||
assert Voucher.objects.count() == 0
|
||||
|
||||
@@ -1106,7 +1106,7 @@ def test_create_multiple_vouchers_duplicate_code(token_client, organizer, event,
|
||||
], format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == [{}, {'code': ['Duplicate voucher code in request.']}]
|
||||
assert resp.data == {1: {'code': ['Duplicate voucher code in request.']}}
|
||||
with scopes_disabled():
|
||||
assert Voucher.objects.count() == 0
|
||||
|
||||
@@ -1214,7 +1214,7 @@ def test_create_multiple_vouchers_duplicate_seat(token_client, organizer, event,
|
||||
], format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == [{}, {'code': ['Duplicate seat ID in request.']}]
|
||||
assert resp.data == {1: {'code': ['Duplicate seat ID in request.']}}
|
||||
with scopes_disabled():
|
||||
assert Voucher.objects.count() == 0
|
||||
|
||||
|
||||
@@ -311,7 +311,7 @@ def test_renderer_batch_invalid(env, token_client, position):
|
||||
format='json',
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {"parts": [{"orderposition": ["Invalid pk \"-2\" - object does not exist."]}]}
|
||||
assert resp.data == {"parts": {0: {"orderposition": ["Invalid pk \"-2\" - object does not exist."]}}}
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/ticketpdfrenderer/render_batch/'.format(env[0].slug, env[0].slug),
|
||||
@@ -326,7 +326,7 @@ def test_renderer_batch_invalid(env, token_client, position):
|
||||
format='json',
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {"parts": [{"override_layout": ["Invalid pk \"-2\" - object does not exist."]}]}
|
||||
assert resp.data == {"parts": {0: {"override_layout": ["Invalid pk \"-2\" - object does not exist."]}}}
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/ticketpdfrenderer/render_batch/'.format(env[0].slug, env[0].slug),
|
||||
@@ -341,7 +341,7 @@ def test_renderer_batch_invalid(env, token_client, position):
|
||||
format='json',
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {"parts": [{"override_channel": ["Object with identifier=magic does not exist."]}]}
|
||||
assert resp.data == {"parts": {0: {"override_channel": ["Object with identifier=magic does not exist."]}}}
|
||||
|
||||
resp = token_client.post(
|
||||
'/api/v1/organizers/{}/events/{}/ticketpdfrenderer/render_batch/'.format(env[0].slug, env[0].slug),
|
||||
|
||||
Reference in new issue
Block a user