Printed 黃建華Oracle - EBS Workflow
Printed 黃建華Oracle - EBS Workflow
E 最佳技术
术实践
践
E-B
BUSINEESS SUITE
U
ORA
ACLE 核心应
核 应用技
技术
Workfloww
Author: 黄建华
MSN: huajhua@ho
otmail.com
Creation
n Date: April 17, 200
07
Last Updated: November 11,
1 2010
Documeent Ref: <Document Reference Number>
N
Version: DRAFT 1A
Approvals:
<Approver 1>
<Approver 2>
Document Control
Change Record
4
Reviewers
Name Position
Distribution
Note To Holders:
If you receive an electronic copy of this document and print it out, please write your
name on the equivalent of the cover page, for document control purposes.
If you receive a hard copy of this document, please write your name on the front
cover, for document control purposes.
Contents
1. Oracle Workflow基础
职责:System Administrator
用户: SYSADMIN
1.1. 工作流概述
工作流在EBS中的地位
Workflow是EBS的基础架构技术之一,系统中大部分流程性的通知和审批控制、账户
按规则自动生成都是通过Workflow实现的;R11i之后,模块间的协调,有一小部分也
是通过Workflow的Business Event完成的。
每种技术都有自己的特点和应用方向,仔细阅读下表,我们可以体会何种场景该使用
Workflow。
EBS中的技术 特点 企业应用
Oracle DB 关系型数据库,其实是最佳的设计模式和开发框架 所有MIS系统的基础,最可靠的数据持久存储
用于业务逻辑实现;系统质量的优劣、性能的高
PL/SQL 标准SQL+编程语言,Oracle所有开发工具的基石
低,很大程度上取决于PL/SQL
Reports 过去流行的可视化报表设计环境,开发效率高 数据检索+报表展现,尤其是单据打印
Discoverer BI展现工具,基于主题视图,分析企业数据 因为布局工作量小,被广泛应用于普通报表开发
ADI/Web ADI 从日记账和FA起家,逐步发展为EBS最强的桌面工具 数据检索+Excel展现、数据批量录入和修改
基于XML工业标准,数据抽取与展现分离,布局设 数据检索+报表展现,除了单据打印,还可发布至
XML Publisher
计平易近人又高度灵活丰富,与Java亲密集成 合作伙伴
Concurrent 基于时间的任务并发、排队,合理利用系统资源 立即、定时或周期执行程序、报表、维护和监控
Flexfield EBS最富特色的自定义字段,智能组合、智能验证 会计科目、物料分类,业务特有信息的记录和传递
Forms 最快捷的数据库应用系统开发环境,UI不够友好 Windows版的数据录入+数据处理+数据检索
JSP/JTF/OAF 效率比较高的基于浏览器的应用开发框架 纯Web版的数据录入+数据处理+数据检索
Workflow 灵活的流程定义/自动化、通知发送、系统间集成 流程式审批、流程式数据传递、事件式系统集成
Alert 基于触发器和定时器的数据监控、预警通知 企业核心数据监控、系统运行异常监控
Interface/API 各模块开发人员留出的,除了UI外的数据“出入口” 客户化业务、外围系统与核心ERP的集成
Web Service 基于Internet的计算和服务,可用于数据交换 跑在Internet上的Interface/API
……
Workflow满足的四个重要商业需求
1、 发送通知
Workflow可以发送两种类型的通知:消息性通知,如“你的申请被审批了”,不需要
接收者做出任何响应;回应式通知,如“GL日记账需要你的审批”,接收者需要做出
相应的Response,工作流才能继续前进。
通知除了在系统中可以查看、处理外,也可以通过Mail查看、处理;可以本人处理,
也可以转交他人处理。
2、 流程定义
如果能够将企业业务科学的分解至合理的粒度——子流程,那么不同业务在IT上的实
现,就是将这些子流程有机的组合在一起。比如,销售订单工作流中的每一个子流
程,是Oracle对销售业务分析后分解出的最佳粒度,不同企业可选择既有的流程组
合,亦可重新组装。
3、 系统自动化
信息系统的自动化,是离不开信息流的,所以Workflow是天然的自动化工具,上面的
流程定义,实际上亦可看作流程自动化,Worflow的极致就是Automation。
4、 系统间集成
如果把企业运作看作“当发生某个A事件时,需要我们作出一个或者一连串响应”,那
么就可以理解,Oracle为什么将Workflow的“业务事件系统”置于系统间集成的地位
——包括与业务伙伴的集成。
比如,S系统产生了一笔出库,需要在D系统完成订单的发运和开票,我们有很多种方
案来实现,如果用“业务事件系统”,那么S系统只要向D系统发送一个消息说“我做
了一笔出库”,D系统将自动触发“订单的发运和开票”操作。
因为消息的发送,实际上是基于Oracle AQ这个现成、可靠的系统,S和D系统不需要
时时连线;因为消息的处理是由“业务事件系统”根据“订阅关系”自动调度的,D系
统也不需要不断的问S系统,你有没有数据。
下面继续列举的,是利用Workflow的特性,进行的信息系统开发应用。
5、 并行处理
如果有10000张订单需要同时处理,那么最好考虑并发,否则性能将糟糕透顶。在EBS
环境下有3种选择,一是不推荐使用的Job,二是推荐使用的并发请求,三是
Workflow,尤其适用于处理过程中可能需要稍作停顿,等待某种干预的时候。
6、 异步执行
同步执行,意味着,如果一个耗时的处理不完成,程序将停止响应,尤其是UI界面,
如果长时间“不许动”,绝对导致使用者的反感。
如果这个耗时的动作,和用户目前的操作关系不大,可以放到后台慢慢去运行,那么
就可以获得非常好的“系统响应时间”,在EBS中可以通过提交一个并发请求或者启动
一个工作流来实现这种异步执行。
Workflow在EBS中的应用
下表按模块列举了EBS中的部分工作流:
模块 应用
日记帐审批、GL自动分配(GL成批分配流程、GL分配流程、GL过帐流程、GL经常性日记帐流
总帐模块(GL)
程、PA分配组流程)、GIS(Global Intercompany System)通知
AP采购卡经理审批事务处理、AP采购卡员工核实工作流、AP费用报表、AP开放接口导入、PO
应付模块(AP)
发送采购单据通知(PO单据审批催函)
下面的SQL可以查当前系统中所有的工作流:
具体实例
1、 GL日记帐审批流程
公司 成本中心 会计科目 产品 备注
3、 OM周期活动的控制
订单输入
预订
挑选发放
发货确认
库存接口 应收接口
完成
工作流的演进
Workflow的体系结构
简单的体系结构图:
Email通知
Workflow
Loader
工作流引擎
工作流监控器
Workflow
Builder
内置通知
Notification
Mailer
应用服务器
Web 浏览器
复杂的体系结构图:
A A
Directory Services
A
Users Roles
A A AQ
Workflow
Web
Builder
XML
Notification
Mail Files
Notificatio
Applications Oracle Workflow Enabled Application
Browser Application
Oracle server
Client Server
1.2. 必要设置
下载
http://www.oracle.com/technology/software/products/workflow/index.html。
Workflow Builder安装
选择一个独立的Home。
配置Workflow Builder的tnsnames
按照往常步骤配置tnsnames和hosts。
如果是功能顾问,再看一下补充内容:通常从别人那里把tnsnames拷贝过来就可以,
不过有时候不行;道理很简单,tnsnames.ora和sqlnet.ora两个加起来才构成SQL*Net
协议的基本配置文件,而不同公司的sqlnet.ora可能会不一样;所以把这两个文件全部
拷贝过来就99.99%不会有问题了。
配置Workflow Builder的nls_lang
语言和区域设置成和数据库服务器一样;字符集一般也是一样;如果服务器端为
UTF8,那么就要设置成ZHS16GBK等,看情况而定。
配置服务器端(Embedded)
通常安装完EBS,服务器端就自动配置好了,除了Mail功能。
新版EBS都用基于Java的Notification Mailer。可以参考本文的“Workflow
Notification Mailer Configuration”章节,这里先略过。
配置服务器端(独立版本)
先装好数据库如9i,然后根据说明安装Workflow Server。
我最初学习Workflow的时候就是用8i数据库加独立版的Workflow Server。下面是我
当初的一些笔记:
根据Server安装指南一般可以完成Workflow Server的配置。按我的经验,有几个地方需要注意
1、可以直接使用8i的http,不用安装IAS,根据Server安装指南配置httpd.conf的别名即可;http服
务起不来的可能情况2、
httpd.conf语法错误,这个没什么好说的
之前的服务没有正常结束,一般重新启动计算机即可;或者杀掉java进程,如果有的话
新安装了Oracle其它产品,导致路径引用错误;我的解决办法是把新安装软件在环境变量
Path中添加的路径移到最后
2、Notification默认的配置是html email,这个时候易遇到Notification就报错,因为我们自己一般
没有配置Mail服务器,所以需要在Global Workflow Preferences里面把Send me electronic mail
notifications设置为Do not send me mail
新建一个WFT文件
N: Workflow Builder/File/New
在开发阶段Workflow源代码一般保存在本地,扩展名是wft。我们新建一个工作流文
件,然后保存,假定文件名为:CUX_WF_DEMO.wft。
新建一个Item Type
Item Type是个抽象的概念,为方便理解,可以看作就是一个工作流。
引用标准Workflow
N: Workflow Builder/File/Open
我们选择从数据库打开,输入APPS用户名和密码及TNSNAME。找到Standard,点击
<<移入Visible区,OK打开。
打开后把Standard这个Item Type拖到我们创建的文件下面。
然后赶紧关闭刚才打开的Standard工作流,以免误操作。N: Workflow
Builder/File/Close Store,在弹出的保存确认界面选择No。
*顺便看下,本地Workflow文件的图标和从数据打开的不一样。
*实际开发中,我们有必要再建立一个自己的Standard。
以后在我们的工作流中就可以很方便的使用一些标准的工作流对象了。现在结果如
下:
N: 右键Process/New Process
输入内部名称和显示名称。
实际开发中可以先建立子流程,在建立顶层流程。注意这里的Runnable是选中的,所
以该Process可以运行。一个Item Type下,可以有很多个Runnable的Process。
Process是个流程图,由Notification、Function、子Process组成,开始于一个Start
Function,结束于一个或多个End Function,中间是Notification和Function组成的业
务流程,在这个级别上可以把Notification、Function、子Process看成是一样的即
activity,他们都有返回值,不同的结果走不同的流程,由此组成一个符合业务需要的
图表。
一个Process至少要包含一个Start和一个End节点,所以现在点击保存,会报
Validation Warning,不过还是可以保存到磁盘。
完成一个简单的Top Process
N:
这个时候,要在这里修改一下属性。选中Start节点,右键,选择Property,把
Start/End从Normal改为Start:
同样,把End节点的Start/End从Normal改为End。
然后,右键Start节点,不要放开鼠标,拖到End节点,这样就把这两个点连起来了。
这样,一个最简单的工作流就做好了。结果如下:
方式一:直接通过Workflow Builder保存到数据库
N: Workflow Builder/File/Save As
点OK就行。
开发的时候用这种模式。
方式二:Workflow工具WFLOAD
N: Telnet
首先用FTP工具把Oracle_EBS_11i_WF_DEMO.wft上传到应用服务器,比如
$FND_TOP/install。这里的例子是上传到客户化应用目录:$CUX_TOP/install。
然后运行wfload(注意UNIX区分大小写):
cd $CUX_TOP/install
N: System Administrator/View/Request/Submit
首先用FTP工具把CUX_WF_DEMO.wft上传到应用服务器,同上。
然后到系统管理员职责提交请求:
嘿嘿,Mode选Upload,File要写绝对路径,上面的画面用环境变量是有问题的哦!
Item Type放空。
上线安装的时候用这种模式。
1.5. 先睹为快:一个简单例子.运行
方式一:Workflow管理界面
实际上可以从很多地方进,而且不同版本不一样。这里是11.5.9以上的版本,之前的版
本直接就有Find Process菜单。
注意,只有Workflow的管理员用户进来后面才有Run列!
也可以从上面的画面的“Administrator”Tab页查看和设置。
接下来,点击 ,出来:
按照上图内容输入。Item Key是本工作流运行实例的标志;相对的保存在数据库中
Item Type可理解为一个定义或者一个Template。User Key是用户看到的实例标志。
点击Run Workflow。
运行情况查看
选择“Status Monitor”Tab页。输入查询条件查询,出来刚才运行的CUX_DEMO实
例:
点击Status Diagram,可以看到,由于例子太简单已经运行到终点,且都是“绿
线”,说明没有错误:
方式二:PL/SQL启动
N:
DECLARE
l_item_key VARCHAR2(30) := 'CUX_DEMO_002';
l_user_item_key VARCHAR2(30) := 'CUX_DEMO_UK_002';
l_item_type VARCHAR2(30) := 'CUX_DEMO';
l_process VARCHAR2(30) := 'CUX_TOP';
BEGIN
--01 创建
wf_engine.createprocess(itemtype => l_item_type,
itemkey => l_item_key,
process => l_process,
user_key => l_user_item_key);
--02 初始化
--本例不需要
--03 启动
wf_engine.startprocess(itemtype => l_item_type, itemkey => l_item_key);
COMMIT;
dbms_output.put_line(l_item_key);
END;
既然是PL/SQL,所以在Form等地方也是这样启动的。实际使用中几乎都是这样启动
工作流的。所以下面的例子开始不用方式一了。
接下来和上面的方式一一样去“Status Monitor”Tab页查看了。
2. 其他特性和功能实例
上面的例子虽然极其简单,但演示了整个过程,至少可以初学者迈出第一步;接下来
我们看看一些其他重要的功能,至于基本操作,就不再详细说明了。
2.1. 第2个例子:Notification
准备
新建6个Attribute
N: 选中Attribute/右键/New Attribute
Workflow 其他特性和功能实例 18 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
按如下表数据建立Attribute,用来保存提交者和审批者的信息。
这里先理解上面为什么要建3个类似的属性。对于程序来说ID是关键的,来源于各个表
如FND_USER或者HR_EMPLOYEES;对于Workflow来说Name是关键的,来源于表
WF_ROLES;对于最终User来说,Display Name是关键的,来源于表WF_ROLES。
新建1个Message
N: 选中Message/右键/New Message
Workflow 其他特性和功能实例 19 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
注意上面对变量的引用方式;实际上Subject也可以引用变量,这样可以做到动态
Subject。
确定的时候系统提示找不到“SUBMITER_DSP_NAME”。
Message中引用的变量必须在自己的Attribute中。可以手工建立:选中新建的这个
Message/右键/New Attribute。简单起见,我们直接把Item Type级别的
SUBMITER_DSP_NAME复制到新建的这个Message下面。
新建1个Notification
N: 选中Notification/右键/New Notification
Workflow 其他特性和功能实例 20 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
修改CUX_TOP
这个时候,再右键这里的Requisition Approval这个Notification查看属性,发现多了
一个Tab:Node。只有在具体Process中的Notification才有这个Node Tab。按照如下
画面设置Performer,也就是通知接收人。
Workflow 其他特性和功能实例 21 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
接下来的操作是:把原来指向End的箭头左键拖到指向Requisition Approval,再从
Requisition Approval右键拖一条线到End,重新布局。结果如下:
另存到数据库中
略。
启动工作流
先要找个测试用户,可以是SYSADMIN;这里我用HUAJHUA。为使测试顺利,我验
证了一下:
说明Huajhua这个用户已经关联了员工,且同步到了WF_ROLES这个表了。关于
WF_ROLES请看下面配置章节的“目录服务”。
Workflow 其他特性和功能实例 22 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
启动脚本如下:(注意学习下面的初始化脚本)
DECLARE
l_item_key VARCHAR2(30) := 'CUX_DEMO_003';
l_user_item_key VARCHAR2(30) := 'CUX_DEMO_UK_003';
l_item_type VARCHAR2(30) := 'CUX_0002';
l_process VARCHAR2(30) := 'CUX_TOP';
l_user_name wf_roles.NAME%TYPE;
l_display_name wf_roles.display_name%TYPE;
BEGIN
--01 创建
wf_engine.createprocess(itemtype => l_item_type,
itemkey => l_item_key,
process => l_process,
user_key => l_user_item_key);
--02 初始化
wf_directory.getusername(p_orig_system => l_orig_system,
p_orig_system_id => l_submiter_id,
p_name => l_user_name,
p_display_name => l_display_name);
Workflow 其他特性和功能实例 23 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
p_display_name => l_display_name);
--03 启动
wf_engine.startprocess(itemtype => l_item_type, itemkey => l_item_key);
COMMIT;
dbms_output.put_line(l_item_key);
END;
查看运行结果
先用Huajhua登录系统。
按照例子1种的查看方式,进入Notification Tab页;当然系统中很多地方都有
Notification这个菜单,基本都是一样的。结果如下:
点击Subject列的链接可以看到:
Workflow 其他特性和功能实例 24 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
退出,换成Sysadmin登录,来看看Diagram:
由于这个例子的通知不需要响应(Response),也就是不需要返回值,所以整个工作
流已经成功运行到End。
准备
新建1个Lookup Type
N: 选中Lookup Type/右键/New
可以直接使用Standard的Lookup Type;如果Standard的不符合要求,可以自己建。
这里我们拷贝标准的:从Standard下CTRL+拖动Approval到我们的Lookup Types
下,并改名,然后加一个Lookup Codes。
Workflow 其他特性和功能实例 25 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
按如下表数据建立Lookup Types,用来代表审批者的审批选项。
新建2个Item Type级别的Attribute
N:
修改Message的属性
N:
首先把上面新建的Attribute统统拉下来;其中关键要改一下 Note属性的Source为
Response,这个用来保留审批者输入的备注信息。
Workflow 其他特性和功能实例 26 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
内容如下
再修改Subject为:
修改Text Body,内容为:
From &SUBMITER_DSP_NAME
修改HTML Body,内容为:
<br>
From &SUBMITER_DSP_NAME
<br>
<br>
&NOTE
Workflow 其他特性和功能实例 27 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
修改Notification属性
N:
修改Process的流程
现在测试
N:
Workflow 其他特性和功能实例 28 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
这个时候如果保存到数据,并用脚本启动工作流,已经可以在通知的界面上看到审批
按钮了,点击Approve完成审批。这个就不再详细说明了。
创建客户化表和对象
N:
-- Create table
create table CUX_WF_DEMO_DOCUMENTS
(
DOCUMENT_ID NUMBER,
DOCUMENT_NUMBER VARCHAR2(30),
DOCUMENT_AMOUNT NUMBER,
AUTHORIZATION_STATUS VARCHAR2(20),
SUBMITER_ID NUMBER,
APPROVER_ID NUMBER,
NOTE VARCHAR2(4000)
);
-- Create/Recreate indexes
create unique index CUX_WF_DEMO_DOCUMENTS_U1 on CUX_WF_DEMO_DOCUMENTS
(DOCUMENT_ID);
-- Create Sequence
create sequence CUX_WF_DEMO_DOCUMENTS_S;
编写Package,包含4个Procedure
N: PL/SQL Developer
这里的Procedure指PL/SQL Procedure,到时候用在Workflow的Function上。
Procedure的参数是固定的,不能多也不能少;而且里面的代码块基本上也是相同的。
代码如下:
--初始化代码
PROCEDURE initialize(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2);
--审批通过
PROCEDURE approve_result(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2);
Workflow 其他特性和功能实例 29 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
--取消
PROCEDURE cancel_result(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2);
--拒绝
PROCEDURE reject_result(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2);
END;
--取得下一个审批者,可以通过各种方式取得
--1、自己客户化表维护审批路径
--2、用HR中维护的上下级关系
--3、用HR中维护的职位层次并利用PO的用工层次表
--4、用审批管理器OAM/AME
--另外,可以判断审批者的审批权限,如果权限不足,可以直接在找下一个人,这个由业务规则决定
--这里简单起见,直接用本身
PROCEDURE get_next_approver(p_approver_id IN NUMBER,
x_next_approver_id OUT NUMBER) IS
BEGIN
x_next_approver_id := p_approver_id;
END;
--初始化代码
PROCEDURE initialize(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2) IS
l_document_id NUMBER;
l_document_number cux_wf_demo_documents.document_number%TYPE;
l_document_amount NUMBER;
l_submiter_id NUMBER;
Workflow 其他特性和功能实例 30 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
l_submiter_user_name wf_roles.NAME%TYPE;
l_submiter_display_name wf_roles.display_name%TYPE;
x_approver_id NUMBER;
l_approver_user_name wf_roles.NAME%TYPE;
l_approver_display_name wf_roles.display_name%TYPE;
BEGIN
resultout := wf_engine.eng_null;
RETURN;
END IF;
--获得记录ID
l_document_id := wf_engine.getitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'DOCUMENT_ID');
--获得需审批数据
SELECT doc.document_number, doc.document_amount, doc.submiter_id
INTO l_document_number, l_document_amount, l_submiter_id
FROM cux_wf_demo_documents doc
WHERE doc.document_id = l_document_id;
--取得提交者名字信息
wf_directory.getusername(p_orig_system => l_orig_system,
p_orig_system_id => l_submiter_id,
p_name => l_submiter_user_name,
p_display_name => l_submiter_display_name);
--设置提交者名字信息到工作流
wf_engine.setitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'SUBMITER_ID',
avalue => l_submiter_id);
Workflow 其他特性和功能实例 31 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
wf_engine.setitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'SUBMITER_DSP_NAME',
avalue => l_submiter_display_name);
--设置审批数据信息到工作流
wf_engine.setitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'DOCUMENT_NUMBER',
avalue => l_document_number);
--获得审批者
get_next_approver(l_submiter_id, x_approver_id);
--取得审批者名字信息
wf_directory.getusername(p_orig_system => l_orig_system,
p_orig_system_id => x_approver_id,
p_name => l_approver_user_name,
p_display_name => l_approver_display_name);
--设置审批者名字信息
wf_engine.setitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'APPROVER_ID',
avalue => x_approver_id);
resultout := 'COMPLETE';
EXCEPTION
Workflow 其他特性和功能实例 32 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
RAISE;
END;
--审批通过
--这里面可以判断审批者的审批权限
PROCEDURE approve_result(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2) IS
l_document_id NUMBER;
l_note cux_wf_demo_documents.note%TYPE;
l_approver_id NUMBER;
BEGIN
resultout := wf_engine.eng_null;
RETURN;
END IF;
--获得记录ID
l_document_id := wf_engine.getitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'DOCUMENT_ID');
--获得审批者ID
l_approver_id := wf_engine.getitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'APPROVER_ID');
--获得审批意见
l_note := wf_engine.getitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'NOTE');
--更新数据表
Workflow 其他特性和功能实例 33 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
UPDATE cux_wf_demo_documents doc
SET doc.approver_id = l_approver_id,
doc.note = l_note,
doc.authorization_status = 'APPROVED'
WHERE doc.document_id = l_document_id;
resultout := 'COMPLETE';
EXCEPTION
RAISE;
END;
-取消
PROCEDURE cancel_result(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2) IS
l_document_id NUMBER;
l_note cux_wf_demo_documents.note%TYPE;
l_approver_id NUMBER;
BEGIN
resultout := wf_engine.eng_null;
RETURN;
END IF;
--获得记录ID
l_document_id := wf_engine.getitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'DOCUMENT_ID');
--获得审批者ID
l_approver_id := wf_engine.getitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'APPROVER_ID');
Workflow 其他特性和功能实例 34 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
--获得审批意见
l_note := wf_engine.getitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'NOTE');
--更新数据表
UPDATE cux_wf_demo_documents doc
SET doc.approver_id = l_approver_id,
doc.note = l_note,
doc.authorization_status = 'CANCEL'
WHERE doc.document_id = l_document_id;
resultout := 'COMPLETE';
EXCEPTION
RAISE;
END;
--拒绝
PROCEDURE reject_result(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2) IS
l_document_id NUMBER;
l_note cux_wf_demo_documents.note%TYPE;
l_approver_id NUMBER;
BEGIN
resultout := wf_engine.eng_null;
RETURN;
END IF;
--获得记录ID
l_document_id := wf_engine.getitemattrnumber(itemtype => itemtype,
Workflow 其他特性和功能实例 35 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
itemkey => itemkey,
aname => 'DOCUMENT_ID');
--获得审批者ID
l_approver_id := wf_engine.getitemattrnumber(itemtype => itemtype,
itemkey => itemkey,
aname => 'APPROVER_ID');
--获得审批意见
l_note := wf_engine.getitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'NOTE');
--更新数据表
UPDATE cux_wf_demo_documents doc
SET doc.approver_id = l_approver_id,
doc.note = l_note,
doc.authorization_status = 'REJECT'
WHERE doc.document_id = l_document_id;
resultout := 'COMPLETE';
EXCEPTION
RAISE;
END;
END;
新建4个Function
N: 选中Function/右键/新建
Workflow 其他特性和功能实例 36 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
具体设置如下:
第一个Function相当于我们例子2种的初始化作用,后面3个Function分别对应审批者
的3种审批结果。
修改Process的流程
把4个Function拖进来,重新布局如下(不要告诉我不会哦!):
Workflow 其他特性和功能实例 37 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
测试:启动
N:
首先还是确认一下提交者ID,我做这个文档的时候是在不同环境做的。
DECLARE
l_item_key VARCHAR2(30);
l_user_item_key VARCHAR2(30);
l_item_type VARCHAR2(30) := 'CUX_0003';
l_process VARCHAR2(30) := 'CUX_TOP';
l_submiter_id NUMBER := 6987;
l_document_id NUMBER;
BEGIN
--00 业务数据录入
SELECT cux_wf_demo_documents_s.NEXTVAL INTO l_document_id FROM dual;
Workflow 其他特性和功能实例 38 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
submiter_id)
VALUES
(l_document_id,
'DOC' || lpad(l_document_id, '8', '0'),
l_document_id * round(dbms_random.VALUE * 100000, 2),
'ENTERED',
l_submiter_id);
--01 创建
l_item_key := l_document_id;
l_user_item_key := 'DOC' || lpad(l_item_key, '8', '0');
wf_engine.createprocess(itemtype => l_item_type,
itemkey => l_item_key,
process => l_process,
user_key => l_user_item_key);
--02 初始化
wf_engine.setitemattrnumber(itemtype => l_item_type,
itemkey => l_item_key,
aname => 'DOCUMENT_ID',
avalue => l_document_id);
--03 启动
wf_engine.startprocess(itemtype => l_item_type, itemkey => l_item_key);
COMMIT;
dbms_output.put_line(l_item_key);
END;
测试:审批
N: Notification
由于先前我做了几下测试,所以这里的号码是6了。
Workflow 其他特性和功能实例 39 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
点击Approve按钮
测试:验证表数据
N:
SELECT *
FROM cux_wf_demo_documents doc
WHERE doc.document_number = DOC00000006;
结果如下:
测试:看工作流程图
N: sysadmin登录
可以看到已经正常Complete了。
Workflow 其他特性和功能实例 40 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
N:
这个工作在这里做有点晚了:建立自己的标准Item Type。内容如下:
同时把例子3中的Lookup Type拖到CUX_STDD中(不要按CTRL)。
准备:拷贝CUX_0003成CUX_0004
N: Copy/Paste
N: Copy/Paste
查看Process中Requisition Approval的属性,并设置Timeout属性,这里设置1分钟是
为了方便测试。
超时一般是针对Notification的,意思是多长时间之后不处理该消息就算超时,超时也
是一种返回结果。
N:
从Standard中把Loop Counter拖过来,并设置属性如下:
Workflow 其他特性和功能实例 41 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
这里是Constant 3,说明循环3次。实际上循环次数可以是动态的Attribute。
N:
从Standard中把Defer Thread拖过来,不用设置属性,不过可以注意一下Function是
WF_STANDARD.DEFER,我们也可以新建这样的Defer Function。实际上,标准功
能中的大部分Item,我们都可以参照着自己创建。
Defer的意思相当于Pause,意思是工作流到这个地方暂停,需要外力(可用程序、可
用下面讲的请求)来推动。
增加一个标准Function: End
N:
注意,这次比较特殊,不设置其Start/End属性为End,而是保留默认的Normal。
N:
操作略,结果如下:
Workflow 其他特性和功能实例 42 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
测试:启动
N:
首先还是确认一下提交者ID,我做这个文档的时候是在不同环境做的。
DECLARE
l_item_key VARCHAR2(30);
l_user_item_key VARCHAR2(30);
l_item_type VARCHAR2(30) := 'CUX_0004';
l_process VARCHAR2(30) := 'CUX_TOP';
l_submiter_id NUMBER := 6187;
l_document_id NUMBER;
BEGIN
--00 业务数据录入
SELECT cux_wf_demo_documents_s.NEXTVAL INTO l_document_id FROM dual;
Workflow 其他特性和功能实例 43 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
(l_document_id,
'DOC' || lpad(l_document_id, '8', '0'),
l_document_id * round(dbms_random.VALUE * 100000, 2),
'ENTERED',
l_submiter_id);
--01 创建
l_item_key := l_document_id;
l_user_item_key := 'DOC' || lpad(l_item_key, '8', '0');
wf_engine.createprocess(itemtype => l_item_type,
itemkey => l_item_key,
process => l_process,
user_key => l_user_item_key);
--02 初始化
wf_engine.setitemattrnumber(itemtype => l_item_type,
itemkey => l_item_key,
aname => 'DOCUMENT_ID',
avalue => l_document_id);
--03 启动
wf_engine.startprocess(itemtype => l_item_type, itemkey => l_item_key);
COMMIT;
dbms_output.put_line(l_item_key);
END;
测试:验证
N: APPS/APPS
下面SQL可以查看现在发出的通知:
SELECT wfn.notification_id,
wfn.message_type,
wfn.recipient_role,
wfn.status,
wfn.subject,
wfn.due_date,
wfn.end_date
Workflow 其他特性和功能实例 44 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
FROM wf_notifications wfn
WHERE wfn.message_type = 'CUX_0004'
AND wfn.subject LIKE '%DOC00000022%'
ORDER BY wfn.notification_id DESC
结果如下:
说明目前只有一条消息,并且是Open的,注意due_date。
用Huajhua登录上去看Notification,确实有一条:
N: System Administrator职责
不要审批,一分钟之后该通知会超时,但状态还是Open的,其实还可以审批。
处理Timeout类型活动。运行完再到数据库查询,结果如下:
Workflow 其他特性和功能实例 45 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
104156 CUX_0004 HUAJHUA CANCELED Document : DOC00000022
Requires Your Approval 2005-12-13 9:47:34 2005-12-13 9:53:10
超时的已被自动取消,重新发出通知。
再等1分钟,重复上述步骤;再等1分钟,重复上述步骤;再等1分钟,这个时候退出循
环了。
最终4条Notification都是CANCELED,审批人再也看不到消息,没有机会审批;用
sysadmin登录查看运行状态图:
发现停在Defer Thread。
N: System Administrator职责
注意上面参数变化。再去看运行状态图:
Workflow 其他特性和功能实例 46 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
可以看到,已经过去了,到了最后的End节点,不过这个时候工作流状态还是Active,
而不是正常的Complete或者Error:
这个是因为我们上面故意没有设置End的属性。
N: System Administrator职责
注意上面参数变化。结果如下:
下面的处理可以是Suspend、Cancel、Retry、Skip,是具体情况而定。我们这里用
Skip即可,因为已经是最后,只是我们设计失误导致问题,不用什么处理了。
Workflow 其他特性和功能实例 47 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
准备:拷贝CUX_0004成CUX_0005
N: Copy/Paste
添加Function:Wait
设置属性如下:
布局如下:
Workflow 其他特性和功能实例 48 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
添加1个Process
N:
设置属性如下:
并按下图添加标准节点,操作和注意点参考前面例子。
Workflow 其他特性和功能实例 49 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
着重看下Continue Flow
N:
从标准的拖过来,我们不用修改任何属性,即可和父工作流关联。
关键属性,呵呵,明眼人一看就知道怎么回事了:
Internal Name:CONTINUEFLOW
Display Name: Continue Flow
Function Name: WF_STANDARD.CONTINUEFLOW
Label: CONTINUEFLOW
Waiting Activity Label: WAITFORFLOW
Waiting Flow: Master
Workflow 其他特性和功能实例 50 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
修改Demo Top Process
N:
N:
从标准的拖过来,我们不用修改任何属性,即可和子工作流关联。
关键属性,呵呵,明眼人一看就知道怎么回事了:
Internal Name:WAITFORFLOW
Display Name: Wait For Flow
Function Name: WF_STANDARD.WAITFORFLOW
Workflow 其他特性和功能实例 51 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
Label: WAITFORFLOW
Waiting Activity Label: CONTINUEFLOW
Continuation Flow: Detail
测试:启动
N:
DECLARE
l_item_key VARCHAR2(30);
l_user_item_key VARCHAR2(30);
l_item_type VARCHAR2(30) := 'CUX_0005';
l_process VARCHAR2(30) := 'CUX_TOP';
l_child_item_key VARCHAR2(30);
l_child_user_item_key VARCHAR2(30);
l_child_item_type VARCHAR2(30) := 'CUX_0005';
l_child_process VARCHAR2(30) := 'CUX_CHILD';
--00 业务数据录入
SELECT cux_wf_demo_documents_s.NEXTVAL INTO l_document_id FROM dual;
--01 创建
l_item_key := l_document_id;
l_user_item_key := 'DOC' || lpad(l_item_key, '8', '0');
Workflow 其他特性和功能实例 52 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
wf_engine.createprocess(itemtype => l_item_type,
itemkey => l_item_key,
process => l_process,
user_key => l_user_item_key);
-- 定义主从关系,必须在createprocess后startprocess前,
-- parent_context是父工作流Wait节点的label,如果是一个Wait节点就不用指定了
wf_engine.setitemparent(itemtype => l_child_item_type,
itemkey => l_child_item_key,
parent_itemtype => l_item_type,
parent_itemkey => l_item_key,
parent_context => NULL);
--02 初始化
wf_engine.setitemattrnumber(itemtype => l_item_type,
itemkey => l_item_key,
aname => 'DOCUMENT_ID',
avalue => l_document_id);
--03 启动
wf_engine.startprocess(itemtype => l_item_type, itemkey => l_item_key);
wf_engine.startprocess(itemtype => l_child_item_type,
itemkey => l_child_item_key);
COMMIT;
dbms_output.put_line(l_item_key);
END;
测试:看下父工作流状态图
N:
Workflow 其他特性和功能实例 53 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
测试:看下子工作流状态图
N:
停在我们安排的Defer Thread。
N:
操作略。
测试:再看下父工作流状态图
N:
Workflow 其他特性和功能实例 54 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
测试:再看下子工作流状态图
N:
已经结束。
准备:拷贝CUX_0005成CUX_0006
N: Copy/Paste
添加Attribute
N:
Workflow 其他特性和功能实例 55 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
Internal Name Display Name Type
DOCUMENT_DETAILS Document Details Document
OPEN_FORM_COMMAND Open Document Form
ORG_ID Operating Unit ID Number
N:
其次添加两个Attribute:
#HIDE_REASSIGN,可以隐藏标准的Reassign按钮
#HIDE_MOREINFO,可以隐藏标准的Request Information按钮
Detail Lines:
Workflow 其他特性和功能实例 56 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
&DOCUMENT_DETAILS
添加2个Procedure到Package中
N:
--设置Document类型Attribute,为了不影响前面的例子,独立写了个Procedure
PROCEDURE initialize2(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2) IS
BEGIN
resultout := wf_engine.eng_null;
RETURN;
END IF;
--设置Form类型Attribute
--格式'FUNCATION_NAME:PARAMETER=VALUE'
--Function_Name如果在系统中不存在,界面上就不会有那个链接
wf_engine.setitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'OPEN_FORM_COMMAND',
avalue => 'FND_FNDSCAUS');
--设置Document类型Attribute
wf_engine.setitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'DOCUMENT_DETAILS',
avalue =>
'PLSQLCLOB:CUX_WF_DEMO_PKG.GET_DOCUMENT_DETAILS/' ||
itemtype || ':' || itemkey);
EXCEPTION
END;
Workflow 其他特性和功能实例 57 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
--获得Document Attribute内容
PROCEDURE get_document_details(document_id IN VARCHAR2,
display_type IN VARCHAR2,
document IN OUT CLOB,
document_type IN OUT VARCHAR2) IS
l_item_type wf_items.item_type%TYPE;
l_item_key wf_items.item_key%TYPE;
l_document_id NUMBER;
l_org_id NUMBER;
BEGIN
fnd_client_info.set_org_context(to_char(l_org_id));
--方法1
dbms_lob.createtemporary(lob_loc => l_clob_document,
cache => TRUE,
dur => dbms_lob.session);
dbms_lob.OPEN(lob_loc => l_clob_document,
open_mode => dbms_lob.lob_readwrite);
wf_notification.writetoclob(l_clob_document, l_document);--追加,可不断写
dbms_lob.append(document, l_clob_document);
IF (dbms_lob.ISOPEN(l_clob_document) = 1) THEN
dbms_lob.CLOSE(l_clob_document);
Workflow 其他特性和功能实例 58 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
dbms_lob.freetemporary(l_clob_document);
END IF;
--方法2
document := document || l_document;
END;
添加Initialize2节点
N:
测试:启动
N:
基本和例子5一样
DECLARE
l_item_key VARCHAR2(30);
l_user_item_key VARCHAR2(30);
l_item_type VARCHAR2(30) := 'CUX_0006';
l_process VARCHAR2(30) := 'CUX_TOP';
l_child_item_key VARCHAR2(30);
l_child_user_item_key VARCHAR2(30);
l_child_item_type VARCHAR2(30) := 'CUX_0006';
l_child_process VARCHAR2(30) := 'CUX_CHILD';
--00 业务数据录入
SELECT cux_wf_demo_documents_s.NEXTVAL INTO l_document_id FROM dual;
--01 创建
l_item_key := l_document_id;
l_user_item_key := 'DOC' || lpad(l_item_key, '8', '0');
--定义主从关系,必须在createprocess后startprocess前
--parent_context是父工作流Wait节点的label,如果是一个Wait节点就不用指定了
wf_engine.setitemparent(itemtype => l_child_item_type,
itemkey => l_child_item_key,
parent_itemtype => l_item_type,
parent_itemkey => l_item_key,
parent_context => NULL);
--02 初始化
wf_engine.setitemattrnumber(itemtype => l_item_type,
itemkey => l_item_key,
aname => 'DOCUMENT_ID',
avalue => l_document_id);
Workflow 其他特性和功能实例 60 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
itemkey => l_item_key,
aname => 'SUBMITER_ID',
avalue => l_submiter_id);
--03 启动
wf_engine.startprocess(itemtype => l_item_type, itemkey => l_item_key);
wf_engine.startprocess(itemtype => l_child_item_type,
itemkey => l_child_item_key);
COMMIT;
dbms_output.put_line(l_item_key);
END;
测试:通知内容
N:
其它需要的操作请看例子5。最后看到的Notification如下:
可以看到Document Details显示出来了,界面上少了两个按钮;多了一个Open
Document链接。
Workflow 其他特性和功能实例 61 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
3. 常用代码块
3.1. Startup
代码实例
这个是上面的启动脚本3:
l_user_name wf_roles.NAME%TYPE;
l_display_name wf_roles.display_name%TYPE;
BEGIN
--01 创建
wf_engine.createprocess(itemtype => l_item_type,
itemkey => l_item_key,
process => l_process,
user_key => l_user_item_key);
--02 初始化
wf_directory.getusername(p_orig_system => l_orig_system,
p_orig_system_id => l_submiter_id,
p_name => l_user_name,
p_display_name => l_display_name);
Workflow 常用代码块 62 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
aname => 'SUBMITER_NAME',
avalue => l_user_name);
--03 启动
wf_engine.startprocess(itemtype => l_item_type, itemkey => l_item_key);
COMMIT;
dbms_output.put_line(l_item_key);
END;
3.2. Notification
代码实例
这个是上面例子4的脚本:
Workflow 常用代码块 63 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
SELECT wfn.notification_id,
wfn.message_type,
wfn.recipient_role,
wfn.status,
wfn.subject,
wfn.due_date,
wfn.end_date
FROM wf_notifications wfn
WHERE wfn.message_type = 'CUX_0004'
AND wfn.subject LIKE '%DOC00000022%'
ORDER BY wfn.notification_id DESC
3.3. Active节点和当前属性值
Active节点代码实例
这个可以用来获得activity,后续章节需要:
SELECT was.item_type,
was.item_key,
wpa.process_name || ':' || wpa.instance_label activity,
was.activity_status,
was.activity_result_code,
was.assigned_user,
was.notification_id,
was.begin_date,
pro.display_name process_name,
act.display_name activity_name
FROM apps.wf_item_activity_statuses was,
apps.wf_process_activities wpa,
apps.wf_activities_vl pro,
apps.wf_activities_vl act,
applsys.wf_items wi
WHERE was.process_activity = wpa.instance_id
AND wpa.process_item_type = pro.item_type
AND wpa.process_name = pro.NAME
AND wpa.process_version = pro.version
AND wpa.activity_item_type = act.item_type
AND wpa.activity_name = act.NAME
AND was.item_type = wi.item_type
AND was.item_key = wi.item_key
AND wi.begin_date >= act.begin_date
AND wi.begin_date < nvl(act.end_date, wi.begin_date + 1)
Workflow 常用代码块 64 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
AND was.item_type = 'OEOL'
AND was.item_key = '3598788'
AND was.end_date IS NULL;
当前属性值代码实例
这个可以用来获得当前属性值:
SELECT val.item_type,
val.item_key,
val.NAME,
val.text_value,
val.number_value,
val.date_value,
val.event_value
FROM applsys.wf_item_attribute_values val
WHERE val.item_type = 'OEOL'
AND val.item_key = '3434182';
3.4. Retry和Skip
代码实例
假定我们Retry上面的INITIALIZE节点,这样不管当前工作流运行到哪里了,都将从
INITIALIZE这个节点开始运行,这个是比较危险的动作。
BEGIN
-- 初始化,根据实际环境修改,这样可以获得环境变量,主要是Org_id,一般不需要
fnd_global.apps_initialize(user_id => 6187,
resp_id => 50237,
resp_appl_id => 20003);
-- Call the procedure
wf_engine.handleerror(itemtype => 'CUX_0004',
itemkey => '23',
activity => 'CUX_TOP:INITIALIZE',
command => wf_engine.eng_retry);
END;
Skip的意思是跳过节点的执行,比如某个Function的处理或者审批通知,也是个比较
危险的动作。把上面的wf_engine.eng_retry改为wf_engine.eng_skip就可以了。
这里要注意的是activity参数,它是<节点所在Process的Internal_Name>:<本身的
Label>。Label在属性的Note的Tab页,默认和自己的Internal_Name相同。
Workflow 常用代码块 65 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
3.5. Complete
代码实例
完成一个节点,比如模拟审批,需要针对有Result Type的节点。下面的代码是模拟审
批通知,结果是拒绝。
BEGIN
-- 初始化,根据实际环境修改,这样可以获得环境变量,主要是Org_id,一般不需要
fnd_global.apps_initialize(user_id => 6187,
resp_id => 50237,
resp_appl_id => 20003);
-- Call the procedure
wf_engine.completeactivity(itemtype => 'CUX_0004',
itemkey => '23',
activity => 'CUX_TOP:REQ_APPROVAL',
RESULT => 'REJECTED');
END;
这里要注意的是activity参数,它是<节点所在Process的Internal_Name>:<本身的
Label>。Label在属性的Note的Tab页,默认和自己的Internal_Name相同。
3.6. 处理Defer
代码实例
BEGIN
-- 初始化,根据实际环境修改,这样可以获得环境变量,主要是Org_id,一般不需要
fnd_global.apps_initialize(user_id => 6187,
resp_id => 50237,
resp_appl_id => 20003);
-- Call the procedure
wf_engine.processdeferred(itemtype => 'CUX_0004');
END;
3.7. 建立父子关系
代码实例
来自上面的例子5。
Workflow 常用代码块 66 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
DECLARE
……
BEGIN
-- 初始化,根据实际环境修改,这样可以获得环境变量,主要是Org_id,一般不需要
fnd_global.apps_initialize(user_id => 6187,
resp_id => 50237,
resp_appl_id => 20003);
……
-- 定义主从关系,必须在createprocess后startprocess前,
-- parent_context是父工作流Wait节点的label,如果是一个Wait节点就不用指定了
wf_engine.setitemparent(itemtype => l_child_item_type,
itemkey => l_child_item_key,
parent_itemtype => l_item_type,
parent_itemkey => l_item_key,
parent_context => NULL);
……
END;
3.8. Document和Forms
代码实例
来自上面的例子6。
--设置Document类型Attribute,为了不影响前面的例子,独立写了个Procedure
PROCEDURE initialize2(itemtype IN VARCHAR2,
itemkey IN VARCHAR2,
actid IN NUMBER,
funcmode IN VARCHAR2,
resultout OUT NOCOPY VARCHAR2) IS
BEGIN
resultout := wf_engine.eng_null;
RETURN;
END IF;
--设置Form类型Attribute
--格式'FUNCTION_NAME:PARAMETER=VALUE'
--Function_Name如果在系统中不存在,界面上就不会有那个链接
wf_engine.setitemattrtext(itemtype => itemtype,
Workflow 常用代码块 67 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
itemkey => itemkey,
aname => 'OPEN_FORM_COMMAND',
avalue => 'FNDSCSGN');
--设置Document类型Attribute
wf_engine.setitemattrtext(itemtype => itemtype,
itemkey => itemkey,
aname => 'DOCUMENT_DETAILS',
avalue =>
'PLSQLCLOB:CUX_WF_DEMO_PKG.GET_DOCUMENT_DETAILS/' ||
itemtype || ':' || itemkey);
EXCEPTION
END;
--获得Document Attribute内容
PROCEDURE get_document_details(document_id IN VARCHAR2,
display_type IN VARCHAR2,
document IN OUT CLOB,
document_type IN OUT VARCHAR2) IS
l_item_type wf_items.item_type%TYPE;
l_item_key wf_items.item_key%TYPE;
l_document_id NUMBER;
l_org_id NUMBER;
BEGIN
Workflow 常用代码块 68 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
itemkey => l_item_key,
aname => 'DOCUMENT_ID');
fnd_client_info.set_org_context(to_char(l_org_id));
--方法1
dbms_lob.createtemporary(lob_loc => l_clob_document,
cache => TRUE,
dur => dbms_lob.session);
dbms_lob.OPEN(lob_loc => l_clob_document,
open_mode => dbms_lob.lob_readwrite);
wf_notification.writetoclob(l_clob_document, l_document);
dbms_lob.append(document, l_clob_document);
IF (dbms_lob.ISOPEN(l_clob_document) = 1) THEN
dbms_lob.CLOSE(l_clob_document);
dbms_lob.freetemporary(l_clob_document);
END IF;
--方法2
document := document || l_document;
END;
3.9. Test工作流
代码实例
DECLARE
l_actid NUMBER;
x_resultout VARCHAR2(4000);
BEGIN
SELECT instance_id
INTO l_actid
FROM wf_process_activities
WHERE process_item_type = 'OEOL'
Workflow 常用代码块 69 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
AND process_name = 'REPRICE_LINE'
AND activity_name = 'REPRICE';
dbms_output.put_line(x_resultout);
END;
3.10. Cancel/Abort工作流
代码实例
BEGIN
-- Call the procedure
wf_engine.abortprocess(itemtype => 'POERROR', itemkey => 'WF181816');
END;
3.11. Purge工作流实例/定义
wf_purge包用来清理工作流数据。
清除运行时数据
如果item type的Persistence设置为Temporary时,在设置的参数n天后自动删除。
BEGIN
-- Call the procedure
WF_PURGE.Total(itemtype => 'POERROR', itemkey => 'WF181816');
END;
清除工作流定义
@$FND_TOP/sql/wfrmitt.sql。
Workflow 常用代码块 70 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
3.12. 最新n条Notification
代码实例
比如取10条:
SELECT *
FROM (SELECT * FROM wf_notifications a ORDER BY a.notification_id DESC)
WHERE rownum <= 10
ORDER BY notification_id
3.13. 等待发送Mail的Notification
代码实例
注意:status = 'SENT'的记录说明已经成功发送。
外发Mail通常在如下Queue中:
SELECT *
FROM wf_notification_out wno
WHERE wno.state = 0
AND wno.corrid LIKE 'APPS%'
3.14. Queue相关
Queue的有效性
如果有使用的Queue处于无效状态,请依照Metalink 275571.1处理。
Queue的订阅Rule
Workflow 常用代码块 71 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
3.15. 未完待续
Workflow 常用代码块 72 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
4. 审批路径
4.1. 客户化表
说明
没什么好说的了。
4.2. 员工上下级
说明
直接取HR员工上定义的上下级关系来来处理审批路径问题。
有时间我再补充这方面内容。
4.3. 职位层次
说明
一般是借用PO的审批层次方案来处理审批路径问题。至于审批权限,也可以参照PO的
来做,也可以客户化表来做。
有时间我再补充这方面内容。
4.4. OAM/AME
说明
创建客户化表和对象
N:
插入业务数据
N:
DECLARE
l_header_rec cux_ame_test_headers_all%ROWTYPE;
l_line_rec cux_ame_test_lines_all%ROWTYPE;
BEGIN
SELECT cux_ame_test_headers_s.NEXTVAL
INTO l_header_rec.header_id
FROM dual;
l_header_rec.amount := 123456;
l_header_rec.last_updated_by := 24894;
l_header_rec.approval_status := 'ENTERED';
COMMIT;
END;
Workflow 审批路径 74 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
创建客户化Transaction Type
名字:CUX_AME_TEST_DESC
参数:
SELECT to_char(line_id)
FROM cux_ame_test_lines_all
WHERE header_id = :transactionid
ORDER BY line_id
增加标准Attribute到客户化Transaction Type
增加标准Attribute:OW_EMPTY_APPROVAL_GROUPS
增加自定义Attribute到客户化Transaction Type
名字:CUX_AME_TEST_AMOUNT
参数:
动态Usage
SELECT amount
FROM cux_ame_test_headers_all
WHERE header_id = :transactionId
增加自定义Group
并添加User类型的Member若干
增加自定义Condition
增加自定义Rule
参数:
N:数据库
以下脚本实际上可以用在Workflow的Function中。
DECLARE
l_next_approver ame_util.approverrecord;
l_result VARCHAR2(30) := 'APPROVED';
l_header_id NUMBER;
l_app_id NUMBER := 20002;
l_transaction_type VARCHAR2(30) := 'CUX_AME_TEST_ID';
l_header_rec cux_ame_test_headers_all%ROWTYPE;
l_line_rec cux_ame_test_lines_all%ROWTYPE;
BEGIN
SELECT cux_ame_test_headers_s.NEXTVAL
INTO l_header_rec.header_id
FROM dual;
l_header_rec.amount := 123456;
l_header_rec.last_updated_by := 24894;
l_header_rec.approval_status := 'ENTERED';
COMMIT;
l_header_id := l_header_rec.header_id;
LOOP
ame_api.getnextapprover(l_app_id,
l_header_id,
l_transaction_type,
l_next_approver);
Workflow 审批路径 76 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
dbms_output.put_line('user_id:' || l_next_approver.user_id);
dbms_output.put_line('person_id:' || l_next_approver.person_id);
dbms_output.put_line('first_name:' || l_next_approver.first_name);
dbms_output.put_line('last_name:' || l_next_approver.last_name);
dbms_output.put_line('api_insertion:' || l_next_approver.api_insertion);
dbms_output.put_line('authority:' || l_next_approver.authority);
dbms_output.put_line('approval_status:' ||
l_next_approver.approval_status);
dbms_output.put_line('approval_type_id:' ||
l_next_approver.approval_type_id);
dbms_output.put_line('group_or_chain_id:' ||
l_next_approver.group_or_chain_id);
dbms_output.put_line('occurrence:' || l_next_approver.occurrence);
--dbms_output.put_line('source:' || l_next_approver.SOURCE);
ELSE
ame_api.updateapprovalstatus2(applicationidin => l_app_id,
transactionidin => l_header_id,
approvalstatusin => ame_util.rejectstatus,
approverpersonidin => NULL,
approveruseridin => l_next_approver.user_id,
transactiontypein => l_transaction_type);
END IF;
COMMIT;
END LOOP;
END;
Workflow 审批路径 77 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳
佳技术实践 Doc Ref: <Documentt Reference Num
mber>
November 11, 2010
5. Work
kflow No
otification
n Mailer Configu
uration
这里指嵌 Workflow。
嵌在EBS中的W
参考资料见Orracle的《Ora
完整的参 acle Workflo
ow Administrrator's Guidee》。
$FND_T
TOP/admin/
/sql下有Worrkflow管理和
和诊断脚本。
5.1. Basicc
设置步骤
骤
摘自Oraacle Workflow
w Administrrator's Guidee。下面的章节 Required的和
节详细说明R 和比
较有用的
的设置步骤。
目录服务
务
Workflo
ow的核心功能 消息(Notificaation),要发
能之一就是消 发消息,当然
然要有接收人,这
个接收人 个user、一个eemployee、一
人可能是一个 一个Responsiibility、一个
个客户、一个职
职位
等等。
中这些接收人分
在EBS中 分散在各个模
模块的各个表 kflow Enginee仅承认WF_表
表中,而Work 表中
的接收人
人。
Workflow Worrkflow Notificattion Mailer Con
nfiguration 788 of 90
File Ref: 深入浅
浅出Oracle EBS之 例详解.docx (v
之Workflow实例 v. DRAFT 1A )
Company Coonfidential - Forr internal use on
nly
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
Oracle目录服务的作用就是把这些分散的资料按照统一的格式集中起来,存在
WF_LOCAL系列的表中,并以来源字段区分。这样我们在程序中如果要找某一个接收
人,仅从WF_LOCAL系列的表中查询即可(实际应用中,是调用一个标准API从
WF_ROLES视图取数),不需要记住所有的源表。
接收人分用户和角色,角色包含一个或多个用户,对应的视图为
wf_users/wf_roles/wf_user_roles。如果消息的接收人为职责,那么这个职责下的所
有用户都会收到消息。这个好理解,不多说。
下面以EBS的登录user为例。
1. 原来存储的表为:fnd_user,假定这里面有个用户User_Name为huajhua,User_ID
为1001
2. 对应一个按照目录服务格式要求的视图:wf_fnd_usr_roles
3. WF Bulk Synchronize Local Tables请求会把wf_fnd_usr_roles的数据同步到
wf_local_roles中,orig_system字段标志为fnd_usr
4. 如果以后我们要发通知给huajhua,那么通过API可以获得该用户:
WF_DIRECTORY.GETROLENAME(‘FND_USR’, 1001,x_name,x_displayname)
值得一提的是如果User和Employee关联了,那么orig_system将是PER。举几个例子:
所以,总的来说,Workflow的目录服务就是收集用户和角色信息,以统一的格式提供
给Workflow消息系统使用。包括:
1. 一套本地表:WF_LOCALXXX
2. 一套实际使用的视图:WF_USERS/WF_ROLES/WF_USER_ROELS
3. 一套各来源视图:WF_<Orig_System>_ROLES
4. 一个批量同步请求集:Synchronize Workflow LOCAL tables(增量同步需要安装
Patch,请看Notes171703.1)
5. 一套API:WF_DIRECTORY
Table Partition
随着业务的增长和历史数据的增多,有几个工作流的表会越来越大,如果不进行分
区,其性能(DML和Export/Import)是比较糟糕的。默认情况下,只有目录服务的
几个表是按来源分区过的;其他的表,需要运
需要分区的表和索引为:目录服务表、WF_ITEM_ACTIVITY_STATUSES及索引、
WF_ITEM_ACTIVITY_STATUSES_H及索引、WF_ITEM_ATTRIBUTE_VALUES及
索引、WWF_ITEMS及索引。以WF_ITEM_ATTRIBUTE_VALUES为例,它保留的是
工作流实例的各个属性值,XX公司在Purge之后这个表仍然有7000万条记录,Export
这个表要37个小时。
以下SQL用来查看分区情况:
SELECT t.owner, t.table_name, t.partitioned
FROM all_tables t
WHERE t.table_name LIKE 'WF%'
ORDER BY t.partitioned
Directory Service
如果我们加了个fnd user,但没跑这个同步程序(可能是还没到计划时间),那么
Workflow并不知道有这个用户存在,这就导致为什么有“我跑过了Fill Employee
Hierarchy,为什么通知还是没发到XXX”的问题。实际上,对于通知没发到XXX的问
题,有如下原因:
1. 程序错误,没有设置正确的Notification Performer
2. 如果是PO,可能没跑Fill Employee Hierarchy
3. 一个Employee分配给了多个User,那么其实只有第一个User收到了消息
4. 数据还没有同步到Workflow,即没跑Synchronize Workflow LOCAL tables
Background Engines
如果我们Schedule了该请求,但有时候等不及,也可手工提交;下面的例子是最常见
的处理销售订单行Defer的请求:
Global Preferences
定义Workflow全局参数。仅需关注两个参数。
N: SYS/Workflow/Global Preferences
Parameter Value
Workflow Administrator *
WF_RESOUCE环境变量
WF_RESOURCE环境变量用于存储指向Workflow资源文件,EBS的资源文件
为%FND_TOP%/%APPLRSC%/wf<language>.res,不需要设置该变量。
Imail设置(也可以用任何其他Mail服务器,比如公司的邮件服务器)
1. 按照默认选项安装Imail
2. 启动Imail的服务:SMTP/IMAP/Queue Manager/POP3
3. 创建Notification Mailer需要的用户,假定是wfmail;另外再建一个测试账号
huajhua
4. 用邮件客户端(文档说必须,所以我用Imail自带的Client)给wfmail创建三个目
录:INBOX、PROCESS、DISCARD
进入Workflow的配置管理界面
1. 进入OAM,需要有System Administrator职责:
3. 进入Service Components管理界面
启动两个Container服务
* 这两个玩意儿其实是Concurrent Manager的两个Administer。启动这两个服务后,
到系统中去看,这两个Administer也起来了。
参考设置:
Parameter Value 说明
0 表 示 没 有 Inbound 消 息 , 这 样 就 不 要 求
Inbound Thread Count 0 Mail服务器支持IMAP4。如果要在邮件中
直接审批,需要设置为1。
Inbound Email Account
Server Name huajhua 邮件服务器
User Name wfmail 用户名
Password wfmail 密码
Outbound Email Account
Server Name huajhua 邮件服务器
User Name wfmail 用户名
Test Address test@huajhua 测试邮件和Reply-to Address不能相同
Send
Workflow Workflow Notification Mailer Configuration 84 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
Parameter Value 说明
Reply-to Address wfmail@huajhua
第7步是测试,一定要从LOV里面选一个角色,Oracle会按照这个角色的
“Notification Style”给前面设置的Test Address发一个通知,请记住ID号。
测试角色有两个要求:需要有emali地址(随意,如果和User和员工关联了,员工上需
要设置Mail)、mail类型的Notification Style。否则mail无法正确发到Test Address。
测试
用客户端收test@huajhua的信,看ID号就可以知道是第7步测试步骤发来的;最直接就
是在Imail的管理器里面看相应用户的邮箱是否有东西。
6. 常见问题
6.1. 问题记录
邮件失败ORA-20002: 2018
ORA-20002: 2018: Unable to generate the notification XML. Caused by: 2020: Error
when getting notification content。
原因可能是通知设置方式不对,比如把MAILHTM2设置成了HTMLMAIL。
错误信息没有正确显示,而是“原因: sqlerrm”
Note:313802.1。
配置保存在哪里
旧版保存在$FND_TOP/resource/wfmail.cfg,新版在哪里?
日志保存在哪里
启用调式模式
启动Debug后,所有邮件将发给Test Address!
Workflow 常见问题 86 of 90
File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only
Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010
Add open issues that you identify while writing or reviewing this document to the
open issues section. As you resolve issues, move them to the closed issues section
and keep the issue ID the same. Include an explanation of the resolution.
When this deliverable is complete, any open issues should be transferred to the
project- or process-level Risk and Issue Log (PJM.CR.040) and managed using a
project level Risk and Issue Form (PJM.CR.040). In addition, the open items should
remain in the open issues section of this deliverable, but flagged in the resolution
column as being transferred.
Open Issues
Closed Issues