参数和宏的极致使用
本文通过一个使用参数和宏结合实现复杂数据权限需求的案例,分享给大家一个经验:不管多么复杂的数据权限业务逻辑,集智数据平台的报表系统都可以实现。
应用场景说明
??? 某医疗用品制造商使用了润乾集智数据平台来搭建报表管理系统,集智数据平台中用户、组织机构和角色数据保持与客户原有EOS系统数据同步。报表数据从以EOS数据为基础的视图库中抽取。
??? 权限控制涉及到了系统权限和较为复杂的数据权限。系统权限中除了基本的组织机构授权和角色权限以处,还衍生出多种角色权限。比如每一用户都关联了一个权限标志位,而权限标志位又分为普通、部门和全部三种。其中普通权限用户只能看到本人及下级人员数据信息,部门权限用户可以看到本部门内容的数据信息,全部权限用户可以看到全部数据信息,无权限过滤。
??? 但是该单位的销售职位中存在RSM、TSM和TSR三种角色,它们存在上下级关系,职位由高到低依次是RSM、TSM和TSR。并且,TSM有权力跟代理商签订代理协议。TSM可以选择自己跟踪代理协议、分配给TSR跟踪代理协议和自己与TSR同时跟踪代理协议这种跟踪方法。
??? 鉴于以上业务事实,客户提出在相关报表中(设为R)要求实现如下业务逻辑:将R分配给用户后,要求根据“权限标志位”判断出用户能访问的数据范围。同时,当用户登录后,在参数模板中还要求根据sys_UserID筛选出该用户能访问的代理商以及该用户的RSM。RSM的显示规则是:当用户权限标志位为“普通”时,若登录用户为TSR,则显示其上级TSM;若若登录用户为TSM,则显示为自己;若登录用户为RSM,则显示为其下属的所有TSM。当用户权限标志位为“部门”和“全部”时,则按“权限标志位”判断规则显示数据。
实现过程
框架
??? 本实现过程先搭框架,再具体实现,以使读者能够更清晰地理解整个实现过程。
?/SPAN> 查询权限标志位
??? 增加一个参数“mapKey”,使用query()查询并返回权限标志位
?/SPAN> 搭建权限标志位逻辑
??? Case(mapKey,”普通权限”,”操作1”,”部门权限”,”操作2”,”全部权限操作3”)
?/SPAN> 实现普通权限时操作1
??? 若操作1是查询代理商,则通过sysDistributor、syslicencetsmshare、sysperson和t_user表之间的关联关系查出代理商并返回。
??? 若操作1是查询RSM,则通过syslicencetsmshar、syslicencetsrshare、sysperson和t_user表之间的关联关系查出RSM并返回。
?/SPAN> 实现部门权限时操作2
??? 若操作2是查询代理商,则先通过DistributorAgreement、Distributor、ProductKind和sysperson表之间的关联关系构造出一个含有代理商名称、TSM以及TSM所属部门的视图“DistributorAgreement”。然后从DistributorAgreement查出登录人员所在部门的所有代理商并返回。
??? 若操作2是查询RSM,则通过sysagreement、productdept和rt_roleuser表之间的关联关系查出RSM并返回。
?/SPAN> 实现全部权限时操作3
??? 不进行数据过滤,直接取全量数据即可。
?/SPAN> 将权限标志位逻辑封闭到宏中
?将宏结果交给数据集?/SPAN>
实例
??? 在框架基础上,实现实例。
?/SPAN> 查询权限标志位
参数名称 参数类型 值表达式 参数说明
sys_UserID 字符串 集智数据平台传入参数模板的登录用户ID
mapKey 字符串 query2(”mis2datasource”,”select role_id from RT_ROLEUSER where user_id=? and role_id in (3,4,5)”,@sys_UserID) 权限标志位
?/SPAN> 搭建权限标志位逻辑
Case(mapKey,”普通权限”,”操作1”,”部门权限”,”操作2”,”全部权限操作3”)
?/SPAN> 实现普通权限时操作1
??? 若操作1是查询代理商,则:
select DistributorName_C as 代理商中文名称 from sysDistributor where DistributorID in (select distinct DistributorID from syslicencetsmshare where personid in (select personid from sysperson where personname in (select user_name from sjmreport.dbo.t_user where user_id = ‘”+sys_UserID+”‘))) order by DistributorName_C
??? 若操作1是查询RSM,则增加一个参数dmgr,以判断登录用户是否是TSM,若返回值为0,说明是TSR,否则为TSM。参数及相关业务逻辑如下:
参数名称 参数类型 值表达式 参数说明
dmgr 整数 query2(”eosreport”,”select count(*) from syslicencetsmshare where personid in (select personid from sysperson where personname in (select user_name from sjmreport.dbo.t_user where user_id = ?))”,@sys_UserID) 判断登录用户是否是TSM,若返回值为0,说明是TSR,否则为TSM
if(dmgr>=1,”select user_name as 经理名 from sjmreport.dbo.t_user where user_id = ‘”+sys_UserID+”‘”,”select personname as 经理名 from sysperson where personid in(select personid from syslicencetsmshare where pk_lictsmshare in(select pk_lictsmshare from syslicencetsrshare where personid in(select personid from sysperson where personname in(select user_name from sjmreport.dbo.t_user where user_id = ‘”+sys_UserID+”‘))))”)
?/SPAN> 实现部门权限时操作2
??? 若操作2是查询代理商,则:
SELECT 代理商中文名称 FROM sysagreement where 部门 in(select role_name from sjmreport.dbo.t_role where role_id in(select role_id from sjmreport.dbo.rt_roleuser where user_id=’”+sys_UserID+”‘ and role_id in (22,23,24,25,26,27)))
??? 若操作2是查询RSM,则:
select distinct 区域销售经理 as 经理名 from sysagreement where 部门 in(SELECT 部门代码 FROM productdept where 部门ID in(select role_id-21 from sjmreport.dbo.rt_roleuser where user_id=’”+sys_UserID+”‘ and role_id in (22,23,24,25,26,27)))
?/SPAN> 实现全部权限时操作3
??? 若操作2是查询代理商,则:
select DistributorName_C as 代理商中文名称 from sysDistributor where DistributorID in (select distinct DistributorID from syslicencetsmshare) order by DistributorName_C
??? 若操作2是查询RSM,则:
select distinct 区域销售经理 as 经理名 from sysagreement
?/SPAN> 将权限标志位逻辑封闭到宏中
宏名称 类型 值表达式
代理商 动态宏 case(mapKey, “3″,”select DistributorName_C as 代理商中文名称 from sysDistributor where DistributorID in (select distinct DistributorID from syslicencetsmshare where personid in (select personid from sysperson where personname in (select user_name from sjmreport.dbo.t_user where user_id = ‘”+sys_UserID+”‘))) order by DistributorName_C”,”4″,”SELECT 代理商中文名称 FROM sysagreement where 部门 in(select role_name from sjmreport.dbo.t_role where role_id in(select role_id from sjmreport.dbo.rt_roleuser where user_id=’”+sys_UserID+”‘ and role_id in (22,23,24,25,26,27)))”,”select DistributorName_C as 代理商中文名称 from sysDistributor where DistributorID in (select distinct DistributorID from syslicencetsmshare) order by DistributorName_C”)
TSM 动态宏 case(mapKey, “3″,if(dmgr>=1,”select user_name as 经理名 from sjmreport.dbo.t_user where user_id = ‘”+sys_UserID+”‘”,”select personname as 经理名 from sysperson where personid in(select personid from syslicencetsmshare where pk_lictsmshare in(select pk_lictsmshare from syslicencetsrshare where personid in(select personid from sysperson where personname in(select user_name from sjmreport.dbo.t_user where user_id = ‘”+sys_UserID+”‘))))”),”4″,”select distinct 区域销售经理 as 经理名 from sysagreement where 部门 in(SELECT 部门代码 FROM productdept where 部门ID in(select role_id-21 from sjmreport.dbo.rt_roleuser where user_id=’”+sys_UserID+”‘ and role_id in (22,23,24,25,26,27)))”,”select distinct 区域销售经理 as 经理名 from sysagreement”)
?/SPAN> 将宏结果交给数据集
将“代理商”和“TSM”使用复杂SQL数据集封闭即可。
总结
??? 以上实现案例仅是针对在参数模板中进行数据权限控制的情况。当参数模板中数据传递到报表模板时还需要针对入参匹配数据,真正实现数据权限控制。不过,相对此过程参数模板中的控制就简单多了,不此不再实现。
??? 实现以上业务逻辑也实属无奈。当集智数据平台与其它系统共享库表,集智数据平台业务数据结构必须依赖于共享库表时,该案例还是有一定的借鉴意义。
??? 这种实现方案能避免就尽量避免,不能避免时,也要相信集智数据平台的报表系统能够很好地解决的。
更多了解各种复杂问题的处理,可以参考:让业务用户随时可以自己定义查询报表、多级部门角色按不同权限查看不同数据。