FIX #35 and #36: add new event stati canceled and realized
Some checks failed
buildbot/tox Build done.

This commit is contained in:
2021-01-07 12:52:21 +01:00
parent 642971e469
commit 269d59f460
10 changed files with 164 additions and 8 deletions

View File

@@ -39,8 +39,10 @@
<div class="pull-right">
{% if not event.registration_required %}
<span class="label label-success">{% trans 'Anmeldung nicht erforderlich' %}</span>
{% elif is_done %}
<span class="label label-default">{% trans 'Veranstaltung beendet' %}</span>
{% elif is_canceled %}
<span class="label label-dav-mandarin">{% trans 'Veranstaltung abgesagt' %}</span>
{% elif is_realized or is_expired %}
<span class="label label-dav-lime">{% trans 'Veranstaltung beendet' %}</span>
{% elif event.registration_closed %}
<span class="label label-danger">{% trans 'Anmeldung geschlossen' %}</span>
{% elif event.is_deadline_expired %}

View File

@@ -115,3 +115,19 @@ class EventRegistrationClosedMail(AbstractEventMail):
context = super(EventRegistrationClosedMail, self)._get_context_data(extra_context=extra_context)
context['editor'] = self._editor
return context
class EventCanceledMail(AbstractEventMail):
_subject = u'Veranstaltung abgesagt'
_template_name = 'dav_events/emails/event_canceled.txt'
def __init__(self, editor=None, *args, **kwargs):
self._editor = editor
super(EventCanceledMail, self).__init__(*args, **kwargs)
def _get_context_data(self, extra_context=None):
context = super(EventCanceledMail, self)._get_context_data(extra_context=extra_context)
context['editor'] = self._editor
return context

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2021-01-07 11:20
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dav_events', '0040_auto_20201216_1712'),
]
operations = [
migrations.AlterField(
model_name='eventstatus',
name='bootstrap_context',
field=models.CharField(blank=True, choices=[('default', 'default'), ('primary', 'primary'), ('success', 'success'), ('info', 'info'), ('warning', 'warning'), ('danger', 'danger'), ('black', 'black'), ('dav-purple', 'dav-purple'), ('dav-lime', 'dav-lime'), ('dav-cyan', 'dav-cyan'), ('dav-caramel', 'dav-caramel'), ('dav-mandarin', 'dav-mandarin'), ('dav-brown', 'dav-brown')], max_length=20),
),
]

View File

@@ -13,6 +13,12 @@ BOOTSTRAP_CONTEXT_CHOICES = (
('warning', 'warning'),
('danger', 'danger'),
('black', 'black'),
('dav-purple', 'dav-purple'),
('dav-lime', 'dav-lime'),
('dav-cyan', 'dav-cyan'),
('dav-caramel', 'dav-caramel'),
('dav-mandarin', 'dav-mandarin'),
('dav-brown', 'dav-brown'),
)

View File

@@ -0,0 +1,14 @@
Hallo {{ recipient.first_name }},
{{ editor.get_full_name|default:'Jemand' }} hat die folgende Veranstaltung abgesagt:
{{ event }}
Link zur Veranstaltung:
{{ base_url }}{{ event.get_absolute_url }}
Ausschreibung:
==============
{{ event.render_as_text }}{% if internal_note %}
Bearbeitungshinweis:
====================
{{ internal_note }}{% endif %}

View File

@@ -146,6 +146,28 @@
{% trans 'Veröffentlichung bestätigen' %}
</a>
{% endif %}
{% if has_permission_realize and is_started and not is_canceled %}
<a id="btn-realize" class="btn btn-sm {% if not is_realized %}btn-dav-lime{% else %}btn-default disabled{% endif %}"
href="{% url 'dav_events:updatestatus' event.pk 'realized' %}">
{% if is_realized %}
{% bootstrap_icon 'check' %}&thinsp;
{% else %}
{% bootstrap_icon 'unchecked' %}&thinsp;
{% endif %}
{% trans 'Durchgeführt' %}
</a>
{% endif %}
{% if has_permission_cancel and is_submitted and not is_realized %}
<a id="btn-cancel" class="btn btn-sm {% if not is_canceled %}btn-dav-mandarin{% else %}btn-default disabled{% endif %}"
href="{% url 'dav_events:updatestatus' event.pk 'canceled' %}">
{% if is_canceled %}
{% bootstrap_icon 'check' %}&thinsp;
{% else %}
{% bootstrap_icon 'unchecked' %}&thinsp;
{% endif %}
{% trans 'Abgesagt' %}
</a>
{% endif %}
{% if has_permission_clear %}
<a id="btn-confirmclearance" class="btn btn-sm {% if not is_cleared %}btn-black{% else %}btn-default disabled{% endif %}"
href="{% url 'dav_events:updatestatus' event.pk 'cleared' %}">

View File

@@ -182,8 +182,10 @@
<strong>{% trans 'Anmeldestatus' %}:</strong>
{% if not event.registration_required %}
<span class="label label-success">{% trans 'Anmeldung nicht erforderlich' %}</span>
{% elif is_done %}
<span class="label label-default">{% trans 'Veranstaltung beendet' %}</span>
{% elif is_canceled %}
<span class="label label-dav-mandarin">{% trans 'Veranstaltung abgesagt' %}</span>
{% elif is_realized or is_expired %}
<span class="label label-dav-lime">{% trans 'Veranstaltung beendet' %}</span>
{% elif event.registration_closed %}
<span class="label label-danger">{% trans 'Anmeldung geschlossen' %}</span>
{% elif event.is_deadline_expired %}

View File

@@ -54,7 +54,17 @@
<form action="" method="post">
{% csrf_token %}
{% if is_expired %}
{% if is_realized %}
<div class="alert alert-info alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% trans 'Diese Veranstaltung wurde bereits durchgeführt.' %}
</div>
{% elif is_canceled %}
<div class="alert alert-info alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% trans 'Diese Veranstaltung ist abgesagt.' %}
</div>
{% elif is_expired %}
<div class="alert alert-info alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% trans 'Diese Veranstaltung ist bereits ausgelaufen.' %}

View File

@@ -151,6 +151,8 @@ class EventDetailView(EventPermissionMixin, generic.DetailView):
context['has_permission_submit'] = self.has_permission('submit', obj)
context['has_permission_accept'] = self.has_permission('accept', obj)
context['has_permission_publish'] = self.has_permission('publish', obj)
context['has_permission_cancel'] = self.has_permission('cancel', obj)
context['has_permission_realize'] = self.has_permission('realize', obj)
context['has_permission_clear'] = self.has_permission('clear', obj)
context['has_permission_update'] = self.has_permission('update', obj)
context['is_submitted'] = obj.workflow.has_reached_status('submitted')
@@ -159,6 +161,10 @@ class EventDetailView(EventPermissionMixin, generic.DetailView):
context['is_publishing_any'] = obj.workflow.has_reached_status('publishing*')
context['is_published'] = obj.workflow.has_reached_status('published')
context['is_published_any'] = obj.workflow.has_reached_status('published*')
context['is_started'] = obj.first_day <= datetime.date.today()
context['is_expired'] = obj.workflow.has_reached_status('expired')
context['is_canceled'] = obj.workflow.has_reached_status('canceled')
context['is_realized'] = obj.workflow.has_reached_status('realized')
context['is_cleared'] = obj.workflow.has_reached_status('cleared')
return context
@@ -212,7 +218,9 @@ class EventRegistrationsView(EventPermissionMixin, generic.DetailView):
context['has_permission_update_participants'] = self.has_permission('update-participants', event)
context['has_permission_payment'] = self.has_permission('payment', event)
context['is_published_any'] = event.workflow.has_reached_status('published*')
context['is_done'] = event.workflow.has_reached_status('expired')
context['is_expired'] = event.workflow.has_reached_status('expired')
context['is_canceled'] = event.workflow.has_reached_status('canceled')
context['is_realized'] = event.workflow.has_reached_status('realized')
participants = event.participants.all()
context['participants'] = participants
@@ -527,6 +535,12 @@ class EventUpdateStatusView(EventPermissionMixin, generic.DetailView):
elif status.startswith('publish'):
if not self.has_permission('publish', event):
raise PermissionDenied(status)
elif status.startswith('cancel'):
if not self.has_permission('cancel', event):
raise PermissionDenied(status)
elif status.startswith('realize'):
if not self.has_permission('realize', event):
raise PermissionDenied(status)
elif status.startswith('clear'):
if not self.has_permission('clear', event):
raise PermissionDenied(status)
@@ -540,6 +554,10 @@ class EventUpdateStatusView(EventPermissionMixin, generic.DetailView):
message = _(u'Veranstaltung ist noch nicht eingereicht.')
elif return_code == 'not-accepted':
message = _(u'Veranstaltung ist noch nicht freigegeben.')
elif return_code == 'already-realized':
message = _(u'Veranstaltung wurde bereits durchgeführt.')
elif return_code == 'not-started':
message = _(u'Veranstaltung hat noch nicht begonnen.')
messages.error(request, message)
return HttpResponseRedirect(event.get_absolute_url())
@@ -563,6 +581,10 @@ class EventUpdateStatusView(EventPermissionMixin, generic.DetailView):
messages.success(request, _(u'Veranstaltung freigegeben.'))
elif status.startswith('publish'):
messages.success(request, _(u'Veröffentlichung registriert.'))
elif status.startswith('cancel'):
messages.success(request, _(u'Absage vermerkt.'))
elif status.startswith('realize'):
messages.success(request, _(u'Durchführung vermerkt.'))
elif status.startswith('clear'):
messages.success(request, _(u'Abrechnung vermerkt.'))
else:
@@ -600,10 +622,12 @@ class EventUpdateView(EventPermissionMixin, generic.UpdateView):
context['has_permission_accept'] = self.has_permission('accept', obj)
context['has_permission_update'] = self.has_permission('update', obj)
context['has_permission_publish'] = self.has_permission('publish', obj)
context['is_expired'] = obj.workflow.has_reached_status('expired')
context['is_accepted'] = obj.workflow.has_reached_status('accepted')
context['is_publishing'] = obj.workflow.has_reached_status('publishing')
context['is_publishing_any'] = obj.workflow.has_reached_status('publishing*')
context['is_accepted'] = obj.workflow.has_reached_status('accepted')
context['is_expired'] = obj.workflow.has_reached_status('expired')
context['is_canceled'] = obj.workflow.has_reached_status('canceled')
context['is_realized'] = obj.workflow.has_reached_status('realized')
if 'form' in kwargs and kwargs['form'].errors:
context['decollapseAllForms'] = True

View File

@@ -31,6 +31,8 @@ DEFAULT_EVENT_STATI = {
'published_web': (79, _(u'Veröffentlicht (Web)'), 'success'),
'published': (80, _(u'Veröffentlicht'), 'success'),
'expired': (100, _(u'Ausgelaufen'), None),
'canceled': (101, _(u'Abgesagt'), 'dav-mandarin'),
'realized': (102, _(u'Durchgeführt'), 'dav-lime'),
'cleared': (110, _(u'Abgerechnet'), 'black'),
}
@@ -216,6 +218,24 @@ class BasicWorkflow(object):
valid = False
return_code = 'not-accepted'
message = u'Event is not accepted.'
elif code.startswith('cancel'):
if not self.has_reached_status('submitted'):
valid = False
return_code = 'not-submitted'
message = u'Event is not submitted.'
elif self.has_reached_status('realized'):
valid = False
return_code = 'already-realized'
message = u'Event was already realized.'
elif code.startswith('realize'):
if event.first_day <= today:
valid = False
return_code = 'not-started'
message = u'Event has not begun.'
elif not self.has_reached_status('accepted'):
valid = False
return_code = 'not-accepted'
message = u'Event is not accepted.'
if callback is not None:
callback(valid, return_code, message, *args, **kwargs)
@@ -400,6 +420,16 @@ class BasicWorkflow(object):
email = emails.EventToPublishFacebookMail(recipient=recipient, event=event, editor=updater,
confirm_publication_action=action)
email.send()
elif flag.status.code == 'canceled':
# Who should be informed about the cancelation?
recipients = [event.owner]
recipients += get_users_by_role('manager_super')
recipients += get_users_by_role('office')
for recipient in recipients:
if recipient.email and recipient.email != updater.email:
email = emails.EventCanceledMail(recipient=recipient, event=event, editor=updater)
email.send()
#
# Permissions
@@ -432,6 +462,16 @@ class BasicWorkflow(object):
elif permission == 'publish':
if has_role(user, 'publisher'):
return True
elif permission == 'cancel':
if user == event.owner:
return True
if has_role(user, 'manager_super'):
return True
if has_role(user, 'office'):
return True
elif permission == 'realize':
if user == event.owner:
return True
elif permission == 'clear':
if has_role(user, 'manager_super'):
return True