diff --git a/doc/development/api/general.rst b/doc/development/api/general.rst index 3ae3021679..1b23ffd240 100644 --- a/doc/development/api/general.rst +++ b/doc/development/api/general.rst @@ -51,7 +51,7 @@ Backend .. automodule:: pretix.base.signals - :members: logentry_display + :members: logentry_display, requiredaction_display Vouchers """""""" diff --git a/doc/development/implementation/models.rst b/doc/development/implementation/models.rst index b9b1874871..bda59b9cb8 100644 --- a/doc/development/implementation/models.rst +++ b/doc/development/implementation/models.rst @@ -29,6 +29,9 @@ Organizers and events .. autoclass:: pretix.base.models.EventPermission :members: +.. autoclass:: pretix.base.models.RequiredAction + :members: + Items ----- diff --git a/src/pretix/base/migrations/0053_auto_20170104_1252.py b/src/pretix/base/migrations/0053_auto_20170104_1252.py new file mode 100644 index 0000000000..67f0fd2244 --- /dev/null +++ b/src/pretix/base/migrations/0053_auto_20170104_1252.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2017-01-04 12:52 +from __future__ import unicode_literals + +import django.core.validators +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + +import pretix.base.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0052_auto_20161231_1533'), + ] + + operations = [ + migrations.CreateModel( + name='RequiredAction', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('datetime', models.DateTimeField(auto_now_add=True, db_index=True)), + ('done', models.BooleanField(default=False)), + ('action_type', models.CharField(max_length=255)), + ('data', models.TextField(default='{}')), + ], + options={ + 'ordering': ('datetime',), + }, + ), + migrations.AlterField( + model_name='event', + name='slug', + field=models.SlugField(help_text='Should be short, only contain lowercase letters and numbers, and must be unique among your events. This will be used in order codes, invoice numbers, links and bank transfer references.', validators=[django.core.validators.RegexValidator(message='The slug may only contain letters, numbers, dots and dashes.', regex='^[a-zA-Z0-9.-]+$'), pretix.base.validators.EventSlugBlacklistValidator()], verbose_name='Short form'), + ), + migrations.AddField( + model_name='requiredaction', + name='event', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pretixbase.Event'), + ), + migrations.AddField( + model_name='requiredaction', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/src/pretix/base/models/__init__.py b/src/pretix/base/models/__init__.py index d980f55df2..5e8e722538 100644 --- a/src/pretix/base/models/__init__.py +++ b/src/pretix/base/models/__init__.py @@ -1,7 +1,9 @@ from .auth import U2FDevice, User from .base import CachedFile, LoggedModel, cachedfile_name from .checkin import Checkin -from .event import Event, EventLock, EventPermission, EventSetting +from .event import ( + Event, EventLock, EventPermission, EventSetting, RequiredAction, +) from .invoices import Invoice, InvoiceLine, invoice_filename from .items import ( Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota, diff --git a/src/pretix/base/models/event.py b/src/pretix/base/models/event.py index 6cf56ce223..7cb28195cf 100644 --- a/src/pretix/base/models/event.py +++ b/src/pretix/base/models/event.py @@ -359,3 +359,42 @@ class EventLock(models.Model): event = models.CharField(max_length=36, primary_key=True) date = models.DateTimeField(auto_now=True) token = models.UUIDField(default=uuid.uuid4) + + +class RequiredAction(models.Model): + """ + Represents an action that is to be done by an admin. The admin will be + displayed a list of actions to do. + + :param datatime: The timestamp of the required action + :type datetime: datetime + :param user: The user that performed the action + :type user: User + :param done: If this action has been completed or dismissed + :type done: bool + :param action_type: The type of action that has to be performed. This is + used to look up the renderer used to describe the action in a human- + readable way. This should be some namespaced value using dotted + notation to avoid duplicates, e.g. + ``"pretix.plugins.banktransfer.incoming_transfer"``. + :type action_type: str + :param data: Arbitrary data that can be used by the log action renderer + :type data: str + """ + datetime = models.DateTimeField(auto_now_add=True, db_index=True) + done = models.BooleanField(default=False) + user = models.ForeignKey('User', null=True, blank=True, on_delete=models.PROTECT) + 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, request): + from ..signals import requiredaction_display + + for receiver, response in requiredaction_display.send(self.event, action=self, request=request): + if response: + return response + return self.action_type diff --git a/src/pretix/base/signals.py b/src/pretix/base/signals.py index ba2b4d2c2c..715751fa09 100644 --- a/src/pretix/base/signals.py +++ b/src/pretix/base/signals.py @@ -110,7 +110,21 @@ To display an instance of the ``LogEntry`` model to a human user, ``pretix.base.signals.logentry_display`` will be sent out with a ``logentry`` argument. The first received response that is not ``None`` will be used to display the log entry -to the user. +to the user. The receivers are expected to return plain text. + +As with all event-plugin signals, the ``sender`` keyword argument will contain the event. +""" + +requiredaction_display = EventPluginSignal( + providing_args=["action", "request"] +) +""" +To display an instance of the ``RequiredAction`` model to a human user, +``pretix.base.signals.requiredaction_display`` will be sent out with a ``action`` argument. +You will also get the current ``request`` in a different argument. + +The first received response that is not ``None`` will be used to display the log entry +to the user. The receivers are expected to return HTML code. As with all event-plugin signals, the ``sender`` keyword argument will contain the event. """ diff --git a/src/pretix/control/templates/pretixcontrol/event/actions.html b/src/pretix/control/templates/pretixcontrol/event/actions.html new file mode 100644 index 0000000000..86a1714be6 --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/event/actions.html @@ -0,0 +1,25 @@ +{% extends "pretixcontrol/items/base.html" %} +{% load i18n %} +{% block title %}{% trans "Current issues" %}{% endblock %} +{% block inside %} +
+ + {% trans "Hide message" %} + + {{ action.datetime|date:"SHORT_DATETIME_FORMAT" }} +
+ {{ action.display|safe }} ++ + {% trans "Hide message" %} + + {{ action.datetime|date:"SHORT_DATETIME_FORMAT" }} +
+ {{ action.display|safe }} +