1. 整体解决方案概述
权限设计主要有一下几大部分组成:
PassPort:
针对现在系统的分析,系统之间有部分信息是共享的,这部分信息将由中心话的Passport来统一维护
- 用于中心存放用户,组织架构,渠道,品牌和产品相关的信息。
- 有关员工信息,可以从现有HR系统或者MDM中取得。
- 有关外部人员活动目录,可以专门在本PassPort系统中维护。
权限订阅模块:
负责订阅接受Passport发出的相关实体修改的信息。
资源权限绑定:
有效的将资源-角色-组-成员在数据库中简历绑定。
数据权限高速内存数据缓存:
将数据权限相关的数据缓存在内存,提供高性能访问能力。
Struts页面权限过滤和绑定:
使用Struts的tag动态根据资源权限的设置,决定页面中资源(按钮,菜单,URL,页面元素)的访问能力。
数据权限过滤:
根据数据过滤权限的特定,定义的数据权限过滤的通用数据结构。
根据业务集成和整合的需要,和优先级别的需要,权限部分的开发设计将逐步推进,初期会以各应用系统为单元进行资源权限和数据权限的改造,随后将根据重要业务系统的需要,逐步建立中心话的passport。
- 通用的数据管理;
- 通用Service;
- 数据权限系统同构;
- UI风格一致;
- 安全的访问控制;
- 可复用的API;
- 统一的资源权限控制;
- 统一和中心话的数据字典维护。
(1)功能级授权采用通常的权限分组,角色绑定资源的通用设计思路来完成。基本设计思路如下图:
资源权限绑定概览
资源:
菜单,按钮,URL,页面中的任何元素。
角色:
根据业务定义的各种角色,比如订单生成角色,结算角色等。
组:
用于联系角色和用户。
用户:
系统中登录的用户。
(2)资源权限在开发,测试,项目上线后维护中的不同作用:
项目开发和测试阶段:
- 项目开发人员和业务人员共同确定什么资源需要权限管理并在系统中定义资源。
- 在页面当中定义控制资源访问的tag。
- 根据业务模块的不同定义相应的增删改查的角色。
- 绑定角色和资源。
在项目上线之后和运维阶段:
- 在需要的时候可以继续建立更多的角色,并绑定角色和已有的资源。
- 建立用户组。
- 绑定用户组和已有的角色。
- 为用户组指定管理员,并授予管理员管理用户组的权限,用户组的管理员一般是业务人员的领导。
- 用户组管理员根据本部门的需要和调整,来动态的增减用户组的成员。
- 被加入用户组的成员立刻获得系统相应访问资源的访问和使用权限,无需修改代码。
分组和角色分别都有两种类型,一种是管理类型,一种是普通类型,以下做详细说明:
- 分组管理类型,针对业务人员,拥有管理类型的分组则可以把其他人加入到该组里。
- 分组普通类型,针对业务人员,拥有普通类型的分组只能自己使用分组里的角色和资源,不能授权给其他人。
- 角色管理类型,针对管理人员,拥有管理类型的角色可以修改角色与资源的对应关系。
- 角色普通类型,针对所有人,拥有普通类型的角色只能访问角色对应的资源而不能修改其关联关系。
分组表设计(Group)
列 |
类型 |
空 |
说明 |
Id |
Number(10) |
Not null |
PK |
Name |
Varchar2(128) |
Not null |
组名称 |
Admin |
Boolean |
Not null |
是否为管理类型 |
功能级授权的意义在于对页面可见元素的操作性,单纯从页面的可见性可简单划分成如下几个部分:
- 菜单,包括一级菜单和多级菜单,在系统中可分为顶部菜单,左侧菜单,左侧菜单子菜单。
- 按钮(通常"取消"或"返回"之类的按钮不会纳入权限管理)。
- 页面可见元素,比如表格、DIV标签等等,凡是页面可见的内容。
以上三点其实都可以归结为第三点,即:任何页面可见的元素均可纳入功能级权限管理。
实现方法:采用自写JSP标签完成,执行该标签时需要从后台或缓存中查找当前用户是否有使用当前资源的权限,如果有则正常显示,如果没有则将标签内所有内容从服务端剔除后再响应客户端。如下图:
资源权限流程
[java] view plain copy
- publicclassAuthTagextendsStrutsBodyTagSupport{
- private Set<String>authCodeSet;
- publicvoidsetCode(String code) {
- String[] codes = code.split(",");
- authCodeSet = newHashSet<String>(Arrays.asList(codes));
- }
- publicintdoStartTag() throwsJspException {
- HttpSessionhttpSession = pageContext.getSession();
- Authentication authentication = (Authentication)httpSession.getAttribute(SessionSecurityConstants.KEY_AUTHENTICATION);
- if(authentication == null){
- returnSKIP_BODY;
- }
- if(hasAuth(authentication)){
- returnEVAL_BODY_INCLUDE;
- }
- returnSKIP_BODY;
- }
- privatebooleanhasAuth(Authentication authentication){
- for(String auth: authCodeSet){
- if(authentication.getComponentResources().contains(auth)){
- returntrue;
- }
- }
- returnfalse;
- }
- }
页面元素的可见性并不能控制URL的可访问性,在系统设计中,使用Struts2的拦截器机制来过滤URL,防止用户不通过页面直接通过URL访问系统。
系统资源的抽取设计。
系统资源包含了以上提到的两个部分页面元素和URL,两种资源在某些时候是可组合的,比如按钮点击后提交URL,则该按钮与该URL可组成一个资源。
页面元素可独立成为一个资源,而URL不能脱离页面元素独立成为资源。每个资源都有唯一的标标识。
资源与资源之间也存在层级关系,比如下图:
列名类型(长度) 可否空 |
说明 |
Key varchar2(256) not null |
标识资源的唯一的代码 |
Name varchar2(256) not null |
资源名称 |
Url varchar2(256) null |
对应的URL |
Parent_key varchar2(256) null |
父资源代码 |
Desc varchar2(256) null |
描述或备注信息 |
Key值的设定建议采用会意的字符串,比如新增按钮资源属于第三级资源则它的代码应该为"sysres_duty_add".
对资源的授权采用ZTree插件实现,效果见下图:
对资源进行管理的树状插件
[html] view plain copy
- <%@ taglib prefix="hop" uri="/restree" %>
- <res:treeurlres:treeurl="resTree.action"
- expandUrl="expandResTree.action"
- async="true"
- chkType="check"
- id="demoTree"/>
数据权限业务关键字定义
- 把与岗位关联的所有内容翻译位岗码.
- 将岗码存储与人员及客户等表中.
- 将所有关联表放入系统缓存.
- 通过查询岗码在内存中完成对数据的操作.
岗码大体结构
- 用表的主键做唯一标识码,用下划线"_"连接,岗码与岗码之间用分号分";"分隔.
- 每个小段落的岗码第一位都设置为功能位,默认值位D.
- 空位N.
- 当功能为值位A的时候表示全部,详见下图:
岗码的格式规则
岗码格式如下:
岗位ID_岗位类型(管理/业务)_岗位职位_工贸ID_渠道ID_经营体ID_产品线code_BUCode_品牌_型号经营体.
注意:根据业务需要,岗码会不断的扩充,以存储更多用于分析查询的信息.
岗码生成和岗码从数据库刷新至业务服务器
点实时更新策略所使用的脚本。
实时更新策略
对于更新相对较频繁的表(如人员表、岗位表),首先在该表上设立触发器,基于表做的所有修改将记录到历史表中,系统定时扫描历史表,发现改动则执行SQL脚本更新岗码,并更新缓存。这里的更新指单条记录的更新,非批量更新。
- 下图中红色部分活动图表示任何系统对基础表改动时需要执行的内容。
-
蓝色部分活动图可以采用两种方式实现
- 从数据库层面执行定时任务,扫描历史表变动.
- 从应用服务器发起定时任务,扫描历史表.
- 橙色的部分活动图表示应用服务器执行过程。
当蓝色部分使用应用服务的时候可以直接更新缓存,从而略过橙色部分活动图。
历史表ecc_oms.sys.his
列名类型(长度) 可否空 |
说明 |
Id Number(12) not null PK |
PK |
Table_name varchar2(128) not null |
表名 |
PK_Valuevarchar(512) not null |
主键值如:123, 张三 |
PK_namevarchar(128) not null |
主键字段如:empId, empName |
Oper_type number(2) not null |
操作类型:增:1、删:2、改:3 |
Create_time Date not null |
创建时间 |
flag varchar2(1) not null |
完成标记位: 0:未完成,1完成 |
(1) 新增用户-岗位关系表和岗位-用户岗码关系表:ecc_oms.sys_emp_code
Emp_id :用户ID
Code_id:岗码ID-对应ecc_oms.ecc_oms.sys_code表主键
(2) 岗位-客户岗码关系表:ecc_oms.ecc_oms.sys_cust_code
Cust_code:客户code
Code_id:岗码ID
系统启动时,将所有岗码涉及到的表全部读取成JavaBean(不是持久化对象),放在缓存中。
/**********资源相关**********/
人员信息: ecc_oms.sys_employee
组织(部门信息)信息: ecc_oms.sys_org
职位信息: ecc_oms.duty_title
区域(工贸)基本信息-ecc_oms.sys_area_info
所属产品线,产品系统的产品(型号)信息:ecc_fnd.product_v
产品线信息:ecc_fnd.product_line_v
大小渠道基本信息-ecc_fst.sales_channel_properties
岗位基本信息:ecc_fst.station_config
客户关系信息 -ecc_customer.customer_info_v
BU信息表 -ecc_oms.sys_bu_info
BU与产品线对应关系表 -ecc_fnd.bu_product_group_pl
/*********授权相关*********/
--组织经营体: ecc_oms.SYS_ORG_SALECHANN
--组织产品线: ecc_oms.sys_org_prod
--组织职位: ecc_oms.org_duty_title
岗码表: ecc_oms.sys_station_config
用户岗码表: ecc_oms.sys_emp_code
客户岗码表: ecc_oms.sys_cust_code
经营体与小渠道关系信息(按产品线): ecc_fst.sales_channel_manager_relation
客户信息表-二级区域与客户关系表
主要类列表和简单描述:
类/接口名 |
简介 |
核心接口描述 |
CacheServiceFacade |
暴露给客户端远程调用的接口 |
1.根据用户id和岗位查询该用户的客户列表,返回结果集自动关联客户对应的产品线信息 |
DefaultCacheServiceFacade |
CacheServiceFacade的默认实现类,根据请求的岗位类型自动判断查找客户信息 |
|
CacheService |
从缓存中读取数据的顶层接口,定义内存中数据的读取接口 |
1.根据用户id查找用户信息 |
AbstractCacheService |
CacheService的抽象实现,读取客户数据的公共方法抽取在里面 |
|
CacheServiceA |
AbstractCacheService的子类实现,为MD_XSJL下单 门店销售经理查找客户逻辑 |
|
CacheServiceB |
AbstractCacheService的子类实现,BU代表下单 |
|
CacheService |
AbstractCacheService的子类实现,查询权限信息实现 |
|
CacheLoader |
缓存加载器 |
1.将指定表的数据加载到内存中 |
DefaultCacheLoader |
CacheLoader接口的实现类 |
|
TableOperation |
对单表进行的操作接口,用户往操作历史里插入记录时单条更新/删除缓存操作 |
1.根据操作记录对缓存进行操作 |
AbstractTableOperation |
TableOperation的抽象实现,定义公共操作方法 |
|
BasGCustomerInfoTableOperation |
AbstractTableOperation类的子类,表示 |
|
ReloadTableCacheJob |
定时任务,重新载入主数据表到缓存,每小时执行一次 |
|
UpdateCacheJob |
根据操作历史记录,对缓存中的数据进行单条更新,每15分钟执行一次 |
|
UpdateCodeJob |
定时任务,定期扫描岗码历史表ecc_oms.sys_his,调用存储过程,触发更新岗码操作,每10分钟执行一次 |
|
在客户端调用的应用中定义一个springbean,如下:
[html] view plain copy
- <beanidbeanid="cacheServiceFacade"class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
- <propertynamepropertyname="serviceUrl"value="http://127.0.0.1:8011/authentication/remoting/cacheServiceFacade"/><!--这个是服务器端暴露的远程访问地址-->
- <propertynamepropertyname="serviceInterface"value="com.ouc.oms.authentication.cache.manager.CacheServiceFacade"/><!--这个是远程调用接口声明 -->
- </bean>
Java代码调用:
[html] view plain copy
- CacheServiceFacadecacheServiceFacade =applicationContext.getBean("cacheServiceFacade",CacheServiceFacade.class);
- Set<CustomerInfoC>customerInfos =cacheServiceFacade.findCustomerByEmpId(11712L,"PR");
- //something else
将需要客户端调用的接口方法添加在CacheServiceFacade类中,并编写实现类。
客户端调用根据实际情况可进行调整,以下给出样例
[html] view plain copy
- publicinterfaceCacheService {
- /**
- * 根据人员ID查找客户
- */
- public List<Integer>findCustomerByEmpId(int id);
- 一、PR下单
- 1.根据人员ID查找岗位ID
- select ser.fst_submit_station_id – 岗ID
- From ecc_fst.station_employee_relationser – 岗人关系表
- where ser.employee_id = 46 – 登陆人员ID
- and ser.enable_flag = 'T' – 有效标识
- and ser.delete_flag = 'F' – 删除标识
- 2.根据岗ID查到PR岗
- selectsc.fst_submit_station_id, -- 岗位ID
- sc.fst_submit_station_code, -- 岗位编码
- sc.fst_submit_station_name, -- 岗位名称
- sc.product_line_id, -- 产品线ID
- sc.product_series_code-- 产品组(与产品线ID互斥,两个列只有一个值有效,若产品组有效要根据该编码转换成产品线ecc_fnd.bu_product_group_pl)
- Fromecc_fst.station_configsc-- 岗位信息表
- wheresc.fst_submit_station_idin (92172, 91239, 91241) -- 岗位ID
- andsc.fst_role_lookup_code = 'PR'-- 业务类型
- andsc.enable_flag = 'T'-- 有效标识
- andsc.delete_flag = 'F'-- 删除标识
- 3.根据岗ID查找每个岗所属的客户
- select scr.fst_submit_station_id, – 岗ID
- scr.customer_id – 客户ID(Number列,有科学计数法的主键)
- From ecc_fst.station_customer_relationscr
- where scr.fst_submit_station_id in (92172, 91239, 91241) – 岗位ID
- and scr.enable_flag = 'T' – 有效标识
- and scr.delete_flag = 'F' – 删除标识
- 4.根据客户ID查找客户属性
- selectciv.customer_code, -- 客户编码
- civ.customer_name, -- 客户名称
- civ.customer_flag, -- 客户类型 SX:伞下 HS:海伞 NULL:正常客户
- civ.first_region_code,-- 市场经营体编码
- civ.dqd_code, -- 大渠道编码
- civ.xqd_code-- 小渠道编码
- fromecc_customer.customer_info_vciv-- 客户信息表
- whereciv.customer_idin (20090507033457) -- 客户ID
- 一、门店销售经理(MD_XSJL)下单
- 1.根据人员ID查找岗位ID
- select ser.fst_submit_station_id – 岗ID
- From ecc_fst.station_employee_relationser – 岗人关系表
- where ser.employee_id = 6946 – 登陆人员ID
- and ser.enable_flag = 'T' – 有效标识
- and ser.delete_flag = 'F' – 删除标识
- 2.根据岗ID查到PR岗
- selectsc.fst_submit_station_id, -- 岗位ID
- sc.fst_submit_station_code, -- 岗位编码
- sc.fst_submit_station_name, -- 岗位名称
- sc.product_line_id, - 产品线ID-
- sc.product_series_code-- 产品组
- Fromecc_fst.station_configsc-- 岗位信息表
- wheresc.fst_submit_station_idin (92172, 91239, 91241) -- 岗位ID
- andsc.fst_role_lookup_code = 'MD_XSJL'-- 业务类型
- andsc.enable_flag = 'T'-- 有效标识
- andsc.delete_flag = 'F'-- 删除标识
- 3.根据岗ID查找每个岗所属的客户
- select scr.fst_submit_station_id, – 岗ID
- scr.customer_id – 客户ID(Number列,有科学计数法的主键)
- From ecc_fst.station_customer_relationscr
- where scr.fst_submit_station_id in (92172, 91239, 91241) – 岗位ID
- and scr.enable_flag = 'T' – 有效标识
- and scr.delete_flag = 'F' – 删除标识
- 4.根据客户ID查找客户属性
- selectciv.customer_code, -- 客户编码
- civ.customer_name, -- 客户名称
- civ.customer_flag, -- 客户类型 SX:伞下 HS:海伞 NULL:正常客户
- civ.first_region_code,-- 市场经营体编码
- civ.dqd_code, -- 大渠道编码
- civ.xqd_code-- 小渠道编码
- fromecc_customer.customer_info_vciv-- 客户信息表
- whereciv.customer_idin (20090507033457) -- 客户ID
- 一、 BU代表下单(BU_WGG_1,BU_WGG_2,BU_ACG,BU_DPG,BU_LE,BU_LF)下单
- 1.根据人员ID查找岗位ID
- select ser.fst_submit_station_id – 岗ID
- From ecc_fst.station_employee_relationser – 岗人关系表
- where ser.employee_id = 6946 – 登陆人员ID
- and ser.enable_flag = 'T' – 有效标识
- and ser.delete_flag = 'F' – 删除标识
- 2.根据岗ID查到PR岗
- selectsc.fst_submit_station_id, -- 岗位ID
- sc.fst_submit_station_code, -- 岗位编码
- sc.fst_submit_station_name, -- 岗位名称
- sc.product_line_id, - 产品线ID-
- sc.product_series_code – 产品组
- Fromecc_fst.station_configsc-- 岗位信息表
- wheresc.fst_submit_station_idin (92172, 91239, 91241) -- 岗位ID
- andsc.fst_role_lookup_codein (BU_WGG_1,BU_WGG_2,BU_ACG,BU_DPG,BU_LE,BU_LF)-- 业务类型
- andsc.product_line_id = 777
- andsc.enable_flag = 'T'-- 有效标识
- andsc.delete_flag = 'F'-- 删除标识
- 3.根据岗ID查找每个岗所属的品牌
- selectscp.pro_value, -- 品牌标识
- scp.pro_remark-- 品牌名称
- fromecc_fst.station_config_propertyscp
- wherescp.fst_submit_station_id = 92349
- andscp.delete_flag = '0'
- 4.根据岗位ID查找二级区域(网格)
- selectst.sale_area_code, -- 区域编码
- st.sale_area_name-- 区域名称
- Fromecc_fnd.sale_area_station_infost-- 岗区关系表
- wherest.station_config_id = 92349-- 岗位ID
- andst.product_line_id = 777-- 产品线ID 1169用777代表
- andst.enable_flag = 'T'
- andst.delete_flag = 'F'
- 5.根据区域编码查找区域信息
- selectmkt.area_code, -- 区域编码
- mkt.area_name, -- 区域名称
- mkt.mkt_lookup_type-- 市场级别 S:社区店 T:专卖店
- Fromecc_fnd.mkt_area_infomkt-- 区域信息表
- wheremkt.area_code = 'CMI35899'-- 区域编码
- andmkt.enable_flag = 'T'
- andmkt.product_line_id = 777-- 产品线ID
- 下接...
- 6.根据区域编码查颗粒度
- selectsur.small_unit_id, -- 颗粒度ID
- sur.small_unit_code-- 颗粒度编码
- Fromecc_fnd.sale_area_unit_relationsur-- 区域与颗粒度关系表
- wheresur.area_code = 'CMI00069'-- 区域编码
- andsur.product_line_id = 777-- 产品线ID 1169用777代表
- andsur.enable_flag = 'T'
- andsur.delete_flag = 'F'
- 7.根据颗粒度查客户
- selectciv.customer_code, -- 客户编码
- civ.customer_name, -- 客户名称
- civ.customer_flag, -- 客户类型 SX:伞下 HS:海伞 NULL:正常客户
- civ.first_region_code,-- 市场经营体编码
- civ.dqd_code, -- 大渠道编码
- civ.xqd_code-- 小渠道编码
- fromecc_customer.customer_info_vciv-- 客户信息表
- whereciv.area_code = 'KLD2009000326'
- /**
- * 根据人员ID查找产品线
- */
- public List<ProdC>findProdByEmpId(int id);
- 1.根据人员ID查找岗位ID
- select ser.fst_submit_station_id – 岗ID
- From ecc_fst.station_employee_relationser – 岗人关系表
- where ser.employee_id = 6946 – 登陆人员ID
- and ser.enable_flag = 'T' – 有效标识
- and ser.delete_flag = 'F' – 删除标识
- 2.根据岗ID查到PR岗
- selectsc.fst_submit_station_id, -- 岗位ID
- sc.fst_submit_station_code, -- 岗位编码
- sc.fst_submit_station_name, -- 岗位名称
- sc.product_line_id, -- 产品线ID
- sc.product_series_code-- 产品组(与产品线ID互斥,两个列只有一个值有效,若产品组有效要根据该编码转换成产品线ecc_fnd.bu_product_group_pl)
- Fromecc_fst.station_configsc-- 岗位信息表
- wheresc.fst_submit_station_idin (92172, 91239, 91241) -- 岗位ID
- andsc.fst_role_lookup_code = 'PR'-- 业务类型
- andsc.enable_flag = 'T'-- 有效标识
- andsc.delete_flag = 'F'-- 删除标识
- 若产品组有效要根据该编码转换成产品线
- selectp.product_code, -- 产品线编码
- p.product_id, -- 产品线ID
- p.product_name, -- 产品线名称
- p.group_code-- BU编码
- Fromecc_fnd.bu_product_group_plp-- 产品BU对照表
- wherep.group_code = 'WGG01'-- BU编码
- 2.2.若产品线不为空
- selectplv.PRODUCT_ID, -- 产品ID
- plv.PRODUCT_CODE, -- 产品编码
- plv.PRODUCT_LINE_NAME-- 产品名称
- Fromecc_fnd.product_line_vplv-- 产品线表
- whereplv.PRODUCT_ID = 100000-- 产品线ID
- 2.3.BU代表下单的场合BU_WGG_1,BU_WGG_2,BU_ACG,BU_DPG,BU_LE,BU_LF
- selectb.product_id, -- 产品线ID
- b.product_code, -- 产品线编码
- b.product_name-- 产品线名称
- Fromecc_fnd.bu_product_groupb-- BU与产品线关系表
- whereb.group_code = 'BU_WGG_1'-- BU编码
[html] view plain copy
- /**
- * 根据人员ID查找经营体
- */
- public List<SalechannC>findScalByEmpId(int id);
- 1.根据人员ID查经营体ID
- selectom.sale_manager_id, -- 经营体ID
- om.sale_manager_code-- 经营体编码
- FromECC_OMS.SYS_EMP_SALECHANNOM-- 人员经营体关系表
- whereom.emp_id = 49485-- 人员ID
- andom.enable_flag = 'T'
- andom.delete_flag = 'F'
- 2.根据经营体ID或编码查经营体名称
- select cm.sales_chan_manager_code, – 经营体编码
- cm.sales_chan_manager_name – 经营体名称
- from ECC_FST.SALES_CHANNEL_MANAGER CM – 经营体信息表
- where(cm.sales_chann_manager_id = 1 – 经营体ID
- or cm.sales_chan_manager_code = '1001')-- 经营体编码
- andcm.enable_flag = 'T'
- andcm.delete_flag = 'F';
- /**
- * 根据人员ID查找渠道
- */
- public List<ChannelC>findChannelByEmpId(int id);
- /**
- * 根据人员ID查找工贸
- */
- public List<AreaC>findAreaByEmpId(int id);
- 1.根据人员ID查工贸ID或编码
- selectam.area_id, -- 工贸ID
- am.area_code-- 工贸编码
- FromECC_OMS.SYS_EMP_AREAAM-- 人区关系表
- wheream.emp_id = 3549-- 人员ID
- andam.enable_flag = 'T'
- andam.delete_flag = 'F'
- 2.根据工贸ID或编码查名称(有两个表)
- selecta.area_code, -- 工贸编码
- a.area_name-- 工贸名称
- fromECC_OMS.SYS_AREA_INFOa-- 工贸信息表
- where (a.area_id = 519-- 工贸ID
- ora.area_code = '12C01') -- 工贸编码
- anda.enable_flag = 'T'
- anda.delete_flag = 'F'
- selectmkt.area_code, -- 工贸编码
- mkt.area_name-- 工贸名称
- fromecc_fnd.mkt_area_infomkt-- 区域信息表
- wheremkt.area_code = '12C01'-- 工贸编码
- andmkt.enable_flag = 'T'
- /**
- * 根据人员ID查找产品线
- */
- public List<CustomerC>findCustByEmpId(int id);
- 1.根据人员查产品线ID和编码
- select sep.prod_id, – 产品线ID
- sep.prod_code – 产品线编码
- from ecc_oms.sys_emp_prodsep – 人员产品线关系表
- where sep.emp_id = 11433 – 人员ID
- andsep.enable_flag = 'T'
- andsep.delete_flag = 'F'
- 2.根据产品线ID或产品线编码查名称
- selectplv.PRODUCT_CODE, -- 产品线编码
- plv.PRODUCT_LINE_NAME-- 产品线名称
- Fromecc_fnd.product_line_vplv-- 产品线信息表
- where (plv.PRODUCT_ID = 100000-- 产品线ID
- orplv.PRODUCT_CODE = 'AA') -- 产品线编码
- /**
- * 根据客户ID查找人员
- */
- public List<Integer>findEmpByCustId(int id);
- 根据findCustomerByEmpId反向查
- }