NC31审批流程开发文档
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
NC31审批流程开发文档
NC31审批流程开发文档_v1.2
NC31审批流程开发文档
版本:V1.2
发布日期:20XX年6月部门:NC_UAP NC31的流程平台包括业务流程和审批流程两个部分。
NC31对审批流程进行了较大的改进,而业务流程还是沿用NC30版本的应用模式和功能。
本文是对NC31的审批流程开发进行的规范说明。
参考文档:
1.《NC30审批流培训文档》2.《NC31审批流使用文档》3.《NC31业务流程开发文档》
NC31审批流程开发文档_v1.2
一、概述
NC31审批流程平台为NC各种单据的审批处理提供了一个统一的平台机制。
原有审批流应用模型(NC30版本)在一定程度上满足不了日益复杂的业务需求,定义模型也存在混淆难以理解的弊病。
NC31审批流使用了新的工作流执行引擎,它要求有严格的流程定义。
基于任务驱动的执行引擎使得流程流转与用户交互分离开来,具有更强的健壮性。
在业务客户端应用模式上,NC31还是沿袭NC30审批流中的单据动作驱动,即通过单据动作(比如提交、审批、弃审、驳回等)来驱动流程流转。
在开发模式
上,完善并规范了原有的一些开发规范。
本文将详细进行阐述。
二、系统结构
三、开发步骤
3.1
注册单据类型
单据类型是NC系统中比较重要的数据,注册在表《NC31业务流程开发文档》2.2节。
这里列出了几个与审批流相关的属性字段:bd_billtype
中,业务操作都需要用到它。
参见
NC31审批流程开发文档_v1.2
单据类型编码
NC31扩展了编码最大长度为4个字符,由NC设计部统一规划和命名。
一般由系统安装时预置,也可由用户自定义。
单据UI类名语法结构如下:
从语法图可知,UI类名称一般注册为以下几种形式:
Ync.ui.card.test.TestBillCardUI YPnc.ui.card.test.TestBillCardUI
NPK000********** *****AA***-*****000494 Nnc.ui.fa.BillCardUI
nc.ui.rc.audit.CardAuditUI Pnc.ui.fi.fiapply.FIApplyMange
注:如果某单据类型希望走审批流,建议UI类名注册为以Y开头。
非PK方式的UI类名必须实现接口nc.ui.pf.query.ICheckRetVO,参见4.8.6节。
审批流检查类需要执行审批流的单据类型都必须注册该信息,一般
由DMO或BO类实现,主要用途如下:
NC31审批流程开发文档_v1.2
1.用于回写单据的审批状态。
2.用于过滤活动的实际执行者。
审批流检查类需要实现的接口参见4.8节。
功能编码对于需要执行审批流的单据类型,一般都关联有且仅有一个功能节点编码。
一个用户对某单据类型拥有权限,实际上是对该功能节点拥有权限。
功能编码还可用于获取查询模板。
对于UI类名注册为P模式的单据类型,其UI类名最好与功能编码表示的功能点的UI类名保持一致。
自定义项def1
该项用于注册业务类型调整后的处理类,即单据类型与业务类型的关联关系被修改后的业务处理类。
被
nc.bs.pub.pf.PfSaveAfterBusi.adjustAfterBusiOp()实例化后调用。
如果该项未注册,但该登录公司启用了“PO采购管理”模块,则默认处理类为
nc.bs.pu.po.PoToPfDMO。
自定义项def3 动作执行前的UI端处理,被
nc.ui.pub.pf.PfUtilClient.processAction()实例化后调用。
该类必须实现nc.ui.pub.pf.IUIBeforeProcAction接口(参见《NC31业务流程开发文档》3.6.1节)。
如果该项未注册,但单据类型编码以“D”、“E”、“F”开头,则默认为nc.ui.ep.dj.Arap_ProcAction类。
3.2开发业务单据
业务单据的开发主要包括:数据库设计、数据访问DMO、单据聚合VO、单据UI、单据动作及其执行脚本、单据动作组、单据状态组、单据
函数注册、单据组件注册、VO对照表。
当然还有查询模板和打印模板等。
更详细的请参考UAP组织编写的《UI工厂文档――模式化快速开发手册》。
这里只对两点进行重提:1.VO对照表pub_votable 与单据VO相互间的数据交换规则(参考NC31业务流程开发文档)不同,这里的VO对照表是用以详细描述某单据类型的。
主要包括单据主子表的VO 对象类名、主子表的表名等信息。
其中
注:每一个需要走审批流的单据类型,其数据库表和主表聚合VO中都应该包含这几个属性字段,并将其字段名称在此注册。
NC31审批流程开发文档_v1.2
3.3定义审批流程
利用NC31的审批流设计器,根据实际业务需求设计审批流程。
参考《NC31审批流使用文档》
四、开发指导
4.1动作处理
动作处理时序图1:
NC31审批流程开发文档_v1.2
业务
图1非审批类动作处理
动作处理时序图2:
NC31审批流程开发文档_v1.2
图2审批类动作处理
4.1.1 UI端调用-PfUtilClient
1.单据动作处理(非“*****")
Object nc.ui.pub.pf.PfUtilClient.processAction(Container parent,
String actionName, String billType, String currentDate, AggregatedValueObject vo, Object userObj,
String strBeforeUIClass, AggregatedValueObject checkVo ) throws Exception
功能:
1.判断是否进行动作前提示
NC31审批流程开发文档_v1.2
2.动作执行前的事前处理
3.如果是新增单据后保存(动作为SAVE),或修改单据后保存(动作为SAVE或EDIT),而且单
据类型的注册类名以Y开头,则可能需要指派信息4.后台执行动作处理- PfUtilBO.processAction(…)
5.如果动作执行的返回值为IProcActionRetObject,则进行事后前台处理
6.如果上述过程发生异常,且异常为IPfRetException,则判断异常是否需要进行业务处
理后继续执行事后处理
7.判断返回对象是否为PfUtilActionVO,然后前台显示
2.单据动作处理,但不启动审批流
Object nc.ui.pub.pf.PfUtilClient. processActionNoSendMessage (
Container parent, String actionName, String billType, String currentDate, AggregatedValueObject vo, Object userObj,
String strBeforeUIClass, AggregatedValueObject checkVo ) throws Exception
功能:
1.判断是否进行动作前提示2.动作执行前的事前处理
3.后台执行动作处理-PfUtilBO.processAction(…)
4.如果动作执行的返回值为IProcActionRetObject,则进行事后前台处理
5.如果上述过程发生异常,且异常为IPfRetException,则判断异常是否需要进行业务处
理后继续执行事后处理
6.判断返回对象是否为PfUtilActionVO,然后前台显示
NC31审批流程开发文档_v1.2
3.单据动作处理("*****")
Object nc.ui.pub.pf.PfUtilClient.processActionFlow(Container parent, String actionName, String billType, String currentDate, AggregatedValueObject vo, Object userObj,
String strBeforeUIClass ) throws Exception
功能:
1.判断是否进行动作前提示2.动作执行前的事前处理
3.如果单据动作以"*****"开头,检查该单据是否处于审批流中并打
开审批对话框4.后台执行动作处理- PfUtilBO.processAction(…) 5.如果动作执行的返回值为IProcActionRetObject,则进行事后前台处理
6.如果上述过程发生异常,且异常为IPfRetException,则判断异常是否需要进行业务处
理后继续执行事后处理
7.判断返回对象是否为PfUtilActionVO,然后前台显示
4.单据动作批处理(非"*****")
NC31审批流程开发文档_v1.2
Object[] nc.ui.pub.pf.PfUtilClient.processBatch(Container parent,
String actionName, String billType, String currentDate,
AggregatedValueObject[] voAry, Object[] userObjAry, String strBeforeUIClass ) throws Exception
功能:
1.判断是否进行动作前提示2.动作执行前的事前处理
3.后台执行动作处理- PfUtilBO.processBatch(…)
4.如果返回对象为IProcActionRetObject,则按照事后业务进行处理
5.如果上述过程发生异常,且异常为IPfRetException,则判断是否需要进行业务处理后
继续进行动作处理
参数说明:
5.单据动作批处理("*****")
Object[] nc.ui.pub.pf.PfUtilClient.processBatchFlow(Container parent, String actionName, String billType, String currentDate,
AggregatedValueObject[] voAry, Object[] userObjAry ) throws Exception
功能:
1.判断是否进行动作前提示2.动作执行前的事前处理
3.如果单据动作以"*****"开头,检查第一张单据是否可被当前操作员审批并打开审批对
话框
4.后台执行批动作处理- PfUtilBO.processBatch(…)
NC31审批流程开发文档_v1.2
5.如果动作执行的返回值为IProcActionRetObject,则进行事后前台处理
6.如果上述过程发生异常,且异常为IPfRetException,则判断异常是否需要进行业务处
理后继续执行事后处理
7.判断返回对象是否为PfUtilActionVO,然后前台显示
参数说明:
4.1.2 BS端调用-PfUtilBO
1.单据动作处理
Object nc.bs.pub.pf.PfUtilBO.processAction(
String actionName, String billType, String currentDate,
PfUtilWorkFlowVO workFlow, AggregatedValueObject vo, Object userObj ) throws RemoteException
功能:
1.数据加锁和一致性检查
2.动作执行前的工作流处理(弃审或删除)3.进行动作约束检查
4.执行动作脚本,并返回值
5.如果返回值为IWorkFlowRet,则直接返回6.判断动作是否为最后一个动作,执行动作驱动
7.如果动作编码以“SAVE”或“EDIT”结尾,则尝试启动审批流
NC31审批流程开发文档_v1.2
2.单据动作批处理
Object[] nc.bs.pub.pf.PfUtilBO.processBatch(
String actionName, String billType, String currentDate,
AggregatedValueObject[] vos, Object[] userObjAry, PfUtilWorkFlowVO workflow ) throws RemoteException
功能:
1.遍历一遍单据VO数组,进行动作执行前的工作流处理(弃审或
删除)以及动作约束检查2.执行动作脚本,并返回值(要么为null,要么为Object[])
3.遍历处理后的单据VO数组,判断动作是否为最后一个动作,执
行动作驱动;同时进行动
作执行后的工作流处理(依次启动审批流)。
参数说明:
4.1.3返回值
UI端PfUtilClient动作处理的返回值就是对应BS端动作处理的返回值。
BS端动作处理PfUtilBO.processAction(…)以及批处理
PfUtilBO.processBatch(…)的返回值受动作脚本返回值(参见4.2.2节)的影响。
4.1.4动作驱动
在BS端PfUtilBO动作处理的过程中,在执行完动作脚本后,根据其返回值的不同可能会进行动作驱动――依次执行被驱动的单据动作脚本,同时如果被驱动动作编码为“SAVE”或“EDIT”结尾,还尝试启动审批流。
比如动作驱动:
30_*****-7D_*****E 7D_***** 4F_SAVE 5G_NIKE
在NC30中,执行完7D_*****E之后,如果启动了审批流,则退出后继驱动。
这是一个Bug。
NC31审批流程开发文档_v1.2
但NC31中,执行完7D_*****E之后,如果启动了审批流,仍然遍历被驱动的动作,但不会执行同单据类型的动作。
也就是说,仍然会执行
4F_SAVE和5G_NIKE动作脚本,但不会执行7D_*****。
不执行动作驱动的情形:
1.动作脚本返回值为IWorkFlowRet。
2.动作脚本返回值为Object[],且Object类型为IWorkflowBatch,并指明了不进行动作驱动。
3.当前动作非单据类型注册的结束动作。
4.2动作脚本
4.2.1执行脚本编写
动作脚本是单据动作的后台执行体。
通过功能点:客户化-〉二次开发工具-〉单据管理-〉单据动作执行脚本来进行编写。
保存时会自动生成脚本class文件。
在这里可以对从UI端传递过来的单据聚合VO进行业务处理,这其中就包含有对审批流的处理。
该功能点为方便执行脚本的编写,提供了单据类型注册的应用组件、应用函数以及常用语法。
注意:该功能点必须在集团下使用,否则产生错误的脚本class文件。
在开发环境中,我们一般把通过功能点生成的诸如N_40_*****.java动作脚本源文件导入到项目中进行开发。
但如果直接对源文件进行修改,记得要修改相应的getCodeRemark()方法,否则通过功能节点打开时,将会看到不一致的脚本。
下面对单据动作脚本中与审批流相关的常用语法宏进行分析。
当然,完全可以不使用下述的语法宏而直接使用Java标准语法来编写动作执行脚本。
动作脚本类图:
常用语法:
NC31审批流程开发文档_v1.2
语法宏与实际代码的对照表:
NC31审批流程开发文档_v1.2
注意:单据批动作处理必须与批量的动作脚本相对应!
4.2.2返回值
NC31审批流程开发文档_v1.2
4.3状态回写与查询
4.3.1单据审批状态
一旦单据送审到审批流中,单据便处于某个审批状态。
在审批流内部,单据的内部审批状态有
5
自由态
即单据尚在编写中(已保存或尚未保存)并未提交到审批流的状态。
提交态
通过执行单据动作SAVE或EDIT,将单据送审后的状态。
提交态是审批流内部的一个状态,它的回写并不通过审批流检查类进行。
只能由业务组通过SAVE动作脚本自己对单据状态进行设置。
所以有的业务组的单据并没有提交态的概念。
审批进行中
流程实例正处于运行中的状态。
审批完成
如果流程实例正常运行完成,该单据的审批过程即完成。
审批流程结束后具有最终审批结果:通过或不通过,这也是单据的最终审批结果。
状态转换图如下所示:
NC31审批流程开发文档_v1.2
业务单据根据自己的业务需求也可定义自己的审批状态,但不可与上述5种状态相冲突。
比如UI
在各个状态下对单据的业务处理(比如是否可删除、是否可编辑等)由业务组自己控制。
参见节和节。
4.3.2状态回写
分为两种,一种是对单据聚合VO的回写,一种是对单据数据库表的回写。
都是在动作执行脚本中完成。
参见4.8.1节。
NC31审批流程开发文档_v1.2
4.3.3状态查询
后台API:
int nc.bs.pub.pf.PfUtilBO.queryWorkFlowStatus( String busiType, //业务类型PK String billType, //单据类型PK String billId) //单据Id
4.4送审
送审也称为提交,就是单据产生后进入到流程平台并启动审批流的步骤,通过调用单据动作处理来完成。
审批流的触发支持两种单据动作,分别为“SAVE”和“EDIT”,即动作编码以两者结尾即可。
送审后,流程平台会根据单据类型和制单人ID查找符合条件的流程定义并实例化然后启动它。
如果找不到流程定义,则不启动审批流。
送审分为两种情形,一种是前台送审,即业务UI新增单据后保存并提交;另一种是后台送审,即某张单据在后台推式生成另一张单据时。
4.4.1动作处理
前台送审调用示例:
Object retObj = nc.ui.pub.pf.PfUtilClient.processAction(parentUI, “SAVE”, “D1”, “20XX年-05-30 12:23:44”, billVo, userObj, null, null )如果单据数据billVo中没有保存制单人的信息,则可通过动作编码来传递。
但要求原动作编码不能长于20个字符。
Object retObj = nc.ui.pub.pf.PfUtilClient.processAction(parentUI,
“SAVE”+billMakerUserId, “D1”, “20XX年-05-30 12:23:44”, billVo, userObj, null, null )
后台送审调用示例:
NC31审批流程开发文档_v1.2
Object retObj = new PfUtilBO().processAction(parentUI,
“SAVE”, “D1”, “20XX年-05-30 12:23:44”, null, billVo, userObj )
前台送审与后台送审的区别在于,前台送审会先向服务器获取流程定义中第一个审批人的可指派(参见《NC31审批流使用文档》4.1.6节)信息,以便于与客户端交互。
而后台送审则默认为不可指派。
对于单张单据的送审,也可以按照批量(参见4.4.3)的方式来处理(这种应用在NC财务和供应链产品中比较常见),这时VO数组中传递的就是一张单据。
4.4.2动作脚本
送审的动作脚本没有特殊的要求,可以在脚本中进行单据VO的保存,也可以对单据VO进行更新。
但如果单据UI的开发使用了UI工厂,
为了维护单据数据的一致性,可在脚本中调用如下方法来保存单据并更新聚合VO。
retObj=runClass("nc.bs.trade.business.HYPubBO", "commitBill", "nc.vo.pub.AggregatedValueObject:01",vo,m_keyHas,m_methodReturnHas );
或者
SuperVO headVO = (SuperVO) billVo.getParentVO(); //主表必须为SuperVO SuperDMO dmo = new SuperDMO();
//从数据库获取到更新了ts的VO
billVo.setParentVO(dmo.queryByPrimaryKey(headVO.getClass(), headVO.getPrimaryKey()));
注意:NC30要求送审的动作脚本必须返回ArrayList或String类型的对象,在NC31中并没有这种限制了,但前提是单据聚合VO中包含有完整的单据号和单据ID信息。
4.4.3批量处理
批量送审是指多张(包括单张)单据产生后一起进行送审处理。
多张单据的制单人可以相同,也可以不相同,但必须保证批处理的单据是同类型的。
不同制单人的多张单据一起送审可能会启动不同的审批流程。
所以对于前台的批量送审,并不会与用户交互来获取指派信息,而默认为不指派。
但如果批量送审的单据VO数组中只包含一张单据,则还是会与用户交互来获取指派信息。
前台批送审调用示例:
Object retObj = nc.ui.pub.pf.PfUtilClient.processBatch(parentUI,
“SAVE”, “D1”, “20XX年-05-30 12:23:44”, billVoAry, userObjAry, null)后台批送审调用示例:
Object retObj = new PfUtilBO().processBatch(parentUI,
“SAVE”, “D1”, “20XX年-05-30 12:23:44”, billVoAry, userObjAry, null) NC31审批流程开发文档_v1.2
4.4.4特殊应用
下面对如下几种特殊应用进行分析,
1.对于保存/提交分离的应用,制单人保存后,由业务组控制非制单人可否提交单据;审批流会根
据单据VO中的制单人信息来获取审批流定义并启动审批流。
2.多次提交问题:
a) 单据提交后会启动审批流,这时如果再次修改后提交,会删除旧的流程实例和工作项记录,
并重新启动审批流。
b) 如果业务组没有控制单据审批进行中的不可编辑,那么单据在审批过程中可被修改,然后
再次提交,这时执行完动作脚本后,
EngineService.sendWorkFlowOnSave()会直接返回而不会再次启动审批流。
c) 单据审批完成后(即审批流程结束后),再次修改该单据并提交,这时会重新启动一个审
批流程,同时保留了原已结束流程所产生的工作项(参见《NC31审
批流使用文档》4.1.13节)记录。
4.5审批
审批是登录到NC的操作员完成流程平台分配给他的工作项的过程,它是驱动流程流转的关键应用。
每个工作项的审批有“通过”、“不通过”和“驳回到制单人”三种结果。
关于工作项的审批结果与流程审批结果的异同,参见《NC31审批流使用文档lj》4.1.3节。
根据单据是否启动了审批流,审批分为:
有流程实例:单据送审后,根据制单人查询到流程定义,并启动了流程实例。
如果对一个尚未提交的单据进行审批,会提示“单据尚未提交,无法审批。
”的错误。
无流程实例:单据送审后,根据制单人查询不到流程定义,即没有启动流程实例。
不管其是否提交,都不会启动审批流,任何人都可直接审批通过。
这种审批由于没有流程实例和工作项,并不属于真正意义上的流程审批,更多的是进行业务处理。
根据业务需求,审批还分为两种情形,一种是前台审批,即业务UI 查询到单据后进行审批或者通过待办事务来审批;另一种是后台审批,会将单据直接审批通过。
后台审批只适用于无流程实例的情形,对于启动了流程实例的单据,不可进行后台审批。
4.5.1动作处理
前台审批调用示例:
Object retObj = nc.ui.pub.pf.PfUtilClient.processActionFlow(parentUI, “*****”, “D1”, “20XX年-05-30 12:23:44”, billVo, userObj, null)
如果单据数据billVo中没有保存当前审批人的信息,则可通过动作编码来传递。
Object retObj = nc.ui.pub.pf.PfUtilClient.processActionFlow(parentUI, “*****”+checkUserId, “D1”, “20XX年-05-30 12:23:44”, billVo, userObj, null,)
后台审批调用示例:
NC31审批流程开发文档_v1.2
Object retObj = new PfUtilBO().processAction(parentUI,
“*****”, “D1”, “20XX年-05-30 12:23:44”, null, billVo, userObj )
对于单张单据的审批,也可以按照批量(参见4.5.3节)的方式来处理(这种应用在NC财务和供应链产品中比较常见),这时VO数组中传递的就是一张单据。
4.5.2动作脚本
审批的动作脚本具有特殊的要求。
可对单据VO进行更新操作,也可在审批通过(分为两种,每个工作项的审批通过和整个流程的审批通过)后进行业务处理。
单张单据审批动作脚本示例:
Object m_sysflowObj = procActionFlow(vo); /** 流程仍处于审批进行中时直接返回IWorkFlowRet */ if (m_sysflowObj != null) { return
m_sysflowObj; }
doBusi(getVo()); //审批流程结束(通过)后的业务处理
如果单据UI的开发使用了UI工厂,为了维护单据数据的一致性,需要在脚本中调用如下方法来更新聚合VO。
SuperVO headVO = (SuperVO) billVo.getParentVO(); //主表必须为SuperVO SuperDMO dmo = new SuperDMO();
//从数据库获取到更新了ts的VO
billVo.setParentVO(dmo.queryByPrimaryKey(headVO.getClass(), headVO.getPrimaryKey()));
4.5.3批量处理
批量审批是指当前操作员对查询到的多张(包括单张)单据一起进行审批处理。
必须保证当前操作员对这些单据都具有审批权限(即都轮到他审批)。
批审批的动作脚本具有特殊的要求,可参考如下示例。
Hashtable m_sysHasNoPassAndGonging = procFlowBacth(vo) ; for (int i = 0; i getVos().length; i++) {
Object obj = m_sysHasNoPassAndGonging.get(String.valueOf(i)); if (obj == null)
doBusi(getVos()[i]); //审批流程结束(通过)后的业务处理
}
//控制可否进行动作驱动
BatchWorkflowRet bwr = new BatchWorkflowRet();
bwr.setNoPassAndGoing(m_sysHasNoPassAndGonging);
bwr.setUserObj(getVos());
return new Object[]{bwr}; //动作脚本返回值。