def wf_send_msg(users, msg_type, event=None, ext_ctx=None): if not users: return users = set(users) if event: # ignore operator if event.user in users: users = users.remove(event.user) for send_msg in settings.WF_SEND_MSG_FUNCS: as_callable(send_msg)(users, msg_type, event, ext_ctx)
class ExecuteBackToTransitionView(ExecuteTransitionView): form_classes = { 'form': as_callable(settings.BACK_TO_ACTIVITY_FORM) } def has_permission(self, request, instance, task, transition): # TODO ... return True def get_form_kwargs(self, form_class_key, form_class): """ Returns the keyword arguments for instantiating the form. """ kwargs = super().get_form_kwargs(form_class_key, form_class) kwargs['process_instance'] = self.process_instance return kwargs def get_init_transition(self, process_instance, request): return process_instance.get_back_to_transition() def get_transition_before_execute(self, cleaned_data): back_to_node = cleaned_data.get('back_to_node') transition = self.transition transition.output_node = Node.objects.get(pk=back_to_node) return transition
class AddAssigneeView(ExecuteTransitionView): form_classes = {'form': as_callable(settings.ADD_ASSIGNEE_FORM)} def get_form_kwargs(self, form_class_key, form_class): kwargs = super().get_form_kwargs(form_class_key, form_class) kwargs['instance'] = self.process_instance return kwargs def get_init_transition(self, process_instance, request): return process_instance.get_add_assignee_transition() def do_transition(self, cleaned_data): request = self.request transition = self.get_transition_before_execute(cleaned_data) comment = cleaned_data.get('comment') attachments = cleaned_data.get('attachments') user = request.user instance = self.process_instance assignees = cleaned_data.get('assignees', []) for assignee in assignees: instance.create_task(assignee, is_joint=True) msg = 'Add assignee %s.' % ', '.join( [GET_USER_DISPLAY_NAME_FUNC(e) for e in assignees]) messages.info(request, msg) comment = msg + '\n' + comment event = create_event(instance, transition, comment=comment, user=user, old_node=instance.cur_node, new_node=instance.cur_node) event.attachments.add(*attachments) wf_send_msg(assignees, 'new_workitem', event)
class BatchExecuteTransitionView(FormView): template_name = 'lbworkflow/batch_transition_form.html' form_class = as_callable(settings.BATCH_WORK_FLOW_FORM) def get_success_url(self): return reverse("wf_todo") def get_transition_name(self): return 'Agree' def get_context_data(self, **kwargs): kwargs['task_list'] = self.task_list kwargs['transition_name'] = self.get_transition_name() return super(BatchExecuteTransitionView, self).get_context_data(**kwargs) def get_transition(self, process_instance): pass def add_processed_message(self, process_instance, act_descn='Processed'): add_processed_message(self.request, process_instance, act_descn) def post(self, request, *args, **kwargs): if not request.POST.get('do_submit'): return self.get(request, *args, **kwargs) return super(BatchExecuteTransitionView, self).post(request, *args, **kwargs) def form_valid(self, form): user = self.request.user cleaned_data = form.cleaned_data for task in self.task_list: if task.user != user: # TODO message for ignore continue instance = task.instance transition = self.get_transition(task.instance) comment = cleaned_data.get('comment') attachments = cleaned_data.get('attachments') TransitionExecutor(user, instance, task, transition, comment, attachments).execute() self.add_processed_message(instance) return HttpResponseRedirect(self.get_success_url()) def get_task_list(self, request): task_pk_list = request.POST.getlist('wi') task_pk_list = [e for e in task_pk_list if e] task_list = Task.objects.filter(status='in progress', pk__in=task_pk_list) return task_list def dispatch(self, request, *args, **kwargs): self.task_list = self.get_task_list(request) return super(BatchExecuteTransitionView, self).dispatch(request, *args, **kwargs)
class BatchExecuteTransitionView(FormView): template_name = "lbworkflow/batch_transition_form.html" form_class = as_callable(settings.BATCH_WORK_FLOW_FORM) success_url = reverse_lazy("wf_todo") def get_context_data(self, **kwargs): kwargs["task_list"] = self.task_list kwargs["transition_name"] = self.get_transition_name() return super().get_context_data(**kwargs) def get_transition_name(self): return "Agree" def get_transition(self, process_instance): pass def add_processed_message(self, process_instance, act_descn="Processed"): add_processed_message(self.request, process_instance, act_descn) def post(self, request, *args, **kwargs): if not request.POST.get("do_submit"): return self.get(request, *args, **kwargs) return super().post(request, *args, **kwargs) def form_valid(self, form): user = self.request.user cleaned_data = form.cleaned_data for task in self.task_list: if task.user != user: # TODO message for ignore continue instance = task.instance transition = self.get_transition(task.instance) comment = cleaned_data.get("comment") attachments = cleaned_data.get("attachments") TransitionExecutor( user, instance, task, transition, comment, attachments ).execute() self.add_processed_message(instance) return super().form_valid(form) def get_task_list(self, request): task_pk_list = request.POST.getlist("wi") task_pk_list = [e for e in task_pk_list if e] task_list = Task.objects.filter( status="in progress", pk__in=task_pk_list ) return task_list def dispatch(self, request, *args, **kwargs): self.task_list = self.get_task_list(request) return super().dispatch(request, *args, **kwargs)
class ExecuteTransitionView(TemplateResponseMixin, FormsView): """ request.GET: ts_id: transition pk wi_id: work item pk pid: process instance pk (not used) """ form_classes = {'form': as_callable(settings.WORK_FLOW_FORM)} def get_success_url(self): return reverse("wf_todo") def get_template_names(self): try: return super(ExecuteTransitionView, self).get_template_names() except ImproperlyConfigured: base_tmpl = 'lbworkflow/do_transition_form.html' _meta = self.object._meta app_label = _meta.app_label object_name = _meta.object_name.lower() return [ "%s/%s/%s" % ( app_label, object_name, base_tmpl, ), "%s/%s" % ( app_label, base_tmpl, ), base_tmpl ] def get_init_transition(self, process_instance, request): ts_id = request.GET.get('ts_id') return Transition.objects.get(pk=ts_id) def get_task(self, request): # TODO admin may don't have task, need auto create a work item for admin wi_id = request.GET.get('wi_id') user = request.user return get_or_none(Task, Q(user=user) | Q(agent_user=user), id=wi_id) def init_process_data(self, request): task = self.get_task(request) if not task: self.raise_no_permission_exception() instance = task.instance self.transition = self.get_init_transition(instance, request) self.task = task self.process_instance = instance self.object = instance.content_object def raise_no_permission_exception(self, instance=None): from django.template import Context, Template t = Template(""" <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> No permission to perform this action {% if instance %} <br/> <a href="{% url 'wf_detail' instance.pk %}"> View this process </a> {% endif %} </body> </html> """) http_response = HttpResponse(t.render(Context({"instance": instance})), content_type='text/html', status=403) raise HttpResponseException(http_response) def has_permission(self, request, instance, task, transition): node_is_ok = (transition.input_node == instance.cur_node and task.node == instance.cur_node and task.status == 'in progress') user_is_ok = (request.user in [task.user, task.agent_user] or instance.is_wf_admin(request.user)) is_ok = node_is_ok and user_is_ok return is_ok def check_permission(self, request): """ If no permission raise HttpResponseException """ if not self.has_permission(request, self.process_instance, self.task, self.transition): self.raise_no_permission_exception(self.process_instance) def get_transition_before_execute(self, cleaned_data): return self.transition def do_transition(self, cleaned_data): comment = cleaned_data.get('comment') attachments = cleaned_data.get('attachments') user = self.request.user instance = self.process_instance transition = self.get_transition_before_execute(cleaned_data) TransitionExecutor(user, instance, self.task, transition, comment, attachments).execute() def add_processed_message(self, process_instance, act_descn='Processed'): add_processed_message(self.request, process_instance, act_descn) def save_form(self, form): return form.save() def forms_valid(self, **forms): form = forms.pop('form') if isinstance(form, ModelForm): wf_obj = self.save_form(form) # update cache for wf_obj self.object = wf_obj self.process_instance = wf_obj.pinstance for other_form in forms: self.save_form(other_form) self.do_transition(form.cleaned_data) self.add_processed_message(self.process_instance) return HttpResponseRedirect(self.get_success_url()) def get_context_data(self, **kwargs): kwargs = super(ExecuteTransitionView, self).get_context_data(**kwargs) kwargs['task'] = self.task kwargs['transition'] = self.transition kwargs.update(user_wf_info_as_dict(self.object, self.request.user)) return kwargs def dispatch(self, request, *args, **kwargs): self.request = request try: self.init_process_data(request) self.check_permission(request) return super(ExecuteTransitionView, self).dispatch(request, *args, **kwargs) except HttpResponseException as error: return error.http_response
def handle(self, *args, **options): func = options['func'] func = as_callable(func) func()
def get_permit_query_param(self, user, q_param): # override this function to add addition permit get_permit_query_param = as_callable(PROCESS_INSTANCE_GET_PERMIT_QUERY_PARAM_FUNC) return get_permit_query_param(user, q_param)
class ExecuteTransitionView(TemplateResponseMixin, FormsView): """ request.GET: ts_id: transition pk wi_id: work item pk pid: process instance pk (not used) """ form_classes = {"form": as_callable(settings.WORK_FLOW_FORM)} success_url = reverse_lazy("wf_todo") def get_template_names(self): try: return super().get_template_names() except ImproperlyConfigured: base_tmpl = "lbworkflow/do_transition_form.html" _meta = self.object._meta app_label = _meta.app_label object_name = _meta.object_name.lower() return [ "%s/%s/%s" % ( app_label, object_name, base_tmpl, ), "%s/%s" % ( app_label, base_tmpl, ), base_tmpl, ] def get_init_transition(self, process_instance, request): ts_id = request.GET.get("ts_id") return Transition.objects.get(pk=ts_id) def get_task(self, request): # TODO admin may don't have task, need auto create a work item for admin wi_id = request.GET.get("wi_id") user = request.user return get_or_none(Task, Q(user=user) | Q(agent_user=user), id=wi_id) def init_process_data(self, request): task = self.get_task(request) if not task: self.raise_no_permission_exception() instance = task.instance self.transition = self.get_init_transition(instance, request) self.task = task self.process_instance = instance self.object = instance.content_object def raise_no_permission_exception(self, instance=None): raise PermissionDenied() def has_permission(self, request, instance, task, transition): node_is_ok = ( transition.input_node == instance.cur_node and task.node == instance.cur_node and task.status == "in progress" ) user_is_ok = ( request.user in [ task.user, task.agent_user, ] or instance.is_wf_admin(request.user) ) is_ok = node_is_ok and user_is_ok return is_ok def check_permission(self, request): """If no permission raise HttpResponseException""" if not self.has_permission( request, self.process_instance, self.task, self.transition ): self.raise_no_permission_exception(self.process_instance) def get_transition_before_execute(self, cleaned_data): return self.transition def do_transition(self, cleaned_data): comment = cleaned_data.get("comment") attachments = cleaned_data.get("attachments") user = self.request.user instance = self.process_instance transition = self.get_transition_before_execute(cleaned_data) TransitionExecutor( user, instance, self.task, transition, comment, attachments ).execute() def add_processed_message(self, process_instance, act_descn="Processed"): add_processed_message(self.request, process_instance, act_descn) def save_form(self, form): return form.save() def forms_valid(self, **forms): form = forms.pop("form") if isinstance(form, ModelForm): wf_obj = self.save_form(form) # update cache for wf_obj self.object = wf_obj self.process_instance = wf_obj.pinstance for other_form in forms: self.save_form(other_form) self.do_transition(form.cleaned_data) self.add_processed_message(self.process_instance) return super().forms_valid(**forms) def get_context_data(self, **kwargs): kwargs = super().get_context_data(**kwargs) kwargs["task"] = self.task kwargs["transition"] = self.transition kwargs.update(user_wf_info_as_dict(self.object, self.request.user)) return kwargs def dispatch(self, request, *args, **kwargs): self.request = request try: self.init_process_data(request) self.check_permission(request) return super().dispatch(request, *args, **kwargs) except HttpResponseException as error: return error.http_response
class BatchExecuteTransitionView(FormView): # template_name = 'lbworkflow/batch_transition_form.html' template_name = 'myworkflow/mywf_batch_agree.html' form_class = as_callable(settings.BATCH_WORK_FLOW_FORM) def get_success_url(self): return reverse("wf_todo") def get_transition_name(self): return 'Agree' def get_context_data(self, **kwargs): kwargs['task_list'] = self.task_list kwargs['transition_name'] = self.get_transition_name() return super().get_context_data(**kwargs) def get_transition(self, process_instance): # print('2222') pass def add_processed_message(self, process_instance, act_descn='Processed'): add_processed_message(self.request, process_instance, act_descn) def post(self, request, *args, **kwargs): if not request.POST.get('do_submit'): return self.get(request, *args, **kwargs) return super().post(request, *args, **kwargs) def form_valid(self, form): user = self.request.user cleaned_data = form.cleaned_data for task in self.task_list: if task.user != user: # TODO message for ignore continue instance = task.instance # 获取lbworkflow_processinstance的summary字段内容 # print(instance.content_object) # 定期策划01 # print(task.instance) # print(222222222222222222) # 52 transition = self.get_transition(task.instance) comment = cleaned_data.get('comment') attachments = cleaned_data.get('attachments') # print('11',transition) # 11 Regularworkplan - Agree # print(transition.output_node) # 二级审批 TransitionExecutor( user, instance, task, transition, comment, attachments ).execute() # res_a = ProcessInstance.objects.filter(cur_node=task.node_id) res_e = Event.objects.filter(task=task.id) # res.instance_id res_task = Task.objects.filter(id=task.id) res_pi = ProcessInstance.objects.filter(id=res_task[0].instance.id) # print(res_e[0].instance) # print(task.user) for res in res_e: # print(res_e[0].instance,res_e[0].user,res_e[0].old_node,res_e[0].task,res_e[0].comment) # print("611111111111") # print(comment) # res = TaskHistory.objects.all() # print(res) # print(111111111111111111111111) TaskHistory.objects.create(node_name=task.node,approve_name=user,created_name=res_pi[0].id,approve_type=res.act_type,content=res.comment,process_id=int(res.instance_id),created_time=task.created_on) self.add_processed_message(instance) return HttpResponseRedirect(self.get_success_url()) def get_task_list(self, request): task_pk_list = request.POST.getlist('wi') task_pk_list = [e for e in task_pk_list if e] task_list = Task.objects.filter(status='in progress', pk__in=task_pk_list) return task_list def dispatch(self, request, *args, **kwargs): self.task_list = self.get_task_list(request) return super().dispatch(request, *args, **kwargs)
from django.shortcuts import get_object_or_404 from django.shortcuts import redirect from django.shortcuts import render from django.urls import reverse from lbutils import as_callable from lbworkflow import settings from lbworkflow.models import Process from lbworkflow.models import ProcessCategory from lbworkflow.models import ProcessInstance from .helper import import_wf_views from .helper import user_wf_info_as_dict from systemsettings.views import menu_data can_edit_wf = as_callable(settings.CAN_EDIT_WF_FUNC) can_submit_wf = as_callable(settings.CAN_SUBMIT_WF_FUNC) can_view_wf = as_callable(settings.CAN_VIEW_WF_FUNC) def new(request, wf_code): # 创建新的工单,wf_code 为models名称 views = import_wf_views(wf_code) process = Process.objects.get(code=wf_code) if not can_submit_wf(process, request.user): raise PermissionDenied return views.new(request, wf_code=wf_code) def show_list(request, wf_code): views = import_wf_views(wf_code) return views.show_list(request, wf_code=wf_code)
def load_wf_data(app, wf_code=""): if wf_code: func = "%s.wfdata.load_%s" % (app, wf_code) else: func = "%s.wfdata.load_data" % app as_callable(func)()
def safe_eval(source, globals, *args, **kwargs): globals['Q'] = Q for s in settings.EVAL_FUNCS: globals[s[0]] = as_callable(s[1]) source = source.replace('import', '') return eval(source, globals, *args, **kwargs)