上次对这个Actions and Recommendations进行了初步研究,因为一些问题没有得到很好的解决,又花了很多时间,终于得到了一个比较好的解决方案。小结一下。
1. 生成Actions and Recommendations下栏目最基本的有两种方法:一是通过Deployment,优点是操作简单,另外,还可以很方便地通过点击Add按钮添加项目,缺点是无法定义这些项目显示在A&R下的条件。二是通过Process Builder。官方文档上介绍的主要是这两种方法,另外还有通过Apex或者web service来建。
2.Process Builder的主要优点是比较简单直观,另外的优点主要是因为运行在System Context下,可以不受当前用户的权限限制,而且,通过它去运行某些Flow,同样也在System Context下,不受权限限制。但是,如果通过它去运行Record triggered Flow,则不是在System Context下,因为Record triggered Flow只能运行在当前用户权限下,无法修改这一设置。
Process Builder的主要缺点是:
1)除非触发条件设置得能够保证执行一次后就不可能再触发,或者开始设置成只在建新纪录时才触发,否则因为它无法检查Flow或者QuickAction是否已经存在,会在A&R下重复建项目。
2)在Process Builder下调用Apex,无法获得返回值,相当于只能调用void类型的方法。
3)不支持before saved类型的触发。
2. 另一个方法是用Flow来建,又可分为用Record triggered Flow和Auto launched flow。前者的好处主要是有个$Record变量,不需要再用一个Get Record元素去取当前SObject的信息,另外的优点是支持before saved类型的触发条件。但是缺点一是不能运行在System Context下,某些牵涉到用户权限的需求不能实现。二是$Record变量在调试Flow时反而不方便。
前者的缺点正好是后者的优点,而优点又成了后者的缺点。
而两者共同的优点是
1)可以用图形化的形式定义触发条件,比较适合编程经验少,但熟悉业务逻辑的管理员和业务分析员
2)调用Apex,可以获得返回值。
两者共同的缺点就是某些操作比较笨拙。比如遍历时,实现如下的逻辑:
bool isFound = false;
foreach (foo in bar) {
if (满足某个条件) {
isFound = true;
break;
}
}
if (isFound == true) {//后续操作
}
如果用Flow来实现就很麻烦,无法实现上面的break操作,只能全部遍历完再来判断isFound == true。
3. 不管用哪种方法,在A&R下显示项目,本质是对RecordAction对象的操作。下面谈有关的问题。第一个问题:如何避免在A&R下生成重复项?
固然可以用Flow来实现,但很麻烦,所以考虑用Apex。因为业务逻辑放在Flow里比较好,所以打算用Apex来找出已经存在的RecordAction,然后返回Flow尚未存在,需要创建的RecordAction。然后Flow里设置触发条件,再用Creat Record元素来建RecordAction。这是最初的设计。
后来发现主要缺点是Flow里的元素比较多,线条很多,看上去有点乱。但这还不是主要问题,碰到了第二个问题:如何当一个Flow执行一遍,完成之后,避免在A&R下再次生成项目?
因为Flow完成后,只要刷新页面,对应的RecordAction就会自动删除,然后就只有在RecordActionHistory里才找得到踪迹。而RecordActionHistory是所谓的Big Object,不能在触发器里直接查询,一查就报错。虽然调试Flow的时候好好的,不出错,但一旦正式运行,马上出错。
为了解决这个问题,先是发现QuickAction执行后,对应的RecordAction不会删除,就考虑用QuickAction来包装Flow。但发现QuickAction缺省是在一个模态框里显示,而Flow缺省应该是在一个Tab里显示,结果被QuickAction包装后,也执行在模态框里,界面很难看。只好又做了个Lightning Component,用它打开另外一个Lightning Component,并显示在Tab里,在第二个Lightning Component里再去运行Flow。然后把第一个Lightning Component加到QuickAction里,就基本做好了。显然,一层套一层,很麻烦。而且很快发现一个问题。就是QuickAction的RecordAction不会显示Complete状态(所以它不会被删掉),但这样一来,也无从得知Flow到底有没有运行完。
做了半天白做了,还好柳暗花明又一村,终于又找到一个办法,就是用future方法也即异步模式去查RecordActionHistory。
同时,修改了设计,用apex实现查找已存在的RecordAction和已经执行完毕的Flow类型的RecordAction(QuickAction类型的还是没法查),然后直接用apex创建RecordAction。这样一来,查找,创建的功能全移到apex,Flow那头只剩下定义触发条件和给apex提供输入参数的几个元素,顿时清爽了许多。
从Flow调用apex(用Process Builder也一样),需要在apex类里定义一个带@invocableMethod属性的方法,而且一个类里只能有一个方法带此属性。另外,只允许一个输入参数。如果输入参数是List>,再套上一个List,就能传入多个值了。
还有前面已经提到,Flow里的PickList域,传到apex后,需要用String.valueOf()才能取值,否则报cast错误。这是Salesforce的bug。
另外,在带@invocableMethod属性的方法里可以调用带@future属性的方法,也是诸多限制。首先不允许传对象类型的参数,只能传List
意犹未尽,又添加了一些功能,比如允许用户指定不需要查RecordActionHistory,甚至可以允许重复项。还允许当Flow的触发条件不满足时,删除对应的RecordAction。因为@invocableMethod只能传一个参数,Flow里又难以使用自定义对象,所以只好在RecordAction的Status域上做文章,自己定义Unlinked表示删除,Paused表示不需要查RecordActionHistory,Started表示允许重复项。缺省的New则表示不允许重复项,也必须查RecordActionHistory。这样,功能又增强了。
补充:
开始时把所有查RecordAction和RecortActionHistory的操作全部放在@future方法里,但在调试时发现无法删除记录,插记录时也有问题,移出来就好了。看来这个@future方法很tricky,尽量避免。最后修改为只有查RecortActionHistory的功能放在@future方法里,同时添加代码,在@future方法里再查一次RecordAction,因为@future方法执行时,说不定对象有变化,再查一次比较保险。
另外将来如要再拓展功能,也许可加一个用户自定义对象,这样在Flow里设参数就方便了,不用再利用RecordAction的Status域。现在先对付着用。
在折腾A&R的过程中,接触了一些相关技术,使用了一些相关工具,得到不少副产品,算是有所收获。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章