财务专业用语中app是什么意思(财务软件的含义)

使用本示例需通过docker容器,请先下拉jxTMS的docker镜像并按说明启动tms容器,并从helloWorld开始尝试。

兴趣点

有句话说的好:手里拿着锤子,看什么都象钉子。所以在实现了低成本快速定制之后,必然会出现越来越多的数字化需求,奉行打铁式迭代的jxTMS该如何把这些迭代低成本的串起来而不至出现相互干扰呢?!

比如,我们首先制作了一个报销审批流程,该流程假定最后的审批人是CEO,那么当CEO同意之后,会发生什么呢?应该是财务部门将该笔费用纳入拨款计划,进行相关的财务作业了,但一般来说财务系统都是专业软件,所以开始肯定需要人员手工作业来协调,但随着企业数字化的普及,可能就想去除两系统间的人工作业这个瓶颈,增加了自动化协调工具。但这可能导致已经稳定运行的报销审批流程也要进行修改,说不得还需要两系统进行大量的联合调试。这就增加了定制成本,阻碍了业务系统随动业务发展进行低成本升级。

有鉴于此,jxTMS引入了一个概念:兴趣点。即在可能会引发系统勾连的地方,广播一个兴趣事件,感兴趣的就去捕获了自行处理,而不管有没有感兴趣的,触发源都不关心。

那么,针对上面所说的报销审批流程,在开始阶段,感兴趣的是人,是特定的财务人员,由其进行查看后进行手工作业来协调两系统。以后,则可以是一个函数,由其接收流程数据对象后,执行自动化协调工作。

这就大大降低了业务系统各功能模块之间的耦合度,配合jxTMS的热机刷新能力,在大幅度降低定制成本的同时还保证了业务系统的稳定性、可靠性。

jxTMS的兴趣点其实类似于一种独特的消息通知【需要同时适应人员的手工操作和机器的自动执行】,当预设的条件满足【即只对符合条件的数据对象感兴趣】时,我们就会得到通知。

对于人员来说,由于兴趣点其实就是条件查询,而我们前面演示过了条件查询,大家可以看到工作量还是比较大的,所以jxTMS还针对人员接收的兴趣点提供了统一的界面和处理机制,从而大幅度降低了以人员为目标的兴趣点的开发工作。

我们下面就来演示以人员为目标的兴趣点的制作,自动化的兴趣点等以后有需要时再进行演示。还是先看效果再来讲解。

增加流水号

流程等业务管理,都需要一个独一无二的流水号作为流程的识别名。jxTMS提供了非常方便的流水号生成办法:

首先在capa.py文件中重载SerialNumberModel函数:

def SerialNumberModel(self): return 'demo-{YYYY}{MM}{DD}{SND3}'

大家看到SerialNumberModel函数的返回值应该能猜到是流水号的生成模板,等大家看到效果后我们再来详细讲解。同时在流程的数据对象生成处(大家想想是在哪呢)添加一条语句以使得在流程创建时,利用SerialNumberModel函数返回的模板来创建流水号:

self.currentAffair.Category=self.getSerialNumber(db,'demo')

getSerialNumber函数会自动调用SerialNumberModel获取流水号的模板,创建一个叫做demo的流水号生成序列,然后根据此序列生成一个流水号。修改后的如下:

@myModule.request('sfDemo', 'demoApply', 'dual')def sfDemoApply_dual(self, db, ctx,ca,active): self.currentAffair.Name=self.getInput('demoName') self.currentAffair.Category=self.getSerialNumber(db,'demo') self.currentAffair.Type=self.getInput('demoType') self.currentAffair.Purpose='demo' self.currentAffair.State=0 self.currentAffair.Info.set('creator',ctx.getCaller().abbreviation()) self.currentAffair.CreatorID=ctx.getCaller().id() #业务合规性检查 #self.restrict(db,ctx,'testDemoRule') #提示并关闭界面 return True

注:我们注释掉了业务合规性的检查

我们还需要增加一个兴趣点的定义:

@myModule.interest('demo','兴趣点demo'.decode('utf-8'),False)def interest_demo(): ''' role manager when field.Type=='demo' ''' passdef getSN(self,jo): return jo.Categorydef getState(self,jo): if jo.State == 0: return '执行中'.decode('utf-8') return '执行完毕'.decode('utf-8')# 因为兴趣点是通用的,所以针对兴趣点demo的显示准备数据def transForInterest(self,ctx,json,jo): json.set('affairName',jo.Name) json.set('affairCategory',self.getSN(jo)) json.set('creator',jo.Info.get('creator')) json.set('CreateTime',jo.CreateTime) json.set('affairState',selfgetState(jo)) json.set("readed", jo.getReadStr(ctx.getCaller().id())) json.set('op',self.getViewA(self.getFullName(),self.viewWebInterface(),jo.Name,jo.ID))

可以看到,兴趣点的处理,全部都是在capa.py文件中。我们先看下效果,将capa.py文件按用sftp管理jxTMS的代码所述更新到/home/tms/codeDefine/demo/demo/demo1目录中。

然后执行一次热机刷新后,由于快捷栏中的入口有变化【多了一个:关注点->兴趣点demo】,所以先要退出登录,再次登录后点击快捷栏中的【演示->发起申请】,一定要注意的是在类型栏中一定要输入demo,然后大家一路把这个流程跑完。

然后请点击快捷栏中的【关注点->兴趣点demo】,大家会看到:



大家点击最后一列的【查看】,看看能否看到刚审批完的这个流程。大家回看一下我们上面对capa.py文件的修改,应该能看出来我们一共做了5个工作:

重载SerialNumberModel函数,来定义流程的流水号在流程创建时,生成流水号定义一个名为兴趣点demo的兴趣点为列表显示兴趣点demo,重载了transForInterest函数为兴趣点demo的列表显示准备数据sfDemo流程使用affair类来记录流程数据,但affair的State属性为整数,为便于用户理解,定义一个getState函数用于显示流程状态流水号模板

大家对照兴趣点列表中的识别号和SerialNumberModel返回的流水号模板,应该基本能猜出来模板的大致含义了。流水号模板中用大括号括起来的会用上下文中的数据进行替换来生成最终的流水号,这些大括号括起来的识别元组包括:

YYYY:4位的年MM:2位的月DD:2位的天hh:2位的时mm:2位的分ss:2位的秒SNDd:日流水,d是一个数字,代表长度,如SND4,是0001-9999共4位,是本流水号生产序列今天生成的第几个流水号SNMd:月流水,d是一个数字,代表长度,如SNM5,是00001-99999共4位,是本流水号生产序列本月生成的第几个流水号SNYd:年流水,d是一个数字,代表长度,如SNY6,是000001-999999共4位,是本流水号生产序列今年生成的第几个流水号SNTd:总流水,d是一个数字,代表长度,如SNT7,是0000001-9999999共7位,是本流水号生产序列总共生成的第几个流水号Purpose:用途,来自名为snPurpose的输入变量

如:【销售订单-{Purpose}-{YYYY}{MM}{DD}{SNM4}】在snPurpose的输入变量为vip时,应形如:

销售订单-vip-202106181234定义兴趣点

和业务规则的定义类似,兴趣点也是利用@修饰来加载doc进行定义的。修饰函数myModule.interest有两个参数:

兴趣类型,区分各种兴趣点兴趣点的名字,这里是:兴趣点demo,这个名字会显示到指定的角色的快捷栏中的兴趣点下

兴趣点的定义格式是:

role 角色名列表 when 条件表达式

其中:

角色名列表:对该兴趣点感兴趣的有哪些角色名,如果有多个,则以英文逗号分隔

注:只有指定的角色才能看到这个兴趣点入口

条件表达式:参考业务规则的条件表达式

注:和业务规则中不同的是,兴趣中的数据对象默认就是self.currentAffair,所以其不需要业务规则中访问数据对象时的冠字【a0:】,所以兴趣点demo中的field,就是访问self.currentAffair的属性

则兴趣点demo的意思就是:当self.currentAffair的Type属性等于demo时,就通知manager角色【映射给了manager用户,所以我们才能看到这个兴趣点的入口】。那么兴趣点是什么时候触发的呢?!

jxTMS默认是在流程结束时触发兴趣点的检测开发者还可以在需要的任何时候,手动触发兴趣点的检测。通过执行:
public final void interest(IDBop db,context ctx,String interestType,orm jo) throws Exception;

在python中调用形如:

self.interest(db,ctx,interestType,jo)

其中的interestType就是我们在interest_demo的修饰中所指定的兴趣类型

兴趣点列表

当指定的角色点击相应的兴趣点入口时,系统会查询符合条件的数据对象,然后transForInterest来将这些数据对象逐行显示出来。

注:transForInterest中json所设置的对象名对应兴趣点列表的各列名,所以大家如果自己想调整显示内容的话,json各对象名不能动。如果大家不打算自己调整,是可以不继承transForInterest函数的,jxTMS内部的transForInterest函数就是如此显示的。本示例只是向大家演示如果要调整该如何实现

结语

原则上,jxTMS支持两种联动模型:

基于兴趣点的被动模式,即在联动触发点,触发源只是简单的触发一个兴趣广播,谁有兴趣谁就接收该广播自己处理;而不管有没有感兴趣的,触发源既不关心也不受任何影响。即双方属于无耦合基于业务数据的主动模式,业务数据类似于微服务,以规定格式提供数据服务,则在联动触发点,请求联动方主动请求业务数据供应方。也就是说,主动模式下,请求方的逻辑是需要供应方来支持的,也即请求方的逻辑中嵌入了供应方的能力,属于深度耦合