Publish workflow is now fully functional.
This commit is contained in:
1
TODO.txt
1
TODO.txt
@@ -14,7 +14,6 @@
|
||||
- erster teil des anmeldungshowto editierbar
|
||||
- feld 'anmeldung nicht nötig'
|
||||
- publizierendes feld für redaktionellen hinweis
|
||||
- status veröffentlicht
|
||||
- für heft: wochentage abkürzen
|
||||
- vortreffen ohne datum?
|
||||
|
||||
|
||||
@@ -134,13 +134,13 @@ class EventAcceptedMail(AbstractEventMail):
|
||||
class EventToPublishMail(AbstractEventMail):
|
||||
_template_name = 'dav_events/emails/event_to_publish.txt'
|
||||
|
||||
def __init__(self, set_published_action=None, *args, **kwargs):
|
||||
self._set_published_action = set_published_action
|
||||
def __init__(self, confirm_publication_action=None, *args, **kwargs):
|
||||
self._confirm_publication_action = confirm_publication_action
|
||||
super(EventToPublishMail, self).__init__(*args, **kwargs)
|
||||
|
||||
def _get_context_data(self, extra_context=None):
|
||||
context = super(EventToPublishMail, self)._get_context_data(extra_context=extra_context)
|
||||
context['set_published_url'] = self._set_published_action.get_absolute_url()
|
||||
context['confirm_publication_url'] = self._confirm_publication_action.get_absolute_url()
|
||||
return context
|
||||
|
||||
def _get_subject(self, **kwargs):
|
||||
|
||||
@@ -71,7 +71,7 @@ class EventUpdateForm(forms.ModelForm):
|
||||
model = models.Event
|
||||
fields = '__all__'
|
||||
exclude = ('accepted', 'accepted_at', 'accepted_by',
|
||||
'published', 'published_at', 'published_by',)
|
||||
'publication_confirmed', 'publication_confirmed_at', 'publication_confirmed_by',)
|
||||
|
||||
|
||||
class EventCreateForm(ModelMixin, ChainedForm):
|
||||
@@ -815,10 +815,10 @@ class ChargesForm(EventCreateForm):
|
||||
class SummaryForm(EventCreateForm):
|
||||
_form_title = _(u'Zusammenfassung')
|
||||
|
||||
planned_publish_date = forms.DateField(required=False,
|
||||
label=_(u'Voraussichtliche Veröffentlichung'),
|
||||
widget=forms.HiddenInput())
|
||||
planned_publish_issue = forms.CharField(required=False)
|
||||
planned_publication_date = forms.DateField(required=False,
|
||||
label=_(u'Voraussichtliche Veröffentlichung'),
|
||||
widget=forms.HiddenInput())
|
||||
planned_publication_issue = forms.CharField(required=False)
|
||||
|
||||
internal_note = forms.CharField(required=False,
|
||||
label=_(u'Bearbeitungshinweis'),
|
||||
@@ -841,10 +841,10 @@ class SummaryForm(EventCreateForm):
|
||||
deadline = None
|
||||
|
||||
if deadline:
|
||||
publish_deadline = deadline - datetime.timedelta(app_config.settings.publish_before_deadline_days)
|
||||
publication_deadline = deadline - datetime.timedelta(app_config.settings.publish_before_deadline_days)
|
||||
else:
|
||||
first_day = self._session_data.get('first_day')
|
||||
publish_deadline = first_day - datetime.timedelta(app_config.settings.publish_before_begin_days)
|
||||
publication_deadline = first_day - datetime.timedelta(app_config.settings.publish_before_begin_days)
|
||||
|
||||
today = datetime.date.today()
|
||||
|
||||
@@ -863,9 +863,9 @@ class SummaryForm(EventCreateForm):
|
||||
if issue_deadline > issue_release:
|
||||
issue_deadline = datetime.date(year - 1, issue['deadline'][1], issue['deadline'][0])
|
||||
|
||||
if publish_deadline > issue_release and today < issue_deadline:
|
||||
self.fields['planned_publish_date'].initial = issue_release
|
||||
self.fields['planned_publish_issue'].initial = u'%s/%s' % (issue['issue'], year)
|
||||
if publication_deadline > issue_release and today < issue_deadline:
|
||||
self.fields['planned_publication_date'].initial = issue_release
|
||||
self.fields['planned_publication_issue'].initial = u'%s/%s' % (issue['issue'], year)
|
||||
break_outer_loop = True
|
||||
break
|
||||
|
||||
|
||||
40
dav_events/migrations/0015_auto_20180226_1253.py
Normal file
40
dav_events/migrations/0015_auto_20180226_1253.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.9 on 2018-02-26 12:53
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dav_events', '0014_auto_20180225_1757'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='event',
|
||||
old_name='planned_publish_date',
|
||||
new_name='planned_publication_date',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='event',
|
||||
old_name='published',
|
||||
new_name='publication_confirmed',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='event',
|
||||
old_name='published_at',
|
||||
new_name='publication_confirmed_at',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='event',
|
||||
old_name='published_by',
|
||||
new_name='publication_confirmed_by',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='oneclickaction',
|
||||
name='command',
|
||||
field=models.CharField(choices=[(b'EA', b'accept event'), (b'EP', b'confirm publication of an event'), (b'EL', b'login and go to event list')], max_length=2),
|
||||
),
|
||||
]
|
||||
@@ -46,14 +46,14 @@ class Event(models.Model):
|
||||
blank=True,
|
||||
null=True,
|
||||
default=None)
|
||||
published = models.BooleanField(default=False)
|
||||
published_at = models.DateTimeField(blank=True,
|
||||
null=True)
|
||||
published_by = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.SET(get_ghost_user),
|
||||
related_name='+')
|
||||
publication_confirmed = models.BooleanField(default=False)
|
||||
publication_confirmed_at = models.DateTimeField(blank=True,
|
||||
null=True)
|
||||
publication_confirmed_by = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.SET(get_ghost_user),
|
||||
related_name='+')
|
||||
|
||||
# DescriptionForm
|
||||
title = models.CharField(max_length=config.TITLE_MAX_LENGTH)
|
||||
@@ -163,8 +163,8 @@ class Event(models.Model):
|
||||
blank=True)
|
||||
|
||||
# SummaryForm
|
||||
planned_publish_date = models.DateField(blank=True,
|
||||
null=True)
|
||||
planned_publication_date = models.DateField(blank=True,
|
||||
null=True)
|
||||
internal_note = models.TextField(blank=True)
|
||||
|
||||
class Meta:
|
||||
@@ -235,7 +235,7 @@ class Event(models.Model):
|
||||
action = OneClickAction(command='EP')
|
||||
action.parameters = '{event},{user}'.format(event=self.id, user=user.id)
|
||||
action.save()
|
||||
email = emails.EventToPublishMail(recipient=user, event=self, set_published_action=action)
|
||||
email = emails.EventToPublishMail(recipient=user, event=self, confirm_publication_action=action)
|
||||
email.send()
|
||||
|
||||
email = emails.EventAcceptedMail(recipient=self.owner, event=self)
|
||||
@@ -245,35 +245,37 @@ class Event(models.Model):
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_published(self, user=None):
|
||||
def confirm_publication(self, user=None):
|
||||
if not self.accepted:
|
||||
logger.warning('Event.set_published(): event is not accepted yet! (Event: %s)', self.event)
|
||||
logger.warning('Event.confirm_publication(): event is not accepted yet! (Event: %s)', self.event)
|
||||
|
||||
if not self.published:
|
||||
self.published = True
|
||||
self.published_at = timezone.now()
|
||||
if not self.publication_confirmed:
|
||||
self.publication_confirmed = True
|
||||
self.publication_confirmed_at = timezone.now()
|
||||
if user:
|
||||
self.published_by = user
|
||||
self.publication_confirmed_by = user
|
||||
else:
|
||||
logger.warning('Event.set_published(): no user given! (Event: %s)', self.event)
|
||||
logger.warning('Event.confirm_publication(): no user given! (Event: %s)', self.event)
|
||||
self.save()
|
||||
logger.info('Event is published: %s', self)
|
||||
|
||||
def get_status(self):
|
||||
now = datetime.date.today()
|
||||
today = datetime.date.today()
|
||||
if self.alt_last_day:
|
||||
if self.alt_last_day < now:
|
||||
if self.alt_last_day < today:
|
||||
return 'expired'
|
||||
elif self.last_day:
|
||||
if self.last_day < now:
|
||||
if self.last_day < today:
|
||||
return 'expired'
|
||||
elif self.alt_first_day:
|
||||
if self.alt_first_day < now:
|
||||
if self.alt_first_day < today:
|
||||
return 'expired'
|
||||
elif self.first_day and self.first_day < now:
|
||||
elif self.first_day and self.first_day < today:
|
||||
return 'expired'
|
||||
|
||||
if self.published:
|
||||
if self.publication_confirmed and self.planned_publication_date and self.planned_publication_date > today:
|
||||
return 'publishing'
|
||||
elif self.publication_confirmed:
|
||||
return 'published'
|
||||
elif self.accepted:
|
||||
return 'accepted'
|
||||
@@ -413,7 +415,7 @@ class Event(models.Model):
|
||||
'trainer_3_email': self.trainer_3_email,
|
||||
'trainer_3_phone': self.trainer_3_phone,
|
||||
'registration_howto': self.registration_howto,
|
||||
'planned_publish_date': self.planned_publish_date,
|
||||
'planned_publication_date': self.planned_publication_date,
|
||||
'internal_note': self.internal_note,
|
||||
}
|
||||
return context
|
||||
@@ -432,7 +434,7 @@ class Event(models.Model):
|
||||
class OneClickAction(models.Model):
|
||||
COMMANDS = (
|
||||
('EA', 'accept event'),
|
||||
('EP', 'report publishing of an event'),
|
||||
('EP', 'confirm publication of an event'),
|
||||
('EL', 'login and go to event list')
|
||||
)
|
||||
|
||||
@@ -512,16 +514,16 @@ class OneClickAction(models.Model):
|
||||
event_id, user_id = self.parameters.split(',')
|
||||
event = Event.objects.get(id=event_id)
|
||||
user = get_user_model().objects.get(id=user_id)
|
||||
if event.published:
|
||||
if event.publication_confirmed:
|
||||
status = 'info'
|
||||
message = (ugettext(u'Veröffentlichung wurde bereits von %(fullname)s bestätigt.') %
|
||||
{'fullname': event.published_by.get_full_name()})
|
||||
{'fullname': event.publication_confirmed_by.get_full_name()})
|
||||
text = unicode(event)
|
||||
text += u'\n'
|
||||
text += (ugettext(u'Bestätigt am: %(date)s') %
|
||||
{'date': event.published_at.strftime('%d.%m.%Y %H:%M:%S')})
|
||||
{'date': event.publication_confirmed_at.strftime('%d.%m.%Y %H:%M:%S')})
|
||||
else:
|
||||
event.set_published(user)
|
||||
event.confirm_publication(user)
|
||||
status = 'success'
|
||||
message = ugettext(u'Veröffentlichung registriert.')
|
||||
text = unicode(event)
|
||||
|
||||
@@ -6,6 +6,6 @@ Die Redaktion wurden informiert, um deine Veranstaltung zu veröffentlichen.
|
||||
Link zur Veranstaltung:
|
||||
{{ base_url }}{{ event.get_absolute_url }}
|
||||
|
||||
Voraussichtliche Veröffentlichung: {% if planned_publish_date %}{{ planned_publish_date|date:'l, d. F Y' }}{% else %}In wenigen Tagen{% endif %}
|
||||
Voraussichtliche Veröffentlichung: {% if planned_publication_date %}{{ planned_publication_date|date:'l, d. F Y' }}{% else %}In wenigen Tagen{% endif %}
|
||||
-----
|
||||
{{ event.render_as_text }}-----
|
||||
|
||||
@@ -7,7 +7,7 @@ Der folgende Link führt zur Veranstaltung:
|
||||
Über den folgenden Link kannst du die Veranstaltung unmittelbar freigeben:
|
||||
{{ base_url }}{{ accept_url }}
|
||||
|
||||
Veröffentlichung: {% if planned_publish_date %}{{ planned_publish_date|date:'l, d. F Y' }}{% else %}sofort{% endif %}
|
||||
Veröffentlichung: {% if planned_publication_date %}{{ planned_publication_date|date:'l, d. F Y' }}{% else %}sofort{% endif %}
|
||||
{% if internal_note %}Bearbeitungshinweis:
|
||||
{{ internal_note }}
|
||||
{% endif %}-----
|
||||
|
||||
@@ -6,9 +6,9 @@ Die Veranstaltung wurde {% if event.accepted_by %}von {{ event.accepted_by.get_f
|
||||
Der folgende Link führt zur Veranstaltung:
|
||||
{{ base_url }}{{ event.get_absolute_url }}
|
||||
Über den folgenden Link kannst du die Veröffentlichung unmittelbar bestätigen:
|
||||
{{ base_url }}{{ set_published_url }}
|
||||
{{ base_url }}{{ confirm_publication_url }}
|
||||
|
||||
Veröffentlichung: {% if planned_publish_date %}{{ planned_publish_date|date:'l, d. F Y' }}{% else %}sofort{% endif %}
|
||||
Veröffentlichung: {% if planned_publication_date %}{{ planned_publication_date|date:'l, d. F Y' }}{% else %}sofort{% endif %}
|
||||
{% if internal_note %}Bearbeitungshinweis:
|
||||
{{ internal_note }}
|
||||
{% endif %}----- Plain Text -----
|
||||
|
||||
@@ -6,7 +6,7 @@ Die entsprechenden Referenten wurden informiert, um deine Veranstaltung frei zu
|
||||
Link zur Veranstaltung:
|
||||
{{ base_url }}{{ event.get_absolute_url }}
|
||||
|
||||
Voraussichtliche Veröffentlichung: {% if planned_publish_date %}{{ planned_publish_date|date:'l, d. F Y' }}{% else %}In wenigen Tagen{% endif %}
|
||||
Voraussichtliche Veröffentlichung: {% if planned_publication_date %}{{ planned_publication_date|date:'l, d. F Y' }}{% else %}In wenigen Tagen{% endif %}
|
||||
-----
|
||||
{{ event.render_as_text }}-----
|
||||
{% if internal_note %}Bearbeitungshinweis:
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
<span class="label label-info">{% trans 'Ausgelaufen' %}</span>
|
||||
{% elif status == 'published' %}
|
||||
<span class="label label-success">{% trans 'Veröffentlicht' %}</span>
|
||||
{% elif status == 'publishing' %}
|
||||
<span class="label label-warning">{% trans 'Veröffentlichung' %}: {{ event.planned_publication_date|date:'d.m.Y' }}</span>
|
||||
{% elif status == 'accepted' %}
|
||||
<span class="label label-warning">{% trans 'Freigegeben' %}</span>
|
||||
{% elif status == 'submitted' %}
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<div class="col-sm-4">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<label>{{ form.planned_publish_date.label }}</label>
|
||||
{% if form.planned_publish_date.value %}
|
||||
<p>{{ form.planned_publish_date.value|date:'l, d. F Y' }} ({{ form.planned_publish_issue.value }})</p>
|
||||
<label>{{ form.planned_publication_date.label }}</label>
|
||||
{% if form.planned_publication_date.value %}
|
||||
<p>{{ form.planned_publication_date.value|date:'l, d. F Y' }} ({{ form.planned_publication_issue.value }})</p>
|
||||
{% else %}
|
||||
<p>{% trans 'In wenigen Tagen' %}</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="modal-setpublished-dialog" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div id="modal-confirmpublication-dialog" class="modal fade" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -43,7 +43,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn btn-success" href="{% url 'dav_events:event_setpublished' event.pk %}">
|
||||
<a class="btn btn-success" href="{% url 'dav_events:event_confirmpublication' event.pk %}">
|
||||
{% bootstrap_icon 'ok' %} 
|
||||
{% trans 'Ja' %}
|
||||
</a>
|
||||
@@ -81,8 +81,8 @@
|
||||
{% endif %}
|
||||
{% if has_permission_publish %}
|
||||
<a class="btn {% if event.get_status == 'accepted' %}btn-success{% else %}btn-default disabled{% endif %}"
|
||||
data-toggle="modal" data-target="#modal-setpublished-dialog">
|
||||
{% if event.published %}
|
||||
data-toggle="modal" data-target="#modal-confirmpublication-dialog">
|
||||
{% if event.publication_confirmed %}
|
||||
{% bootstrap_icon 'check' %} 
|
||||
{% else %}
|
||||
{% bootstrap_icon 'unchecked' %} 
|
||||
@@ -144,7 +144,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
{% if event.published %}
|
||||
{% if event.publication_confirmed %}
|
||||
<span class="text-success">{% bootstrap_icon 'check' %}</span>
|
||||
{% else %}
|
||||
{% bootstrap_icon 'unchecked' %}
|
||||
@@ -152,9 +152,9 @@
|
||||
 <strong>{% trans 'Veröffentlicht' %}:</strong>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
{% if event.published %}
|
||||
{{ event.published_at|date:'l, d. F Y, H:i' }} {% trans 'Uhr' %}<br />
|
||||
{% trans 'von' %} {{ event.published_by.get_full_name }}
|
||||
{% if event.publication_confirmed %}
|
||||
{{ event.publication_confirmed_at|date:'l, d. F Y, H:i' }} {% trans 'Uhr' %}<br />
|
||||
{% trans 'von' %} {{ event.publication_confirmed_by.get_full_name }}
|
||||
{% else %}
|
||||
<br /><br />
|
||||
{% endif %}
|
||||
@@ -163,8 +163,8 @@
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<strong>{% trans 'Veröffentlichen' %}</strong><br />
|
||||
{% if event.planned_publish_date %}
|
||||
{{ event.planned_publish_date|date:'l, d. F Y' }}
|
||||
{% if event.planned_publication_date %}
|
||||
{{ event.planned_publication_date|date:'l, d. F Y' }}
|
||||
{% else %}
|
||||
{% trans 'Unverzüglich' %}
|
||||
{% endif %}
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
<span class="label label-info">{% trans 'Ausgelaufen' %}</span>
|
||||
{% elif event.get_status == 'published' %}
|
||||
<span class="label label-success">{% trans 'Veröffentlicht' %}</span>
|
||||
{% elif event.get_status == 'publishing' %}
|
||||
<span class="label label-warning">{% trans 'Veröffentlichung' %}: {{ event.planned_publication_date|date:'d.m.Y' }}</span>
|
||||
{% elif event.get_status == 'accepted' %}
|
||||
<span class="label label-warning">{% trans 'Freigegeben' %}</span>
|
||||
{% elif event.get_status == 'submitted' %}
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
{% trans 'Diese Veranstaltung ist bereits ausgelaufen.' %}
|
||||
</div>
|
||||
{% elif event.get_status == 'published' %}
|
||||
{% elif event.get_status == 'published' or event.get_status == 'publishing' %}
|
||||
<div class="alert alert-danger alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<strong>{% trans 'Achtung!' %}</strong> {% trans 'Diese Veranstaltung wurde bereits veröffentlicht.' %}
|
||||
<strong>{% trans 'Achtung!' %}</strong> {% trans 'Diese Veranstaltung wird/wurde bereits veröffentlicht.' %}
|
||||
{% trans 'Änderungen müssen mit allen Beteiligten abgesprochen werden.' %}
|
||||
</div>
|
||||
{% elif event.get_status == 'accepted' %}
|
||||
|
||||
@@ -11,7 +11,8 @@ urlpatterns = [
|
||||
url(r'^events/create$', views.events.EventCreateView.as_view(), name='event_create'),
|
||||
url(r'^events/export$', views.events.EventListExportView.as_view(), name='event_list_export'),
|
||||
url(r'^events/(?P<pk>\d+)/accept', views.events.EventAcceptView.as_view(), name='event_accept'),
|
||||
url(r'^events/(?P<pk>\d+)/setpublished', views.events.EventSetPublishedView.as_view(), name='event_setpublished'),
|
||||
url(r'^events/(?P<pk>\d+)/confirmpublication',
|
||||
views.events.EventConfirmPublicationView.as_view(), name='event_confirmpublication'),
|
||||
url(r'^events/(?P<pk>\d+)/edit', views.events.EventUpdateView.as_view(), name='event_update'),
|
||||
url(r'^events/(?P<pk>\d+)/', views.events.EventDetailView.as_view(), name='event_detail'),
|
||||
url(r'^action/(?P<pk>[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})/',
|
||||
|
||||
@@ -127,7 +127,7 @@ class EventPermissionMixin(object):
|
||||
if has_role(user, 'manage_{}'.format(obj.sport.lower())):
|
||||
return True
|
||||
elif permission == 'update':
|
||||
if not obj.accepted and not obj.published:
|
||||
if not obj.accepted and not obj.publication_confirmed:
|
||||
if has_role(user, 'manage_all'):
|
||||
return True
|
||||
if has_role(user, 'manage_{}'.format(obj.sport.lower())):
|
||||
@@ -177,13 +177,13 @@ class EventAcceptView(EventDetailView):
|
||||
return HttpResponseRedirect(event.get_absolute_url())
|
||||
|
||||
|
||||
class EventSetPublishedView(EventDetailView):
|
||||
class EventConfirmPublicationView(EventDetailView):
|
||||
permission = 'publish'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
event = self.get_object()
|
||||
if event.accepted:
|
||||
event.set_published(request.user)
|
||||
event.confirm_publication(request.user)
|
||||
messages.success(request, _(u'Veröffentlichung registriert.'))
|
||||
else:
|
||||
messages.error(request, _(u'Veranstaltung ist noch nicht freigegeben.'))
|
||||
|
||||
Reference in New Issue
Block a user