forked from CGM_Public/pretix_original
Some wizard processing logic
This commit is contained in:
@@ -8,6 +8,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from pretix.base.forms import I18nModelForm
|
||||
from pretix.base.models import Item, ItemVariation, Quota, Voucher
|
||||
from pretix.base.models.vouchers import _generate_random_code
|
||||
|
||||
|
||||
class VoucherForm(I18nModelForm):
|
||||
@@ -90,9 +91,8 @@ class VoucherForm(I18nModelForm):
|
||||
}
|
||||
)
|
||||
|
||||
if 'codes' in data:
|
||||
data['codes'] = [a.strip() for a in data.get('codes', '').strip().split("\n") if a]
|
||||
cnt = len(data['codes']) * data['max_usages']
|
||||
if 'number' in data:
|
||||
cnt = data['number'] * data['max_usages']
|
||||
else:
|
||||
cnt = data['max_usages']
|
||||
|
||||
@@ -182,6 +182,22 @@ class VoucherBulkForm(VoucherForm):
|
||||
label=_("Product"),
|
||||
widget=forms.RadioSelect
|
||||
)
|
||||
price_mode = forms.ChoiceField(
|
||||
choices=Voucher.PRICE_MODES,
|
||||
)
|
||||
has_valid_until = forms.BooleanField()
|
||||
value_percent = forms.DecimalField(
|
||||
required=False,
|
||||
max_digits=10, decimal_places=2
|
||||
)
|
||||
value_subtract = forms.DecimalField(
|
||||
required=False,
|
||||
max_digits=10, decimal_places=2
|
||||
)
|
||||
value_set = forms.DecimalField(
|
||||
required=False,
|
||||
max_digits=10, decimal_places=2
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Voucher
|
||||
@@ -203,21 +219,35 @@ class VoucherBulkForm(VoucherForm):
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
|
||||
if Voucher.objects.filter(code__in=data['codes'], event=self.instance.event).exists():
|
||||
raise ValidationError(_('A voucher with one of this codes already exists.'))
|
||||
if data.get('has_valid_until', False) and not data.get('valid_until'):
|
||||
raise ValidationError(_('You did not specify an expiration date for the vouchers.'))
|
||||
|
||||
if data.get('price_mode', 'none') != 'none':
|
||||
if data.get('value_%s' % data['price_mode']) is None:
|
||||
raise ValidationError(_('You specified that the vouchers should modify the products price '
|
||||
'but did not specify a value.'))
|
||||
|
||||
return data
|
||||
|
||||
def save(self, event, *args, **kwargs):
|
||||
objs = []
|
||||
for code in self.cleaned_data['codes']:
|
||||
|
||||
codes = set()
|
||||
while len(codes) < self.cleaned_data['number']:
|
||||
new_codes = set()
|
||||
for i in range(min(self.cleaned_data['number'] - len(codes), 500)):
|
||||
# Work around SQLite's SQLITE_MAX_VARIABLE_NUMBER
|
||||
new_codes.add(_generate_random_code())
|
||||
new_codes -= set([v['code'] for v in Voucher.objects.filter(code__in=new_codes).values('code')])
|
||||
codes |= new_codes
|
||||
|
||||
for code in codes:
|
||||
obj = copy.copy(self.instance)
|
||||
obj.event = event
|
||||
obj.code = code
|
||||
data = dict(self.cleaned_data)
|
||||
data['code'] = code
|
||||
data['bulk'] = True
|
||||
del data['codes']
|
||||
obj.save()
|
||||
objs.append(obj)
|
||||
return objs
|
||||
|
||||
@@ -8,18 +8,14 @@
|
||||
<h1>{% trans "Create new vouchers" %}</h1>
|
||||
<form action="" method="post" class="form-inline" id="voucher-create">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
{% capture as number_field silent %} {% bootstrap_field form.number layout="inline" %} {% endcapture %}
|
||||
{% capture as max_usages_field silent %} {% bootstrap_field form.max_usages layout="inline" %} {% endcapture %}
|
||||
{% capture as valid_until_field silent %} {% bootstrap_field form.valid_until layout="inline" %} {% endcapture %}
|
||||
{% capture as value_field_percent silent %}
|
||||
<input class="form-control price" name="price[percent]" type="text"> {% endcapture %}
|
||||
{% capture as value_field_subtract silent %}
|
||||
<input class="form-control price" name="price[subtract]" type="text"> {% endcapture %}
|
||||
{% capture as value_field_set silent %}
|
||||
<input class="form-control price" name="price[set]" type="text"> {% endcapture %}
|
||||
{% capture as value_field_percent silent %} {% bootstrap_field form.value_percent layout="inline" %} {% endcapture %}
|
||||
{% capture as value_field_subtract silent %} {% bootstrap_field form.value_subtract layout="inline" %} {% endcapture %}
|
||||
{% capture as value_field_set silent %} {% bootstrap_field form.value_set layout="inline" %} {% endcapture %}
|
||||
|
||||
{% bootstrap_form_errors form type="all" %}
|
||||
{% bootstrap_form_errors form %}
|
||||
|
||||
<div class="wizard-step" id="step-number">
|
||||
<div class="wizard-step-inner">
|
||||
@@ -38,13 +34,13 @@
|
||||
<h4>{% trans "How long should the vouchers be valid?" %}</h4>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="has_valid_until" value="no">
|
||||
<input type="radio" name="has_valid_until" value="" {% if request.POST and not "has_valid_until" in request.POST %}checked="checked"{% endif %}>
|
||||
{% trans "The whole presale period" %}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="has_valid_until" value="yes">
|
||||
<input type="radio" name="has_valid_until" value="on" {% if "on" == request.POST.has_valid_until %}checked="checked"{% endif %}>
|
||||
{% blocktrans trimmed %}
|
||||
Only valid until {{ valid_until_field }}
|
||||
{% endblocktrans %}
|
||||
@@ -65,7 +61,7 @@
|
||||
<h4>{% trans "Should the vouchers modify the product's price?" %}</h4>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="price_mode" value="none">
|
||||
<input type="radio" name="price_mode" value="none" {% if "none" == request.POST.price_mode %}checked="checked"{% endif %}>
|
||||
{% trans "No, just allow to buy this product" %}
|
||||
<span class="help-block">
|
||||
{% trans "This is useful if you have products that can only be bought using vouchers. It also allows you to just block quota for someone (see next step)." %}
|
||||
@@ -74,7 +70,7 @@
|
||||
</div>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="price_mode" value="percent">
|
||||
<input type="radio" name="price_mode" value="percent" {% if "percent" == request.POST.price_mode %}checked="checked"{% endif %}>
|
||||
{% blocktrans trimmed %}
|
||||
Reduce price by {{ value_field_percent }} %
|
||||
{% endblocktrans %}
|
||||
@@ -82,7 +78,7 @@
|
||||
</div>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="price_mode" value="subtract">
|
||||
<input type="radio" name="price_mode" value="subtract" {% if "subtract" == request.POST.price_mode %}checked="checked"{% endif %}>
|
||||
{% blocktrans trimmed with currency=request.event.currency %}
|
||||
Reduce price by {{ value_field_subtract }} {{ currency }}
|
||||
{% endblocktrans %}
|
||||
@@ -90,7 +86,7 @@
|
||||
</div>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="price_mode" value="set">
|
||||
<input type="radio" name="price_mode" value="set" {% if "set" == request.POST.price_mode %}checked="checked"{% endif %}>
|
||||
{% blocktrans trimmed with currency=request.event.currency %}
|
||||
Change price to {{ value_field_set }} {{ currency }}
|
||||
{% endblocktrans %}
|
||||
@@ -104,13 +100,13 @@
|
||||
<h4>{% trans "Should the vouchers block quota?" %}</h4>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="block_quota" value="no">
|
||||
<input type="radio" name="block_quota" value="" {% if request.POST and not "block_quota" in request.POST %}checked="checked"{% endif %}>
|
||||
{% trans "No" %}
|
||||
</label>
|
||||
</div>
|
||||
<div class="radio radio-alt">
|
||||
<label>
|
||||
<input type="radio" name="block_quota" value="yes">
|
||||
<input type="radio" name="block_quota" value="on" {% if "on" == request.POST.block_quota %}checked="checked"{% endif %}>
|
||||
{% trans "Yes" %}
|
||||
<span class="help-block">
|
||||
{% trans "If you select this option, these vouchers will be guaranteed, i.e. the applicable quotas will be reduced in a way that these vouchers can be redeemed as long as they are valid, even if your event sells out otherwise." %}
|
||||
@@ -136,10 +132,10 @@
|
||||
</div>
|
||||
|
||||
{% eventsignal request.event "pretix.control.signals.voucher_form_html" form=form %}
|
||||
<div class="submit-group" id="step-save">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Create" %}
|
||||
</button>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -37,17 +37,12 @@
|
||||
</p>
|
||||
|
||||
<a href="{% url "control:event.vouchers.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new voucher" %}</a>
|
||||
<a href="{% url "control:event.vouchers.bulk" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create multiple new vouchers" %}</a>
|
||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create new vouchers" %}</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>
|
||||
<a href="{% url "control:event.vouchers.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new voucher" %}</a>
|
||||
<a href="{% url "control:event.vouchers.bulk" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="btn btn-default"><i class="fa fa-plus"></i>
|
||||
{% trans "Create multiple new vouchers" %}</a>
|
||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create new vouchers" %}</a>
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-quotas">
|
||||
|
||||
@@ -5,6 +5,7 @@ $(function () {
|
||||
}
|
||||
|
||||
function show_step(state_el) {
|
||||
var was_visible = state_el.is(':visible');
|
||||
state_el.animate({
|
||||
'height': 'show',
|
||||
'opacity': 'show',
|
||||
@@ -15,13 +16,15 @@ $(function () {
|
||||
}, 400);
|
||||
var offset = state_el.offset();
|
||||
var body = $("html, body");
|
||||
if (offset.top > $("body").scrollTop() + $(window).height() - 160) {
|
||||
if (!was_visible && offset.top > $("body").scrollTop() + $(window).height() - 160) {
|
||||
body.animate({scrollTop: offset.top + 200}, '400', 'swing');
|
||||
}
|
||||
}
|
||||
|
||||
$(".wizard-step, .wizard-advanced").hide();
|
||||
$(".wizard-step").first().show();
|
||||
if ($(".alert-danger").length === 0) {
|
||||
$(".wizard-step, .wizard-advanced, #step-save").hide();
|
||||
$(".wizard-step").first().show();
|
||||
}
|
||||
|
||||
$("#id_number, #id_max_usages").on("change keydown keyup", function () {
|
||||
if ($("#id_number").val() && $("#id_max_usages").val()) {
|
||||
@@ -35,12 +38,14 @@ $(function () {
|
||||
}).on("change dp.change", function () {
|
||||
if ($("input[name=has_valid_until][value=no]").prop("checked") || $("#id_valid_until").val()) {
|
||||
show_step($("#step-products"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("input[name=has_valid_until]").on("change", function () {
|
||||
if ($("input[name=has_valid_until][value=no]").prop("checked") || $("#id_valid_until").val()) {
|
||||
if ($("input[name=has_valid_until]").not("[value=on]").prop("checked") || $("#id_valid_until").val()) {
|
||||
show_step($("#step-products"));
|
||||
} else {
|
||||
$("#id_valid_until").focus();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -50,14 +55,11 @@ $(function () {
|
||||
|
||||
$("#step-price input").on("change keydown keyup", function () {
|
||||
var mode = $("input[name=price_mode]:checked").val();
|
||||
var show_next = (
|
||||
mode === 'none'
|
||||
|| (mode === 'percent' && $("input[name='price[percent]']").val())
|
||||
|| (mode === 'subtract' && $("input[name='price[subtract]']").val())
|
||||
|| (mode === 'set' && $("input[name='price[set]']").val())
|
||||
);
|
||||
var show_next = (mode === 'none' || $("input[name='value_" + mode + "']").val());
|
||||
if (show_next) {
|
||||
show_step($("#step-block"));
|
||||
} else {
|
||||
$("input[name='value_" + mode + "']").focus();
|
||||
}
|
||||
});
|
||||
$("#step-price input[type=text]").on("focus change keyup keydown", function () {
|
||||
@@ -67,6 +69,7 @@ $(function () {
|
||||
|
||||
$("input[name=block_quota]").on("change", function () {
|
||||
show_step($("#step-advanced"));
|
||||
show_step($("#step-save"));
|
||||
});
|
||||
|
||||
$("#wizard-advanced-show").on("click", function (e) {
|
||||
|
||||
Reference in New Issue
Block a user