from __future__ import absolute_import, unicode_literals 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 get_object_or_404 from django.utils.translation import ugettext_lazy as _ from django.views.generic import FormView from acls.models import AccessControlList from common.views import ( AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView, SingleObjectEditView, SingleObjectListView ) from documents.models import Document from permissions import Permission from .forms import ( WorkflowForm, WorkflowInstanceTransitionForm, WorkflowStateForm, WorkflowTransitionForm ) from .models import Workflow, WorkflowInstance, WorkflowState, WorkflowTransition from .permissions import ( permission_workflow_create, permission_workflow_delete, permission_workflow_edit, permission_workflow_view, permission_document_workflow_view, permission_document_workflow_transition ) class DocumentWorkflowInstanceListView(SingleObjectListView): def dispatch(self, request, *args, **kwargs): try: Permission.check_permissions(request.user, [permission_document_workflow_view]) except PermissionDenied: AccessControlList.objects.check_access(permission_document_workflow_view, request.user, self.get_document()) return super(DocumentWorkflowInstanceListView, self).dispatch(request, *args, **kwargs) def get_document(self): return get_object_or_404(Document, pk=self.kwargs['pk']) def get_queryset(self): return self.get_document().workflows.all() def get_context_data(self, **kwargs): context = super(DocumentWorkflowInstanceListView, self).get_context_data(**kwargs) context.update( { 'hide_link': True, 'object': self.get_document(), 'title': _('Workflows for document: %s') % self.get_document(), } ) return context class WorkflowInstanceDetailView(SingleObjectListView): def dispatch(self, request, *args, **kwargs): try: Permission.check_permissions(request.user, [permission_document_workflow_view]) except PermissionDenied: AccessControlList.objects.check_access(permission_document_workflow_view, request.user, self.get_workflow_instance().document) return super(WorkflowInstanceDetailView, self).dispatch(request, *args, **kwargs) def get_workflow_instance(self): return get_object_or_404(WorkflowInstance, pk=self.kwargs['pk']) def get_queryset(self): return self.get_workflow_instance().log_entries.order_by('-datetime') def get_context_data(self, **kwargs): context = { 'navigation_object_list': ['object', 'workflow_instance'], 'object': self.get_workflow_instance().document, 'object_list': self.get_queryset(), 'title': _('Log entries'), 'hide_object': True, 'title': _('Detail of workflow: %(workflow)s') % { 'workflow': self.get_workflow_instance() }, 'workflow_instance': self.get_workflow_instance(), } return context class WorkflowInstanceTransitionView(FormView): form_class = WorkflowInstanceTransitionForm template_name = 'appearance/generic_form.html' def dispatch(self, request, *args, **kwargs): try: Permission.check_permissions(request.user, [permission_document_workflow_transition]) except PermissionDenied: AccessControlList.objects.check_access(permission_document_workflow_transition, request.user, self.get_workflow_instance().document) return super(WorkflowInstanceTransitionView, self).dispatch(request, *args, **kwargs) def form_valid(self, form): transition = self.get_workflow_instance().workflow.transitions.get(pk=form.cleaned_data['transition']) self.get_workflow_instance().do_transition(comment=form.cleaned_data['comment'], transition=transition, user=self.request.user) return HttpResponseRedirect(self.get_success_url()) def get_form_kwargs(self): kwargs = super(WorkflowInstanceTransitionView, self).get_form_kwargs() kwargs['workflow'] = self.get_workflow_instance() return kwargs def get_workflow_instance(self): return get_object_or_404(WorkflowInstance, pk=self.kwargs['pk']) def get_context_data(self, **kwargs): context = super(WorkflowInstanceTransitionView, self).get_context_data(**kwargs) context.update( { 'navigation_object_list': ['object', 'workflow_instance'], 'object': self.get_workflow_instance().document, 'submit_label': _('Submit'), 'title': _('Do transition for workflow: %s') % self.get_workflow_instance(), 'workflow_instance': self.get_workflow_instance(), } ) return context def get_success_url(self): return self.get_workflow_instance().get_absolute_url() # Setup class SetupWorkflowListView(SingleObjectListView): extra_context = { 'title': _('Workflows'), 'hide_link': True, } model = Workflow view_permission = permission_workflow_view class SetupWorkflowCreateView(SingleObjectCreateView): form_class = WorkflowForm model = Workflow view_permission = permission_workflow_create success_url = reverse_lazy('document_states:setup_workflow_list') class SetupWorkflowEditView(SingleObjectEditView): form_class = WorkflowForm model = Workflow view_permission = permission_workflow_edit success_url = reverse_lazy('document_states:setup_workflow_list') class SetupWorkflowDeleteView(SingleObjectDeleteView): model = Workflow view_permission = permission_workflow_delete success_url = reverse_lazy('document_states:setup_workflow_list') class SetupWorkflowDocumentTypesView(AssignRemoveView): decode_content_type = True object_permission = permission_workflow_edit left_list_title = _('Available document types') right_list_title = _('Document types assigned this workflow') def add(self, item): self.get_object().document_types.add(item) # TODO: add task launching this workflow for all the document types of # item def get_object(self): return get_object_or_404(Workflow, pk=self.kwargs['pk']) def left_list(self): return AssignRemoveView.generate_choices(self.get_object().get_document_types_not_in_workflow()) def right_list(self): return AssignRemoveView.generate_choices(self.get_object().document_types.all()) def remove(self, item): self.get_object().document_types.remove(item) # TODO: add task deleting this workflow for all the document types of # item def get_context_data(self, **kwargs): data = super(SetupWorkflowDocumentTypesView, self).get_context_data(**kwargs) data.update({ 'title': _('Document types assigned the workflow: %s') % self.get_object(), 'object': self.get_object(), }) return data class SetupWorkflowStateListView(SingleObjectListView): def dispatch(self, request, *args, **kwargs): try: Permission.check_permissions(request.user, [permission_workflow_edit]) except PermissionDenied: AccessControlList.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.check_permissions(request.user, [permission_workflow_edit]) except PermissionDenied: AccessControlList.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) class SetupWorkflowStateDeleteView(SingleObjectDeleteView): model = WorkflowState view_permission = permission_workflow_delete def get_context_data(self, **kwargs): context = super(SetupWorkflowStateDeleteView, self).get_context_data(**kwargs) context.update( { 'navigation_object_list': ['object', 'workflow_instance'], 'object': self.get_object().workflow, 'workflow_instance': self.get_object(), } ) return context def get_success_url(self): return reverse('document_states:setup_workflow_States', args=[self.get_object().workflow.pk]) class SetupWorkflowStateEditView(SingleObjectEditView): form_class = WorkflowStateForm model = WorkflowState view_permission = permission_workflow_edit def get_context_data(self, **kwargs): context = super(SetupWorkflowStateEditView, self).get_context_data(**kwargs) context.update( { 'navigation_object_list': ['object', 'workflow_instance'], 'object': self.get_object().workflow, 'workflow_instance': self.get_object(), } ) return context def get_success_url(self): return reverse('document_states:setup_workflow_states', args=[self.get_object().workflow.pk]) # Transitions class SetupWorkflowTransitionListView(SingleObjectListView): def dispatch(self, request, *args, **kwargs): try: Permission.check_permissions(request.user, [permission_workflow_edit]) except PermissionDenied: AccessControlList.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.check_permissions(request.user, [permission_workflow_edit]) except PermissionDenied: AccessControlList.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_form_kwargs(self): kwargs = super(SetupWorkflowTransitionCreateView, self).get_form_kwargs() kwargs['workflow'] = self.get_workflow() return 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_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()) class SetupWorkflowTransitionDeleteView(SingleObjectDeleteView): model = WorkflowTransition view_permission = permission_workflow_delete def get_context_data(self, **kwargs): context = super(SetupWorkflowTransitionDeleteView, self).get_context_data(**kwargs) context.update( { 'object': self.get_object().workflow, 'navigation_object_list': ['object', 'workflow_instance'], 'workflow_instance': self.get_object(), } ) return context def get_success_url(self): return reverse('document_states:setup_workflow_transitions', args=[self.get_object().workflow.pk]) class SetupWorkflowTransitionEditView(SingleObjectEditView): form_class = WorkflowTransitionForm model = WorkflowTransition view_permission = permission_workflow_edit def get_context_data(self, **kwargs): context = super(SetupWorkflowTransitionEditView, self).get_context_data(**kwargs) context.update( { 'navigation_object_list': ['object', 'workflow_instance'], 'object': self.get_object().workflow, 'workflow_instance': self.get_object(), } ) return context def get_form_kwargs(self): kwargs = super(SetupWorkflowTransitionEditView, self).get_form_kwargs() kwargs['workflow'] = self.get_object().workflow return kwargs def get_success_url(self): return reverse('document_states:setup_workflow_transitions', args=[self.get_object().workflow.pk])