friday night work

This commit is contained in:
Fred 2017-10-27 23:00:30 +02:00
parent d400cabfde
commit 51994b4600
10 changed files with 250 additions and 45 deletions

View File

@ -40,7 +40,7 @@ INSTALLED_APPS = [
'evolus',
'jci',
'reversion',
'process'
'process',
]
MIDDLEWARE = [

Binary file not shown.

View File

@ -6,7 +6,7 @@ from .models import Audience, Document, DocumentType, Version, Site, Structure,
class DocumentAdmin(VersionAdmin):
list_filter = ('type', 'audiences', 'sites', 'structures')
list_filter = ('type', 'title')
class DocumentTypeAdmin(admin.ModelAdmin):

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.5 on 2017-10-27 19:13
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('auth', '0008_alter_user_username_max_length'),
('evolus', '0011_auto_20171027_1512'),
]
operations = [
migrations.AddField(
model_name='audience',
name='group',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='auth.Group'),
preserve_default=False,
),
]

View File

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.5 on 2017-10-27 20:32
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('evolus', '0012_audience_group'),
]
operations = [
migrations.RemoveField(
model_name='historicaldocument',
name='history_user',
),
migrations.RemoveField(
model_name='historicaldocument',
name='manager',
),
migrations.RemoveField(
model_name='historicaldocument',
name='type',
),
migrations.RenameField(
model_name='version',
old_name='published',
new_name='is_published',
),
migrations.AlterField(
model_name='document',
name='type',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='evolus.DocumentType'),
preserve_default=False,
),
migrations.AlterField(
model_name='version',
name='document',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='evolus.Document'),
),
migrations.DeleteModel(
name='HistoricalDocument',
),
]

View File

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.5 on 2017-10-27 20:55
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('evolus', '0013_auto_20171027_2032'),
]
operations = [
migrations.RemoveField(
model_name='document',
name='audiences',
),
migrations.RemoveField(
model_name='document',
name='sites',
),
migrations.RemoveField(
model_name='document',
name='standards',
),
migrations.RemoveField(
model_name='document',
name='structures',
),
]

View File

@ -5,15 +5,17 @@ This module defines the structure and properties of documents.
from django.db import models
from closuretree.models import ClosureModel
from simple_history.models import HistoricalRecords
from django.contrib.auth.models import User
from django.contrib.auth.models import Group, User
import reversion
from process.models import Approval
from jci.models import Standard
class Audience(ClosureModel):
name = models.CharField(max_length=50)
parent = models.ForeignKey('self', related_name='children', null=True, blank=True)
group = models.ForeignKey(Group)
def __str__(self):
return self.name
@ -41,6 +43,17 @@ class Structure(ClosureModel):
return self.name
class Keyword(ClosureModel):
name = models.CharField(max_length=255)
parent = models.ForeignKey('self', null=True, blank=True)
selectable = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class DocumentType(models.Model):
name = models.CharField(max_length=50)
level = models.IntegerField()
@ -56,16 +69,11 @@ class DocumentType(models.Model):
@reversion.register()
class Document(models.Model):
audiences = models.ManyToManyField(Audience)
sites = models.ManyToManyField(Site)
standards = models.ManyToManyField(Standard, related_name='documents')
structures = models.ManyToManyField(Structure)
title = models.CharField(max_length=255)
overview = models.TextField(blank=True, null=True)
type = models.ForeignKey(DocumentType, null=True)
type = models.ForeignKey(DocumentType)
created_at = models.DateTimeField(auto_now_add=True)
manager = models.ForeignKey(User)
history = HistoricalRecords()
@property
def last_published_version(self):
@ -83,6 +91,48 @@ class Document(models.Model):
except Version.DoesNotExist:
return 'None'
def create_new_version(self):
"""Creates a new version for this document.
By default, version 0.0 is created with the chosen template for this document.
:raises
IndexError if there is a current version still in draft
:returns
A new `Version` object if it needs to be created.
Raises an `IndexError` exception instead.
"""
latest_version = self.versions.last()
if not latest_version or latest_version.is_published:
latest_version = Version(
document = self,
file = self.type.template,
revision = 1,
major = self.major,
)
latest_version.save()
return latest_version
if not latest_version.is_published:
raise IndexError('The latest version is still in draft.\n '
'Publish this first before creating a new one.')
@property
def major(self):
latest_version = self.versions.filter(published=True).last()
if latest_version:
return latest_version.major
return 0
@property
def revision(self):
latest_version = self.versions.last()
if latest_version:
return latest_version.revision
return 0
@reversion.create_revision()
def save(self, *args, **kwargs):
super().save()
@ -90,52 +140,50 @@ class Document(models.Model):
def __str__(self):
return self.title
def update_version(self, document):
pass
def publish(self):
pass
class Keyword(ClosureModel):
name = models.CharField(max_length=255)
parent = models.ForeignKey('self', null=True, blank=True)
selectable = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
@reversion.register()
class Version(models.Model):
document = models.ForeignKey(Document)
document = models.ForeignKey(Document, related_name='versions')
file = models.FileField(upload_to='revisions/')
keywords = models.ManyToManyField(Keyword, blank=True, related_name='document_versions')
major = models.PositiveIntegerField()
revision = models.PositiveIntegerField()
published = models.BooleanField(default=False)
is_published = models.BooleanField(default=False)
revised_at = models.DateTimeField(null=True, blank=True)
authors = models.ManyToManyField(User, related_name='authors')
reviewers = models.ManyToManyField(User, related_name='reviewers')
validators = models.ManyToManyField(User, related_name='validators')
created_at = models.DateTimeField(auto_now_add=True)
@reversion.create_revision()
def publish(self):
if not self.is_published:
if self.validators.count() == 0:
raise ValueError('There are no validators for this version. \n'
'Please, add at least one of them.')
Approval.objects.get_or_create(
document_version=self
)
@reversion.create_revision()
def update(self, *args, **kwargs):
if not self.is_published:
self.revision = self.revision + 1
return super().save(*args, **kwargs)
raise ValueError('A published version cannot be updated.')
@reversion.create_revision()
def save(self, *args, **kwargs):
self.revision = self.revision + 1
super().save(*args, **kwargs)
super().save()
class Meta:
unique_together = ('document', 'major')
@property
def status(self):
return 'Published' if self.published else 'Draft'
return 'Published' if self.is_published else 'Draft'
def __str__(self):
return 'v{}.{} ({})'.format(self.major, self.revision, self.status)
def publish(self):
pass

View File

@ -1,3 +1,36 @@
from django.test import TestCase
from django.contrib.auth.models import User, Group
from model_mommy import mommy
# Create your tests here.
class TestDocument(TestCase):
def setUp(self):
self.document = mommy.make('evolus.Document')
def test_create_document_version(self):
version = self.document.create_new_version()
self.assertEquals('v0.1 (Draft)', str(version))
def test_document_major_version(self):
self.assertEquals(0, self.document.major)
v1 = self.document.create_new_version()
self.assertEquals(0, self.document.major)
def test_document_major_version_0(self):
v1 = self.document.create_new_version()
v1.publish()
self.assertEquals(1, self.document.major)
self.assertEquals(0, v1.revision)
def test_document_version_update(self):
v1 = self.document.create_new_version()
print(v1)
self.assertEquals(1, v1.revision)
v1.update()
self.assertEquals(2, v1.revision)
v1.update()
self.assertEquals(3, v1.revision)
v1.publish()
self.assertEquals(0, v1.revision)

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.5 on 2017-10-27 20:55
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('process', '0003_auto_20170921_1855'),
]
operations = [
migrations.RemoveField(
model_name='process',
name='process_type',
),
]

View File

@ -2,12 +2,9 @@ from django.db import models
from django.contrib.auth.models import User
from evolus.models import Version
class Process(models.Model):
process_type = models.CharField(max_length=50)
document_version = models.ForeignKey(Version)
document_version = models.ForeignKey('evolus.Version')
def percentage_of_completion(self):
total = self.tasks.count()
@ -15,13 +12,8 @@ class Process(models.Model):
return self.tasks.filter(status=3).count() / self.tasks.count() * 100
return 'NaN'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.pk and not self.process_type:
self.process_type = self.PROCESS_TYPE
def __str__(self):
return '{}: {}'.format(self.process_type, self.document_version)
return 'Process on {}'.format(self.document_version)
def create_task(self, assigned_to):
task, created = Task.objects.get_or_create(status=1, assigned_to=assigned_to, process=self)
@ -50,6 +42,12 @@ class Task(models.Model):
class Meta:
unique_together = ('assigned_to', 'process', 'status')
def save(self, *args, **kwargs):
super().save()
if self.process.percentage_of_completion == 100.0:
self.process.finalize()
class PublishedProcessMixin(object):
def save(self, *args, **kwargs):
@ -80,6 +78,12 @@ class Approval(Process, DraftProcessMixin):
for validator in self.document_version.validators.all():
self.create_task(validator)
def finalize(self):
self.document_version.is_published = True
self.document_version.major = self.document_version.major + 1
self.document_version.revision = 0
self.document_version.save()
class GatherComments(Process, DraftProcessMixin):
PROCESS_TYPE = 'GatherComments'