From 8ff3747a15895e6e13cbccbd133fafd26469f165 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Tue, 13 Jan 2015 04:13:49 -0400 Subject: [PATCH] Initial import of the document states app --- mayan/apps/document_states/__init__.py | 44 +++++ mayan/apps/document_states/admin.py | 18 ++ mayan/apps/document_states/forms.py | 19 ++ mayan/apps/document_states/links.py | 14 ++ .../migrations/0001_initial.py | 151 ++++++++++++++ ...__add_field_workflowtransition_workflow.py | 80 ++++++++ ...tion_workflow_origin_state_destination_.py | 78 ++++++++ ...elogentry_document__del_field_workflowi.py | 112 +++++++++++ ...label__add_unique_workflowstate_workflo.py | 84 ++++++++ ...tion_label__del_unique_workflowtransiti.py | 90 +++++++++ .../document_states/migrations/__init__.py | 0 mayan/apps/document_states/models.py | 118 +++++++++++ mayan/apps/document_states/permissions.py | 14 ++ mayan/apps/document_states/tests.py | 3 + mayan/apps/document_states/urls.py | 18 ++ mayan/apps/document_states/views.py | 187 ++++++++++++++++++ mayan/apps/main/static/main/icons/table.png | Bin 0 -> 920 bytes mayan/settings/base.py | 1 + mayan/urls.py | 1 + 19 files changed, 1032 insertions(+) create mode 100644 mayan/apps/document_states/__init__.py create mode 100644 mayan/apps/document_states/admin.py create mode 100644 mayan/apps/document_states/forms.py create mode 100644 mayan/apps/document_states/links.py create mode 100644 mayan/apps/document_states/migrations/0001_initial.py create mode 100644 mayan/apps/document_states/migrations/0002_auto__add_field_workflowtransition_workflow.py create mode 100644 mayan/apps/document_states/migrations/0003_auto__add_unique_workflowtransition_workflow_origin_state_destination_.py create mode 100644 mayan/apps/document_states/migrations/0004_auto__del_field_workflowinstancelogentry_document__del_field_workflowi.py create mode 100644 mayan/apps/document_states/migrations/0005_auto__del_unique_workflowstate_label__add_unique_workflowstate_workflo.py create mode 100644 mayan/apps/document_states/migrations/0006_auto__del_unique_workflowtransition_label__del_unique_workflowtransiti.py create mode 100644 mayan/apps/document_states/migrations/__init__.py create mode 100644 mayan/apps/document_states/models.py create mode 100644 mayan/apps/document_states/permissions.py create mode 100644 mayan/apps/document_states/tests.py create mode 100644 mayan/apps/document_states/urls.py create mode 100644 mayan/apps/document_states/views.py create mode 100644 mayan/apps/main/static/main/icons/table.png diff --git a/mayan/apps/document_states/__init__.py b/mayan/apps/document_states/__init__.py new file mode 100644 index 0000000000..cb2205565b --- /dev/null +++ b/mayan/apps/document_states/__init__.py @@ -0,0 +1,44 @@ +from __future__ import unicode_literals + +from django.utils.translation import ugettext as _ + +from common.utils import encapsulate +from navigation.api import register_links, register_model_list_columns +from project_setup.api import register_setup + +from .models import Workflow, WorkflowState, WorkflowTransition +from .links import (link_setup_workflow_create, link_setup_workflow_delete, + link_setup_workflow_edit, link_setup_workflow_list, + link_setup_workflow_states, link_setup_workflow_states_create, + link_setup_workflow_transitions, link_setup_workflow_transitions_create) + +register_setup(link_setup_workflow_list) + +register_model_list_columns(Workflow, [ + { + 'name': _('Initial state'), + 'attribute': encapsulate(lambda workflow: workflow.get_initial_state() or _('None')) + }, +]) + +register_model_list_columns(WorkflowState, [ + { + 'name': _('Is initial state?'), + 'attribute': 'initial' + }, +]) + +register_model_list_columns(WorkflowTransition, [ + { + 'name': _('Origin state'), + 'attribute': 'origin_state' + }, + { + 'name': _('Destination state'), + 'attribute': 'destination_state' + }, +]) + +register_links([Workflow, 'document_states:setup_workflow_create', 'document_states:setup_workflow_list'], [link_setup_workflow_list, link_setup_workflow_create], menu_name='secondary_menu') +register_links([Workflow], [link_setup_workflow_states, link_setup_workflow_transitions, link_setup_workflow_edit, link_setup_workflow_delete]) +register_links([Workflow], [link_setup_workflow_states_create, link_setup_workflow_transitions_create], menu_name='sidebar') diff --git a/mayan/apps/document_states/admin.py b/mayan/apps/document_states/admin.py new file mode 100644 index 0000000000..b223625e10 --- /dev/null +++ b/mayan/apps/document_states/admin.py @@ -0,0 +1,18 @@ +from django.contrib import admin + +from .models import Workflow, WorkflowState, WorkflowTransition + + +class WorkflowStateInline(admin.TabularInline): + model = WorkflowState + + +class WorkflowTransitionInline(admin.TabularInline): + model = WorkflowTransition + + +class WorkflowAdmin(admin.ModelAdmin): + inlines = [WorkflowStateInline, WorkflowTransitionInline] + + +admin.site.register(Workflow, WorkflowAdmin) diff --git a/mayan/apps/document_states/forms.py b/mayan/apps/document_states/forms.py new file mode 100644 index 0000000000..c2e4a32f9c --- /dev/null +++ b/mayan/apps/document_states/forms.py @@ -0,0 +1,19 @@ +from __future__ import unicode_literals + +from django import forms +from django.utils.translation import ugettext_lazy as _ + +from .models import WorkflowState, WorkflowTransition + + +class WorkflowStateForm(forms.ModelForm): + class Meta: + fields = ('initial', 'label') + model = WorkflowState + + +class WorkflowTransitionForm(forms.ModelForm): + class Meta: + # TODO: restrict states to the ones of this workflow + fields = ('label', 'origin_state', 'destination_state') + model = WorkflowTransition diff --git a/mayan/apps/document_states/links.py b/mayan/apps/document_states/links.py new file mode 100644 index 0000000000..bf0f94fe7e --- /dev/null +++ b/mayan/apps/document_states/links.py @@ -0,0 +1,14 @@ +from __future__ import unicode_literals + +from django.utils.translation import ugettext_lazy as _ + +link_setup_workflow_list = {'text': _('Workflows'), 'view': 'document_states:setup_workflow_list', 'famfam': 'table', 'icon': 'table.png'} +link_setup_workflow_create = {'text': _('Create'), 'view': 'document_states:setup_workflow_create', 'famfam': 'table_add'} +link_setup_workflow_delete = {'text': _('Delete'), 'view': 'document_states:setup_workflow_delete', 'args': 'object.pk', 'famfam': 'table_delete'} +link_setup_workflow_edit = {'text': _('Edit'), 'view': 'document_states:setup_workflow_edit', 'args': 'object.pk', 'famfam': 'table_edit'} + +link_setup_workflow_states = {'text': _('States'), 'view': 'document_states:setup_workflow_states', 'args': 'object.pk', 'famfam': 'style'} +link_setup_workflow_states_create = {'text': _('Create state'), 'view': 'document_states:setup_workflow_states_create', 'args': 'object.pk', 'famfam': 'style_add'} + +link_setup_workflow_transitions = {'text': _('Transitions'), 'view': 'document_states:setup_workflow_transitions', 'args': 'object.pk', 'famfam': 'lightning'} +link_setup_workflow_transitions_create = {'text': _('Create transition'), 'view': 'document_states:setup_workflow_transitions_create', 'args': 'object.pk', 'famfam': 'lightning_add'} diff --git a/mayan/apps/document_states/migrations/0001_initial.py b/mayan/apps/document_states/migrations/0001_initial.py new file mode 100644 index 0000000000..60d8ef7b31 --- /dev/null +++ b/mayan/apps/document_states/migrations/0001_initial.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Workflow' + db.create_table(u'document_states_workflow', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('label', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + )) + db.send_create_signal(u'document_states', ['Workflow']) + + # Adding model 'WorkflowState' + db.create_table(u'document_states_workflowstate', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('workflow', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_states.Workflow'])), + ('label', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + ('initial', self.gf('django.db.models.fields.BooleanField')(default=False)), + )) + db.send_create_signal(u'document_states', ['WorkflowState']) + + # Adding model 'WorkflowTransition' + db.create_table(u'document_states_workflowtransition', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('label', self.gf('django.db.models.fields.CharField')(unique=True, max_length=255)), + ('origin_state', self.gf('django.db.models.fields.related.ForeignKey')(related_name=u'origins', to=orm['document_states.WorkflowState'])), + ('destination_state', self.gf('django.db.models.fields.related.ForeignKey')(related_name=u'destinations', to=orm['document_states.WorkflowState'])), + )) + db.send_create_signal(u'document_states', ['WorkflowTransition']) + + # Adding model 'DocumentTypeWorkflow' + db.create_table(u'document_states_documenttypeworkflow', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('document_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.DocumentType'])), + ('workflow', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_states.Workflow'])), + )) + db.send_create_signal(u'document_states', ['DocumentTypeWorkflow']) + + # Adding unique constraint on 'DocumentTypeWorkflow', fields ['document_type', 'workflow'] + db.create_unique(u'document_states_documenttypeworkflow', ['document_type_id', 'workflow_id']) + + # Adding model 'WorkflowInstance' + db.create_table(u'document_states_workflowinstance', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('workflow', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_states.Workflow'])), + ('document', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document'])), + )) + db.send_create_signal(u'document_states', ['WorkflowInstance']) + + # Adding unique constraint on 'WorkflowInstance', fields ['document', 'workflow'] + db.create_unique(u'document_states_workflowinstance', ['document_id', 'workflow_id']) + + # Adding model 'WorkflowInstanceLogEntry' + db.create_table(u'document_states_workflowinstancelogentry', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('workflow_instace', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_states.WorkflowInstance'])), + ('datetime', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('document', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document'])), + )) + db.send_create_signal(u'document_states', ['WorkflowInstanceLogEntry']) + + + def backwards(self, orm): + # Removing unique constraint on 'WorkflowInstance', fields ['document', 'workflow'] + db.delete_unique(u'document_states_workflowinstance', ['document_id', 'workflow_id']) + + # Removing unique constraint on 'DocumentTypeWorkflow', fields ['document_type', 'workflow'] + db.delete_unique(u'document_states_documenttypeworkflow', ['document_type_id', 'workflow_id']) + + # Deleting model 'Workflow' + db.delete_table(u'document_states_workflow') + + # Deleting model 'WorkflowState' + db.delete_table(u'document_states_workflowstate') + + # Deleting model 'WorkflowTransition' + db.delete_table(u'document_states_workflowtransition') + + # Deleting model 'DocumentTypeWorkflow' + db.delete_table(u'document_states_documenttypeworkflow') + + # Deleting model 'WorkflowInstance' + db.delete_table(u'document_states_workflowinstance') + + # Deleting model 'WorkflowInstanceLogEntry' + db.delete_table(u'document_states_workflowinstancelogentry') + + + models = { + u'document_states.documenttypeworkflow': { + 'Meta': {'unique_together': "((u'document_type', u'workflow'),)", 'object_name': 'DocumentTypeWorkflow'}, + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflow': { + 'Meta': {'object_name': 'Workflow'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'document_states.workflowinstance': { + 'Meta': {'unique_together': "((u'document', u'workflow'),)", 'object_name': 'WorkflowInstance'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowinstancelogentry': { + 'Meta': {'object_name': 'WorkflowInstanceLogEntry'}, + 'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow_instace': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.WorkflowInstance']"}) + }, + u'document_states.workflowstate': { + 'Meta': {'object_name': 'WorkflowState'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'initial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowtransition': { + 'Meta': {'object_name': 'WorkflowTransition'}, + 'destination_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'destinations'", 'to': u"orm['document_states.WorkflowState']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'origins'", 'to': u"orm['document_states.WorkflowState']"}) + }, + u'documents.document': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'}, + 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'default': "u'Uninitialized document'", 'max_length': '255', 'db_index': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "u'eng'", 'max_length': '8'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'8fff74c9-2f45-4a2a-bbdc-2ce727ab9380'", 'max_length': '48'}) + }, + u'documents.documenttype': { + 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}), + 'ocr': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + } + } + + complete_apps = ['document_states'] \ No newline at end of file diff --git a/mayan/apps/document_states/migrations/0002_auto__add_field_workflowtransition_workflow.py b/mayan/apps/document_states/migrations/0002_auto__add_field_workflowtransition_workflow.py new file mode 100644 index 0000000000..2cfc126a0f --- /dev/null +++ b/mayan/apps/document_states/migrations/0002_auto__add_field_workflowtransition_workflow.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'WorkflowTransition.workflow' + db.add_column(u'document_states_workflowtransition', 'workflow', + self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['document_states.Workflow']), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'WorkflowTransition.workflow' + db.delete_column(u'document_states_workflowtransition', 'workflow_id') + + + models = { + u'document_states.documenttypeworkflow': { + 'Meta': {'unique_together': "((u'document_type', u'workflow'),)", 'object_name': 'DocumentTypeWorkflow'}, + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflow': { + 'Meta': {'object_name': 'Workflow'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'document_states.workflowinstance': { + 'Meta': {'unique_together': "((u'document', u'workflow'),)", 'object_name': 'WorkflowInstance'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowinstancelogentry': { + 'Meta': {'object_name': 'WorkflowInstanceLogEntry'}, + 'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow_instace': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.WorkflowInstance']"}) + }, + u'document_states.workflowstate': { + 'Meta': {'object_name': 'WorkflowState'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'initial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowtransition': { + 'Meta': {'object_name': 'WorkflowTransition'}, + 'destination_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'destinations'", 'to': u"orm['document_states.WorkflowState']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'origins'", 'to': u"orm['document_states.WorkflowState']"}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'documents.document': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'}, + 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'default': "u'Uninitialized document'", 'max_length': '255', 'db_index': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "u'eng'", 'max_length': '8'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'a8398ab2-9234-43c8-849c-a875066971d8'", 'max_length': '48'}) + }, + u'documents.documenttype': { + 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}), + 'ocr': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + } + } + + complete_apps = ['document_states'] \ No newline at end of file diff --git a/mayan/apps/document_states/migrations/0003_auto__add_unique_workflowtransition_workflow_origin_state_destination_.py b/mayan/apps/document_states/migrations/0003_auto__add_unique_workflowtransition_workflow_origin_state_destination_.py new file mode 100644 index 0000000000..1feea7fe2b --- /dev/null +++ b/mayan/apps/document_states/migrations/0003_auto__add_unique_workflowtransition_workflow_origin_state_destination_.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding unique constraint on 'WorkflowTransition', fields ['workflow', 'origin_state', 'destination_state'] + db.create_unique(u'document_states_workflowtransition', ['workflow_id', 'origin_state_id', 'destination_state_id']) + + + def backwards(self, orm): + # Removing unique constraint on 'WorkflowTransition', fields ['workflow', 'origin_state', 'destination_state'] + db.delete_unique(u'document_states_workflowtransition', ['workflow_id', 'origin_state_id', 'destination_state_id']) + + + models = { + u'document_states.documenttypeworkflow': { + 'Meta': {'unique_together': "((u'document_type', u'workflow'),)", 'object_name': 'DocumentTypeWorkflow'}, + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflow': { + 'Meta': {'object_name': 'Workflow'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'document_states.workflowinstance': { + 'Meta': {'unique_together': "((u'document', u'workflow'),)", 'object_name': 'WorkflowInstance'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowinstancelogentry': { + 'Meta': {'object_name': 'WorkflowInstanceLogEntry'}, + 'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow_instace': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.WorkflowInstance']"}) + }, + u'document_states.workflowstate': { + 'Meta': {'object_name': 'WorkflowState'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'initial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'states'", 'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowtransition': { + 'Meta': {'unique_together': "((u'workflow', u'origin_state', u'destination_state'),)", 'object_name': 'WorkflowTransition'}, + 'destination_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'destinations'", 'to': u"orm['document_states.WorkflowState']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'origins'", 'to': u"orm['document_states.WorkflowState']"}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'documents.document': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'}, + 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'default': "u'Uninitialized document'", 'max_length': '255', 'db_index': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "u'eng'", 'max_length': '8'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'1fa4f165-792f-4563-aea9-46283b03ddaf'", 'max_length': '48'}) + }, + u'documents.documenttype': { + 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}), + 'ocr': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + } + } + + complete_apps = ['document_states'] \ No newline at end of file diff --git a/mayan/apps/document_states/migrations/0004_auto__del_field_workflowinstancelogentry_document__del_field_workflowi.py b/mayan/apps/document_states/migrations/0004_auto__del_field_workflowinstancelogentry_document__del_field_workflowi.py new file mode 100644 index 0000000000..320583de9e --- /dev/null +++ b/mayan/apps/document_states/migrations/0004_auto__del_field_workflowinstancelogentry_document__del_field_workflowi.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting field 'WorkflowInstanceLogEntry.document' + db.delete_column(u'document_states_workflowinstancelogentry', 'document_id') + + # Deleting field 'WorkflowInstanceLogEntry.workflow_instace' + db.delete_column(u'document_states_workflowinstancelogentry', 'workflow_instace_id') + + # Adding field 'WorkflowInstanceLogEntry.workflow_instance' + db.add_column(u'document_states_workflowinstancelogentry', 'workflow_instance', + self.gf('django.db.models.fields.related.ForeignKey')(default=1, related_name=u'log_entries', to=orm['document_states.WorkflowInstance']), + keep_default=False) + + # Adding field 'WorkflowInstanceLogEntry.transition' + db.add_column(u'document_states_workflowinstancelogentry', 'transition', + self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['document_states.WorkflowTransition']), + keep_default=False) + + + def backwards(self, orm): + + # User chose to not deal with backwards NULL issues for 'WorkflowInstanceLogEntry.document' + raise RuntimeError("Cannot reverse this migration. 'WorkflowInstanceLogEntry.document' and its values cannot be restored.") + + # The following code is provided here to aid in writing a correct migration # Adding field 'WorkflowInstanceLogEntry.document' + db.add_column(u'document_states_workflowinstancelogentry', 'document', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['documents.Document']), + keep_default=False) + + + # User chose to not deal with backwards NULL issues for 'WorkflowInstanceLogEntry.workflow_instace' + raise RuntimeError("Cannot reverse this migration. 'WorkflowInstanceLogEntry.workflow_instace' and its values cannot be restored.") + + # The following code is provided here to aid in writing a correct migration # Adding field 'WorkflowInstanceLogEntry.workflow_instace' + db.add_column(u'document_states_workflowinstancelogentry', 'workflow_instace', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['document_states.WorkflowInstance']), + keep_default=False) + + # Deleting field 'WorkflowInstanceLogEntry.workflow_instance' + db.delete_column(u'document_states_workflowinstancelogentry', 'workflow_instance_id') + + # Deleting field 'WorkflowInstanceLogEntry.transition' + db.delete_column(u'document_states_workflowinstancelogentry', 'transition_id') + + + models = { + u'document_states.documenttypeworkflow': { + 'Meta': {'unique_together': "((u'document_type', u'workflow'),)", 'object_name': 'DocumentTypeWorkflow'}, + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflow': { + 'Meta': {'object_name': 'Workflow'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'document_states.workflowinstance': { + 'Meta': {'unique_together': "((u'document', u'workflow'),)", 'object_name': 'WorkflowInstance'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowinstancelogentry': { + 'Meta': {'object_name': 'WorkflowInstanceLogEntry'}, + 'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'transition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.WorkflowTransition']"}), + 'workflow_instance': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'log_entries'", 'to': u"orm['document_states.WorkflowInstance']"}) + }, + u'document_states.workflowstate': { + 'Meta': {'object_name': 'WorkflowState'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'initial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'states'", 'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowtransition': { + 'Meta': {'unique_together': "((u'workflow', u'origin_state', u'destination_state'),)", 'object_name': 'WorkflowTransition'}, + 'destination_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'destinations'", 'to': u"orm['document_states.WorkflowState']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'origins'", 'to': u"orm['document_states.WorkflowState']"}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'transitions'", 'to': u"orm['document_states.Workflow']"}) + }, + u'documents.document': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'}, + 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'default': "u'Uninitialized document'", 'max_length': '255', 'db_index': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "u'eng'", 'max_length': '8'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'3d36ed9d-3356-4f96-ae65-da677128e0c3'", 'max_length': '48'}) + }, + u'documents.documenttype': { + 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}), + 'ocr': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + } + } + + complete_apps = ['document_states'] \ No newline at end of file diff --git a/mayan/apps/document_states/migrations/0005_auto__del_unique_workflowstate_label__add_unique_workflowstate_workflo.py b/mayan/apps/document_states/migrations/0005_auto__del_unique_workflowstate_label__add_unique_workflowstate_workflo.py new file mode 100644 index 0000000000..81165d4a41 --- /dev/null +++ b/mayan/apps/document_states/migrations/0005_auto__del_unique_workflowstate_label__add_unique_workflowstate_workflo.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Removing unique constraint on 'WorkflowState', fields ['label'] + db.delete_unique(u'document_states_workflowstate', ['label']) + + # Adding unique constraint on 'WorkflowState', fields ['workflow', 'label'] + db.create_unique(u'document_states_workflowstate', ['workflow_id', 'label']) + + + def backwards(self, orm): + # Removing unique constraint on 'WorkflowState', fields ['workflow', 'label'] + db.delete_unique(u'document_states_workflowstate', ['workflow_id', 'label']) + + # Adding unique constraint on 'WorkflowState', fields ['label'] + db.create_unique(u'document_states_workflowstate', ['label']) + + + models = { + u'document_states.documenttypeworkflow': { + 'Meta': {'unique_together': "((u'document_type', u'workflow'),)", 'object_name': 'DocumentTypeWorkflow'}, + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflow': { + 'Meta': {'object_name': 'Workflow'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'document_states.workflowinstance': { + 'Meta': {'unique_together': "((u'document', u'workflow'),)", 'object_name': 'WorkflowInstance'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowinstancelogentry': { + 'Meta': {'object_name': 'WorkflowInstanceLogEntry'}, + 'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'transition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.WorkflowTransition']"}), + 'workflow_instance': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'log_entries'", 'to': u"orm['document_states.WorkflowInstance']"}) + }, + u'document_states.workflowstate': { + 'Meta': {'unique_together': "((u'workflow', u'label'),)", 'object_name': 'WorkflowState'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'initial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'states'", 'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowtransition': { + 'Meta': {'unique_together': "((u'workflow', u'origin_state', u'destination_state'),)", 'object_name': 'WorkflowTransition'}, + 'destination_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'destinations'", 'to': u"orm['document_states.WorkflowState']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}), + 'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'origins'", 'to': u"orm['document_states.WorkflowState']"}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'transitions'", 'to': u"orm['document_states.Workflow']"}) + }, + u'documents.document': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'}, + 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'default': "u'Uninitialized document'", 'max_length': '255', 'db_index': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "u'eng'", 'max_length': '8'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'1ee5fe5a-7e48-4166-a7d0-3b2acc8fb81b'", 'max_length': '48'}) + }, + u'documents.documenttype': { + 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}), + 'ocr': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + } + } + + complete_apps = ['document_states'] \ No newline at end of file diff --git a/mayan/apps/document_states/migrations/0006_auto__del_unique_workflowtransition_label__del_unique_workflowtransiti.py b/mayan/apps/document_states/migrations/0006_auto__del_unique_workflowtransition_label__del_unique_workflowtransiti.py new file mode 100644 index 0000000000..ec1f2dd7b1 --- /dev/null +++ b/mayan/apps/document_states/migrations/0006_auto__del_unique_workflowtransition_label__del_unique_workflowtransiti.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Removing unique constraint on 'WorkflowTransition', fields ['workflow', 'origin_state', 'destination_state'] + db.delete_unique(u'document_states_workflowtransition', ['workflow_id', 'origin_state_id', 'destination_state_id']) + + # Removing unique constraint on 'WorkflowTransition', fields ['label'] + db.delete_unique(u'document_states_workflowtransition', ['label']) + + # Adding unique constraint on 'WorkflowTransition', fields ['workflow', 'label', 'origin_state', 'destination_state'] + db.create_unique(u'document_states_workflowtransition', ['workflow_id', 'label', 'origin_state_id', 'destination_state_id']) + + + def backwards(self, orm): + # Removing unique constraint on 'WorkflowTransition', fields ['workflow', 'label', 'origin_state', 'destination_state'] + db.delete_unique(u'document_states_workflowtransition', ['workflow_id', 'label', 'origin_state_id', 'destination_state_id']) + + # Adding unique constraint on 'WorkflowTransition', fields ['label'] + db.create_unique(u'document_states_workflowtransition', ['label']) + + # Adding unique constraint on 'WorkflowTransition', fields ['workflow', 'origin_state', 'destination_state'] + db.create_unique(u'document_states_workflowtransition', ['workflow_id', 'origin_state_id', 'destination_state_id']) + + + models = { + u'document_states.documenttypeworkflow': { + 'Meta': {'unique_together': "((u'document_type', u'workflow'),)", 'object_name': 'DocumentTypeWorkflow'}, + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflow': { + 'Meta': {'object_name': 'Workflow'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}) + }, + u'document_states.workflowinstance': { + 'Meta': {'unique_together': "((u'document', u'workflow'),)", 'object_name': 'WorkflowInstance'}, + 'document': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['documents.Document']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowinstancelogentry': { + 'Meta': {'object_name': 'WorkflowInstanceLogEntry'}, + 'datetime': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'transition': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['document_states.WorkflowTransition']"}), + 'workflow_instance': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'log_entries'", 'to': u"orm['document_states.WorkflowInstance']"}) + }, + u'document_states.workflowstate': { + 'Meta': {'unique_together': "((u'workflow', u'label'),)", 'object_name': 'WorkflowState'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'initial': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'states'", 'to': u"orm['document_states.Workflow']"}) + }, + u'document_states.workflowtransition': { + 'Meta': {'unique_together': "((u'workflow', u'label', u'origin_state', u'destination_state'),)", 'object_name': 'WorkflowTransition'}, + 'destination_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'destinations'", 'to': u"orm['document_states.WorkflowState']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'origin_state': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'origins'", 'to': u"orm['document_states.WorkflowState']"}), + 'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'transitions'", 'to': u"orm['document_states.Workflow']"}) + }, + u'documents.document': { + 'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'}, + 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'document_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'documents'", 'to': u"orm['documents.DocumentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.CharField', [], {'default': "u'Uninitialized document'", 'max_length': '255', 'db_index': 'True'}), + 'language': ('django.db.models.fields.CharField', [], {'default': "u'eng'", 'max_length': '8'}), + 'uuid': ('django.db.models.fields.CharField', [], {'default': "u'59ce9910-80b7-48b3-8a1a-e9ac0fb412f0'", 'max_length': '48'}) + }, + u'documents.documenttype': { + 'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}), + 'ocr': ('django.db.models.fields.BooleanField', [], {'default': 'True'}) + } + } + + complete_apps = ['document_states'] \ No newline at end of file diff --git a/mayan/apps/document_states/migrations/__init__.py b/mayan/apps/document_states/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mayan/apps/document_states/models.py b/mayan/apps/document_states/models.py new file mode 100644 index 0000000000..253fdfe95c --- /dev/null +++ b/mayan/apps/document_states/models.py @@ -0,0 +1,118 @@ +from __future__ import unicode_literals + +from django.db import models +from django.utils.encoding import python_2_unicode_compatible +from django.utils.translation import ugettext as _ + +from documents.models import Document, DocumentType + + +@python_2_unicode_compatible +class Workflow(models.Model): + label = models.CharField(max_length=255, unique=True, verbose_name=_('Label')) + + def __str__(self): + return self.label + + def get_initial_state(self): + try: + return self.states.get(initial=True) + except self.states.model.DoesNotExist: + return None + + class Meta: + verbose_name = _('Workflow') + verbose_name_plural = _('Workflows') + + +@python_2_unicode_compatible +class WorkflowState(models.Model): + workflow = models.ForeignKey(Workflow, related_name='states', verbose_name=_('Workflow')) + label = models.CharField(max_length=255, verbose_name=_('Label')) + initial = models.BooleanField(default=False, verbose_name=_('Initial')) + + def __str__(self): + return self.label + + def save(self, *args, **kwargs): + if self.initial: + self.workflow.states.all().update(initial=False) + return super(WorkflowState, self).save(*args, **kwargs) + + class Meta: + unique_together = ('workflow', 'label') + verbose_name = _('Workflow state') + verbose_name_plural = _('Workflow states') + + +@python_2_unicode_compatible +class WorkflowTransition(models.Model): + workflow = models.ForeignKey(Workflow, related_name='transitions', verbose_name=_('Workflow')) + label = models.CharField(max_length=255, verbose_name=_('Label')) + + origin_state = models.ForeignKey(WorkflowState, related_name='origins', verbose_name=_('Origin state')) + destination_state = models.ForeignKey(WorkflowState, related_name='destinations', verbose_name=_('Destination state')) + + def __str__(self): + return self.label + + class Meta: + unique_together = ('workflow', 'label', 'origin_state', 'destination_state') + verbose_name = _('Workflow transition') + verbose_name_plural = _('Workflow transitions') + + +@python_2_unicode_compatible +class DocumentTypeWorkflow(models.Model): + document_type = models.ForeignKey(DocumentType, verbose_name=_('Document type')) + workflow = models.ForeignKey(Workflow, verbose_name=_('Workflow')) + + def __str__(self): + return self.label + + class Meta: + unique_together = ('document_type', 'workflow') + verbose_name = _('Document type workflow') + verbose_name_plural = _('Document type workflow') + + +@python_2_unicode_compatible +class WorkflowInstance(models.Model): + workflow = models.ForeignKey(Workflow, verbose_name=_('Workflow')) + document = models.ForeignKey(Document, verbose_name=_('Document')) + + def do_transition(self, transition): + try: + if transition in self.get_current_state().origins: + self.log_entries.create(transition=transition) + except AttributeError: + # No initial state has been set for this workflow + pass + + def get_current_state(self): + try: + return self.log_entries.order_by('datetime').last().transition.destination_state + except AttributeError: + return self.workflow.get_initial_state() + + def __str__(self): + return self.label + + class Meta: + unique_together = ('document', 'workflow') + verbose_name = _('Workflow instance') + verbose_name_plural = _('Workflow instances') + + +@python_2_unicode_compatible +class WorkflowInstanceLogEntry(models.Model): + workflow_instance = models.ForeignKey(WorkflowInstance, related_name='log_entries', verbose_name=_('Workflow instance')) + datetime = models.DateTimeField(auto_now_add=True, verbose_name=_('Datetime')) + transition = models.ForeignKey(WorkflowTransition, verbose_name=_('Transition')) + + def __str__(self): + return self.label + + class Meta: + verbose_name = _('Workflow instance log entry') + verbose_name_plural = _('Workflow instance log entries') diff --git a/mayan/apps/document_states/permissions.py b/mayan/apps/document_states/permissions.py new file mode 100644 index 0000000000..0326eb8cc0 --- /dev/null +++ b/mayan/apps/document_states/permissions.py @@ -0,0 +1,14 @@ +from __future__ import absolute_import, unicode_literals + +from django.utils.translation import ugettext_lazy as _ + +from permissions.models import PermissionNamespace, Permission + +namespace = PermissionNamespace('document_states', _('States')) +PERMISSION_WORKFLOW_CREATE = Permission.objects.register(namespace, 'workflow_create', _('Create workflows')) +PERMISSION_WORKFLOW_DELETE = Permission.objects.register(namespace, 'workflow_delte', _('Delete workflows')) +PERMISSION_WORKFLOW_EDIT = Permission.objects.register(namespace, 'workflow_edit', _('Edit workflows')) +PERMISSION_WORKFLOW_VIEW = Permission.objects.register(namespace, 'workflow_view', _('View workflows')) + +PERMISSION_DOCUMENT_WORKFLOW_VIEW = Permission.objects.register(namespace, 'document_workflow_view', _('View document workflows')) +PERMISSION_DOCUMENT_WORKFLOW_TRANSITION = Permission.objects.register(namespace, 'document_workflow_transition', _('Transition document workflows')) diff --git a/mayan/apps/document_states/tests.py b/mayan/apps/document_states/tests.py new file mode 100644 index 0000000000..7ce503c2dd --- /dev/null +++ b/mayan/apps/document_states/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/mayan/apps/document_states/urls.py b/mayan/apps/document_states/urls.py new file mode 100644 index 0000000000..df71150610 --- /dev/null +++ b/mayan/apps/document_states/urls.py @@ -0,0 +1,18 @@ +from django.conf.urls import patterns, url + +from .views import (SetupWorkflowCreateView, SetupWorkflowDeleteView, + SetupWorkflowEditView, SetupWorkflowListView, + SetupWorkflowStateListView, SetupWorkflowStateCreateView, + SetupWorkflowTransitionListView, SetupWorkflowTransitionCreateView) + +urlpatterns = patterns('', + url(r'^setup/all/$', SetupWorkflowListView.as_view(), name='setup_workflow_list'), + url(r'^setup/create/$', SetupWorkflowCreateView.as_view(), name='setup_workflow_create'), + url(r'^setup/(?P\d+)/edit/$', SetupWorkflowEditView.as_view(), name='setup_workflow_edit'), + url(r'^setup/(?P\d+)/delete/$', SetupWorkflowDeleteView.as_view(), name='setup_workflow_delete'), + url(r'^setup/(?P\d+)/states/$', SetupWorkflowStateListView.as_view(), name='setup_workflow_states'), + url(r'^setup/(?P\d+)/states/create/$', SetupWorkflowStateCreateView.as_view(), name='setup_workflow_states_create'), + + url(r'^setup/(?P\d+)/transitions/$', SetupWorkflowTransitionListView.as_view(), name='setup_workflow_transitions'), + url(r'^setup/(?P\d+)/transitions/create/$', SetupWorkflowTransitionCreateView.as_view(), name='setup_workflow_transitions_create'), +) diff --git a/mayan/apps/document_states/views.py b/mayan/apps/document_states/views.py new file mode 100644 index 0000000000..9a6f2aad6a --- /dev/null +++ b/mayan/apps/document_states/views.py @@ -0,0 +1,187 @@ +from __future__ import absolute_import, unicode_literals + +from django.conf import settings +from django.contrib import messages +from django.core.exceptions import PermissionDenied +from django.core.urlresolvers import reverse, reverse_lazy +from django.db.utils import IntegrityError +from django.http import HttpResponseRedirect +from django.shortcuts import render_to_response, get_object_or_404 +from django.template import RequestContext +from django.utils.http import urlencode +from django.utils.translation import ugettext_lazy as _, ungettext + +from acls.models import AccessEntry +from common.views import (SingleObjectCreateView, SingleObjectDeleteView, + SingleObjectEditView, SingleObjectListView) +from permissions.models import Permission + +from .forms import WorkflowStateForm, WorkflowTransitionForm +from .models import Workflow +from .permissions import PERMISSION_WORKFLOW_CREATE, PERMISSION_WORKFLOW_DELETE, PERMISSION_WORKFLOW_EDIT, PERMISSION_WORKFLOW_VIEW + + +class SetupWorkflowListView(SingleObjectListView): + extra_context = { + 'title': _('Workflows'), + 'hide_link': True, + } + model = Workflow + view_permission = PERMISSION_WORKFLOW_VIEW + + +class SetupWorkflowCreateView(SingleObjectCreateView): + model = Workflow + view_permission = PERMISSION_WORKFLOW_CREATE + success_url = reverse_lazy('document_states:setup_workflow_list') + + +class SetupWorkflowEditView(SingleObjectEditView): + model = Workflow + object_permission = PERMISSION_WORKFLOW_EDIT + success_url = reverse_lazy('document_states:setup_workflow_list') + + +class SetupWorkflowDeleteView(SingleObjectDeleteView): + model = Workflow + object_permission = PERMISSION_WORKFLOW_DELETE + success_url = reverse_lazy('document_states:setup_workflow_list') + + +# States + +class SetupWorkflowStateListView(SingleObjectListView): + def dispatch(self, request, *args, **kwargs): + try: + Permission.objects.check_permissions(request.user, [PERMISSION_WORKFLOW_EDIT]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_WORKFLOW_EDIT, request.user, self.get_workflow()) + + return super(SetupWorkflowStateListView, self).dispatch(request, *args, **kwargs) + + def get_workflow(self): + return get_object_or_404(Workflow, pk=self.kwargs['pk']) + + def get_queryset(self): + return self.get_workflow().states.all() + + def get_context_data(self, **kwargs): + context = super(SetupWorkflowStateListView, self).get_context_data(**kwargs) + context.update( + { + 'hide_link': True, + 'object': self.get_workflow(), + 'title': _('States of workflow: %s') % self.get_workflow() + } + ) + + return context + + +class SetupWorkflowStateCreateView(SingleObjectCreateView): + form_class = WorkflowStateForm + + def dispatch(self, request, *args, **kwargs): + try: + Permission.objects.check_permissions(request.user, [PERMISSION_WORKFLOW_EDIT]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_WORKFLOW_EDIT, request.user, self.get_workflow()) + + return super(SetupWorkflowStateCreateView, self).dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super(SetupWorkflowStateCreateView, self).get_context_data(**kwargs) + context.update( + { + 'object': self.get_workflow(), + 'title': _('Create states for workflow: %s') % self.get_workflow() + } + ) + return context + + def get_workflow(self): + return get_object_or_404(Workflow, pk=self.kwargs['pk']) + + def get_queryset(self): + return self.get_workflow().states.all() + + def get_success_url(self): + return reverse('document_states:setup_workflow_states', args=[self.kwargs['pk']]) + + def form_valid(self, form): + self.object = form.save(commit=False) + self.object.workflow = self.get_workflow() + self.object.save() + return super(SetupWorkflowStateCreateView, self).form_valid(form) + + +# Transitions + +class SetupWorkflowTransitionListView(SingleObjectListView): + def dispatch(self, request, *args, **kwargs): + try: + Permission.objects.check_permissions(request.user, [PERMISSION_WORKFLOW_EDIT]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_WORKFLOW_EDIT, request.user, self.get_workflow()) + + return super(SetupWorkflowTransitionListView, self).dispatch(request, *args, **kwargs) + + def get_workflow(self): + return get_object_or_404(Workflow, pk=self.kwargs['pk']) + + def get_queryset(self): + return self.get_workflow().transitions.all() + + def get_context_data(self, **kwargs): + context = super(SetupWorkflowTransitionListView, self).get_context_data(**kwargs) + context.update( + { + 'hide_link': True, + 'object': self.get_workflow(), + 'title': _('Transitions of workflow: %s') % self.get_workflow() + } + ) + + return context + + +class SetupWorkflowTransitionCreateView(SingleObjectCreateView): + form_class = WorkflowTransitionForm + + def dispatch(self, request, *args, **kwargs): + try: + Permission.objects.check_permissions(request.user, [PERMISSION_WORKFLOW_EDIT]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_WORKFLOW_EDIT, request.user, self.get_workflow()) + + return super(SetupWorkflowTransitionCreateView, self).dispatch(request, *args, **kwargs) + + def get_context_data(self, **kwargs): + context = super(SetupWorkflowTransitionCreateView, self).get_context_data(**kwargs) + context.update( + { + 'object': self.get_workflow(), + 'title': _('Create transitions for workflow: %s') % self.get_workflow() + } + ) + return context + + def get_workflow(self): + return get_object_or_404(Workflow, pk=self.kwargs['pk']) + + def get_queryset(self): + return self.get_workflow().transitions.all() + + def get_success_url(self): + return reverse('document_states:setup_workflow_transitions', args=[self.kwargs['pk']]) + + def form_valid(self, form): + self.object = form.save(commit=False) + self.object.workflow = self.get_workflow() + try: + self.object.save() + except IntegrityError: + messages.error(self.request, _('Unable to save transition; integrity error.')) + return super(SetupWorkflowTransitionCreateView, self).form_invalid(form) + else: + return HttpResponseRedirect(self.get_success_url()) diff --git a/mayan/apps/main/static/main/icons/table.png b/mayan/apps/main/static/main/icons/table.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1e11a83410d46c6912689110b05a8e16eee606 GIT binary patch literal 920 zcmV;J184k+P)`(YZ2MPt(oFg$RqAXOr6{HS)~KtZIc zucWeB_fla+?&fR;-;e`YBve~MLWpuOLP8B~HPgD3A6iJIO0r=xzV4CCC*c^AQ2IUz zu_P7C*lbCvG~ABx-?g(<5|;5k+!&d($E6jPSsu^K+xN;p;L>C*Su_oyR zyn{IwR)!RROt#mjbBi1%YLcyMoQgnSIo%g0;qIH08=mK%%`I#RE^Cz}Y$~t=7n5oh z?A7q&;OOgptCF+pUCqipev`PpnsHbfD_`Gzb1=FZeTe(LEIsj~