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 }}   -
- {% csrf_token %} - -
-
- {% 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 }}   +
+ {% csrf_token %} + +
+
+ {% 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