其中借方与贷方金额的获取,如: select (
case cila.inv_type
when 'IN' then(
case cila.type_code when 'GL' then ACCOUNTED_DR when 'AP' then AP_ACCOUNTED end )end ) JieFang_Total
From **** case语句可嵌套,每嵌套一次需用end结束,最后一层case语句中获得所需数据通过这种方法可获得任意一行记录中的某个字段.
3、报表的调试比较简单可用打印语句输出xml语句比较异常数据,或者输出其他提示语句显示程序已经执行到哪。如本例中我自己得到的输出:
其中的现有量现有单价总价的输出均为空(NOW_NUM、NOW_PRICE、NOW_TOTAL),因为提供的数据中没有一行是既有借方也有贷方金额的,所以对于这种数据要注意空值的处理. 四、FORM开发:
1、关于VPD的理解:
一个用户对应一个或多个职责,一个职责对应一个或多个菜单,一个底层菜单对应一个Function,一个Function对应一个报表、表单或者程序。一个职责对应一个请求组,一个请求组对应多个报表、程序.
通过安全策略来动态返回一个条件(WHERE子句)使得从行级别对数据进行屏蔽,将一个或多个安全策略与表或视图关联后,就实现了Oracle数据库的VPD功能.在MOAC中使用的是安全性配置文件来实现对OU访问的控制,先定义好安全性配置文件,然后将该文件使用预制文件的形式定义在职责或者用户,让这个用户可以访问安全性配置文件所分配的安全OU。
在MOAC中主要使用的是按组织限制访问,在按组织访问设置的过程中该处定义的OU即是多OU的根本.在多OU的设置开始我们会定义一个安全性配置文件和设置当前的安全性配置文件,该配置文件中定义了一系列组织访问的权限控制,我们可以使用下面的语句查询出当前使用的安全性控制文件
SELECT security_profile_name, business_group_id,
view_all_orgnization_flag
FROM per_security_profiles
WHERE security_profile_id =
to_number(fnd_profile.value(‘XLA_MO_SECURITY_PROFILE_LEVEL’)); 可以通过以下语句获取当前安全性配置文件和当前用户在当前职责下可访问的OU
SELECT per.orgnazation_id,organization_id, hr.NAME name FROM per_orgnazation_list per, Hr_operating_units hr WHERE per.secutity_profile_id =
to_number(fnd_profile.VALUE(‘XLA_MO_SECURITY_PROFILE_LEVEL’))
AND hr.orgnization_id = per.orgnization_id
AND hr.usable_flag is null;
如我在CUX_INV_MATERIAL_ALL表中建立的Org_Id字段,可在策略函数中通过此字段产生Where子句,筛选可操作客户化职责下物料维护菜单的OU.当用户进入YD_GL_ALL_总账超级用户
职责时将初始化用户的上下文,通过MO_GLOBAL的一系列方法设置CONTEXT的值(包括访问模式和当前Org_Id)。然后将该上下文中保存的Org_Id与通过策略函数筛选的Org_Id组进行比较,若上下文中存在策略函数中定义的安全id,则符合条件并将查询结果输出给用户。。在PL/SQL中查询数据时我们经常需要初始化上下文的值,在单OU模式下只需要与当前存储的唯一Org_Id比较,所以初始化应用程序环境与上下文后(set_policy_context)即可得到正确数据。但是当通过多OU访问时,还需要多做一步工作,即向PO_GLOB_ORG_ACCESS_TEMP表中插入当前能操作的ORG_ID.这两项工作均在mo_global.init('SQLAP')中完成。
因此 初始化工作可如下:
fnd_global.apps_initialize(user_id => 1230,
resp_id => 50541, resp_appl_id => 200);
mo_global.init('SQLAP');
系统环境变量由应用、责任、用户等组成,数值上应用>责任>用户,优先级上应用<责任<用户。
以上工作完成后,当用户进入不同的职责中时,此回话便保存了用户的职责id,且系统通过MO_GLOBAL的一些列方法将其值存入PO_GLOB_ORG_ACCESS_TEMP表,然后设置
CONTEXT的值(包括访问模式和当前Org_Id).然后便可在FORM中的记录组OPERATING_UNITS中输入查询语句如下: SELECT ouv.Org_Id,
ouv.operating_unit, ouv.Org_Desc
FROM CUX_OPERATING_UNITS_V2 ouv
WHERE mo_global.check_access(ouv.org_id) = 'Y'
这样便通过VPD筛选出符合要求的安全数据.筛选出来之后怎么用呢?
首先在用户打开浏览器后通过FORM中的parameter变量获取:
procedure pre_form is
l_default_org_id number;
l_default_ou_name varchar2(240);
l_ou_count number; l_security_profile_id number;
begin
MO_GLOBAL.init(‘CUX’);
mo_utils.get_default_ou(l_default_org_id, l_default_ou_name, l_ou_count);
copy(l_default_org_id,'PARAMETER.mo_default_org_id'); copy(l_default_ou_name,'PARAMETER.mo_default_ou_name'); copy(l_ou_count,'PARAMETER.mo_ou_count');
--判断是否找到了OU,如果没有找到,则报错 if nvl(l_ou_count,0) <=0 then
fnd_message.debug('错误001:没有找到相应的OU,请联系系统管理员或开发人员!');
raise form_trigger_failure;
end if;
end pre_form;
获取上述三个参数后,就能参照业务需求完成触发器与界面的编写了
2、FORM开发概览: (1)、Form Builder安装:
配置TNSNAME,路径:Oracle_Home/network/admin/ tnsnames.ora
配置FORMS_PATH:如C:\\OA_FORMS;C:\\OA_RESOURCE这里是下载服务器上引用的库文件与标准Form存放的本地路径,可在同一文件夹下创建本机的工作目录如C:\\evelopement以方便管理.
配置NLS_LANG: 修改注册表:Local Machine/Software/Oracle/NLS_LANG改为AMERICAN_AMERICA.ZHS16GBK,这样开发IDE使用英文,字符集可满足英文、简体中文、繁体中文的需要。
下载必要的库文件与TEMPLATE.fmb存储到FORMS_PATH路径下
(2)、创建数据库对象,要求:表、序列、索引建在应用数据库用户下,表放在数据表空间中,索引放在索引表空间中;视图、包建在APPS下,表和序列需要在APPS下创建别名.
表通常包含以下字段:
1、 一个表关键字id,通常与表名,并用每个sequence为表记录获得一个唯一值;
2、 创建一个Org_Id,根据不同的开发选用不同层次的组织id,通常用的是职责id,本例的物料维护跑在OU层所以用_ALL命名; 3、 5个who字段,由Form的内部机制管理.
视图的创建视应用而定,不过通常视图包含基表中的所有字段以备扩展用,视图中必须包含row_id字段
(3)、基本开发流程
1、将ORACLE_FORM路径下的Template.fmb下载到工作目录下,更改FORM中的NAME属性,并以相同的名字保存到文件夹中; 2、删除多余的对象:Data Blocks下的两个块——BLOCKNAME、DETAILBLOCK, Canvases下的一个画布——BLOCKNAME; 3、修改Windows的名称,通常可以取名为MAIN_WIN;
4、修改2个触发器一个程序单元:PRE_FORM、WHEN-NEW-FORM-INSTANCE,与app_%Program Units下的close_window触发器(注意尖括号不保留,如'
'SALES_ORDER');
5、创建Block数据块,可使用向导不过用向导创建出来的数据块与视图中字段的名字相同,因此在视图创建的过程中最好取定适合的名字以避免更改. 6、设置Block属性及其Subclass,设置item属性及其Subclass;
7、设置画布属性及其Subclass,注意其与Window的关系设置;并调整画布的布局;
8、编写数据操作触发器Program Unit,使用CUX_PLSQL_AUTOCREAT指定块名基表名以完成基本数据记录操作的触发器,其中必用到View中定义的row_id字段,使用FOR UPDATE OF NO WAIT语句锁记录。
(如果使用基表创建数据块,则只能使用基表的主键而非row_id取记录并完成update、delete与insert逻辑,或者不编写该触发器); 9、在数据块的触发器中调用8中的存储过程. 10、根据业务需求完成其他触发器的编写.
11、上传编译(排错时注意更新时间),编译代码: frmcmp_batch $CUX_TOP/forms/ZHS/CUX_INV_CODE.fmb apps/apps output_file=$CUX_TOP/forms/ZHS/CUX_INV_CODE.fmx 最终的fmb文件与fmx文件名一致.
12、注册Form,定义Function,加入菜单。这里的定义过程与之前的职责到菜单、功能的过程相反,注意定义Function时Form、源文件中Form名字、文件名三者要一致.
(4)、参数、LOV、导航条、滚动条、日历、主从块.
1、Parameter:
Parameter是Form级参数,外部程序在调用Form时,也可传递具体的参数值,从而达到对Form的某种控制;如果不考虑外部程序传递,完全可以创建一个不基于数据库、字段不
显示的特殊块来替代Parameter,通常对Parameter的初始化需要在Form级触发器Pre-Form中完成. 我们可以根据当前用户的Profile来取得其对应的OU。
2、LOV:
LOV的功能可用向导完成,注意在输入query语句后可选择LOV显示的排版顺序,此外只要在LOV中出现的字段都应该定义在该数据块的基础视图中,并可在向导中设置各个字段的显示宽度、标题等.
3、导航条、滚动条
导航条与滚动条都设置在表单的边框附近,边框应留出0.1mm的距离因此画布的宽度除了各个数据项外应预留0.5mm.此外滚动条属于数据块的属性,添加滚动条前应先明确此滚动条操作的是那一部分数据块.
4、 日历:
Form中没有日历控件,日期的选择是通过一个特殊的Windowss实现的,因为系统封装的比较好,我们需要按照如下三个步骤实现日期的选择: