diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index c27ede80a0..7973ef92f1 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -472,6 +472,10 @@ class OrderPosition(AbstractPosition): answ.save() if cartpos.voucher: Voucher.objects.filter(pk=cartpos.voucher.pk).update(redeemed=F('redeemed') + 1) + cartpos.voucher.log_action('pretix.voucher.redeemed', { + 'order_code': order.code + }) + cartpos.delete() return ops diff --git a/src/pretix/control/logdisplay.py b/src/pretix/control/logdisplay.py index e4174d38a3..4f311afc36 100644 --- a/src/pretix/control/logdisplay.py +++ b/src/pretix/control/logdisplay.py @@ -5,6 +5,7 @@ from django.dispatch import receiver from django.utils import formats from django.utils.translation import ugettext_lazy as _ +from pretix.base.i18n import LazyI18nString from pretix.base.models import Event, ItemVariation, LogEntry from pretix.base.signals import logentry_display @@ -61,44 +62,65 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): 'pretix.event.order.refunded': _('The order has been refunded.'), 'pretix.event.order.canceled': _('The order has been canceled.'), 'pretix.event.order.placed': _('The order has been created.'), + 'pretix.event.order.contact.changed': _('The email address has been changed from "{old_email}" ' + 'to "{new_email}".'), 'pretix.event.order.invoice.generated': _('The invoice has been generated.'), 'pretix.event.order.invoice.regenerated': _('The invoice has been regenerated.'), 'pretix.event.order.invoice.reissued': _('The invoice has been reissued.'), 'pretix.event.order.comment': _('The order\'s internal comment has been updated.'), 'pretix.event.order.payment.changed': _('The payment method has been changed.'), - 'pretix.event.order.expire_warning_sent': _('An email has been sent with a warning that the order is about to expire.'), + 'pretix.event.order.expire_warning_sent': _('An email has been sent with a warning that the order is about ' + 'to expire.'), 'pretix.user.settings.2fa.enabled': _('Two-factor authentication has been enabled.'), 'pretix.user.settings.2fa.disabled': _('Two-factor authentication has been disabled.'), 'pretix.user.settings.2fa.regenemergency': _('Your two-factor emergency codes have been regenerated.'), + 'pretix.user.settings.2fa.device.added': _('A new two-factor authentication device "{name}" has been added to ' + 'your account.'), + 'pretix.user.settings.2fa.device.deleted': _('The two-factor authentication device "{name}" has been removed ' + 'from your account.'), 'pretix.control.auth.user.forgot_password.mail_sent': _('Password reset mail sent.'), - 'pretix.control.auth.user.forgot_password.recovered': _('The password has been reset.') - + 'pretix.control.auth.user.forgot_password.recovered': _('The password has been reset.'), + 'pretix.voucher.added': _('The voucher has been created.'), + 'pretix.voucher.changed': _('The voucher has been modified.'), + 'pretix.voucher.deleted': _('The voucher has been deleted.'), + 'pretix.voucher.redeemed': _('The voucher has been redeemed in order {order_code}.'), + 'pretix.event.item.added': _('The product has been created.'), + 'pretix.event.item.changed': _('The product has been modified.'), + 'pretix.event.item.deleted': _('The product has been deleted.'), + 'pretix.event.item.variation.added': _('The variation "{value}" has been created.'), + 'pretix.event.item.variation.deleted': _('The variation "{value}" has been deleted.'), + 'pretix.event.item.variation.changed': _('The variation "{value}" has been modified.'), + 'pretix.event.quota.added': _('The quota has been added.'), + 'pretix.event.quota.deleted': _('The quota has been deleted.'), + 'pretix.event.quota.changed': _('The quota has been modified.'), + 'pretix.event.category.added': _('The category has been added.'), + 'pretix.event.category.deleted': _('The category has been deleted.'), + 'pretix.event.category.changed': _('The category has been modified.'), + 'pretix.event.question.added': _('The question has been added.'), + 'pretix.event.question.deleted': _('The question has been deleted.'), + 'pretix.event.question.changed': _('The question has been modified.'), } + + data = json.loads(logentry.data) + + if logentry.action_type.startswith('pretix.event.item.variation'): + if 'value' not in data: + # Backwards compatibility + var = ItemVariation.objects.filter(id=data['id']).first() + if var: + data['value'] = str(var.value) + else: + data['value'] = '?' + else: + data['value'] = LazyI18nString(data['value']) + if logentry.action_type in plains: - return plains[logentry.action_type] + return plains[logentry.action_type].format_map(data) if logentry.action_type.startswith('pretix.event.order.changed'): return _display_order_changed(sender, logentry) - if logentry.action_type.startswith('pretix.event.order.contact.changed'): - data = json.loads(logentry.data) - return _('The email address has been changed from "{old}" to "{new}".').format( - old=data['old_email'], - new=data['new_email'], - ) - - if logentry.action_type == 'pretix.user.settings.2fa.device.added': - data = json.loads(logentry.data) - return _('A new two-factor authentication device "{name}" has been added to your account.').format( - name=data['name'] - ) - if logentry.action_type == 'pretix.user.settings.2fa.device.deleted': - data = json.loads(logentry.data) - return _('The two-factor authentication device "{name}" has been removed from your account.').format( - name=data['name'] - ) if logentry.action_type == 'pretix.user.settings.changed': - data = json.loads(logentry.data) text = str(_('Your account settings have been changed.')) if 'email' in data: text = text + ' ' + str(_('Your email address has been changed to {email}.').format(email=data['email'])) diff --git a/src/pretix/control/templates/pretixcontrol/item/index.html b/src/pretix/control/templates/pretixcontrol/item/index.html index b433e844c8..7a0684dc52 100644 --- a/src/pretix/control/templates/pretixcontrol/item/index.html +++ b/src/pretix/control/templates/pretixcontrol/item/index.html @@ -4,29 +4,43 @@ {% block inside %}
{% csrf_token %} -
- {% trans "General information" %} - {% bootstrap_field form.name layout="horizontal" %} - {% bootstrap_field form.active layout="horizontal" %} - {% bootstrap_field form.category layout="horizontal" %} - {% bootstrap_field form.admission layout="horizontal" %} - {% bootstrap_field form.description layout="horizontal" %} - {% bootstrap_field form.picture layout="horizontal" %} -
-
- {% trans "Price settings" %} - {% bootstrap_field form.default_price layout="horizontal" %} - {% bootstrap_field form.tax_rate layout="horizontal" %} - {% bootstrap_field form.free_price layout="horizontal" %} -
-
- {% trans "Availability" %} - {% bootstrap_field form.available_from layout="horizontal" %} - {% bootstrap_field form.available_until layout="horizontal" %} - {% bootstrap_field form.require_voucher layout="horizontal" %} - {% bootstrap_field form.hide_without_voucher layout="horizontal" %} - {% bootstrap_field form.allow_cancel layout="horizontal" %} -
+
+
+
+ {% trans "General information" %} + {% bootstrap_field form.name layout="horizontal" %} + {% bootstrap_field form.active layout="horizontal" %} + {% bootstrap_field form.category layout="horizontal" %} + {% bootstrap_field form.admission layout="horizontal" %} + {% bootstrap_field form.description layout="horizontal" %} + {% bootstrap_field form.picture layout="horizontal" %} +
+
+ {% trans "Price settings" %} + {% bootstrap_field form.default_price layout="horizontal" %} + {% bootstrap_field form.tax_rate layout="horizontal" %} + {% bootstrap_field form.free_price layout="horizontal" %} +
+
+ {% trans "Availability" %} + {% bootstrap_field form.available_from layout="horizontal" %} + {% bootstrap_field form.available_until layout="horizontal" %} + {% bootstrap_field form.require_voucher layout="horizontal" %} + {% bootstrap_field form.hide_without_voucher layout="horizontal" %} + {% bootstrap_field form.allow_cancel layout="horizontal" %} +
+
+
+
+
+

+ {% trans "Product history" %} +

+
+ {% include "pretixcontrol/includes/logs.html" with obj=item %} +
+
+

- {% if not stats %} -
-

- {% blocktrans trimmed %} - No matching answers found. - {% endblocktrans %} -

- {% if not items %} +
+ {% if not stats %} +

- {% trans "You need to assign the question to a product to collect answers." %} + {% blocktrans trimmed %} + No matching answers found. + {% endblocktrans %}

+ {% if not items %} +

+ {% trans "You need to assign the question to a product to collect answers." %} +

- {% trans "Edit question" %} - {% endif %} -
- {% else %} -
-
+ {% trans "Edit question" %} + {% endif %} +
+ {% else %} +
-
+
@@ -80,6 +80,16 @@
+ {% endif %} +
+
+
+

+ {% trans "Question history" %} +

+
+ {% include "pretixcontrol/includes/logs.html" with obj=question %} +
- {% endif %} +
{% endblock %} diff --git a/src/pretix/control/templates/pretixcontrol/items/quota.html b/src/pretix/control/templates/pretixcontrol/items/quota.html index e1f07d33ba..2b97861d85 100644 --- a/src/pretix/control/templates/pretixcontrol/items/quota.html +++ b/src/pretix/control/templates/pretixcontrol/items/quota.html @@ -15,14 +15,14 @@ {% endif %}
-
+
{% trans "Usage overview" %}
-
+
{% trans "Availability calculation" %}
@@ -59,6 +59,16 @@
{% endif %}
+
+
+
+

+ {% trans "Quota history" %} +

+
+ {% include "pretixcontrol/includes/logs.html" with obj=quota %} +
+
{% eventsignal request.event "pretix.control.signals.quota_detail_html" quota=quota %} {% endblock %} diff --git a/src/pretix/control/templates/pretixcontrol/vouchers/detail.html b/src/pretix/control/templates/pretixcontrol/vouchers/detail.html index 52e1d510b2..638cbc84d4 100644 --- a/src/pretix/control/templates/pretixcontrol/vouchers/detail.html +++ b/src/pretix/control/templates/pretixcontrol/vouchers/detail.html @@ -20,40 +20,54 @@
{% csrf_token %} {% bootstrap_form_errors form %} -
- {% trans "Voucher details" %} - {% bootstrap_field form.code layout="horizontal" %} - {% bootstrap_field form.max_usages layout="horizontal" %} - {% bootstrap_field form.valid_until layout="horizontal" %} - {% bootstrap_field form.block_quota layout="horizontal" %} - {% bootstrap_field form.allow_ignore_quota layout="horizontal" %} -
- -
- {% bootstrap_field form.price_mode show_label=False form_group_class="" %} -
-
- {% bootstrap_field form.value show_label=False form_group_class="" %} -
-
- {% bootstrap_field form.itemvar layout="horizontal" %} -
-
-
-
- {% blocktrans trimmed %} - If you choose "any product" for a specific quota and choose to reserve quota for this - voucher above, the product can still be unavailable to the voucher holder if another quota - associated with the product is sold out! - {% endblocktrans %} +
+
+
+ {% trans "Voucher details" %} + {% bootstrap_field form.code layout="horizontal" %} + {% bootstrap_field form.max_usages layout="horizontal" %} + {% bootstrap_field form.valid_until layout="horizontal" %} + {% bootstrap_field form.block_quota layout="horizontal" %} + {% bootstrap_field form.allow_ignore_quota layout="horizontal" %} +
+ +
+ {% bootstrap_field form.price_mode show_label=False form_group_class="" %} +
+
+ {% bootstrap_field form.value show_label=False form_group_class="" %}
+ {% bootstrap_field form.itemvar layout="horizontal" %} +
+
+
+
+ {% blocktrans trimmed %} + If you choose "any product" for a specific quota and choose to reserve quota for this + voucher above, the product can still be unavailable to the voucher holder if another quota + associated with the product is sold out! + {% endblocktrans %} +
+
+
+
+ {% bootstrap_field form.tag layout="horizontal" %} + {% bootstrap_field form.comment layout="horizontal" %} +
+ {% eventsignal request.event "pretix.control.signals.voucher_form_html" form=form %} +
+
+
+
+

+ {% trans "Voucher history" %} +

+
+ {% include "pretixcontrol/includes/logs.html" with obj=voucher %}
- {% bootstrap_field form.tag layout="horizontal" %} - {% bootstrap_field form.comment layout="horizontal" %} -
- {% eventsignal request.event "pretix.control.signals.voucher_form_html" form=form %} +