注意:设置好安全性配置文件后,一定要跑一个请求:维护安全性清单
在R12版本中,OU的控制采取了MOAC的方式,使用户的操作得到了改善。
而如果客户化的Form能够支持MOAC的功能,需要在界面上提供当前用户可以选择的OU字段供用户选择。
这样在Form的开发过程中需要如下的开发步骤:
1,PRE-FORM 触发器初始化MOAC配置环境
添加如下代码:
MO_GLOBAL.init(‘ONT’);
— global.mo_ou_count
— global.mo_default_org_id
— global.mo_default_ou_name
IF l_default_org_id IS NOT NULL THEN — default org id not null
MO_GLOBAL.SET_POLICY_CONTEXT(‘S’,l_default_org_id);
ELSE
MO_GLOBAL.SET_POLICY_CONTEXT(‘M’,null);
END IF; — default org id not null
这段代码的作用是根据预制文件的设置,初始化OU的信息,将用户可以访问的OU信息插入到mo_glob_org_access_tmp表中,
同时将默认的OU ID、OU Name和OU Count分别写到global.mo_default_org_id, global.mo_default_org_id, global.mo_default_ou_name
具体细节可以查看数据库包:mo_global
2,WHEN-CREATE-RECORD触发器中拷贝OU默认值
在此触发器中将默认的OU ID和OU Name拷贝给Form界面上对应的自动,实现创建记录的时候默认带出默认OU信息。
copy(name_in(‘global.mo_default_org_id’),’’);
copy(name_in(‘global.mo_default_ou_name’),’’);
3,创建OU的LOV
Form界面上的OU 名称字段创建一个LOV,LOV对应记录组的SQL语句如下:
SELECT hr.organization_id organization_id, hr.NAME organization_name
FROM hr_operating_units hr
WHERE mo_global.check_access(hr.organization_id) = ‘Y’
ORDER BY organization_name
其它没有特殊的步骤。
当前职责可访问的OU(MO:安全性配置文件)
--初始化环境
BEGIN
fnd_global.apps_initialize(user_id => 0,
resp_id => 50658,
resp_appl_id => 20003);
mo_global.set_policy_context(p_access_mode => 'S', p_org_id => 82);
mo_global.init('SQLAP');
END;
mo_global.init(<MO>);MO取值 为 FND_MO_PRODUCT_INIT表中
--以下SQL查询当前配置的MO:安全性配置文件
SELECT *
FROM per_security_profiles psp
WHERE psp.security_profile_id =
to_number(fnd_profile.value('XLA_MO_SECURITY_PROFILE_LEVEL'));
--以下SQL用来获取当前安全性配置文件和当前用户可访问的OU
SELECT per.organization_id, hou.name
FROM per_organization_list per, hr_operating_units hou
WHERE per.security_profile_id =
to_number(fnd_profile.value('XLA_MO_SECURITY_PROFILE_LEVEL'))
AND per.organization_id = hou.organization_id
AND hou.usable_flag IS NULL;
在改EBS的BUG过程中,会在网上查找很多资料,这次是碰到一个多组织(Multi Org)的问题,发现Anil Passi写的几篇文章不错,慢慢的会陆续翻译过来,这次翻译的是http://getappstraining.blogspot.com/2006/10/orgid-and-multi-org-in-oracle-apps.html
为什么我们需要org_id
在任何一个跨国公司中, 都会在不同的地区有自主经营的子公司,我们以一个游戏公司为例,公司名称是'GameGold Inc',在文章中我们叫它'黄金游戏公司',在英国和法国都设有组织机构.
请注意以下各点:
1.这家公司(黄金游戏公司)在伦敦和巴黎都有办公室.
2.英国和法国税不同,也就是都有自己的tax code.
3.黄金游戏公司是以单实例的方式来实现Oracle应用程序的(英国和法国都使用一个应用程序数据库).
4.当'英国订单输入'或者'英语应付'用户登录到应用程序后,他们不希望看到法国姐妹公司的税务代码(Tax Code).
5.在黄金游戏公司中单个数据库实例中, 只有一张表用来存储税务列表, 我们假设这张在Oracle中的表名是 'ap_tax_codes_all'.
6. 在这张表中我们假设有两条记录:
记录 1 tax code -"FRVAT"
记录 2 tax code - "UKVAT"
7. 我们再进一步的假设有两个职责:
职责 1 - "French order entry".
职责 2 - "UK order entry"
8. 现在,法国的用户使用职责 1 - "French order entry"
9. 英国的用户就使用职责 2 - "UK order entry"
10. 在订单输入界面, 有一个输入项: Tax Code(或者 VAT Code).
11. 对法国用户来说, 在输入项中, 'UKVAT'是不能在值集列表是出现.
12. 而且, "法国订单输入" 用户只能在税的输入项中选择 "FRVAT".
13. 同样的, 英国的主意输入用户只能选择"UKVAT".
在不用硬编码的情况下,这些是如果实现的呢?答案就是org_id.
这些名词会被习惯性的使用到: ORG_ID/Multi-Org/Operating Unit.
截屏在文章的底部
1. 在应用程序中,你可以定义两个组织机构: "French operations" and "UK Operations", 这些可以通过组织机构定义来实现(截屏).
2.在Oracle应用程序中, 一个组织机构可以归类为HRMS Org, 或者 Inventory Warehouse Org, 或者 Business Group, Operating Unit Org 或者更多的类型. 记住,组织机构类型只是用来标识组织机构定义的一种意思(Organization type is just a mean of tagging a flag to an organization definition).
3.我们定义的这两个组织机构是operating unit类型的, 接下来会用到org_Id 和 operating unit 这两个习惯用语.
4.我们可以说,英国的组织机构有一个内部的organization id = 101, 法国的则是102.
问: 你是如何建立起英国职责(UKresponsibility)和英国组织(UK organization)机构间的关系?
答:在'uk order entry'职责下,设置profile 'MO : Operating Unit'的值为 'UK organization'
问: 系统是如何知道 UKVAT 是属于uk org的?
答: 在 VAT code 输入界面(税务代码会被输入), 下面的语句会被执行:
Insert into ap_vat_codes_all values(:screenblock.vatfield, fnd_profile.value('org_id').
或者, 使用 USERENV('CLIENT_INFO')
下一个问题, 当在值集列表(VAT)中显示VAT Codes 时, 数据库是否会做: select * from ap_vat_codes_all where org_id=fnd_profile.value('ORG_ID')?
答: 是的.
Oracle 会做以下操作
1. 当插入数据库到multi-org表中时,也会同时做insert into (vatcode,org_id) ....
2.用以下方式创建一个视图:
Create or replace view ap_vat_codes as Select * from ap_vat_codes_all where org_id = fnd_profile.value('ORG_ID')
3.在值集列表(LOV)上,select * from ap_vat_codes ,
如果通过以上说明还没有明白, 那么继续往下看.
快速浏览:
1.在多组织环境中(像在一个数据库中的UK和france), 每一张Multi-Org的表都会有一个名为'org_id'的列, 像发票这个的表是对组织敏感的,因为UK的用户没有理由去看到以及修改法国的发票,所以发票的表会有org_id这一列.
2.供应商站点/位置(Vendor Sites/Locations)也是有区分的,因为UK会在dell.co.uk中存放订单而法国则会在dell.co.fr中存放, 这些在Oracle术语中被叫作vendor sites.
3.任何一张multi-org的表(有org_id这一列)的名称,都会以'_all'结束.
4.对每张 _all 的表, Oracle会提供一个名称中没有'_all'的相关视图, 例如create or replace view xx_invoices as select * from xx_invoices_all where org_id=fnd _profile.value('org_id').
5.在插入数据库到这个表中时,org_id列的值也会被填充.
6.如果你想对所有的operating unit做一个输出,那么使用select from _all table.
7.在APPS中的_all 对象会作为一个同义词关联到真实schema中的_all 表,例如,在APPS schema中的po_headers_all是PO schema中po_headers_all的同义词.
8. 使用SQL*Plus 连接到数据库做以下操作:
connect apps/apps@dbapps ;
--假设 101 是法国的 Org Id
execute dbms_application_info.set_client_info ( 101 );
select tax_code from ap_tax_codes ;
---返回 FRVAT
下面是一些截屏:
这是多组织访问的第二篇文章,翻译自Anil Passi的Multi Org R12
我们都知道,在Oracle Release 12中多组织模型(Multi Org)会被改变, 它被叫作多组织访问控制(Multi Org Access Control, MOAC). 我会告诉你做出这样改变的原因以及这将会如何的影响到你. 我也会告诉你如何一点也不影响到你现有的设置[如果你不想使用 MOAC- 多组织访问控制的话]
如果你对EBS R12中的多组织不宵熟悉的话,你可以先看EBS Multi Org 基础. 那会向你解释在R12中当前的多组织模型是如何工作的.请参考链接了解R12中的多组织访问控制 : Whitepaper on User Group Site
业务上这样改变的理由
-----------------------------------------
四年前,我被要求设计一个具有以下需求的应付票据(Payables Invoice)扫描程序:
1. 我的客户有100个以上的法人实体(legal entities)和组织单元(organization units).
2. 他们想在一个中心的地方收取所有的纸质应付票据. 更有效的, 对所有的法人实体/组织单元,所收到的票据都只有一个地址.
3. 所有的票据都在这个中心地方扫描.
4. 扫描的图像通过一个队列被班加罗尔的团队输入到系统中
这样,就出现了些问题:
--------------------------
扫描的票据首先应该根据Operating Uint来排序.
为什么呢? 因为, 对于每一个OU,都有一个不同的 "Payables Clerk" 的职责. 这个可怜的录入员要根据录入票据所属的OU来选择职责. 而且,你也不能强制的要求供应商以XML的形式来过账到你的系统中,所以录入员必须要保证每一张纸制的票据都被录入到正确的组织机构/OU中.
Oracle EBS Release 12 是如何来拯救他的呢?
在 R12中, 那个录入员不再是一个"可怜的录入员", 因为他不必再根据不同的法人实体来改变职责, 这就是Oracle EBS R12设计的强大之处,它迎合了当今共享服务解决方案的需求.
这是否就意味着应付录入职责能访问所有的OU呢?
如果你的业务有这样的需求,那么在R12中就能够做到这样,你可以把一个组织机构层次中的节点或者是Operating Unit列表赋予你的职责, 或者说,你现在可以给一个职责赋予多个Operating Unit,这可以通过组织机构层次或者组织机构列表.
这听起来非常像 HR Security Profiles, 我们可以看看链接 Oracle HRMS Security Profiles ?
是的,实际上R12中的Multi-org模型就是用的是Security Profiles. 如果你看了上面那个链接,你就会对HRMS中的Security Profile有一个更清晰的认识.
这就意味着,一个security profile会作为一个profile选项附加到职责中?
是的.
如果我不想实现这个增强的功能呢? 这会破坏我现有的多组织(multi org)设置吗?
Oracle在升级时有她的高明之处. 除非你启用了Security Profile的特性,否则你的Multi-org将会和R12以前的版本一样工作.
R12中的多组织访问控制依然会填充org_Id列吗?
当然,每一条数据依然和一个单独的org绑定.
我们能重用为HRMS定义的security profiles吗?
我建议你保持Multi-org Security Profile和HRMS Security Profile二者的独立性, HR Security Profiles 也迎合当今的潮流和不同的HR相关属性来保持一定的地位,但我们知道这一次Multi-Org将会胜出.
现在我们回去应付录入中,当录入一张票据时,他们是如何给每个票据指定一个正确的OU呢?
这是通过在窗口中输入OU项的值来实现的,在R12之前的版本中这个项是隐藏的,但是现在在所有用到多组织安全配置的窗体中这个值都是可输入的.
在R12中,用户会输入一个附加项吗?
不完全是,如果你想,你可以根据职责来指定一个默认的OU, 这也是在Profile中实现的.
这个Progile的名字是 [我目前还不知道], 但是它确实存在, 所以我才说了.
所以, 我们会有两个新的profile选项?
没错,一个是用于附加的Surity Profile,另一个用于默认的ORG.
运行dbms_client_info.set_client_info(101)后会发生什么?
这将成为一个冗余的功能,在R12中我们使用包mo_global,这个包在11.5.10中已经存在,而且如果你打开它,你会发现它用的是行级别的安全控制. 从技术上来说我认为 dbms_client_info.set_client_info 还会继续工作下去,但是如果你启用了MultiOrg Security特性后,这将产生无法估计的结果.
这将会如何影响我的客制化?
声明 1 :- 如果你对client-info进行硬编码,那很显然的将不能继续工作
声明 2 :- 同样的, 如果你过去用fnd_profile.org_Id, 那将也不能工作.
如果你决定不在R12中启用多组织访问控制(Multi Org Access Control)的话,那么以上两个声明则不成立.
这是多组织访问的第三篇文章,翻译自Anil Passi的MO_GLOBAL-Dive into R12 Multi Org Design
我希望你已经读了文章 EBS R12 中的 Multi Org . 当我们在思考R12中的 Multi Org 时,总有一些问题会出现在脑海中, 对这些问题最好的分析就是打开包 MO_GLOBAL,别担心你还没有装R12, MO_GLOBAL在11.5.10 就已经有了, 现在让我们开始吧.
在R12中,CLIENT_INFO是如何被替换的呢?
我们先来举个例子.
在R12之前的版本, 你通过以下方法来创建表 PO_HEADERS_ALL
a. 在PO Schema 上创建一张表, 命名为 PO_HEADERS_ALL
b. 在APPS schema 上创建一个同义字(synonym) PO_HEADERS_ALL , 指向 PO.PO_HEADERS_ALL
c. 在APPS schema 上创建视图PO_HEADERS: "select * from po_headers_all where org_id=client_info"
但是在R12中,下面的事情将会发生:
a. 在PO Schema 上创建一张表, 命名为 PO_HEADERS_ALL
b. 在APPS schema 上创建一个同义字(synonym) PO_HEADERS_ALL , 指向 PO.PO_HEADERS_ALL
c. 在APPS 中别一个同义字(synonym) 被创建: PO_HEADERS, 指向 PO_HEADERS_ALL
d. 通过使用 MO_GLOBAL.ORG_SECURITY, 行级别的安全被应用于 PO_HEADERS.
这个可以通过运行 SQL select * from all_policies where object_name='PO_HEADERS' 来再次确认
e. 这个策略的影响是无论何时当你访问 PO_HEADERS 时, Oracle RLS 会动态的扩展WHERE 条件语句,如
SELECT * FROM PO_HEADERS WHERE EXISTS (SELECT 1 FROM mo_glob_org_access_tmp oa WHERE oa.organization_id = org_id)
也请参考下面的 **** .
是否这就意味着,如果我创建一张新的客制化的表,我就要把RLS [ Row Level Security ] 应用在这张表上?
是的没错, 如果这张表包含着以ORG_ID来区分的数据, 那就应该这样. 在这个例子中你所要做的就是将包里的功能MO_GLOBAL.ORG_SECURITY 赋予那些 表/同义字/视图.
Multi Org 的RLS[Row Level security]是否也会被应用在 表/同义字/视图 上呢?
理论上是这样的, RLS 能被应用在以上的任意一个对象中, 但是在实践中,你只会将 RLS 应用在 APPS Schema 中的对象, 这意味着, 你最有可能的就是把RLS应用在同义字上. 基本上, 现在Multi Org 视图已经被受 RLS 保护的同义字替换, 但是, 当访问R12之前版本的Multi-Org安全视图时, 我们不需要修改现有的代码. 现在, 根据ORG_ID来实现数据安全访问的职责依赖于RLS[也被叫作 VPD - Virtual Private Database].
我已经对我的 Multi Org Security Profile 做了些改变, 方式是通过附加一个新的Org层次, 我还需要运行其它的程序吗?
就像我们在HRMS中所做的一样, 所建议的是在Security Profiles上做任何改变后, 都运行程序 "Security List Maintenance"
什么是MO_GLOBAL.INIT
mo_global.init 的目的 :-
它会通过检查是否新的Multi Org Security Profile被设置来决定是否有新的 Security Profile 方法被使用.
如果设置了新的MO security profile, 那么 mo_global.init 会为在 Org Hierarchy 中的每个组织机构插入一条新的记录到表 mo_glob_org_access_tmp 中
mo_global.init 是在何时何地被调用的 ?
这个方法会在你登录后或者是切换职责后立即被调用. 就像FND_GLOBAL.INITIALIZE 被调用一样, 可以安全的确定 Oracle 会在 FND_GLOBAL.INITIALIZE 之后调用 MO_GLOBAL.INIT
mo_glob_org_access_tmp 是一张全局临时表(global temporary table)吗?
是的, 当在你session中的Multi Org初始化之后, 表 mo_glob_org_access_tmp 中, 你的 session 会有 X 条记录 . X 表示的是被赋予 MO Security Profile 的组织机构的数量 [在 security profile 中查看组织层次或者组织列表]
MO_GLOBAL.ORG_SECURITY 的目的是什么 ?
Row-Level-Security 的目的是隐藏某些数据[基于一些条件]. RLS 是通过扩展安全对象上的where条件语句来实现的.
1. MO_GLOBAL.ORG_SECURITY 的功能是返回WHERE条件语句
2. 这个where 条件语句会被扩展到那些已经启用Multi Org行级别安全的 表/同义字/视图 中
MO_GLOBAL.SET_POLICY_CONTEXT 的目的是什么?
这个 procedure 有两个参数
p_access_mode
当你想让你当前的session只会对一个ORG_ID工作时, 输入"S"
当你想让你当前的session只会对多个ORG_ID工作时, 输入"M"
p_org_id
只有当p_access_mode的值是"S"时才需要
在SQL*Plus中,我想对一个指定的Org[单个Org]设置session, 在R12中我该如何做呢?
SQL>> exec MO_GLOBAL.SET_POLICY_CONTEXT('S',101);
在上面的例子中, ORG_ID 101 会被赋予你当前的session.
在其内部, 当你对你的单个org设置上下文(Context)时,这段 蓝色 的代码将会被执行: dbms_session.set_context('multi_org2', 'current_org_id', 101);
**** 如果当前的数据库session被初始化为单个Org[如上面的步骤], 那么在行级别安全(Row-Level-Security)上扩展到对象的 Where 语句就会是
WHERE org_id = sys_context('multi_org2','current_org_id')
为什么我作为一个应用程序技术人员会使用 MO_GLOBAL.SET_POLICY_CONTEXT 呢?
我们假设你想在ORG_ID为101下通过调用API来创建invoice, 但是这个API又没有Org_id的参数,那么你可以这样做:
a. e执行 MO_GLOBAL.SET_POLICY_CONTEXT('S',101)b. 调用 Invoice API, 这将会在其内部从当前的MO上下文(Context)中读取ORG_ID.
在SQL*Plus中,我想模拟一次登录到指定的职责上,我该如何做?
a. 调用 FND_GLOBAL.INITIALIZE
这将会设置你的职责ID,用户ID等等(responsibility id, user_id)
b. 调用 MO_GLOBAL.INIT
这将会你的的职责/用户中读取 MO配置选项的值,并且初始化多组织访问(Multi Org Access).