CONT: continue the previous change.

This commit is contained in:
2019-01-29 17:25:03 +01:00
parent e6a5f9818a
commit 7667277862
14 changed files with 281 additions and 252 deletions

View File

@@ -1,50 +1,72 @@
# -*- coding: utf-8 -*-
import datetime
import logging
import re
from django.apps import apps
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from . import emails
from . import signals
from .utils import get_users_by_role, has_role
logger = logging.getLogger(__name__)
today = datetime.date.today()
DEFAULT_EVENT_STATI = {
'void': (0, _(u'Ungültig'), None),
'draft': (10, _(u'Entwurf'), 'info'),
'submitted': (30, _(u'Eingereicht'), 'danger'),
'accepted': (50, _(u'Freigegeben'), 'warning'),
'publishing_facebook': (68, _(u'Veröffentlichung Facebook am {planned_publication_date}'), 'warning'),
'publishing_web': (69, _(u'Veröffentlichung Web am {planned_publication_date}'), 'warning'),
'publishing': (70, _(u'Veröffentlichung am {planned_publication_date}'), 'warning'),
'published_facebook': (78, _(u'Veröffentlicht Facebook'), 'success'),
'published_web': (79, _(u'Veröffentlicht Web'), 'success'),
'published': (80, _(u'Veröffentlicht'), 'success'),
'expired': (100, _(u'Ausgelaufen'), None),
}
class BasicWorkflow(object):
#
# Status updates
#
@classmethod
def validate_status_code_update(cls, code, event, callback=None, *args, **kwargs):
valid = True
return_code = 'OK'
message = u'OK'
if code.startswith('accept'):
if not event.is_flagged('submitted'):
valid = False
return_code = 'not-submitted'
message = u'Event is not submitted.'
elif code.startswith('publishing'):
if not event.is_flagged('accepted'):
valid = False
return_code = 'not-accepted'
message = u'Event is not accepted.'
elif code.startswith('published'):
if event.planned_publication_date and event.planned_publication_date > today:
valid = False
return_code = 'not-due'
message = u'Event is not due to publication.'
elif not event.is_flagged('accepted'):
valid = False
return_code = 'not-accepted'
message = u'Event is not accepted.'
def __init__(self, event=None):
self._event = event
if callback is not None:
callback(valid, return_code, message, *args, **kwargs)
return valid, return_code, message
#
# Status
#
def get_number(self):
event = self._event
if event.number and event.flags.filter(status__code='accepted').exists():
return event.number
else:
return '%s**/%d' % (event.sport, event.first_day.year % 100)
@classmethod
def status_code_update(cls, event, code=None):
def set_number(self):
event = self._event
counter = 0
year = event.first_day.year
year_begin = datetime.date(year, 1, 1)
year_end = datetime.date(year, 12, 31)
qs = event.objects.filter(number__isnull=False,
sport=event.sport,
first_day__gte=year_begin,
first_day__lte=year_end).order_by('number')
last = qs.last()
if last:
match = re.match(r'^(?P<sport>[A-Z])(?P<count>[0-9][0-9]*)/(?P<year>[0-9][0-9]*)', last.number)
if match:
gd = match.groupdict()
counter = int(gd['count'])
counter += 1
event.number = '%s%02d/%d' % (event.sport, counter, year % 100)
event.save(implicit_update=True)
return event.number
def check_status(self, code=None):
event = self._event
if not event.id:
return
@@ -60,7 +82,7 @@ class BasicWorkflow(object):
# Check if event with accepted flag has a number.
if event.flags.filter(status__code='accepted').exists():
if not event.number:
event.set_next_number()
self.set_number()
logger.info('Setting number on Event %s', event)
if code in (None,
@@ -166,36 +188,131 @@ class BasicWorkflow(object):
timestamp = timezone.make_aware(datetime.datetime.combine(expired_at, midnight))
event.set_flag(status='expired', timestamp=timestamp)
@classmethod
def get_status_flags(cls, event):
cls.status_code_update(event)
last_flag = event.flags.last()
if not last_flag:
#last_flag = event.set_flag('void')
return []
flags = [last_flag]
last_status = last_flag.status
if last_status.code.startswith('publishing_'):
flags += event.flags.filter(status__code='accepted')
elif last_status.code.startswith('published_'):
if event.is_flagged('publishing'):
flags += event.flags.filter(status__code='publishing')
else:
flags += event.flags.filter(status__code='accepted')
return flags
@classmethod
def get_number(cls, event):
if event.number and event.flags.filter(status__code='accepted').exists():
return event.number
def has_reached_status(self, code):
self.check_status(code)
if code == 'publishing':
codes = ['publishing', 'publishing_web', 'publishing_facebook']
elif code == 'published':
codes = ['published', 'published_web', 'published_facebook']
else:
return None
codes = [code]
return self._event.flags.filter(status__code__in=codes).exists()
def validate_status_update(self, code, callback=None, *args, **kwargs):
valid = True
return_code = 'OK'
message = u'OK'
event = self._event
if code.startswith('accept'):
if not self.has_reached_status('submitted'):
valid = False
return_code = 'not-submitted'
message = u'Event is not submitted.'
elif code.startswith('publishing'):
if not self.has_reached_status('accepted'):
valid = False
return_code = 'not-accepted'
message = u'Event is not accepted.'
elif code.startswith('published'):
if event.planned_publication_date and event.planned_publication_date > today:
valid = False
return_code = 'not-due'
message = u'Event is not due to publication.'
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)
return valid, return_code, message
def update_status(self, code, user):
event = self._event
flag = event.flags.filter(status__code=code).last()
if flag:
return flag
valid, return_code, message = self.validate_status_update(code, user)
if not valid:
logger.warning(u'Invalid status update to \'%s\': %s Event: %s', code, message, event)
flag = event.set_flag(status=code, user=user)
self.check_status(code)
signals.event_status_updated.send(sender=self.__class__, event=event, flag=flag)
return flag
def get_status_list(self):
event = self._event
status_list = []
event.workflow.check_status()
last_flag = event.flags.last()
if last_flag:
flags = [last_flag]
last_status = last_flag.status
if last_status.code.startswith('publishing_'):
flags += event.flags.filter(status__code='accepted')
elif last_status.code.startswith('published_'):
if event.flags.filter(status__code='publishing').exists():
flags += event.flags.filter(status__code='publishing')
else:
flags += event.flags.filter(status__code='accepted')
for flag in flags:
format_kwargs = event.get_template_context()
label = flag.status.label.format(**format_kwargs)
flag.status.label = label
status_list.append(flag.status)
return status_list
#
# Permissions
# Permission
#
def has_permission(self, user, permission):
if user.is_superuser:
return True
event = self._event
if permission == 'view':
if user == event.owner:
return True
if has_role(user, 'manager_super'):
return True
if has_role(user, 'manager_{}'.format(event.sport.lower())):
return True
if has_role(user, 'publisher') and self.has_reached_status('accepted'):
return True
elif permission == 'submit':
if user == event.owner:
return True
elif permission == 'accept':
if has_role(user, 'manager_super'):
return True
if has_role(user, 'manager_{}'.format(event.sport.lower())):
return True
elif permission == 'publish':
if has_role(user, 'publisher'):
return True
elif permission == 'update':
if not self.has_reached_status('submitted'):
if user == event.owner:
return True
elif not self.has_reached_status('accepted'):
if has_role(user, 'manager_super'):
return True
if has_role(user, 'manager_{}'.format(event.sport.lower())):
return True
elif has_role(user, 'publisher'):
return True
return False
@classmethod
def has_global_permission(cls, user, permission):
if user.is_superuser:
@@ -205,44 +322,6 @@ class BasicWorkflow(object):
return has_role(user, 'publisher')
return False
@classmethod
def has_object_permission(cls, user, permission, obj):
if user.is_superuser:
return True
if permission == 'view':
if user == obj.owner:
return True
if has_role(user, 'manager_super'):
return True
if has_role(user, 'manager_{}'.format(obj.sport.lower())):
return True
if has_role(user, 'publisher') and obj.is_flagged('accepted'):
return True
elif permission == 'submit':
if user == obj.owner:
return True
elif permission == 'accept':
if has_role(user, 'manager_super'):
return True
if has_role(user, 'manager_{}'.format(obj.sport.lower())):
return True
elif permission == 'publish':
if has_role(user, 'publisher'):
return True
elif permission == 'update':
if not obj.is_flagged('submitted'):
if user == obj.owner:
return True
elif not obj.is_flagged('accepted'):
if has_role(user, 'manager_super'):
return True
if has_role(user, 'manager_{}'.format(obj.sport.lower())):
return True
elif has_role(user, 'publisher'):
return True
return False
#
# Signal handlers
#
@@ -263,11 +342,11 @@ class BasicWorkflow(object):
# Who should be informed about the update?
recipients = [event.owner]
if event.is_flagged('submitted'):
if event.workflow.has_reached_status('submitted'):
# If the event is already submitted, add managers to the recipients.
recipients += get_users_by_role('manager_super')
recipients += get_users_by_role('manager_{}'.format(event.sport.lower()))
if event.is_flagged('accepted'):
if event.workflow.has_reached_status('accepted'):
# If the event is already published, add publishers to the recipients.
recipients += get_users_by_role('publisher_web')
recipients += get_users_by_role('publisher_facebook')
@@ -379,4 +458,4 @@ class BasicWorkflow(object):
return None, None
workflow = BasicWorkflow
DefaultWorkflow = BasicWorkflow