jxTMS是以低成本快速定制为核心诉求的、SaaS模式的二次开发平台,详见:jxTMS简介。本文是讲述jxTMS平台中流程部分是如何设计的,整个系列请访问:jxTMS设计思想
任何企业只要规模稍大,超出了老板的个人精力所能操作的水平,就必须加强企业内部控制。企业内部控制一是强化财务管理,反正只要管住钱,再乱也乱不到哪去;二是加强合规性建设,而合规性的实现主要依靠流程。
流程是以分权制衡来强化监督,以明确责任、操作规范化、全程记录来维持效率,从而实现在权力规范运行的前提下仍能保持一定的效率。
因此,在管理信息化软件来说,管理软件中的流程是具体落实各执行环节的任务分发、记录、追溯、查询。也就是说管理软件重的流程的重点是:
任务分发
执行记录
执行过程的复盘与追溯
流程的列表查询与查看
即,软件部分所承担的主要是推动流程执行、记录执行的相关信息用于事后追责。以不可逃避的事后追责来督促执行者合规、高效执行。
从技术角度来说,流程引擎非常简单,就是一个perti网:各库所就是流程中的各任务环节,库所间的跃迁就是各任务中用户的操作,令牌就是当前正在执行中的任务。
添加了两个虚拟库所:start、end。并约定流程一定要从start节点启动、一旦执行到end节点则意味着流程结束。笔者很快就实现了jxTMS中的流程引擎。
标准流程的每个节点的入与出分别都有两种逻辑关系:与【and】、或【or】。那么每个节点的进出就有四种:
与入:所有前置节点都执行完毕触发了本节点,本节点才会开始执行。如网络设备安装调试,设备到位、通电、网络线路布设完毕等前提条件都满足了才会展开
或入:前置节点中只要有一个执行完毕触发了本节点,本节点就会开始执行。如报销流程中的财务经理审核,可以是财务人员复核后递交执行,也可以是总经理有疑问打回要求补充说明
与出:本节点执行完毕,将触发所有后继节点。如例会上对各部门部署了各自的任务,会后这些部门各自开展自己的工作
或出:本节点执行完毕,【根据用户选择或按条件】从后继节点中挑选一个来触发。如领导审批,在同意和否决中选择其一
但,如果这些节点间的进出逻辑关系不匹配,可能导致流程死锁,即执行不下去了!这个条件就是:某个节点【源点】所有发出的跃迁一定可以收束到另一个节点【目的点】,即这两个节点可在更高层次上约减为一个点。
这里的收束的意思是:不管经过多少个中间库所、以及这些中间库所是或入还是与出,源点所有的与出,一定对应目的点所有与入;源点所有的或出,一定对应目的点所有或入。
简单的说,就是源点的输出一定收敛为目的点的输入,而且两者性质相同。
除了没有输出的end节点,所有节点都必须满足这一条件。
但在实践中发现了一个问题:很多人设计的流程满足不了这个条件,结果导致流程跑不通,锁死了。虽然笔者可以开发检测工具来检测死锁,但检测工具只能检测却无法避免流程设计的错误。
所以笔者仔细分析了大多数的流程,除了规模很大的组织的主流程,大部分流程都是单线推进的,而复杂的主流程对任何企业来说都是核心资产,请专家精心设计是避免不了的。所以jxTMS实在没必要为了兼容复杂流程却导致一般的开发者在开发常见流程时付出高成本!
所以在一般流程的基础上jxTMS实现了:简易流程。即通过对一般的流程增加三个限制:
每个节点都是或入或出
从start节点到end节点【称为正向】是单向逐一推进,即简易流程中正向的各环节是一步一步执行的,不允许跳跃
简易流程执行到某个节点【除end节点】,可以返回之前执行过的某节点【除start节点】重新执行,这种反向是允许跳跃的
即除了start和end节点之外,正向只允许依次递进、反向则可以任意跳跃。在实际的流程中,正向就代表逐级审批、反向就代表打回重做。
注:目前,简易流程和正常流程之间已经实现了融合,即简易流程就相当于正常流程的默认
流程引擎的设计很简单,但想把一个任务正确的分发给正确的员工来执行却不是太容易。
举个最简单的例子,报销流程最为常见,而任何报销流程的第一步都是报销者填写,那第二步则一般是部门经理审批。好,有几个问题大家看看该怎么办?
技术部有技术部经理、销售部有销售部经理,难道还能一个部门一个报销流程吗?那报销流程如何确定这个部门经理到底应该技术部经理还是销售部经理呢?
如果技术部经理自己要报销,那这个部门经理要交给谁来审批?难不成还要自己审批自己?
有的部门有部门经理,可有的部门却没有部门经理,那又该交给谁来审批呢?
某个节点对应的岗位有多个人员,如维修工程师,那该如何确定分发给谁来执行呢?
如果流程被打回到某节点重新执行,可该节点对应的岗位有多个人员,那又该交给谁来执行?
如果某个节点的执行人请假了,那又该分发给谁呢?
这几个问题一问,大家就会明白,各节点任务不能写死一定得是某个具体的人、具体的岗位,而应该基于角色。
注:角色不是职位,可参考:jxTMS中的角色
每个节点可指派给真实角色也可以指派给虚拟角色。如果是指派给真实角色【如财务经理、财务稽核】,则jxTMS会从该角色所映射的成员中选择其一来分发任务;如果是指派给虚拟角色,则jxTMS首先会根据流程创建者所处的部门逐级查找该虚拟角色所对应的真实角色,然后再选择该真实角色所映射的成员进行分发。
如,技术部有软件部和硬件部,则如果报销流程的第三部是总监审批,那jxTMS根据报销人所在的软件部,首先查找该部门有无总监职位,没有找到;则上溯到软件部的上级部门,找到了总监职位:技术总监。然后将审批任务分发该技术总监所对应的成员。
如果要分发的成员就是申请人那该怎么办呢?!
这从管理岗位设置上来说有两种情况:
一种是负责真实性、必要性等审批的业务性审批,如报销流程中的部门经理审批、总监审批,这些审批动作是从业务的角度来核准业务动作是否真实、是否必要,那么该领导自然可为自己担保。所以这种环节的执行人员如果就是申请人,那跳过即可。当然,该企业如果认为没必要节省各级领导的精力而不应跳过,那也可强制不跳
一种是负责专业性、操作性等审批的职能性审批。这是代表组织对整个作业的确认,属于必要的履职行为,所以不管是谁都必须分发去执行
那么,如果该环节没找到具体的执行人那该怎么办?!大家可能会很疑惑,怎么还会有这样的情况?!但其实这是很正常的啊,难道总监的报销单还得让部门经理审批吗?!
没找到就跳过!即相当于本环节被自动确认了!!哇偶,怎么会这样?!那岂非太可怕了!一点都不可怕,因为任何流程都会有各职能部门和各级领导进行审核、核准与审批,真有这样的漏洞在试运行期间就会被发现的。
所以对本节点由谁来执行,jxTMS遵循的是:
如果有指定谁来执行【如技术部经理同意派维修工程师出现场时,具体指定了一个工程师】,那就分发给该人来执行
如果该节点已经有成员执行过了,那强制分发给该成员执行,以提高效率
根据该节点角色来确定执行者,如果有多个执行者,则选择其一
如果执行者就是创建者,则本节点允许跳过,则跳过;将该任务分发给到该成员
如果没有找到执行者,则跳过
这里的跳过,是指jxTMS将以默认操作【accept】将本节点自动执行完毕。
针对请假等需要临时转移执行人的情况,jxTMS提供了替代者,但该机制需要请假、销假的管理非常严密,否则可能导致任务分发出现错误。
会从该角色所映射的成员中选择其一来分发任务
业务只要。因为查询有几个特殊的地方:
条件查询,可以说,任何查询都是带条件的,没条件的查询没有意义,而和update中根据主键值就可以确定条件不同,查询的条件是根据业务需要动态的设置的
多表联合查询,增删改都是对单表的操作,而查询大多数都需要对多个数据表进行联合查询
查询出来的数据可能太多,所以需要分页,可能需要排序、可能需要分组等等
由于数据库中的数据量可能会太大,为了压缩存储的压力,所以经常会用带语义的数字来代替文字描述,但这样的数字如果直接显示给用户,显然用户会看不懂。所以还需要在数据查询出来后进行语义转换或语义补充
所以和增删改直接拼接相应的SQL语句不同,jxTMS针对查询设计了一个SelectSql的类,专门用来组装select语句。jxTMS将之称为一个数据源。
SelectSql主要针对多表联合查询和条件查询,支持设置多个数据表、设置多个条件。其支持三种条件:
不同表中的列比较【当然,一般都是相等】,这主要是用于多表查询时做表间连接
某表某列和某数值的比较,该数值在定义查询条件时静态指定
某表某列和某变量的比较,变量值在执行查询时动态指定
SelectSql有一个概念:条件链,用以简便的区分出or和and连接:同一个条件链是与【and】连接;不同的条件链之间是或【or】连接。默认是对零号链进行设置,也就是默认是and连接。
在需要执行时,需要两步来处置:
将指定的SelectSql克隆出一个新的SelectSql,用来根据业务需要增加临时的额外的查询条件,如【我的任务】在设计时想列表所有指派给自己执行的任务,但可以动态的增加条件查询某个时间段的任务、名字中含有某个关键字的任务等等
将设置好查询条件的SelectSql创建一个执行体,然后如果在创建SelectSql时使用了需在执行时动态指定值的变量,则先要给这些变量赋值;之后如有必要则设置limit和offset【分页查询】;然后才开始执行实际的查询
查询的执行过程是:
根据SelectSql设置的信息生成一个select语句
用此select语句从数据库中查询出一个结果集
根据指定的结果类型,将结果集要么转换为数据对象的队列或一个json数组
大多数的业务活动,都包括两个入口:创建、列表查询。
所以jxTMS针对列表查询做了特别优化,使得可以非常简便的开发一个带条件查询的、分页的列表查询功能。
完成一个完整的列表查询功能,所需要的全部工作包括:
定义一个带查询条件界面、分页的数据表
定义一个数据源,以执行数据库查询
根据用户输入的查询条件,对数据源添加查询条件
如果数据源带有条件变量,则在投入执行前对相应的变量赋值
如需分页,则先查询出符合条件的总行数发送到前端初始化分页控件
执行查询
如有需要,则逐行/逐对象来执行语义转换或语义补充
以低成本定制为核心述求的jxTMS,所以针对上述的列表查询工作流做了相应的优化。使得开发者可以非常简单的按需开发出自己的列表查询功能。
列表查询的完整工作流的说明请参考:jxTMS在线编程手册之列表查询
目前jxTMS已经开放个人注册试用,欢迎大家注册试用:
下面的系列文章讲述了如何用jxTMS开发一个实用的业务功能:
下面的系列文章讲述了jxTMS的一些基本功能: