CONT: continue the previous change.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user