1.工作流引擎实现
mysql> select * from workflow_list;
+----+------+---------------+--------------+-------------+---------------------+--------+-------------+
| id | name | first_step_id | last_step_id | total_steps | insert_time | type | delete_flag |
+----+------+---------------+--------------+-------------+---------------------+--------+-------------+
| 1 | 流程 | 1 | 5 | 5 | 2013-07-22 19:22:52 | change | 0 |
+----+------+---------------+--------------+-------------+---------------------+--------+-------------+
name 流程名称
first_step_id 第一步的stepID
last_step_id 最后一步的stepID
total_steps 流程步骤总数
insert_time 插入时间
type 流程类别(根据实际情况而定,存数据的时候做区别用)
delete_flag 删除标示
mysql> select * from workflow_steps;
+----+---------+--------------+--------------+---------------------+---------+-----------+--------------+
| id | name | prev_step_id | next_step_id | insert_time | role_id | role_type | type |
+----+---------+--------------+--------------+---------------------+---------+-----------+--------------+
| 1 | ????? | 0 | 2 | 2013-07-22 19:23:23 | 9 | 1 | cost_enginer |
| 2 | ??????? | 1 | 3 | 2013-07-22 19:23:53 | 10 | 1 | simple |
| 3 | ?????? | 2 | 4 | 2013-07-22 19:24:15 | 11 | 1 | simple |
| 4 | ?????? | 3 | 0 | 2013-07-22 19:24:27 | 12 | 1 | simple |
+----+---------+--------------+--------------+---------------------+---------+-----------+--------------+
name 步骤名称
prev_step_id 上一步骤ID
next_step_id 下一步骤ID
insert_time 插入时间
role_id,role_type 步骤执行者(role_type=1,role_id 标示明确指定需要user_id=role_id 这个人执行;role_type=2,role_id 标示user角色=role_id 的这群人都能执行)
type 步骤类型(根据实际情况而定,主要是存数据的时候做区别)
--------------------------------------------------------------------------------------------------------------------------------------------------------------
通过以上两个表可以构建流程模板,下面是流程实例:
mysql> select * from workflow_detail;
+--------------------+-------------+----------------+---------------+--------------+--------------+----------------+---------------------+---------------------+------------+------------+--------+------------+
| id | workflow_id | name | first_step_id | next_step_id | next_role_id | next_role_type | insert_time | update_time | other_data | create_uid | type | is_success |
+--------------------+-------------+----------------+---------------+--------------+--------------+----------------+---------------------+---------------------+------------+------------+--------+------------+
| 201307231823122925 | 1 | 1????????????? | 1 | 0 | 0 | 0 | 2013-07-23 18:23:12 | 2013-07-24 10:10:58 | 18 | 1 | change | 2 |
| 201307231856468212 | 1 | ffghh | 1 | 1 | 2 | 2 | 2013-07-23 18:56:46 | 2013-07-23 18:56:46 | 19 | 3 | change | 0 |
| 201307231901039901 | 1 | ?????? | 1 | 0 | 0 | 0 | 2013-07-23 19:01:03 | 2013-07-24 12:44:10 | 20 | 1 | change | 2 |
| 201307231929236393 | 1 | ?????????? | 1 | 0 | 0 | 0 | 2013-07-23 19:29:23 | 2013-07-23 19:32:50 | 21 | 1 | change | 1 |
| 201307231938558609 | 1 | ???? | 1 | 1 | 2 | 2 | 2013-07-23 19:38:55 | 2013-07-23 19:38:55 | 22 | 1 | change | 0 |
| 201307241008212636 | 1 | ??13?????????? | 1 | 0 | 0 | 0 | 2013-07-24 10:08:21 | 2013-07-24 10:41:00 | 23 | 4 | change | -1 |
| 201307241124085112 | 1 | ??????? | 1 | 2 | 10 | 1 | 2013-07-24 11:24:08 | 2013-07-24 11:29:14 | 24 | 5 | change | 0 |
| 201307241126026204 | 1 | 9????????? | 1 | 2 | 10 | 1 | 2013-07-24 11:26:02 | 2013-07-24 11:30:21 | 25 | 4 | change | 0 |
| 201307241228356005 | 1 | ddddfnbgvv | 1 | 3 | 11 | 1 | 2013-07-24 12:28:35 | 2013-07-24 12:32:07 | 26 | 4 | change | 0 |
| 201307241258155752 | 1 | 13???? | 1 | 0 | 0 | 0 | 2013-07-24 12:58:15 | 2013-07-24 13:28:18 | 27 | 4 | change | 2 |
+--------------------+-------------+----------------+---------------+--------------+--------------+----------------+---------------------+---------------------+------------+------------+--------+------------+
ID 实例ID
workflow_id 实例管理的模板
name 实例名称
first_step_id 第一步骤ID,生成实例的时候通过模板clone过来,方便以后操作
next_step_id 下一个步骤需要执行的步骤,如果是0标示没有下一步了,流程执行成功或者失败
next_role_id,next_role_type 下一个步骤执行的角色
insert_time 插入时间 update_time 更新时间
other_data 绑定工作流的具体数据单编号(例如请假需要绑定工作流,直接把请假单编号放到other_data中,具体审批工作流引擎去完成)
create_uid 创建工作流的人
type clone模板过来的,方便以后分类查询使用,不用再去读模板去了
is_success 实例审批状态 0.审批中 -1.失败 1.成功
每个步骤处理的结果
mysql> desc workflow_step_log;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| log_id | varchar(50) | YES | | NULL | |
| step_id | int(11) | YES | | NULL | |
| uid | int(11) | YES | | NULL | |
| result | int(11) | YES | | NULL | |
| remark | text | YES | | NULL | |
| insert_time | datetime | YES | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
log_id 实例ID
step_id 步骤ID
uid 处理人
insert_time 处理时间
result 处理结果 1.同意 -1.拒绝 2.打回
remark 说明
可以再添加一个打回到哪一步的字段
PS:以上是个人原创,有许多地方还欠稳妥,望大牛们多多指教!!!
实现原理是链表的原理,每个节点有前一个节点和后一个节点的标示,将节点串联起来形成一个链
PYTHON 实现的审批:
def simple_approve(log_id,uid,result,remark='',step_id=None):
user = User.query.get(uid)
'''
批准当前步骤
log_id 当前流程实例
uid 当前处理人
result 处理结果
remark 说明
step_id 如果是退回,退回步骤ID
'''
if not log_id:
return False,'log_id为空'
elif not uid:
return False,'处理人ID不存在'
elif result!=0 and result!=1 and result!=-1 and result!=2:
return False,'未能识别处理结果'
elif result==2 and not step_id:
return False,'请选择打回位置'
else:
log_workflow = WorkFlowDetail.query.get(log_id)
if not log_workflow or log_workflow.is_success!=0:
return False,'当前流程不存在'
else:
step = WorkFlowStep.query.get(log_workflow.next_step_id)
#判断处理人是否能处理此步骤
if (step.role_id==uid and step.role_type==1) or (step.role_type==2 and step.role_id==user.role_id):
if result==1: #同意
#流程步骤需要向下走
log_workflow.next_step_id = step.next_step_id
if step.next_step_id ==0:
log_workflow.is_success=1
log_workflow.next_role_id =0
log_workflow.next_role_type =0
else:
next_step = WorkFlowStep.query.get(step.next_step_id)
log_workflow.next_role_id = next_step.role_id
log_workflow.next_role_type = next_step.role_type
elif result==-1: #拒绝
log_workflow.is_success = -1
log_workflow.next_step_id = 0
log_workflow.next_role_id = 0
log_workflow.next_role_type = 0
elif result== 2: #打回
#查询提供的step_id是否是处理过的,如果是才能允许打回到这步骤
log_step = StepLog.query.filter(StepLog.step_id==step_id).filter(StepLog.log_id==log_workflow.id).first()
if log_step:
log_workflow.next_step_id =step_id
rollback_step = WorkFlowStep.query.get(step_id)
log_workflow.next_role_id = rollback_step.role_id
log_workflow.next_role_type = rollback_step.role_type
next_step = WorkFlowStep.query.get(step_id)
log_workflow.next_role_id = next_step.role_id
log_workflow.next_role_type = next_step.role_type
else:
return False,'此流程不允许打回到当前步骤'
#记录处理步骤日志
step_log = StepLog(log_id =log_id,result=result,remark=remark,step_id=step.id,uid=uid)
step_log.save()
log_workflow.save()
else:
return False,'您没有处理当前流程步骤权限'
return True,'处理成功'