diff --git a/src/pretix/base/models/log.py b/src/pretix/base/models/log.py index 02de810f8c..78ebf8016a 100644 --- a/src/pretix/base/models/log.py +++ b/src/pretix/base/models/log.py @@ -1,6 +1,9 @@ from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models +from django.urls import reverse +from django.utils.functional import cached_property +from django.utils.translation import ugettext_lazy as _ class LogEntry(models.Model): @@ -32,7 +35,7 @@ class LogEntry(models.Model): data = models.TextField(default='{}') class Meta: - ordering = ('-datetime', ) + ordering = ('-datetime',) def display(self): from ..signals import logentry_display @@ -41,3 +44,83 @@ class LogEntry(models.Model): if response: return response return self.action_type + + @cached_property + def display_object(self): + from . import Order, Voucher, Quota, Item, ItemCategory, Question, Event + + if self.content_type.model_class() is Event: + return '' + + co = self.content_object + a_map = None + a_text = None + + if isinstance(co, Order): + a_text = _('Order {val}') + a_map = { + 'href': reverse('control:event.order', kwargs={ + 'event': self.event.slug, + 'organizer': self.event.organizer.slug, + 'code': co.code + }), + 'val': co.code, + } + elif isinstance(co, Voucher): + a_text = _('Voucher {val}…') + a_map = { + 'href': reverse('control:event.voucher', kwargs={ + 'event': self.event.slug, + 'organizer': self.event.organizer.slug, + 'voucher': co.id + }), + 'val': co.code[:6], + } + elif isinstance(co, Item): + a_text = _('Product {val}') + a_map = { + 'href': reverse('control:event.item', kwargs={ + 'event': self.event.slug, + 'organizer': self.event.organizer.slug, + 'item': co.id + }), + 'val': co.name, + } + elif isinstance(co, Quota): + a_text = _('Quota {val}') + a_map = { + 'href': reverse('control:event.items.quotas.show', kwargs={ + 'event': self.event.slug, + 'organizer': self.event.organizer.slug, + 'quota': co.id + }), + 'val': co.name, + } + elif isinstance(co, ItemCategory): + a_text = _('Category {val}') + a_map = { + 'href': reverse('control:event.items.categories.show', kwargs={ + 'event': self.event.slug, + 'organizer': self.event.organizer.slug, + 'category': co.id + }), + 'val': co.name, + } + elif isinstance(co, Question): + a_text = _('Question {val}') + a_map = { + 'href': reverse('control:event.items.questions.show', kwargs={ + 'event': self.event.slug, + 'organizer': self.event.organizer.slug, + 'question': co.id + }), + 'val': co.question, + } + + if a_text and a_map: + a_map['val'] = '{val}'.format_map(a_map) + return a_text.format_map(a_map) + elif a_text: + return a_text + else: + return '' diff --git a/src/pretix/control/logdisplay.py b/src/pretix/control/logdisplay.py index 4f311afc36..ec49d92251 100644 --- a/src/pretix/control/logdisplay.py +++ b/src/pretix/control/logdisplay.py @@ -99,6 +99,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): '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.'), + 'pretix.event.settings': _('The event settings have been changed.'), } data = json.loads(logentry.data) @@ -120,6 +121,9 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs): if logentry.action_type.startswith('pretix.event.order.changed'): return _display_order_changed(sender, logentry) + if logentry.action_type.startswith('pretix.event.payment.provider.'): + return _('The payment provider settings have been changed.') + if logentry.action_type == 'pretix.user.settings.changed': text = str(_('Your account settings have been changed.')) if 'email' in data: diff --git a/src/pretix/control/templates/pretixcontrol/event/logs.html b/src/pretix/control/templates/pretixcontrol/event/logs.html new file mode 100644 index 0000000000..d90bd9a99e --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/event/logs.html @@ -0,0 +1,31 @@ +{% extends "pretixcontrol/items/base.html" %} +{% load i18n %} +{% block title %}{% trans "Logs" %}{% endblock %} +{% block inside %} +

{% trans "Logs" %}

+ + {% include "pretixcontrol/pagination.html" %} +{% endblock %} diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 4603c4a157..eac3400d40 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -37,6 +37,7 @@ urlpatterns = [ url(r'^event/(?P[^/]+)/(?P[^/]+)/', include([ url(r'^$', dashboards.event_index, name='event.index'), url(r'^live/$', event.EventLive.as_view(), name='event.live'), + url(r'^logs/$', event.EventLog.as_view(), name='event.log'), url(r'^settings/$', event.EventUpdate.as_view(), name='event.settings'), url(r'^settings/plugins$', event.EventPlugins.as_view(), name='event.settings.plugins'), url(r'^settings/permissions$', event.EventPermissions.as_view(), name='event.settings.permissions'), diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 8d2e15015d..b04f25cc24 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -2,6 +2,7 @@ from collections import OrderedDict from django import forms from django.contrib import messages +from django.contrib.contenttypes.models import ContentType from django.core.files import File from django.core.urlresolvers import reverse from django.db import transaction @@ -10,13 +11,14 @@ from django.http import HttpResponse from django.shortcuts import redirect from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ -from django.views.generic import FormView +from django.views.generic import FormView, ListView from django.views.generic.base import TemplateView, View from django.views.generic.detail import SingleObjectMixin from pretix.base.forms import I18nModelForm from pretix.base.models import ( - CachedTicket, Event, EventPermission, Item, ItemVariation, User, + CachedTicket, Event, EventPermission, Item, ItemVariation, LogEntry, Order, + User, Voucher, ) from pretix.base.services import tickets from pretix.base.services.invoices import build_preview_invoice_pdf @@ -643,3 +645,18 @@ class EventLive(EventPermissionRequiredMixin, TemplateView): 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug }) + + +class EventLog(EventPermissionRequiredMixin, ListView): + template_name = 'pretixcontrol/event/logs.html' + model = LogEntry + context_object_name = 'logs' + paginate_by = 20 + + def get_queryset(self): + qs = self.request.event.logentry_set.all().select_related('user', 'content_type') + if not self.request.eventperm.can_view_orders: + qs = qs.exclude(content_type=ContentType.objects.get_for_model(Order)) + if not self.request.eventperm.can_view_vouchers: + qs = qs.exclude(content_type=ContentType.objects.get_for_model(Voucher)) + return qs