UPD: dav_events: decoupled event model and eventflag model.

This commit is contained in:
2019-02-18 15:57:09 +01:00
parent a62d573b98
commit 6e1a07f3f6
5 changed files with 96 additions and 86 deletions

View File

@@ -52,6 +52,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='eventflag',
name='user',
field=models.ForeignKey(default=dav_events.models.event.get_system_user_id, on_delete=models.SET(dav_events.utils.get_ghost_user), related_name='+', to=settings.AUTH_USER_MODEL),
field=models.ForeignKey(default=dav_events.models.eventflag.get_system_user_id, on_delete=models.SET(dav_events.utils.get_ghost_user), related_name='+', to=settings.AUTH_USER_MODEL),
),
]

View File

@@ -1,3 +1,4 @@
from .event import Event, EventFlag
from .event import Event
from .eventflag import EventFlag
from .eventstatus import EventStatus
from .oneclickaction import OneClickAction

View File

@@ -11,26 +11,22 @@ from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from django.db import models
from django.template.loader import get_template
from django.utils import timezone
from django.utils.translation import get_language, ugettext_lazy as _
from django_countries.fields import CountryField
from .. import choices
from .. import config
from .. import signals
from ..utils import get_ghost_user, get_system_user
from ..utils import get_ghost_user
from ..workflow import DefaultWorkflow
from .eventflag import EventFlag
from .eventstatus import EventStatus, get_or_create_event_status
logger = logging.getLogger(__name__)
def get_system_user_id():
return get_system_user().id
class Event(models.Model):
# Metadata
owner = models.ForeignKey(settings.AUTH_USER_MODEL,
@@ -314,17 +310,6 @@ class Event(models.Model):
logger.info('Event updated: %s', self)
signals.event_updated.send(sender=self.__class__, event=self, diff=diff_lines, user=self.editor)
# TODO: move this into workflow
def set_flag(self, status, **kwargs):
if not isinstance(status, EventStatus):
status = get_or_create_event_status(status)
kwargs['event'] = self
kwargs['status'] = status
flag = EventFlag(**kwargs)
flag.save()
logger.info('Flagging status \'%s\' for %s', status.code, self)
return flag
def get_number(self):
return self.workflow.get_number()
@@ -495,26 +480,3 @@ class Event(models.Model):
template_name = os.path.join('dav_events', 'event', 'default.html')
template = get_template(template_name)
return template.render(self.get_template_context())
# TODO: can we put this into a separated file?
class EventFlag(models.Model):
event = models.ForeignKey(Event, related_name='flags')
status = models.ForeignKey(EventStatus,
on_delete=models.PROTECT,
related_name='+')
timestamp = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(settings.AUTH_USER_MODEL,
default=get_system_user_id,
on_delete=models.SET(get_ghost_user),
related_name='+')
class Meta:
ordering = ['event', 'timestamp', 'status']
def __unicode__(self):
s = u'{status} - {timestamp}'
if self.user:
s += u' by user {user}'
return s.format(status=self.status, timestamp=self.timestamp.strftime('%d.%m.%Y %H:%M:%S'),
user=self.user)

View File

@@ -0,0 +1,31 @@
from django.conf import settings
from django.db import models
from django.utils import timezone
from ..utils import get_ghost_user, get_system_user
def get_system_user_id():
return get_system_user().id
class EventFlag(models.Model):
event = models.ForeignKey('dav_events.Event', related_name='flags')
status = models.ForeignKey('dav_events.EventStatus',
on_delete=models.PROTECT,
related_name='+')
timestamp = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(settings.AUTH_USER_MODEL,
default=get_system_user_id,
on_delete=models.SET(get_ghost_user),
related_name='+')
class Meta:
ordering = ['event', 'timestamp', 'status']
def __unicode__(self):
s = u'{status} - {timestamp}'
if self.user:
s += u' by user {user}'
return s.format(status=self.status, timestamp=self.timestamp.strftime('%d.%m.%Y %H:%M:%S'),
user=self.user)

View File

@@ -8,6 +8,8 @@ from django.utils.translation import ugettext_lazy as _
from . import emails
from . import signals
from .models.eventflag import EventFlag
from .models.eventstatus import get_or_create_event_status
from .utils import get_users_by_role, has_role
logger = logging.getLogger(__name__)
@@ -35,39 +37,20 @@ class BasicWorkflow(object):
#
# Status changes
#
def get_number(self):
# We use EventFlags to store the status information
def _add_flag(self, code, **kwargs):
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)
status = get_or_create_event_status(code)
kwargs['event'] = event
kwargs['status'] = status
flag = EventFlag(**kwargs)
flag.save()
logger.info('Flagging status \'%s\' for %s', status.code, event)
return flag
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.__class__.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
# TODO: the name/intention of this method is unclear.
# Could we make it obsolete? At least it should be private
def check_status(self, code=None):
# TODO: the name/intention of this method is unclear. Could we make it obsolete?
def _check_status(self, code=None):
event = self._event
if not event.id:
return
@@ -78,7 +61,7 @@ class BasicWorkflow(object):
# Check if event has a draft flag.
if not event.flags.filter(status__code='draft').exists():
logger.info('Detected draft state of Event %s', event)
event.set_flag(status='draft', timestamp=event.created_at)
self._add_flag('draft', timestamp=event.created_at)
if code in (None, 'accepted'):
# Check if event with accepted flag has a number.
@@ -130,7 +113,7 @@ class BasicWorkflow(object):
if not timestamp:
timestamp = event.flags.filter(status__code='publishing').last().timestamp
logger.info('Detected published state of Event %s', event)
event.set_flag(status='published', timestamp=timestamp)
self._add_flag('published', timestamp=timestamp)
elif ((publishing_web.exists() or published_web.exists()) and
(publishing_facebook.exists() or published_facebook.exists())):
# All publishers have confirmed the publication date or have published already
@@ -138,7 +121,7 @@ class BasicWorkflow(object):
if not timestamp:
timestamp = pub_flags.last().timestamp
logger.info('Detected general published state of Event %s', event)
event.set_flag(status='published', timestamp=timestamp)
self._add_flag('published', timestamp=timestamp)
else:
if publishing_web.exists() and not published_web.exists():
# One publisher has confirmed the publication date,
@@ -146,20 +129,20 @@ class BasicWorkflow(object):
if not timestamp:
timestamp = event.flags.filter(status__code='publishing_web').last().timestamp
logger.info('Detected published_web state of Event %s', event)
event.set_flag(status='published_web', timestamp=timestamp)
self._add_flag('published_web', timestamp=timestamp)
if publishing_facebook.exists() and not published_facebook.exists():
# One publisher has confirmed the publication date,
# so we can flag, that he/she has published.
if not timestamp:
timestamp = event.flags.filter(status__code='publishing_facebook').last().timestamp
logger.info('Detected published_facebook state of Event %s', event)
event.set_flag(status='published_facebook', timestamp=timestamp)
self._add_flag('published_facebook', timestamp=timestamp)
if published_web.exists() and published_facebook.exists():
# All publishers have published,
# so we can flag the complete published state.
timestamp = pub_flags.last().timestamp
logger.info('Detected general published state of Event %s', event)
event.set_flag(status='published', timestamp=timestamp)
self._add_flag('published', timestamp=timestamp)
elif not publishing.exists() and publishing_web.exists() and publishing_facebook.exists():
# Event is not due to be published yet,
# does not have a general publishing flag,
@@ -168,7 +151,7 @@ class BasicWorkflow(object):
logger.info('Detected publishing state of Event %s', event)
flags = event.flags.filter(status__code__in=('publishing_web', 'publishing_facebook'))
timestamp = flags.order_by('timestamp').last().timestamp
event.set_flag(status='publishing', timestamp=timestamp)
self._add_flag('publishing', timestamp=timestamp)
if code in (None, 'expired'):
# Check if event is expired now and need a expired flag.
@@ -190,10 +173,10 @@ class BasicWorkflow(object):
if expired_at:
logger.info('Detected expired state of Event %s', event)
timestamp = timezone.make_aware(datetime.datetime.combine(expired_at, midnight))
event.set_flag(status='expired', timestamp=timestamp)
self._add_flag('expired', timestamp=timestamp)
def has_reached_status(self, code):
self.check_status(code)
self._check_status(code)
if code == 'publishing*':
codes = ['publishing', 'publishing_web', 'publishing_facebook']
elif code == 'published*':
@@ -243,8 +226,8 @@ class BasicWorkflow(object):
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)
flag = self._add_flag(code, user=user)
self._check_status(code)
signals.event_status_updated.send(sender=self.__class__, event=event, flag=flag)
return flag
@@ -253,7 +236,7 @@ class BasicWorkflow(object):
event = self._event
status_list = []
event.workflow.check_status()
self._check_status()
heaviest_flag = event.flags.order_by('status').last()
if heaviest_flag:
@@ -283,6 +266,39 @@ class BasicWorkflow(object):
return status_list
#
# Status related event properties
#
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)
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.__class__.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
#
# Notifications (loose coupled via signals)
#
@@ -381,7 +397,7 @@ class BasicWorkflow(object):
email.send()
#
# Permission
# Permissions
#
def has_permission(self, user, permission):
if user.is_superuser: