本篇文章总结下oracle retail(retek)系统中实现列表的一些方法,据说该功能实现类似ebs中lookup,不过到目前为止我还没开发过ebs,就先不管retek中的列表实现和ebs中的列表实现有什么异同了。首先,看下面的这两幅图,这是我截自系统中的退货功能的功能图,图中所示的就是我本文想说的列表。
图1:退货类型
图2:退货原因
在retek中实现如上图所示的列表,主要用到的是STAND45库提供的方法,下面逐步展开介绍:
1、STAND45库内置方法介绍
STAND45库中提供的用于生成列表的方法一共有三个,分别是:P_POPULATE_LIST、P_POPULATE_LIST_NO_CLEAR、P_POPULATE_LIST_SECURITY。这三个方法都用来生成列表项,区别是,P_POPULATE_LIST表示无权限差异全部生成,P_POPULATE_LIST_NO_CLEAR只是对P_POPULATE_lIST做了一下处理,去掉了其中的CLEAR_LIST,即不会清除原来的列表项;对于P_POPULATE_LIST_SECURITY生成的列表,加上了一定的安全控制,只允许特定的用户具有其特定的操作权限,即只生成该用户具有操作权限的列表。上面的这三种STAND45库的内置方法,在使用的时候有所不同,到目前为止,我也只见过使用P_POPULATE_LIST和P_POPULATE_LIST_SECURITY,但是,它们相同的地方是生成列表的数据来源都是code_detail表。
在retek中,与生成列表相关的主要有两张表code_head和code_detail,code_head是code头表,对应存储该列表表示的意义,code_detail是code明细表,对应存储列表对应有那些明细。如下图所示:
图3:code_head表
图4:code_detail表
code_head和code_detail表通过code_type字段进行关联。当然,对于P_POPULATE_LIST_SECURITY这个方法,由于其涉及到权限控制,所以还会涉及到sec_form_action、sec_form_action_role、user_role_privs等表,一般开发的时候也无需过多更改这个,所以不详述。
2、使用P_POPULATE_LIST_SECURITY生成列表
使用P_POPULATE_LIST_SECURITY方法来生成有权限控制的列表,例如实现对只有查看权限的用户生成查看,对具有新建、编辑、查看权限的用户生成新建、编辑、查看。
图5:模式列表
比如要通过P_POPULATE_LIST_SECURITY来实现上图的功能,我们可以根据如下步骤:
(1)Step 1:找到该处对应的code编码,这里表示的应该是操作模式,通过查找code_head表,找到对应的code_type。
图6:code_head中查找模式
如上图,查到对应的code_type是ACTN。
(2)Step 2:查找code_detail表找到对应code_type的列表明细。
图7:查找对应的code_detail中的列表明细
(3)在form的P_FORM_STARTUP程序中添加代码如下:p_populate_list_security('B_main.LI_action',
'FM_AREA_RETURN',
NULL,
'ACTN');
注意P_POPULATE_LIST_SECURITY方法有四个参数,第一个参数表示列表要显示的item,第二个是列表所在form的Name,第三个默认为NULL,第四个参数对应你要生成列表对应于code_head和code_detail表中的code_type,前面已经找出来了,这里对应的code_type是ACTN。还有一个需要注意的是,这段实现代码并不是一定要放在P_FORM_STARTUP程序中的,只是一般情况下都是在form运行的时候就生成列表,所以放在了这里,如果需求不是这样的,比如说在某个item改变时重新生成的话,那么这段代码的位置就要看情况改变放置的位置了。
(4)上面的三步已经实现了需求的开发,至于权限的控制,可以不用写什么代码来专门控制,有如下的功能操作界面,这里不详细展开。
图8:模块单元权限设置
3、使用P_POPULATE_LIST生成列表
使用P_POPULATE_LIST方法来生成无权限控制的列表,一般生成那种普遍适用于所有操作用户的,比如该区域退货功能中的退货类型和退货原因。前面的查找对应的code_type操作与上面的P_POPULATE_LIST_SECURITY一致,同样也是在P_FORM_STARTUP中添加代码,只是调用方法的代码不一样,下面列出:p_populate_list('B_main.LI_status',
'ARZT');
该方法有三个参数,第一个参数表示要生成的列表所在的item,第二个参数表示code_type类型,第三个是默认的项,一般可不写。
4、改写代码实现自定义列表生成
有时候客户难免会提出奇葩的需求,而且也会提出奇葩的修改思路,有时候一定要改动内置方法来实现,这个问题我就遇到了。详细需求不谈,大概是要求生成的列表不是从code_detail表中获得,而要自己新建一张表(cmx_rtrs_code_detail),然后在里面存一些自定义的信息。由于这张表不是系统标准表,所以无法调用系统方法实现,只好改写该方法。
下面,就提供一个我曾经改写的P_POPULATE_LIST方法的例子:------------------------------------------------------------------------------------
-- added by HAND-YEDWARD 2014-10-13
-- 自定义生成下拉列表
--
PROCEDURE p_cmx_populate_list(i_item IN VARCHAR2,
i_code_type IN cmx_rtrs_code_detail.business_type%TYPE,
i_default_code IN cmx_rtrs_code_detail.code%TYPE DEFAULT NULL) IS
l_trans_desc code_detail.code_desc%TYPE := NULL; -- 去掉
l_error_message rtk_errors.rtk_text%TYPE := NULL;
l_count code_detail.code_seq%TYPE := 0;
CURSOR c_get_code IS
SELECT cmx_rtrs_code_detail.code
FROM cmx_rtrs_code_detail
WHERE cmx_rtrs_code_detail.business_type = i_code_type
AND cmx_rtrs_code_detail.enabled = 'Y'
ORDER BY code;
BEGIN
clear_list(i_item);
FOR c1 IN c_get_code
LOOP
l_count := l_count + 1;
BEGIN
SELECT code_detail.code_desc
INTO l_trans_desc
FROM code_detail
WHERE code_detail.code_type = 'RTRS'
AND code_detail.code = c1.code;
EXCEPTION
WHEN OTHERS THEN
l_trans_desc := NULL;
END;
add_list_element(i_item,
to_char(l_count),
l_trans_desc,
c1.code);
END LOOP;
IF i_default_code IS NOT NULL THEN
copy(i_default_code,
i_item);
END IF;
EXCEPTION
WHEN form_trigger_failure THEN
RAISE;
WHEN OTHERS THEN
emessage(SQLERRM);
RAISE form_trigger_failure;
END;
---------------------------------------------------------------------------------------------
p_cmx_populate_list就是我改写后的程序,对于P_PULULATE_LIST_SECURITY的改写,思路类似,找到合适的表,然后替换下,并且加上一些必要的处理代码即可。