diff --git a/src/pretix/base/models/base.py b/src/pretix/base/models/base.py
index 658ca12b6d..ccb2c2321b 100644
--- a/src/pretix/base/models/base.py
+++ b/src/pretix/base/models/base.py
@@ -33,7 +33,6 @@ def cached_file_delete(sender, instance, **kwargs):
class LoggingMixin:
- logentries = GenericRelation('LogEntry')
def log_action(self, action, data=None, user=None):
"""
@@ -59,6 +58,10 @@ class LoggingMixin:
class LoggedModel(models.Model, LoggingMixin):
+ logentries = GenericRelation('LogEntry')
class Meta:
abstract = True
+
+ def all_logentries(self):
+ return self.logentries.all().select_related('user')
diff --git a/src/pretix/base/models/log.py b/src/pretix/base/models/log.py
index 4ec9183f61..5e342cde7f 100644
--- a/src/pretix/base/models/log.py
+++ b/src/pretix/base/models/log.py
@@ -28,3 +28,14 @@ class LogEntry(models.Model):
event = models.ForeignKey('Event', null=True, blank=True, on_delete=models.CASCADE)
action_type = models.CharField(max_length=255)
data = models.TextField(default='{}')
+
+ class Meta:
+ ordering = ('-datetime', )
+
+ def display(self):
+ from ..signals import logentry_display
+
+ for receiver, response in logentry_display.send(self.event, logentry=self):
+ if response:
+ return response
+ return self.action_type
diff --git a/src/pretix/base/signals.py b/src/pretix/base/signals.py
index 2d4158b87e..1b422ce5c4 100644
--- a/src/pretix/base/signals.py
+++ b/src/pretix/base/signals.py
@@ -87,3 +87,11 @@ as the first argument.
order_paid = EventPluginSignal(
providing_args=["order"]
)
+
+"""
+This signal is sent out every time we need to display a LogEntry object and we
+don't know how to turn it into human-readable text.
+"""
+logentry_display = EventPluginSignal(
+ providing_args=["logentry"]
+)
diff --git a/src/pretix/control/__init__.py b/src/pretix/control/__init__.py
index 44e4f080d6..94e7d9351f 100644
--- a/src/pretix/control/__init__.py
+++ b/src/pretix/control/__init__.py
@@ -7,5 +7,6 @@ class PretixControlConfig(AppConfig):
def ready(self):
from .views import dashboards # noqa
+ from . import logdisplay # noqa
default_app_config = 'pretix.control.PretixControlConfig'
diff --git a/src/pretix/control/logdisplay.py b/src/pretix/control/logdisplay.py
new file mode 100644
index 0000000000..b22ccbd104
--- /dev/null
+++ b/src/pretix/control/logdisplay.py
@@ -0,0 +1,20 @@
+from django.dispatch import receiver
+from django.utils.translation import ugettext_lazy as _
+
+from pretix.base.signals import logentry_display
+
+
+@receiver(signal=logentry_display, dispatch_uid="pretixcontrol_logentry_display")
+def pretixcontrol_logentry_display(sender, logentry, **kwargs):
+ plains = {
+ 'pretix.event.order.modified': _('The order details have been modified.'),
+ 'pretix.event.order.unpaid': _('The order has been marked as unpaid.'),
+ 'pretix.event.order.resend': _('The link to the order detail page has been resent to the user.'),
+ 'pretix.event.order.expirychanged': _('The order\'s expiry date has been changed.'),
+ 'pretix.event.order.paid': _('The order has been marked as paid.'),
+ 'pretix.event.order.refunded': _('The order has been refunded.'),
+ 'pretix.event.order.cancelled': _('The order has been cancelled.'),
+ 'pretix.event.order.placed': _('The order has been created.'),
+ }
+ if logentry.action_type in plains:
+ return plains[logentry.action_type]
diff --git a/src/pretix/control/templates/pretixcontrol/includes/logs.html b/src/pretix/control/templates/pretixcontrol/includes/logs.html
new file mode 100644
index 0000000000..7f31edb1b2
--- /dev/null
+++ b/src/pretix/control/templates/pretixcontrol/includes/logs.html
@@ -0,0 +1,16 @@
+
diff --git a/src/pretix/control/templates/pretixcontrol/order/index.html b/src/pretix/control/templates/pretixcontrol/order/index.html
index 1780d513c5..16d54a018e 100644
--- a/src/pretix/control/templates/pretixcontrol/order/index.html
+++ b/src/pretix/control/templates/pretixcontrol/order/index.html
@@ -47,186 +47,202 @@
{% endif %}
{% endif %}
-
-
-
- {% trans "Order details" %}
-
-
-
-
- - {% trans "Order code" %}
- - {{ order.code }}
- - {% trans "Order date" %}
- - {{ order.datetime }}
- {% if order.status == "p" %}
- - {% trans "Payment date" %}
- - {{ order.payment_date }}
- {% elif order.status == "n" %}
- - {% trans "Expiry date" %}
- - {{ order.expires }}
- {% endif %}
- - {% trans "User" %}
- -
- {{ order.email }}
-
-
- {% if invoices %}
- - {% trans "Invoices" %}
- -
- {% for i in invoices %}
-
- {% if i.is_cancellation %}{% trans "Cancellation" %}{% else %}{% trans "Invoice" %}{% endif %}
- {{ i.number }} ({{ i.date|date:"SHORT_DATE_FORMAT" }})
- {% if forloop.revcounter0 > 0 %}
-
- {% endif %}
- {% endfor %}
-
- {% endif %}
-
-
-
-
-
-
- {% trans "Ordered items" %}
-
-
-
- {% for line in items.positions %}
-
-
-
{{ line.item.name }}
- {% if line.variation %}
- – {{ line.variation }}
- {% endif %}
- {% if line.voucher %}
-
{% trans "Voucher code used:" %}
-
- {{ line.voucher.code }}
-
- {% endif %}
- {% if line.has_questions %}
-
- {% if line.item.admission and event.settings.attendee_names_asked %}
- - {% trans "Attendee name" %}
- - {% if line.attendee_name %}{{ line.attendee_name }}{% else %}
- {% trans "not answered" %}{% endif %}
- {% endif %}
- {% for q in line.questions %}
- - {{ q.question }}
- - {% if q.answer %}{{ q.answer }}{% else %}
- {% trans "not answered" %}{% endif %}
- {% endfor %}
-
- {% endif %}
-
-
- {{ line.count }}
-
-
- {{ event.currency }} {{ line.price|floatformat:2 }}
-
-
- {{ event.currency }} {{ line.total|floatformat:2 }}
- {% if line.tax_rate %}
-
- {% blocktrans trimmed with rate=line.tax_rate %}
- incl. {{ rate }}% taxes
- {% endblocktrans %}
- {% endif %}
-
-
-
- {% endfor %}
- {% if items.payment_fee %}
-
-
- {% trans "Payment method fee" %}
-
-
- {{ event.currency }} {{ items.payment_fee|floatformat:2 }}
- {% if order.payment_fee_tax_rate %}
-
- {% blocktrans trimmed with rate=order.payment_fee_tax_rate %}
- incl. {{ rate }}% taxes
- {% endblocktrans %}
- {% endif %}
-
-
-
- {% endif %}
-
-
- {% trans "Total" %}
-
-
- {{ event.currency }} {{ items.total|floatformat:2 }}
-
-
-
-
-
+
-
-
+
+
- {% trans "Payment information" %}
+ {% trans "Order details" %}
- {% if order.payment_manual %}
-
- {% trans "The payment state of this order was manually modified." %}
+
+ - {% trans "Order code" %}
+ - {{ order.code }}
+ - {% trans "Order date" %}
+ - {{ order.datetime }}
+ {% if order.status == "p" %}
+ - {% trans "Payment date" %}
+ - {{ order.payment_date }}
+ {% elif order.status == "n" %}
+ - {% trans "Expiry date" %}
+ - {{ order.expires }}
+ {% endif %}
+ - {% trans "User" %}
+ -
+ {{ order.email }}
+
+
+ {% if invoices %}
+ - {% trans "Invoices" %}
+ -
+ {% for i in invoices %}
+
+ {% if i.is_cancellation %}{% trans "Cancellation" %}{% else %}{% trans "Invoice" %}{% endif %}
+ {{ i.number }} ({{ i.date|date:"SHORT_DATE_FORMAT" }})
+ {% if forloop.revcounter0 > 0 %}
+
+ {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+
+
+
+
+
+ {% trans "Ordered items" %}
+
+
+
+ {% for line in items.positions %}
+
+
+
{{ line.item.name }}
+ {% if line.variation %}
+ – {{ line.variation }}
+ {% endif %}
+ {% if line.voucher %}
+
{% trans "Voucher code used:" %}
+
+ {{ line.voucher.code }}
+
+ {% endif %}
+ {% if line.has_questions %}
+
+ {% if line.item.admission and event.settings.attendee_names_asked %}
+ - {% trans "Attendee name" %}
+ - {% if line.attendee_name %}{{ line.attendee_name }}{% else %}
+ {% trans "not answered" %}{% endif %}
+ {% endif %}
+ {% for q in line.questions %}
+ - {{ q.question }}
+ - {% if q.answer %}{{ q.answer }}{% else %}
+ {% trans "not answered" %}{% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+
+ {{ line.count }}
+
+
+ {{ event.currency }} {{ line.price|floatformat:2 }}
+
+
+ {{ event.currency }} {{ line.total|floatformat:2 }}
+ {% if line.tax_rate %}
+
+ {% blocktrans trimmed with rate=line.tax_rate %}
+ incl. {{ rate }}% taxes
+ {% endblocktrans %}
+ {% endif %}
+
+
+
+ {% endfor %}
+ {% if items.payment_fee %}
+
+
+ {% trans "Payment method fee" %}
+
+
+ {{ event.currency }} {{ items.payment_fee|floatformat:2 }}
+ {% if order.payment_fee_tax_rate %}
+
+ {% blocktrans trimmed with rate=order.payment_fee_tax_rate %}
+ incl. {{ rate }}% taxes
+ {% endblocktrans %}
+ {% endif %}
+
+
{% endif %}
- {{ payment }}
- {% if order.status == 'n' %}
-
{% blocktrans trimmed with date=order.expires %}
- The payment has to be completed before {{ date }}.
- {% endblocktrans %}
- {% endif %}
+
+
+ {% trans "Total" %}
+
+
+ {{ event.currency }} {{ items.total|floatformat:2 }}
+
+
+
+
+
+
+
+
+ {% trans "Payment information" %}
+
+
+
+ {% if order.payment_manual %}
+
+ {% trans "The payment state of this order was manually modified." %}
+
+ {% endif %}
+ {{ payment }}
+ {% if order.status == 'n' %}
+
{% blocktrans trimmed with date=order.expires %}
+ The payment has to be completed before {{ date }}.
+ {% endblocktrans %}
+ {% endif %}
+
+
+
+ {% if request.event.settings.invoice_address_asked %}
+
+
+
+
+ {% trans "Invoice information" %}
+
+
+
+
+ - {% trans "Company" %}
+ - {{ order.invoice_address.company }}
+ - {% trans "Name" %}
+ - {{ order.invoice_address.name }}
+ - {% trans "Address" %}
+ - {{ order.invoice_address.street|linebreaksbr }}
+ - {% trans "ZIP code and city" %}
+ - {{ order.invoice_address.zipcode }} {{ addr.city }}
+ - {% trans "Country" %}
+ - {{ order.invoice_address.country }}
+ - {% trans "Phone" %}
+ - {{ order.invoice_address.phone }}
+ {% if request.event.settings.invoice_address_vatid %}
+ - {% trans "VAT ID" %}
+ - {{ order.invoice_address.vat_id }}
+ {% endif %}
+
+
+
+
+ {% endif %}
+
- {% if request.event.settings.invoice_address_asked %}
-
-
-
-
- {% trans "Invoice information" %}
-
-
-
-
- - {% trans "Company" %}
- - {{ order.invoice_address.company }}
- - {% trans "Name" %}
- - {{ order.invoice_address.name }}
- - {% trans "Address" %}
- - {{ order.invoice_address.street|linebreaksbr }}
- - {% trans "ZIP code and city" %}
- - {{ order.invoice_address.zipcode }} {{ addr.city }}
- - {% trans "Country" %}
- - {{ order.invoice_address.country }}
- - {% trans "Phone" %}
- - {{ order.invoice_address.phone }}
- {% if request.event.settings.invoice_address_vatid %}
- - {% trans "VAT ID" %}
- - {{ order.invoice_address.vat_id }}
- {% endif %}
-
-
+
+
+
+
+
+ {% trans "Order history" %}
+
+ {% include "pretixcontrol/includes/logs.html" with obj=order %}
- {% endif %}
+
{% endblock %}
diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py
index 56045877fe..5919d9d7ef 100644
--- a/src/pretix/control/views/orders.py
+++ b/src/pretix/control/views/orders.py
@@ -180,7 +180,7 @@ class OrderTransition(OrderView):
self.order.status = Order.STATUS_PENDING
self.order.payment_manual = True
self.order.save()
- self.order.log_action('pretix.base.order.unpaid', user=self.request.user)
+ self.order.log_action('pretix.event.order.unpaid', user=self.request.user)
messages.success(self.request, _('The order has been marked as not paid.'))
elif self.order.status == 'p' and to == 'r':
ret = self.payment_provider.order_control_refund_perform(self.request, self.order)
@@ -221,7 +221,7 @@ class OrderResendLink(OrderView):
self.order.event, locale=self.order.locale
)
messages.success(self.request, _('The email has been queued to be sent.'))
- self.order.log_action('pretix.base.order.resend', user=self.request.user)
+ self.order.log_action('pretix.event.order.resend', user=self.request.user)
return redirect(self.get_order_url())
@@ -305,7 +305,7 @@ class OrderExtend(OrderView):
if self.form.is_valid():
if oldvalue > now():
messages.success(self.request, _('The payment term has been changed.'))
- self.order.log_action('pretix.order.changed', user=self.request.user, data={
+ self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={
'expires': self.order.expires
})
self.form.save()
@@ -315,7 +315,7 @@ class OrderExtend(OrderView):
is_available = self.order._is_still_available()
if is_available is True:
self.form.save()
- self.order.log_action('pretix.order.changed', user=self.request.user, data={
+ self.order.log_action('pretix.event.order.expirychanged', user=self.request.user, data={
'expires': self.order.expires
})
messages.success(self.request, _('The payment term has been changed.'))
diff --git a/src/static/pretixcontrol/less/orders.less b/src/static/pretixcontrol/less/orders.less
index 166758cbc8..d0fcaa73b2 100644
--- a/src/static/pretixcontrol/less/orders.less
+++ b/src/static/pretixcontrol/less/orders.less
@@ -16,6 +16,17 @@
display: none;
}
}
+
#sumtoggle {
margin-top: 20px;
+}
+
+.logentry {
+ .meta {
+ font-size: 12px;
+ margin: 0 0 5px;
+ }
+ p:last-child {
+ margin-bottom: 0;
+ }
}
\ No newline at end of file