diff --git a/docs/releases/2.2.rst b/docs/releases/2.2.rst index 81d969ebc4..d7e6895f72 100644 --- a/docs/releases/2.2.rst +++ b/docs/releases/2.2.rst @@ -119,6 +119,8 @@ Other changes - Testing for orphaned temporary files and orphaned file handles is now optional and controlled by the COMMON_TEST_FILE_HANDLES and COMMON_TEST_FILE_HANDLES settings. +- Add tool to launch all workflows. GitLab issue #355 + Removals -------- - Removal of the OCR_TESSERACT_PATH configuration setting. @@ -191,5 +193,6 @@ Bugs fixed or issues closed * `GitLab issue #328 `_ Upgrade Warning/Error during performupgrade (v2.1.3 to v2.1.4) * `GitLab issue #342 `_ Tags should be of unordered / unsorted data type * `GitLab issue #343 `_ Bootstrap's dependency on fonts.googleapis.com causes Mayan EDMS web interface load slowly if public internet is unreachable +* `GitLab issue #355 `_ Workflow changes only on new added documents .. _PyPI: https://pypi.python.org/pypi/mayan-edms/ diff --git a/mayan/apps/document_states/apps.py b/mayan/apps/document_states/apps.py index 706d7435d3..e2d2b55aef 100644 --- a/mayan/apps/document_states/apps.py +++ b/mayan/apps/document_states/apps.py @@ -4,11 +4,14 @@ from django.apps import apps from django.db.models.signals import post_save from django.utils.translation import ugettext_lazy as _ +from kombu import Exchange, Queue + from common import ( MayanAppConfig, menu_facet, menu_object, menu_secondary, menu_setup, - menu_sidebar + menu_sidebar, menu_tools ) from common.widgets import two_state_template +from mayan.celery import app from navigation import SourceColumn from rest_api.classes import APIEndPoint @@ -21,7 +24,8 @@ from .links import ( link_setup_workflow_state_delete, link_setup_workflow_state_edit, link_setup_workflow_transitions, link_setup_workflow_transition_create, link_setup_workflow_transition_delete, link_setup_workflow_transition_edit, - link_workflow_instance_detail, link_workflow_instance_transition + link_tool_launch_all_workflows, link_workflow_instance_detail, + link_workflow_instance_transition ) @@ -111,6 +115,23 @@ class DocumentStatesApp(MayanAppConfig): attribute='destination_state' ) + app.conf.CELERY_QUEUES.extend( + ( + Queue( + 'document_states', Exchange('document_states'), + routing_key='converter' + ), + ) + ) + + app.conf.CELERY_ROUTES.update( + { + 'document_states.tasks.task_launch_all_workflows': { + 'queue': 'document_states' + }, + } + ) + menu_facet.bind_links( links=(link_document_workflow_instance_list,), sources=(Document,) ) @@ -153,6 +174,7 @@ class DocumentStatesApp(MayanAppConfig): link_setup_workflow_transition_create ), sources=(Workflow,) ) + menu_tools.bind_links(links=(link_tool_launch_all_workflows,)) post_save.connect( launch_workflow, dispatch_uid='launch_workflow', sender=Document diff --git a/mayan/apps/document_states/links.py b/mayan/apps/document_states/links.py index f9a0e3bba3..4a3abbe7e1 100644 --- a/mayan/apps/document_states/links.py +++ b/mayan/apps/document_states/links.py @@ -7,7 +7,7 @@ from navigation import Link from .permissions import ( permission_workflow_create, permission_workflow_delete, permission_workflow_edit, permission_workflow_transition, - permission_workflow_view, + permission_workflow_tools, permission_workflow_view, ) link_document_workflow_instance_list = Link( @@ -71,6 +71,12 @@ link_setup_workflow_transitions = Link( permissions=(permission_workflow_view,), text=_('Transitions'), view='document_states:setup_workflow_transitions', args='object.pk' ) +link_tool_launch_all_workflows = Link( + icon='fa fa-sitemap', + permissions=(permission_workflow_tools,), + text=_('Launch all workflows'), + view='document_states:tool_launch_all_workflows' +) link_workflow_instance_detail = Link( permissions=(permission_workflow_view,), text=_('Detail'), view='document_states:workflow_instance_detail', args='resolved_object.pk' diff --git a/mayan/apps/document_states/permissions.py b/mayan/apps/document_states/permissions.py index 54ac90f282..470c196a41 100644 --- a/mayan/apps/document_states/permissions.py +++ b/mayan/apps/document_states/permissions.py @@ -24,3 +24,6 @@ permission_workflow_view = namespace.add_permission( permission_workflow_transition = namespace.add_permission( name='workflow_transition', label=_('Transition workflows') ) +permission_workflow_tools = namespace.add_permission( + name='workflow_tools', label=_('Execute workflow tools') +) diff --git a/mayan/apps/document_states/tasks.py b/mayan/apps/document_states/tasks.py new file mode 100644 index 0000000000..ec550c27b3 --- /dev/null +++ b/mayan/apps/document_states/tasks.py @@ -0,0 +1,24 @@ +from __future__ import unicode_literals + +import logging + +from django.apps import apps + +from mayan.celery import app + +logger = logging.getLogger(__name__) + + +@app.task(ignore_result=True) +def task_launch_all_workflows(): + Document = apps.get_model(app_label='documents', model_name='Document') + Workflow = apps.get_model( + app_label='document_states', model_name='Workflow' + ) + + logger.info('Start launching workflows') + for document in Document.objects.all(): + print 'document :', document + Workflow.objects.launch_for(document=document) + + logger.info('Finished launching workflows') diff --git a/mayan/apps/document_states/tests/test_views.py b/mayan/apps/document_states/tests/test_views.py index 251f127f21..a15faab40a 100644 --- a/mayan/apps/document_states/tests/test_views.py +++ b/mayan/apps/document_states/tests/test_views.py @@ -1,8 +1,10 @@ from __future__ import unicode_literals from common.tests.test_views import GenericViewTestCase +from documents.tests.test_views import GenericDocumentViewTestCase from ..models import Workflow, WorkflowState, WorkflowTransition +from ..permissions import permission_workflow_tools from .literals import ( TEST_WORKFLOW_LABEL, TEST_WORKFLOW_INITIAL_STATE_LABEL, @@ -149,3 +151,58 @@ class DocumentStateViewTestCase(GenericViewTestCase): self.assertEquals(WorkflowState.objects.count(), 2) self.assertEquals(Workflow.objects.count(), 1) self.assertEquals(WorkflowTransition.objects.count(), 0) + + +class DocumentStateToolViewTestCase(GenericDocumentViewTestCase): + def _create_workflow(self): + self.workflow = Workflow.objects.create(label=TEST_WORKFLOW_LABEL) + self.workflow.document_types.add(self.document_type) + + def _create_workflow_states(self): + self._create_workflow() + self.workflow_state_1 = self.workflow.states.create( + completion=TEST_WORKFLOW_INITIAL_STATE_COMPLETION, + initial=True, label=TEST_WORKFLOW_INITIAL_STATE_LABEL + ) + self.workflow_state_2 = self.workflow.states.create( + completion=TEST_WORKFLOW_STATE_COMPLETION, + label=TEST_WORKFLOW_STATE_LABEL + ) + + def _create_workflow_transition(self): + self._create_workflow_states() + self.workflow_transition = self.workflow.transitions.create( + label=TEST_WORKFLOW_TRANSITION_LABEL, + origin_state=self.workflow_state_1, + destination_state=self.workflow_state_2, + ) + + def test_tool_launch_all_workflows_view_no_permission(self): + self._create_workflow_transition() + + self.login_user() + + self.assertEqual(self.document.workflows.count(), 0) + + response = self.post( + 'document_states:tool_launch_all_workflows', + ) + self.assertEqual(response.status_code, 403) + self.assertEqual(self.document.workflows.count(), 0) + + def test_tool_launch_all_workflows_view_with_permission(self): + self._create_workflow_transition() + + self.login_user() + self.grant(permission_workflow_tools) + + self.assertEqual(self.document.workflows.count(), 0) + + response = self.post( + 'document_states:tool_launch_all_workflows', + ) + self.assertEqual(response.status_code, 200) + + self.assertEqual( + self.document.workflows.first().workflow, self.workflow + ) diff --git a/mayan/apps/document_states/urls.py b/mayan/apps/document_states/urls.py index b2dacd6293..8b54a58748 100644 --- a/mayan/apps/document_states/urls.py +++ b/mayan/apps/document_states/urls.py @@ -17,8 +17,8 @@ from .views import ( SetupWorkflowStateEditView, SetupWorkflowStateListView, SetupWorkflowTransitionListView, SetupWorkflowTransitionCreateView, SetupWorkflowTransitionDeleteView, SetupWorkflowTransitionEditView, - WorkflowDocumentListView, WorkflowInstanceDetailView, - WorkflowInstanceTransitionView + ToolLaunchAllWorkflows, WorkflowDocumentListView, + WorkflowInstanceDetailView, WorkflowInstanceTransitionView ) urlpatterns = [ @@ -102,6 +102,11 @@ urlpatterns = [ SetupWorkflowTransitionEditView.as_view(), name='setup_workflow_transition_edit' ), + url( + r'^tools/workflow/all/launch/$', + ToolLaunchAllWorkflows.as_view(), + name='tool_launch_all_workflows' + ), ] api_urls = [ diff --git a/mayan/apps/document_states/views.py b/mayan/apps/document_states/views.py index c63ac0f777..d951a25298 100644 --- a/mayan/apps/document_states/views.py +++ b/mayan/apps/document_states/views.py @@ -10,8 +10,8 @@ from django.views.generic import FormView from acls.models import AccessControlList from common.views import ( - AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView, - SingleObjectEditView, SingleObjectListView + AssignRemoveView, ConfirmView, SingleObjectCreateView, + SingleObjectDeleteView, SingleObjectEditView, SingleObjectListView ) from documents.models import Document from documents.views import DocumentListView @@ -24,8 +24,9 @@ from .models import Workflow, WorkflowInstance, WorkflowState, WorkflowTransitio from .permissions import ( permission_workflow_create, permission_workflow_delete, permission_workflow_edit, permission_workflow_transition, - permission_workflow_view, + permission_workflow_tools, permission_workflow_view, ) +from .tasks import task_launch_all_workflows class DocumentWorkflowInstanceListView(SingleObjectListView): @@ -429,3 +430,16 @@ class SetupWorkflowTransitionEditView(SingleObjectEditView): 'document_states:setup_workflow_transitions', args=(self.get_object().workflow.pk,) ) + + +class ToolLaunchAllWorkflows(ConfirmView): + extra_context = { + 'title': _('Launch all workflows?') + } + view_permission = permission_workflow_tools + + def view_action(self): + task_launch_all_workflows.apply_async() + messages.success( + self.request, _('Workflow launch queued successfully.') + )