Refs #126 -- Display logs of vouchers, items, quotas and categories

This commit is contained in:
Raphael Michel
2017-01-03 23:13:27 +01:00
parent dc73018404
commit f4be14eed8
8 changed files with 190 additions and 100 deletions
+4
View File
@@ -472,6 +472,10 @@ class OrderPosition(AbstractPosition):
answ.save() answ.save()
if cartpos.voucher: if cartpos.voucher:
Voucher.objects.filter(pk=cartpos.voucher.pk).update(redeemed=F('redeemed') + 1) 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() cartpos.delete()
return ops return ops
+44 -22
View File
@@ -5,6 +5,7 @@ from django.dispatch import receiver
from django.utils import formats from django.utils import formats
from django.utils.translation import ugettext_lazy as _ 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.models import Event, ItemVariation, LogEntry
from pretix.base.signals import logentry_display 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.refunded': _('The order has been refunded.'),
'pretix.event.order.canceled': _('The order has been canceled.'), 'pretix.event.order.canceled': _('The order has been canceled.'),
'pretix.event.order.placed': _('The order has been created.'), '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.generated': _('The invoice has been generated.'),
'pretix.event.order.invoice.regenerated': _('The invoice has been regenerated.'), 'pretix.event.order.invoice.regenerated': _('The invoice has been regenerated.'),
'pretix.event.order.invoice.reissued': _('The invoice has been reissued.'), '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.comment': _('The order\'s internal comment has been updated.'),
'pretix.event.order.payment.changed': _('The payment method has been changed.'), '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.enabled': _('Two-factor authentication has been enabled.'),
'pretix.user.settings.2fa.disabled': _('Two-factor authentication has been disabled.'), '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.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.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: 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'): if logentry.action_type.startswith('pretix.event.order.changed'):
return _display_order_changed(sender, logentry) 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': if logentry.action_type == 'pretix.user.settings.changed':
data = json.loads(logentry.data)
text = str(_('Your account settings have been changed.')) text = str(_('Your account settings have been changed.'))
if 'email' in data: if 'email' in data:
text = text + ' ' + str(_('Your email address has been changed to {email}.').format(email=data['email'])) text = text + ' ' + str(_('Your email address has been changed to {email}.').format(email=data['email']))
@@ -4,29 +4,43 @@
{% block inside %} {% block inside %}
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data"> <form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
<fieldset> <div class="row">
<legend>{% trans "General information" %}</legend> <div class="col-xs-12 col-lg-10">
{% bootstrap_field form.name layout="horizontal" %} <fieldset>
{% bootstrap_field form.active layout="horizontal" %} <legend>{% trans "General information" %}</legend>
{% bootstrap_field form.category layout="horizontal" %} {% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.admission layout="horizontal" %} {% bootstrap_field form.active layout="horizontal" %}
{% bootstrap_field form.description layout="horizontal" %} {% bootstrap_field form.category layout="horizontal" %}
{% bootstrap_field form.picture layout="horizontal" %} {% bootstrap_field form.admission layout="horizontal" %}
</fieldset> {% bootstrap_field form.description layout="horizontal" %}
<fieldset> {% bootstrap_field form.picture layout="horizontal" %}
<legend>{% trans "Price settings" %}</legend> </fieldset>
{% bootstrap_field form.default_price layout="horizontal" %} <fieldset>
{% bootstrap_field form.tax_rate layout="horizontal" %} <legend>{% trans "Price settings" %}</legend>
{% bootstrap_field form.free_price layout="horizontal" %} {% bootstrap_field form.default_price layout="horizontal" %}
</fieldset> {% bootstrap_field form.tax_rate layout="horizontal" %}
<fieldset> {% bootstrap_field form.free_price layout="horizontal" %}
<legend>{% trans "Availability" %}</legend> </fieldset>
{% bootstrap_field form.available_from layout="horizontal" %} <fieldset>
{% bootstrap_field form.available_until layout="horizontal" %} <legend>{% trans "Availability" %}</legend>
{% bootstrap_field form.require_voucher layout="horizontal" %} {% bootstrap_field form.available_from layout="horizontal" %}
{% bootstrap_field form.hide_without_voucher layout="horizontal" %} {% bootstrap_field form.available_until layout="horizontal" %}
{% bootstrap_field form.allow_cancel layout="horizontal" %} {% bootstrap_field form.require_voucher layout="horizontal" %}
</fieldset> {% bootstrap_field form.hide_without_voucher layout="horizontal" %}
{% bootstrap_field form.allow_cancel layout="horizontal" %}
</fieldset>
</div>
<div class="col-xs-12 col-lg-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Product history" %}
</h3>
</div>
{% include "pretixcontrol/includes/logs.html" with obj=item %}
</div>
</div>
</div>
<div class="form-group submit-group"> <div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save"> <button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %} {% trans "Save" %}
@@ -7,11 +7,25 @@
<form action="" method="post" class="form-horizontal"> <form action="" method="post" class="form-horizontal">
{% csrf_token %} {% csrf_token %}
{% bootstrap_form_errors form %} {% bootstrap_form_errors form %}
<fieldset> <div class="row">
<legend>{% trans "General information" %}</legend> <div class="col-xs-12 col-lg-10">
{% bootstrap_field form.name layout="horizontal" %} <fieldset>
{% bootstrap_field form.description layout="horizontal" %} <legend>{% trans "General information" %}</legend>
</fieldset> {% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.description layout="horizontal" %}
</fieldset>
</div>
<div class="col-xs-12 col-lg-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Category history" %}
</h3>
</div>
{% include "pretixcontrol/includes/logs.html" with obj=category %}
</div>
</div>
</div>
<div class="form-group submit-group"> <div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save"> <button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %} {% trans "Save" %}
@@ -36,31 +36,31 @@
<button class="btn btn-primary" type="submit">{% trans "Filter" %}</button> <button class="btn btn-primary" type="submit">{% trans "Filter" %}</button>
</p> </p>
</form> </form>
{% if not stats %} <div class="row" id="question-stats">
<div class="empty-collection"> {% if not stats %}
<p> <div class="empty-collection col-md-10 col-xs-12">
{% blocktrans trimmed %}
No matching answers found.
{% endblocktrans %}
</p>
{% if not items %}
<p> <p>
{% trans "You need to assign the question to a product to collect answers." %} {% blocktrans trimmed %}
No matching answers found.
{% endblocktrans %}
</p> </p>
{% if not items %}
<p>
{% trans "You need to assign the question to a product to collect answers." %}
</p>
<a href="{% url "control:event.items.questions.edit" event=request.event.slug organizer=request.event.organizer.slug question=question.pk %}" <a href="{% url "control:event.items.questions.edit" event=request.event.slug organizer=request.event.organizer.slug question=question.pk %}"
class="btn btn-primary btn-lg"><i class="fa fa-edit"></i> {% trans "Edit question" %}</a> class="btn btn-primary btn-lg"><i class="fa fa-edit"></i> {% trans "Edit question" %}</a>
{% endif %} {% endif %}
</div> </div>
{% else %} {% else %}
<div class="row" id="question-stats"> <div class="col-md-5 col-xs-12">
<div class="col-md-6 col-xs-12">
<div class="chart" id="question_chart" data-type="{{ question.type }}"> <div class="chart" id="question_chart" data-type="{{ question.type }}">
</div> </div>
<script type="application/json" id="question-chart-data">{{ stats_json|safe }}</script> <script type="application/json" id="question-chart-data">{{ stats_json|safe }}</script>
</div> </div>
<div class="col-md-6 col-xs-12"> <div class="col-md-5 col-xs-12">
<table class="table table-bordered table-hover"> <table class="table table-bordered table-hover">
<thead> <thead>
<tr> <tr>
@@ -80,6 +80,16 @@
</tbody> </tbody>
</table> </table>
</div> </div>
{% endif %}
<div class="col-xs-12 col-lg-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Question history" %}
</h3>
</div>
{% include "pretixcontrol/includes/logs.html" with obj=question %}
</div>
</div> </div>
{% endif %} </div>
{% endblock %} {% endblock %}
@@ -15,14 +15,14 @@
{% endif %} {% endif %}
</h1> </h1>
<div class="row" id="quota-stats"> <div class="row" id="quota-stats">
<div class="col-md-6 col-xs-12"> <div class="col-md-5 col-xs-12">
<legend>{% trans "Usage overview" %}</legend> <legend>{% trans "Usage overview" %}</legend>
<div class="chart" id="quota_chart"> <div class="chart" id="quota_chart">
</div> </div>
<script type="application/json" id="quota-chart-data">{{ quota_chart_data|safe }}</script> <script type="application/json" id="quota-chart-data">{{ quota_chart_data|safe }}</script>
</div> </div>
<div class="col-md-6 col-xs-12"> <div class="col-md-5 col-xs-12">
<legend>{% trans "Availability calculation" %}</legend> <legend>{% trans "Availability calculation" %}</legend>
<div class="row"> <div class="row">
@@ -59,6 +59,16 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div class="col-md-2 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Quota history" %}
</h3>
</div>
{% include "pretixcontrol/includes/logs.html" with obj=quota %}
</div>
</div>
</div> </div>
{% eventsignal request.event "pretix.control.signals.quota_detail_html" quota=quota %} {% eventsignal request.event "pretix.control.signals.quota_detail_html" quota=quota %}
{% endblock %} {% endblock %}
@@ -20,40 +20,54 @@
<form action="" method="post" class="form-horizontal"> <form action="" method="post" class="form-horizontal">
{% csrf_token %} {% csrf_token %}
{% bootstrap_form_errors form %} {% bootstrap_form_errors form %}
<fieldset> <div class="row">
<legend>{% trans "Voucher details" %}</legend> <div class="col-xs-12 col-lg-10">
{% bootstrap_field form.code layout="horizontal" %} <fieldset>
{% bootstrap_field form.max_usages layout="horizontal" %} <legend>{% trans "Voucher details" %}</legend>
{% bootstrap_field form.valid_until layout="horizontal" %} {% bootstrap_field form.code layout="horizontal" %}
{% bootstrap_field form.block_quota layout="horizontal" %} {% bootstrap_field form.max_usages layout="horizontal" %}
{% bootstrap_field form.allow_ignore_quota layout="horizontal" %} {% bootstrap_field form.valid_until layout="horizontal" %}
<div class="form-group"> {% bootstrap_field form.block_quota layout="horizontal" %}
<label class="col-md-3 control-label" for="id_tag">{% trans "Price effect" %}</label> {% bootstrap_field form.allow_ignore_quota layout="horizontal" %}
<div class="col-md-5"> <div class="form-group">
{% bootstrap_field form.price_mode show_label=False form_group_class="" %} <label class="col-md-3 control-label" for="id_tag">{% trans "Price effect" %}</label>
</div> <div class="col-md-5">
<div class="col-md-4"> {% bootstrap_field form.price_mode show_label=False form_group_class="" %}
{% bootstrap_field form.value show_label=False form_group_class="" %} </div>
</div> <div class="col-md-4">
</div> {% bootstrap_field form.value show_label=False form_group_class="" %}
{% bootstrap_field form.itemvar layout="horizontal" %}
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<div class="controls">
<div class="alert alert-info">
{% 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 %}
</div> </div>
</div> </div>
{% bootstrap_field form.itemvar layout="horizontal" %}
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<div class="controls">
<div class="alert alert-info">
{% 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 %}
</div>
</div>
</div>
</div>
{% bootstrap_field form.tag layout="horizontal" %}
{% bootstrap_field form.comment layout="horizontal" %}
</fieldset>
{% eventsignal request.event "pretix.control.signals.voucher_form_html" form=form %}
</div>
<div class="col-xs-12 col-lg-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Voucher history" %}
</h3>
</div>
{% include "pretixcontrol/includes/logs.html" with obj=voucher %}
</div> </div>
</div> </div>
{% bootstrap_field form.tag layout="horizontal" %} </div>
{% bootstrap_field form.comment layout="horizontal" %}
</fieldset>
{% eventsignal request.event "pretix.control.signals.voucher_form_html" form=form %}
<div class="form-group submit-group"> <div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save"> <button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %} {% trans "Save" %}
+2
View File
@@ -831,6 +831,7 @@ class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView
continue continue
self.get_object().log_action( self.get_object().log_action(
'pretix.event.item.variation.deleted', user=self.request.user, data={ 'pretix.event.item.variation.deleted', user=self.request.user, data={
'value': form.instance.value,
'id': form.instance.pk 'id': form.instance.pk
} }
) )
@@ -848,6 +849,7 @@ class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView
form.save() form.save()
if form.has_changed(): if form.has_changed():
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data} change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
change_data['value'] = form.instance.value
change_data['id'] = form.instance.pk change_data['id'] = form.instance.pk
self.get_object().log_action( self.get_object().log_action(
'pretix.event.item.variation.changed' if not created else 'pretix.event.item.variation.changed' if not created else