chore: re-initialize git repository for deployment
This commit is contained in:
@@ -0,0 +1 @@
|
||||
default_app_config = 'workflow.apps.WorkflowConfig'
|
||||
@@ -0,0 +1,118 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from common import generic
|
||||
from workflow.models import Modal,Node,TodoList,Instance,History
|
||||
|
||||
|
||||
class NodeInline(admin.TabularInline):
|
||||
model = Node
|
||||
fields = ['code','name','next_user_handler','can_deny','can_terminate']
|
||||
|
||||
def get_extra(self, request, obj=None, **kwargs):
|
||||
if obj:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
class WorkflowModelAdmin(admin.ModelAdmin):
|
||||
list_display = ['code','name','begin','end']
|
||||
inlines = [NodeInline]
|
||||
readonly_fields = ['app_name','model_name']
|
||||
raw_id_fields = ['content_type']
|
||||
fields = (
|
||||
('begin','end',),('code','name',),('description',),('content_type',),('app_name','model_name',),
|
||||
)
|
||||
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
print kwargs
|
||||
return super(WorkflowModelAdmin,self).get_form(request,obj,**kwargs)
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
import datetime
|
||||
super(WorkflowModelAdmin,self).save_model(request,obj,form,change)
|
||||
|
||||
if not obj.code:
|
||||
code = 'WF%03d' % obj.id
|
||||
obj.code = code
|
||||
obj.save()
|
||||
if not obj.begin:
|
||||
obj.begin = datetime.date.today()
|
||||
obj.end = datetime.date(9999,12,31)
|
||||
app_name = obj.content_type.app_label
|
||||
model_name = obj.content_type.model
|
||||
obj.app_name = app_name
|
||||
obj.model_name = model_name
|
||||
obj.save()
|
||||
|
||||
|
||||
class WorkflowNodeAdmin(admin.ModelAdmin):
|
||||
fields = (
|
||||
('modal',),
|
||||
('name','code',),
|
||||
('start','stop','can_terminate','can_deny','can_edit',),
|
||||
('email_notice','short_message_notice','approve_node',),('next',),
|
||||
('handler_type',),
|
||||
('handler',),
|
||||
('next_user_handler','next_node_handler',),
|
||||
('status_field','status_value',),('action',),
|
||||
('users',),('positions',),('roles',),
|
||||
)
|
||||
list_display = ['code','name','modal','can_deny','can_terminate']
|
||||
list_display_links = ['code','name']
|
||||
list_filter = ['modal']
|
||||
readonly_fields = ['modal','code']
|
||||
filter_horizontal = ['next','users','positions','roles','departments',]
|
||||
radio_fields = {'handler_type':admin.HORIZONTAL}
|
||||
search_fields = ['modal__code','modal__name','code','name']
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
if obj and obj.stop:
|
||||
return ['modal','code','next']
|
||||
return super(WorkflowNodeAdmin,self).get_readonly_fields(request,obj)
|
||||
|
||||
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
|
||||
if db_field.name == 'next':
|
||||
apps = generic.get_app_model_info_from_request(request)
|
||||
# print apps
|
||||
if apps and apps.get('obj'):
|
||||
# print 'it is here'
|
||||
obj = apps.get('obj')
|
||||
# print obj.modal
|
||||
kwargs['queryset'] = Node.objects.filter(modal=obj.modal).exclude(id=obj.id)
|
||||
else:
|
||||
kwargs['queryset'] = Node.objects.filter(id=-1)
|
||||
|
||||
return super(WorkflowNodeAdmin,self).formfield_for_manytomany(db_field,request,**kwargs)
|
||||
|
||||
|
||||
class InstanceAdmin(admin.ModelAdmin):
|
||||
list_display = ['code','modal','starter','start_time','status']
|
||||
readonly_fields = ['code','modal','starter','start_time','status','object_id','approved_time','current_nodes']
|
||||
|
||||
|
||||
class TodoAdmin(admin.ModelAdmin):
|
||||
list_display = ['code_link','modal_dsc','href','node_dsc','is_read','status','submitter','arrived_time']
|
||||
list_filter = ['status']
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super(TodoAdmin,self).get_queryset(request).filter(user=request.user)
|
||||
|
||||
|
||||
class HistoryAdmin(admin.ModelAdmin):
|
||||
list_display = ['inst','node','user','pro_time','memo']
|
||||
|
||||
|
||||
class ContentTypeAdmin(admin.ModelAdmin):
|
||||
list_display = ['app_label','model']
|
||||
search_fields = ['app_label','model']
|
||||
list_per_page = 20
|
||||
list_filter = ['app_label']
|
||||
|
||||
|
||||
admin.site.register(Modal, WorkflowModelAdmin)
|
||||
admin.site.register(Node, WorkflowNodeAdmin)
|
||||
admin.site.register(Instance, InstanceAdmin)
|
||||
admin.site.register(TodoList, TodoAdmin)
|
||||
admin.site.register(History, HistoryAdmin)
|
||||
admin.site.register(ContentType,ContentTypeAdmin)
|
||||
@@ -0,0 +1,9 @@
|
||||
__author__ = 'zhugl'
|
||||
# created at 15-4-22
|
||||
from django.apps.config import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class WorkflowConfig(AppConfig):
|
||||
name = 'workflow'
|
||||
verbose_name = _('workflow')
|
||||
@@ -0,0 +1,272 @@
|
||||
# coding=utf-8
|
||||
from django.db import models
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.html import format_html
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from common import const
|
||||
from syscfg.models import Role
|
||||
from organ.models import Position,OrgUnit
|
||||
|
||||
|
||||
class Modal(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
import datetime
|
||||
index_weight = 1
|
||||
code = models.CharField(_("workflow code"),max_length=const.DB_CHAR_CODE_6,blank=True,null=True)
|
||||
name = models.CharField(_("workflow name"),max_length=const.DB_CHAR_NAME_40)
|
||||
description = models.TextField(_("description"),blank=True,null=True)
|
||||
content_type = models.ForeignKey(ContentType,verbose_name=_("content type"),limit_choices_to={"app_label__in":['basedata','organ']})
|
||||
app_name = models.CharField(_("app name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
|
||||
model_name = models.CharField(_("model name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
|
||||
# added by zhugl 2015-05-10
|
||||
begin = models.DateField(_("begin date"),blank=True,null=True,default=datetime.date.today)
|
||||
end = models.DateField(_("end date"),blank=True,null=True,default=datetime.date(9999,12,31))
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s" % self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("workflow model")
|
||||
verbose_name_plural = _("workflow model")
|
||||
|
||||
|
||||
class Node(models.Model):
|
||||
"""
|
||||
submitter()
|
||||
upper()
|
||||
user()
|
||||
role()
|
||||
position()
|
||||
sql()
|
||||
etc:upper('zhangsan','lisi')
|
||||
"""
|
||||
HANDLER_TYPE = (
|
||||
(1, _("designated user")),
|
||||
(2, _("designated position")),
|
||||
(3, _("designated role")),
|
||||
(4, _("submitter")),
|
||||
)
|
||||
index_weight = 2
|
||||
modal = models.ForeignKey(Modal,verbose_name=_("workflow model"))
|
||||
code = models.CharField(_("node code"),max_length=const.DB_CHAR_CODE_4,blank=True,null=True)
|
||||
name = models.CharField(_("node name"),max_length=const.DB_CHAR_NAME_80)
|
||||
tooltip = models.CharField(_('tooltip words'),blank=True,null=True,max_length=const.DB_CHAR_NAME_120)
|
||||
|
||||
start = models.BooleanField(_("start node"),default=False)
|
||||
stop = models.BooleanField(_("stop node"),default=False)
|
||||
can_terminate = models.BooleanField(_("can terminate"),default=False)
|
||||
can_deny = models.BooleanField(_("can deny"),default=True)
|
||||
can_edit = models.BooleanField(_("can edit"),default=False)
|
||||
|
||||
email_notice = models.BooleanField(_("email notice"),default=True)
|
||||
short_message_notice = models.BooleanField(_("short message notice"),default=False)
|
||||
approve_node = models.BooleanField(_("approve node"),default=False)
|
||||
handler = models.TextField(_("handler"),blank=True,null=True,help_text=u'自定义SQL语句,优先高于指定用户、岗位、角色')
|
||||
# added by zhugl 2015-05-10
|
||||
handler_type = models.IntegerField(_("handler type"),choices=HANDLER_TYPE,default=1)
|
||||
positions = models.ManyToManyField(Position,verbose_name=_("designated position"),blank=True)
|
||||
roles = models.ManyToManyField(Role,verbose_name=_("designated role"),blank=True)
|
||||
users = models.ManyToManyField(User,verbose_name=_("designated user"),blank=True)
|
||||
departments = models.ManyToManyField(OrgUnit,verbose_name=_("designated department"),blank=True)
|
||||
next = models.ManyToManyField('self',blank=True,verbose_name=_("next node"),symmetrical=False)
|
||||
# added by zhugl 2015-06-30
|
||||
next_user_handler = models.CharField(_('next user handler'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
next_node_handler = models.CharField(_('next node handler'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
status_field = models.CharField(_('status field'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
status_value = models.CharField(_('status value'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
action = models.CharField(_('execute action'),blank=True,null=True,max_length=const.DB_CHAR_NAME_40)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
if not self.code:
|
||||
fmt = 'N%02d'
|
||||
self.code = fmt % (self.modal.node_set.count()+1)
|
||||
super(Node,self).save(force_insert,force_update,using,update_fields)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s-%s" % (self.code, self.name)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("workflow node")
|
||||
verbose_name_plural = _("workflow node")
|
||||
|
||||
|
||||
class Instance(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
STATUS = (
|
||||
(1, _("NEW")),
|
||||
(2, _("IN PROGRESS")),
|
||||
(3, _("DENY")),
|
||||
(4, _("TERMINATED")),
|
||||
(9, _("APPROVED")),
|
||||
(99, _("COMPLETED"))
|
||||
)
|
||||
index_weight = 3
|
||||
code = models.CharField(_("code"),blank=True,null=True,max_length=const.DB_CHAR_CODE_10)
|
||||
modal = models.ForeignKey(Modal,verbose_name=_("workflow model"))
|
||||
object_id = models.PositiveIntegerField(_("object id"))
|
||||
starter = models.ForeignKey(User,verbose_name=_("start user"),related_name="starter")
|
||||
start_time = models.DateTimeField(_("start time"),auto_now_add=True)
|
||||
approved_time = models.DateTimeField(_("approved time"),blank=True,null=True)
|
||||
status = models.IntegerField(_("status"),default=1,choices=STATUS)
|
||||
current_nodes = models.ManyToManyField(Node,verbose_name=_("current node"),blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return '%s' % self.code
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(Instance,self).save(force_insert,force_update,using,update_fields)
|
||||
if not self.code:
|
||||
self.code = 'S%05d'%self.id
|
||||
self.save()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("workflow instance")
|
||||
verbose_name_plural = _("workflow instance")
|
||||
|
||||
|
||||
class History(models.Model):
|
||||
"""
|
||||
workflow history
|
||||
"""
|
||||
PROCESS_TYPE = (
|
||||
(0, _("SUBMIT")),
|
||||
(1, _("AGREE")),
|
||||
(3, _("DENY")),
|
||||
(4, _("TERMINATE")),
|
||||
)
|
||||
index_weight = 5
|
||||
inst = models.ForeignKey(Instance,verbose_name=_("workflow instance"))
|
||||
node = models.ForeignKey(Node,verbose_name=_("workflow node"),blank=True,null=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("submitter"))
|
||||
pro_time = models.DateTimeField(_("process time"),auto_now_add=True)
|
||||
pro_type = models.IntegerField(_("process type"),choices=PROCESS_TYPE,default=0)
|
||||
memo = models.CharField(_("memo"),max_length=const.DB_CHAR_NAME_40,blank=True,null=True)
|
||||
|
||||
def get_node_desc(self):
|
||||
if self.node:
|
||||
return self.node.name
|
||||
else:
|
||||
return u'启动'
|
||||
|
||||
def get_action_desc(self):
|
||||
action_mapping = {0:u'提交',1:u'同意',3:u'拒绝',4:u'终止',}
|
||||
# print action_mapping
|
||||
if self.pro_type:
|
||||
return action_mapping[self.pro_type]
|
||||
else:
|
||||
return u'提交'
|
||||
|
||||
def get_memo_desc(self):
|
||||
if self.memo:
|
||||
return self.memo
|
||||
else:
|
||||
return ''
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("workflow history")
|
||||
verbose_name_plural = _("workflow history")
|
||||
ordering = ['inst','pro_time']
|
||||
|
||||
|
||||
class TodoList(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
index_weight = 4
|
||||
code = models.CharField(_("code"),max_length=const.DB_CHAR_CODE_10,blank=True,null=True)
|
||||
inst = models.ForeignKey(Instance,verbose_name=_("workflow instance"))
|
||||
node = models.ForeignKey(Node,verbose_name=_("current node"),blank=True,null=True)
|
||||
app_name = models.CharField(_("app name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
|
||||
model_name = models.CharField(_("model name"),max_length=const.DB_CHAR_NAME_60,blank=True,null=True)
|
||||
user = models.ForeignKey(User,verbose_name=_("handler"))
|
||||
arrived_time = models.DateTimeField(_("arrived time"),auto_now_add=True)
|
||||
is_read = models.BooleanField(_("is read"),default=False)
|
||||
read_time = models.DateTimeField(_("read time"),blank=True,null=True)
|
||||
status = models.BooleanField(_("is done"),default=False)
|
||||
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
super(TodoList,self).save(force_update,force_update,using,update_fields)
|
||||
if not self.code:
|
||||
self.code = 'TD%05d' % self.id
|
||||
self.save()
|
||||
|
||||
def node_dsc(self):
|
||||
if self.node:
|
||||
return u'%s'%self.node.name
|
||||
else:
|
||||
return u'启动'
|
||||
|
||||
def code_link(self):
|
||||
return format_html("<a href='/admin/{}/{}/{}'>{}</a>",
|
||||
self.app_name,self.model_name,self.inst.object_id,self.code)
|
||||
code_link.allow_tags = True
|
||||
code_link.short_description = _("code")
|
||||
|
||||
def href(self):
|
||||
import sys
|
||||
reload(sys)
|
||||
sys.setdefaultencoding("utf-8")
|
||||
ct = ContentType.objects.get(app_label=self.app_name,model=self.model_name)
|
||||
obj = ct.get_object_for_this_type(id=self.inst.object_id)
|
||||
title = u"%s" % (obj)
|
||||
return format_html("<a href='/admin/{}/{}/{}'>{}</a>",
|
||||
self.app_name,self.model_name,self.inst.object_id,title)
|
||||
def modal_dsc(self):
|
||||
return u'%s'%(self.inst.modal.name)
|
||||
modal_dsc.short_description = u'业务流程'
|
||||
|
||||
def start_time(self):
|
||||
return self.inst.start_time.strftime('%Y-%m-%d %H:%M')
|
||||
|
||||
href.allow_tags = True
|
||||
href.short_description = _("description")
|
||||
node_dsc.short_description = _('current node')
|
||||
|
||||
def submitter(self):
|
||||
if self.inst.starter.last_name or self.inst.starter.first_name:
|
||||
return u"%s%s"%(self.inst.starter.last_name,self.inst.starter.first_name)
|
||||
return u"%s"%(self.inst.starter.username)
|
||||
submitter.short_description = _("submitter")
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("workflow todo")
|
||||
verbose_name_plural = _("workflow todo")
|
||||
ordering = ['user','-arrived_time']
|
||||
|
||||
|
||||
def get_modal(app_label,model_name):
|
||||
"""
|
||||
|
||||
:param app_label:
|
||||
:param model_name:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
return Modal.objects.get(app_name=app_label,model_name=model_name)
|
||||
except Exception,e:
|
||||
return None
|
||||
|
||||
|
||||
def get_instance(obj):
|
||||
"""
|
||||
|
||||
:param obj:
|
||||
:return:
|
||||
"""
|
||||
if obj and obj._meta:
|
||||
modal = get_modal(obj._meta.app_label,obj._meta.model_name)
|
||||
if modal:
|
||||
try:
|
||||
return Instance.objects.get(modal=modal,object_id=obj.id)
|
||||
except Exception,e:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,314 @@
|
||||
# coding=utf-8
|
||||
from django.contrib.admin import site
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import connection
|
||||
from django.http.response import HttpResponseRedirect
|
||||
from django.utils.encoding import force_text
|
||||
from django.template.response import TemplateResponse
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from workflow.models import Modal,Instance,TodoList,History,Node
|
||||
from plugin.wfnodes import NextNodeManager,NextNodeHandler
|
||||
from plugin.wfusers import NextUserManager,NextUserHandler
|
||||
from plugin.wfactions import WorkflowActionManager,WorkflowAction
|
||||
|
||||
|
||||
SELECTED_CHECKBOX_NAME = 'NEXT_NODE_USER'
|
||||
|
||||
|
||||
def compile_node_handler(request,obj,next_node):
|
||||
"""
|
||||
:param request:
|
||||
:param obj:
|
||||
:param handler:
|
||||
:return:
|
||||
"""
|
||||
|
||||
handler = next_node.handler
|
||||
next_user_handler = next_node.next_user_handler
|
||||
# next_user_handler 具有最高优先级
|
||||
if next_user_handler:
|
||||
# print 'it is here'
|
||||
klass = NextUserManager().handlers.get(next_user_handler)
|
||||
if klass and isinstance(klass,NextUserHandler):
|
||||
return klass.handle(request,obj,next_node)
|
||||
|
||||
if handler and handler != '':
|
||||
handler = handler.replace("submitter()", request.user.username)
|
||||
handler = handler.replace("suber()", request.user.username)
|
||||
fields = obj._meta.fields
|
||||
for field in fields:
|
||||
name = field.name
|
||||
temp = "{{%s}}" % name
|
||||
val = getattr(obj,name,None)
|
||||
if val:
|
||||
if type(val)!=str:
|
||||
val = str(val)
|
||||
handler = handler.replace(temp,val)
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(handler)
|
||||
rows = [row for row in cursor.fetchall()]
|
||||
return rows
|
||||
else:
|
||||
tp = next_node.handler_type
|
||||
if tp == 1 and next_node.users:
|
||||
# user
|
||||
users = [user for user in next_node.users.all()]
|
||||
return users
|
||||
elif tp == 2 and next_node.positions:
|
||||
# position
|
||||
users = []
|
||||
for position in next_node.positions.all():
|
||||
for employee in position.employee_set.all():
|
||||
users.append(employee.user)
|
||||
return users
|
||||
elif tp == 3 and next_node.roles:
|
||||
# role
|
||||
users = []
|
||||
for role in next_node.roles.all():
|
||||
for user in role.users.all():
|
||||
users.append(user)
|
||||
return users
|
||||
elif tp == 4:
|
||||
# submitter
|
||||
return request.user
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def start(request,app,model,object_id):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:return:
|
||||
"""
|
||||
import datetime
|
||||
content_type = ContentType.objects.get(app_label=app,model=model)
|
||||
obj = content_type.get_object_for_this_type(id=int(object_id))
|
||||
title = _("Are you sure?")
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
has_workflow = False
|
||||
queryset = Modal.objects.filter(content_type=content_type,end__gt=datetime.date.today()).order_by('-end')
|
||||
cnt = queryset.count()
|
||||
workflow_modal = None
|
||||
next_node = None
|
||||
next_users = []
|
||||
has_next_user = False
|
||||
if cnt > 0:
|
||||
has_workflow = True
|
||||
workflow_modal = queryset[0]
|
||||
query_start_node = workflow_modal.node_set.filter(start=1)
|
||||
query_first_node = workflow_modal.node_set.order_by('id')
|
||||
if query_start_node.count() > 0:
|
||||
next_node = query_start_node[0]
|
||||
elif query_first_node.count()>0:
|
||||
next_node = query_first_node[0]
|
||||
if next_node:
|
||||
next_users = compile_node_handler(request,obj,next_node)
|
||||
if len(next_users) > 0:
|
||||
has_next_user = True
|
||||
else:
|
||||
title = _("No workflow model was found")
|
||||
|
||||
try:
|
||||
tmp = Instance.objects.get(modal = workflow_modal,object_id=object_id)
|
||||
messages.warning(request,_("the object is already in workflow"))
|
||||
return HttpResponseRedirect("/admin/%s/%s/%s"%(app,model,object_id))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if request.POST.get("post"):
|
||||
val = request.POST.getlist(SELECTED_CHECKBOX_NAME)
|
||||
workflow_inst = Instance.objects.create(modal=workflow_modal,object_id=object_id,starter=request.user)
|
||||
workflow_inst.current_nodes.add(next_node)
|
||||
workflow_inst.save()
|
||||
workflow_history = History.objects.create(inst=workflow_inst,user=request.user)
|
||||
for user in User.objects.filter(id__in=val):
|
||||
todo = TodoList.objects.create(inst=workflow_inst,node=next_node,user=user,app_name=app,model_name=model)
|
||||
TodoList.objects.create(inst=workflow_inst,user=request.user,app_name=app,model_name=model,is_read=True,
|
||||
read_time=datetime.datetime.now(),status=True)
|
||||
if next_node.status_field and next_node.status_value:
|
||||
try:
|
||||
setattr(obj,next_node.status_field,next_node.status_value)
|
||||
obj.save()
|
||||
except Exception,e:
|
||||
pass
|
||||
messages.success(request,_('workflow started successfully'))
|
||||
return HttpResponseRedirect("/admin/%s/%s/%s"%(app,model,object_id))
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
has_workflow = has_workflow,
|
||||
workflow_modal = workflow_modal,
|
||||
next_node = next_node,
|
||||
has_next_user = has_next_user,
|
||||
next_users = next_users,
|
||||
checkbox_name = SELECTED_CHECKBOX_NAME,
|
||||
)
|
||||
request.current_app = site.name
|
||||
|
||||
return TemplateResponse(request,'default/workflow/workflow_start_confirmation.html', context)
|
||||
|
||||
|
||||
def approve(request,app,model,object_id,operation):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:param operation:
|
||||
:return:
|
||||
"""
|
||||
if operation not in ('1','3','4'):
|
||||
messages.warning(request,_("unkown workflow operation"))
|
||||
return HttpResponseRedirect("/admin/%s/%s/%s"%(app,model,object_id))
|
||||
|
||||
import datetime
|
||||
import copy
|
||||
content_type = ContentType.objects.get(app_label=app,model=model)
|
||||
obj = content_type.get_object_for_this_type(id=int(object_id))
|
||||
title = _("Are you sure?")
|
||||
opts = obj._meta
|
||||
objects_name = force_text(opts.verbose_name)
|
||||
|
||||
has_workflow = False
|
||||
queryset = Modal.objects.filter(content_type=content_type,end__gt=datetime.date.today()).order_by('-end')
|
||||
cnt = queryset.count()
|
||||
workflow_modal = None
|
||||
if cnt > 0:
|
||||
workflow_modal = queryset[0]
|
||||
else:
|
||||
messages.warning(request,_("No workflow model was found"))
|
||||
return HttpResponseRedirect("/admin/%s/%s/%s"%(app,model,object_id))
|
||||
workflow_instance = None
|
||||
try:
|
||||
workflow_instance = Instance.objects.get(modal = workflow_modal,object_id=object_id)
|
||||
except Exception:
|
||||
messages.warning(request,_("please start the workflow first"))
|
||||
return HttpResponseRedirect("/admin/%s/%s/%s"%(app,model,object_id))
|
||||
|
||||
next_nodes = []
|
||||
node_users = []
|
||||
is_stop_node = False
|
||||
node_has_users = False
|
||||
delete_instance = False
|
||||
deny_to_first = False
|
||||
next_node_description = None
|
||||
all_nodes =[x for x in Node.objects.filter(modal=workflow_modal).order_by('-id')]
|
||||
current = workflow_instance.current_nodes.all()
|
||||
current_tmp = copy.deepcopy(current[0])
|
||||
if operation == '4' or operation == '3':
|
||||
next_nodes = ['stop']
|
||||
is_stop_node = True
|
||||
else:
|
||||
if current.count() > 1:
|
||||
pass
|
||||
else:
|
||||
tmp_node = current[0]
|
||||
if tmp_node.stop or tmp_node == all_nodes[0]:
|
||||
next_nodes = ['stop']
|
||||
is_stop_node = True
|
||||
else:
|
||||
if tmp_node.next_node_handler and len(tmp_node.next_node_handler) > 0:
|
||||
hd = tmp_node.next_node_handler
|
||||
klass = NextNodeManager().handlers.get(hd)
|
||||
if klass and isinstance(klass,NextNodeHandler):
|
||||
next_nodes = klass.handle(request,obj,tmp_node)
|
||||
next_node_description = klass.description
|
||||
if next_nodes and len(next_nodes) > 0:
|
||||
pass
|
||||
elif tmp_node.next and tmp_node.next.count()>0:
|
||||
next_nodes = [nd for nd in tmp_node.next.all()]
|
||||
else:
|
||||
position = all_nodes.index(tmp_node)
|
||||
next_nodes = [all_nodes[position-1]]
|
||||
|
||||
if request.POST.get("post"):
|
||||
from django.db import transaction
|
||||
val = request.POST.getlist(SELECTED_CHECKBOX_NAME)
|
||||
memo = request.POST['memo']
|
||||
with transaction.atomic():
|
||||
try:
|
||||
if delete_instance:
|
||||
workflow_instance.delete()
|
||||
else:
|
||||
if is_stop_node:
|
||||
workflow_instance.status = 99
|
||||
if operation in ('3', '4'):
|
||||
workflow_instance.status = int(operation)
|
||||
if not workflow_instance.approved_time and operation == '1':
|
||||
workflow_instance.approved_time = datetime.datetime.now()
|
||||
workflow_instance.current_nodes.clear()
|
||||
workflow_instance.save()
|
||||
else:
|
||||
workflow_instance.current_nodes.clear()
|
||||
workflow_instance.current_nodes.add(next_nodes[0])
|
||||
for user in User.objects.filter(id__in=val):
|
||||
todo = TodoList.objects.create(inst=workflow_instance,node=next_nodes[0],user=user,app_name=app,model_name=model)
|
||||
if current_tmp.status_field and current_tmp.status_value:
|
||||
try:
|
||||
setattr(obj,current_tmp.status_field,current_tmp.status_value)
|
||||
obj.save()
|
||||
except Exception,e:
|
||||
pass
|
||||
History.objects.create(inst=workflow_instance,user=request.user,pro_type=int(operation),memo=memo,node=current_tmp)
|
||||
TodoList.objects.filter(inst=workflow_instance,node=current_tmp,status=0).update(status=1)
|
||||
messages.success(request,_('workflow approved successfully'))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
pass
|
||||
if current_tmp.action and len(current_tmp.action) > 0:
|
||||
action = WorkflowActionManager().actions.get(current_tmp.action)
|
||||
if action and isinstance(action,WorkflowAction):
|
||||
action.action(request,obj,current_tmp,operation)
|
||||
|
||||
return HttpResponseRedirect("/admin/%s/%s/%s"%(app,model,object_id))
|
||||
|
||||
if len(next_nodes) > 0 and not is_stop_node and operation == '1':
|
||||
for node in next_nodes:
|
||||
users = compile_node_handler(request,obj,node)
|
||||
if len(users) > 0:
|
||||
node_has_users = True
|
||||
node_users.append({'node':node,'users':users})
|
||||
|
||||
context = dict(
|
||||
site.each_context(request),
|
||||
title=title,
|
||||
opts=opts,
|
||||
objects_name=objects_name,
|
||||
object=obj,
|
||||
operation = operation,
|
||||
is_stop_node = is_stop_node,
|
||||
delete_instance = delete_instance,
|
||||
node_users = node_users,
|
||||
node_has_users = node_has_users,
|
||||
checkbox_name = SELECTED_CHECKBOX_NAME,
|
||||
)
|
||||
if next_node_description:
|
||||
context.update(dict(next_node_description=next_node_description))
|
||||
return TemplateResponse(request,"default/workflow/workflow_approve_confirmation.html",context)
|
||||
|
||||
|
||||
def restart(request,app,model,object_id,instance):
|
||||
"""
|
||||
|
||||
:param request:
|
||||
:param app:
|
||||
:param model:
|
||||
:param object_id:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
inst = Instance.objects.get(id=int(instance))
|
||||
if request.user == inst.starter:
|
||||
inst.delete()
|
||||
messages.success(request,_("workflow restarted success"))
|
||||
else:
|
||||
messages.warning(request,_("you do not have the permission to restart,only the starter can restart"))
|
||||
except Exception,e:
|
||||
messages.error(request,e)
|
||||
return HttpResponseRedirect("/admin/%s/%s/%s"%(app,model,object_id))
|
||||
Reference in New Issue
Block a user