You are browsing the archive for 2008 九月.

在Report中取得帐户描述(1)

九月 25, 2008 in Oracle EBS二次开发

 

Oracle EBS 11.5.10.2

 

本文是讲解如何使用USER_EXIT用户出口函数取得帐户组合的基础知识篇

 

一、帐户段描述的定义

 

帐户的结构是一个关键性弹性域,帐户段的描述既是对应值集中值的描述,可以通过以下步骤找到对应的帐户段设置 :

 

1. 切换到总帐超级用户职责或者具有相关权限的职责

2. 导航到菜单:Setup–>Financials–>Books–>Define中

3. 查询使用的帐簿,查看其中的Chart of Accounts字段的值

 

gl_sob_define

 

4. 导航到菜单:Setup–>Financials–>Flexfields–>Key–>Segments,查询出关键性弹性域 Accounting Flexfield,并查找出相应的结构

 

gl_sob_segs_enable

 

5. 查看帐户结构中定义的段,可以找出对应的值集名称

 

gl_sob_segs_define

 

6. 导航到菜单:Setup–>Financials–>Flexfields–>Validation–>Values,查找对应的值集,可以查看段值的描述信息

 

 gl_sob_seg_value_set

 

二、SRW内置包

 

SRW内置包是Oracle Report提供的用于PL/SQL应用开发的一个程序包,可以在PL/SQL中使用它的过程、功能和例外。
以下是比较常用的几个过程和函数:

  1. SRW.DO_SQL    执行一段SQL,可以执行DDL和DML语句
  2. SRW.MESSAGE    显示一个消息和消息号码
  3. SRW.REFERENCE    将引用的对象添加到构造依赖列表中,让Report在触发初始化构造的时候对值进行测定
  4. SRW.USER_EXIT    执行用户出口函数

 

需要注意的是:这个内置包是Oracle Report的东西,并不是Oracle EBS的东西,做Oracle EBS开发的同学们不要搞错了

用户出口函数USER EXIT介绍

九月 24, 2008 in Oracle EBS二次开发

 

用户出口函数的概念:

使用PRO*C编写的函数(以Oracle的说法是第三代语言写的),而这类函数基本上没有任何的文档,以Oracle的说法就是“undocumented”,也没有源代码可以看到,因为系统只有编译好的可执行文件。用户出口函数主要用在Oracle Report和Oracle Form的开发中。

 

Report中使用USER_EXIT调用用户出口的语法:
        SRW.USER_EXIT (user_exit_string CHAR),其中user_exit_string是用户出口函数的名称和参数

Form中使用USER_EXIT调用用户出口的语法:
        USER_EXIT  (user_exit_string  VARCHAR2),其中user_exit_string是用户出口函数的名称和参数

 

那Oracle为什么要使用这类函数呢?,根据我的经验和理解:

  1. 为了提高性能,由于有的业务逻辑比较复杂,使用PRO*C来实现可以提高性能
  2. 和操作系统相关的一些操作,由于这类操作涉及操作系统权限、I/O等,使用PRO*C实现最适合
  3. 某些业务逻辑不想让外界知道,使用PRO*C最好,隐藏业务逻辑

 

一、Oracle Report中使用用户出口函数

 

而在Oracle Report中需要去调用用户出口函数的时候就使用SRW.USER_EXIT函数来实现,在Report中如何使用弹性域的用户出口函数在开发手册上已经有了比较详细的使用说明,大的步骤有两个:

  1. 使用 FND FLEXSQL 取得数据,FND FLEXSQL提供的功能就是动态组建SQL语句,并根据提供的参数进行查询
  2. 使用 FND FLEXIDVAL 来格式化数据并显示在报表上面,FND FLEXIDVAL提高的功能就是根据FND FLEXSQL取出的数据根据提供的参数进行格式化

 

在Oracle Report工具中经常使用SRW.USER_EXIT来取得一些和弹性域有关的值:

1)最常见的就是关键性弹性域的描述,Oracle EBS中关键性弹性域中段值的描述是通过独立型值集来定义的,自己来写SQL取得段的描述比较麻烦,主要是随着系统设置的不同,弹性域段的结构是不一样的,而且会出现段之间存在依赖关系的情况,这样取得段值的描述就更麻烦了,而且在报表需求中可能有的地方需要显示一段,有的地方是两段,等等的需求。

实际的例子可以查看GL模块中的标准报表 GLYRLGLG.rdf(Journals – Entry/日记帐 – 分录),当然有这种用法的报表非常多

 

2)而另外一个在Oracle Report常用的用户出口函数是关于本位币和外币转换和格式化的函数,由于很多使用需要在报表中即显示本位币的金额又需要显示外币的金额,但是系统中只存储了本位币的金额;而如果不使用用户出口函数来实现从本位币金额到外币金额的转换,那转换和格式化金额就比较麻烦,使用Oracle已经实现的用户出口函数就比较简单

 

在Report中实现本位币和外币转换格式化的例子有APXINAGE.rdf(Invoice Aging Report/发票帐龄报表),使用的例子:

BEGIN
   SRW.REFERENCE(:C_INV_DUE_AMT_3);
   SRW.REFERENCE(:C_BASE_CURRENCY_CODE);
   SRW.REFERENCE(:P_MIN_PRECISION);
   SRW.USER_EXIT(‘FND FORMAT_CURRENCY
       CODE=”:C_BASE_CURRENCY_CODE”
       DISPLAY_WIDTH=”15″
       AMOUNT=”:C_INV_DUE_AMT_3″
       DISPLAY=”:C_INV_DUE_AMT_3_F”
       MINIMUM_PRECISION=”:P_MIN_PRECISION”‘);
       RETURN(:C_INV_DUE_AMT_3_F);
END;

 

参数的详细解释请参考弹性域使用手册

 

 

二、Oracle Form中使用用户出口函数

 

Oracle Form中调用用户出口函数使用:USER_EXIT。在Form中用户出口函数的使用比较频繁,而且种类也比较繁杂,就拿我们经常使用的一个Form,用户定义的窗口(FNDSCAUS.fmb)
打开看它的源代码,其中就使用了好几个用户出口函数,包Fnd_Encrypt_Pwd中的过程Change_Password,
我摘出了其中的两个出口函数

 

procedure Change_Password is
begin
    — Call custom package to do any custom password inspection.
    user_exit(‘FND GLOBAL TYPE=USERNAME FIELD=”GLOBAL.USER_NAME”‘);
    –
    — Two entries match – encrypt new password
    –
    User_Exit(‘FND PWD TYPE=”USER” ‘||
        ‘USERNAME=”:USER.USER_NAME” ‘||
        ‘PASSWORD=”:USER.USER_PASSWORD” ‘||
        ‘OUT_E_USER_PWD=”:USER.ENCRYPTED_USER_PASSWORD” ‘||
        ‘OUT_E_ORCL_PWD=”:USER.ENCRYPTED_FOUNDATION_PASSWORD” ‘||
        ‘DECRYPT=”N”‘);
end Change_Password;

 

出于用户函数的特殊使用场合、使用目的和实现方法,导致了没有文档的情况,那我们怎么去使用它们呢,个人的经验只有一个办法:
看到Oracle怎么使用就记下,下次需要的使用就按照Oracle的用法去使用它。

 

关于如何开发PRO*C的程序,请参考Oracle Applications开发手册

使用Form个性化修改标准Form的LOV

九月 23, 2008 in Oracle EBS二次开发

在之前的文章 使用Custom.pll修改标准Form的LOV 中描述了如何使用Custom.pll修改LOV,现在介绍另外一种不需要修改fmb文件修改Form LOV的方法,使用Form的个性化工具。

本文结合一个简单的Form做描述,这是没有个性化之前的LOV,LOV取自表FND_USER,没有做任何条件限制。

Old_LOV

 

首先打开Form的个性化工具,点击菜单帮助–诊断–自定义代码–个性化:

Form_Personalization

 

一、选择触发器事件以及触发器对象

 

在打开的个性化窗口中

如下图,其中触发器选择WHEN-NEW-ITEM-INSTANCE,触发器对象选择HEADER.HEADER_ITEM(对应LOV的Item),保存:

Form_Personalization_Condition

 

二、确定触发器动作

    1.创建LOV的Record Group

       切换活动标签页,首先创建Record Group,为了简单起见,写死了一个查询条件,只出来两条记录:

 Form_Personalization_Action1

      

    2.修改LOV的Group Name属性

       在值对应那一栏填上之前创建的Record Group的名字:

Form_Personalization_Action2

 

最后保存退出,重新打开Form,就能看到效果了

New_LOV

 

三、总结

 

Form个性化和Custom.pll都是可以用来个性化Form的方法。当使用Form个性化修改LOV,用来创建的Record Group如果含有Form中的某个Item作为条件时(比如供应商地点的LOV中要以供应商作为条件),这时候如果把带有参数的查询条件作为Record Group的变元就会有问题。
因为个性化中创建Record Group的时候认为变元是一个字符串,我们加入了类似:PO_HEADERS.VENDOR_ID的字样它是不识别的。所以当遇到这样的情况,可以使用Custom.pll,通过name_in(‘PO_HEADERS.VENDOR_ID’)来组合查询条件,然后在每次WHEN-NEW-ITEM-INSTANCE的时候,去动态的设置LOV来达到我们所期望的效果。

总账数据访问安全性控制(5)

九月 23, 2008 in Oracle EBS功能和流程

 

本文介绍在客户化开发的程序中需要考虑总账数据访问安全性的控制

 

一、Form界面开发

如果Form界面中需要引用账户组合,同时希望账户组合受到数据安全性控制,需要增加如下的工作:

  1. 添加GLCORE.pll库文件到Form中
  2. 在账户组合字段的WHEN-VALIDATE-ITEM触发器中添加如下的代码来验证权限

gl_flexfield. validate(ledger_id NUMBER, flexmode VARCHAR2, flexvalue VARCHAR2, alevel VARCHAR2, full_validation BOOLEAN, edate DATE)

 

这个过程验证如果失败后,过程中会抛出这个消息:GLCORE_NO_ACCESS

ledger_id:分类账ID
flexmode:账户组合模式,指弹性域包括:所有段组合,账户段,平衡段和管理段
                  对应可以提供的值:gl_flexfield.ALL_SEGMENTS, gl_flexfield.ACCOUNT, gl_flexfield.BALANCING, gl_flexfield.MANAGEMENT
flexvalue
:账户的段值,根据账户组合模式不同提供不同的值
alevel:数据访问权限级别:完全、写、只读和无权限。
             对应的值:gl_access_set.FULL_ACCESS, gl_access_set.WRITE_ACCESS, gl_access_set.READ_ONLY_ACCESS, gl_access_set.NO_ACCESS
full_validation
:段值是否需要验证
edate:验证段值的日期,此值为null时跳过值的验证

下面是一个实际的代码例子:

gl_flexfield.validate(:HEADER.ledger_id,
         gl_flexfield.ALL_SEGMENTS, :LINES.accounting_flexfield,
         gl_access_set.WRITE_ACCESS, TRUE, :HEADER.default_effective_date);

 

二、SQL编写

 

如果希望编写的SQL执行结果受到数据安全性的控制,需要特别添加限制。

 

1)凭证相关

如果在程序中希望SQL取出的凭证数据受到数据安全性的控制,那需要连接数据库表

GL_JE_SEGMENT_VALUES来过滤数据,主要的字段:

je_header_id:凭证头ID
segment_type_code:段值类型,有B代表平衡段;M代表管理段
segment_value:段值

 

表关系图:

 gl_access_set_je_erd

 

同时检查数据安全性设置表GL_ACCESS_SET_ASSIGNMENTS中的设置:
access_set_id = fnd_profile.value(‘GL_ACCESS_SET_ID’)
ledger_id
segment_value
access_privilege_code

 

下面是一个使用的例子:

SELECT *
  FROM gl_je_batches_headers_v
WHERE chart_of_accounts_id = 101
   AND period_set_name = ‘Accounting’
   AND accounted_period_type = ‘Month’
   AND (gl_je_batches_headers_v.ledger_id IN
       (SELECT acc.ledger_id
           FROM gl_access_set_ledgers acc
          WHERE acc.access_set_id = fnd_profile.value(‘GL_ACCESS_SET_ID’)) AND EXISTS
        (SELECT ‘readable line’
           FROM gl_je_segment_values sv, gl_access_set_assignments acc
          WHERE sv.je_header_id = gl_je_batches_headers_v.je_header_id
            AND sv.segment_type_code = ‘B’
            AND acc.access_set_id = fnd_profile.value(‘GL_ACCESS_SET_ID’)
            AND acc.ledger_id = gl_je_batches_headers_v.ledger_id
            AND acc.segment_value = sv.segment_value))
   AND (je_batch_id = header_je_batch_id_qry + 0)
   AND (header_name = ’06-NOV-02 Project Mfg To Consolidation USD’)
ORDER BY batch_name, period_name

 

2)分类帐相关

如果在程序中希望SQL取出的分类账数据受到数据安全性的控制,那需要连接数据库表
XLA_AE_SEGMENT_VALUES

ae_header_id:分类账头ID
segment_type_code:段值类型,有B代表平衡段;M代表管理段
segment_value:段值

 

表关系图:

 gl_access_set_xla_erd

 

同时检查数据安全性设置表GL_ACCESS_SET_ASSIGNMENTS中的设置:
access_set_id = fnd_profile.value(‘GL_ACCESS_SET_ID’)
ledger_id
segment_value
access_privilege_code

 

一个使用的例子:

SELECT *
  FROM xla_ae_headers xah
WHERE (ledger_id IN
       (SELECT acc.ledger_id
           FROM gl_access_set_ledgers acc
          WHERE acc.access_set_id = fnd_profile.VALUE(‘GL_ACCESS_SET_ID’)) AND
       EXISTS
        (SELECT ‘readable line’
           FROM xla_ae_segment_values sv, gl_access_set_assignments acc
          WHERE sv.ae_header_id = xah.ae_header_id
            AND sv.segment_type_code = ‘B’
            AND acc.access_set_id = fnd_profile.VALUE(‘GL_ACCESS_SET_ID’)
            AND acc.ledger_id = xah.ledger_id
            AND acc.segment_value = sv.segment_value))

 

三、PL/SQL编写

 

如果在客户化编写的PL/SQL程序中需要考虑总账数据安全性控制,使用数据库包GL_FORMSINFO中所提供的过程与方法,下面是它的声明:

SQL> descr GL_FORMSINFO;
Element                   Type     
————————- ———
FULL_ACCESS               CONSTANT 
WRITE_ACCESS              CONSTANT 
READ_ACCESS               CONSTANT 
NO_ACCESS                 CONSTANT 
GET_COA_INFO              PROCEDURE
GET_ACCESS_INFO           PROCEDURE
CHECK_ACCESS              FUNCTION 
GET_LEDGER_TYPE           FUNCTION 
GET_DEFAULT_LEDGER        FUNCTION 
HAS_SINGLE_LEDGER         FUNCTION 
WRITE_ANY_LEDGER          FUNCTION 
GET_LEDGER_INFO           PROCEDURE
VALID_BSV                 FUNCTION 
VALID_MSV                 FUNCTION 
MULTI_ORG                 FUNCTION 
INSTALL_INFO              FUNCTION 
GET_IEA_INFO              PROCEDURE
GET_USAGE_INFO            PROCEDURE
GET_BUSINESS_DAYS_PATTERN PROCEDURE
IEA_DISABLED_SUBSIDIARY   FUNCTION 
GET_INDUSTRY_MESSAGE      FUNCTION 
SESSION_ID                FUNCTION 
SERIAL_ID                 FUNCTION 

程序中使用 CHECK_ACCESS方法即可以检查数据访问安全性。

 

四、凭证导入

 

如果客户化程序需要通过总账接口来导入凭证,那需要注意导入凭证受到数据访问权限设置的控制,因此插入到GL_INTERFACE中的数据要充分考虑这点,一般可以采取如下方式:

  1. 如果运行导入程序的职责不具备完全访问分类账的权限,那可以包装一下导入程序,在调用导入程序之前进行数据的过滤
  2. 如果不希望受到数据访问权限的限制,也可以专门设置一个完整权限访问的职责,用它来进行凭证的导入

 

至此整个“总账数据访问安全性控制”系列已全部结束,下面是系列文章的链接:

 

总账数据访问安全性控制(5)

总账数据访问安全性控制(4)

总账数据访问安全性控制(3)

总账数据访问安全性控制(2)

总账数据访问安全性控制(1)

 

-

总账数据访问安全性控制(4)

九月 22, 2008 in Oracle EBS功能和流程

 

下面介绍启用了数据访问安全性控制之后可能会遇到的问题

 

一、凭证导入失败

 

如果职责设置了受限制的数据访问权限集,很有可能在进行凭证导入的过程中发生错误,由于导入过程中导入程序会检测用户是否有读取数据的权限,如果发现GL_INTERFACE表中包括了一些用户无法在总账模块操作的数据,导入程序会报出如下的错误代码和信息:
EM29 You do not have access to this ledger and account combination.

 

二、无法打开会计期

 

无法打开会计期,打开会计期的按钮是灰色的,如下图:

gl_access_set_cannot_open_period

 

这是由于用户的职责不具备完全访问分类账数据的权限,只要切换到具备完整数据访问权限的职责即可打开会计期了。

 

==