Download as pdf or txt
Download as pdf or txt
You are on page 1of 90

Oraacle ERP最

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>

Copy Number _____


Oracle ERP最佳技术实践 Doc Ref: <Document Reference Number>
November 11, 2010

Document Control

Change Record
4

Date Author Version Change Reference

17-Apr-07 Jianhua.Huang Draft 1a No Previous Document

Reviewers

Name Position

Distribution

Copy No. Name Location

1 Library Master Project Library


2 Project Manager
3
4

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.

Workflow Document Control ii


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

Contents

Document Control ..................................................................................................................ii


1. Oracle Workflow基础............................................................................................... 2
1.1. 工作流概述 .......................................................................................................... 2
1.2. 必要设置 .............................................................................................................. 7
1.3. 先睹为快:一个简单例子.Start to End ............................................................ 8
1.4. 先睹为快:一个简单例子.Save to Database ................................................. 13
1.5. 先睹为快:一个简单例子.运行 ....................................................................... 14
2. 其他特性和功能实例 ............................................................................................... 18
2.1. 第2个例子:Notification ................................................................................. 18
2.2. 第3个例子:Lookup Types和分支处理Function ......................................... 25
2.3. 第4个例子:Loop、Timeout、Defer和Workflow Background Process .. 41
2.4. 第5个例子:Wait、Wait/Continue Process ................................................ 48
2.5. 第6个例子:Document、Forms、Function Result、隐藏标准按钮 ......... 55
3. 常用代码块 ............................................................................................................... 62
3.1. Startup ............................................................................................................... 62
3.2. Notification....................................................................................................... 63
3.3. Active节点和当前属性值................................................................................. 64
3.4. Retry和Skip ...................................................................................................... 65
3.5. Complete........................................................................................................... 66
3.6. 处理Defer .......................................................................................................... 66
3.7. 建立父子关系 .................................................................................................... 66
3.8. Document和Forms .......................................................................................... 67
3.9. Test工作流 ........................................................................................................ 69
3.10. Cancel/Abort工作流 ....................................................................................... 70
3.11. Purge工作流实例/定义 ................................................................................... 70
3.12. 最新n条Notification ........................................................................................ 71
3.13. 等待发送Mail的Notification ........................................................................... 71
3.14. Queue相关 ........................................................................................................ 71
3.15. 未完待续 ............................................................................................................ 72
4. 审批路径 ................................................................................................................... 73
4.1. 客户化表 ............................................................................................................ 73
4.2. 员工上下级 ........................................................................................................ 73
4.3. 职位层次 ............................................................................................................ 73
4.4. OAM/AME ...................................................................................................... 73
5. Workflow Notification Mailer Configuration..................................................... 78
5.1. Basic ................................................................................................................... 78
5.2. Database Layer................................................................................................. 79
5.3. Application Layer ............................................................................................ 80
Workflow Document Control iii
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
5.4. System Layer .................................................................................................... 81
5.5. Notification Mailer .......................................................................................... 82
5.6. 问题记录 ............................................................................................................ 86
6. Open and Closed Issues for this Deliverable ...................................................... 87
Open Issues..................................................................................................................... 87
Closed Issues .................................................................................................................. 87

Workflow Document Control iv


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. 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、 流程定义

Workflow Oracle Workflow基础 2 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
Workflow正如它的字面含义,其专注于“工作流”的定义,用Workflow将如下“活
动”组织成一个个业务蓝图,将是非常直观和容易的:基于PL/SQL的任何处理、基于
AQ的通知、关联流程的等待与启动、瓶颈节点的超时处理。

如果能够将企业业务科学的分解至合理的粒度——子流程,那么不同业务在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单据审批催函)

Workflow Oracle Workflow基础 3 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
模块 应用
应收模块(AR) AR贷项通知单请求审批、AR替代平衡段
PA项目审批工作流、PA预算工作流、PA逐级分配、PA生成项目供应商发票帐户、项目费用报表
项目会计(PA)
帐户生成器
资产模块(FA) FA帐户生成器
CST标准成本计算(WIP差异/WIP估价/保留款冲销/采购价格或产出率差异/库存估价/平均成本
成本模块(CST) 差异/入库检验/在途库存/帐户/制造费用分配/资源分配/组织间信用转让/组织间应付款/组织
间应收款/组织间运费)、CST平均成本计算
OPM产品开发(GMD) OPM质量控制检验测试、OPM质量控制验收样品、OPM质量控制样品创建通知
OPM库存(GMI) OPM批次失效及批次重新测试、激活项目
PJM项目计划例外通知、项目制造系统的项目定义(合同)、项目制造系统的项目定义(间接/资
项目模块(PJM)
本)
GHR等级内提升、GHR人事活动、GHR职位说明、HR任务流(HR聘用人员流程、HR任务流模
人力资源(HR)
板流程、HR职业管理流程)、履历管理复查、人力资源聘用信、人力资源自助应用产品
库存模块(INV) INV物料搬运单审批、库存销货成本帐户
采购模块(PO) PO创建单据、PO确认接收、PO申请审批、PO申请帐户生成器、PO审批、PO帐户生成器
订单管理(OM) OM订单题头、OM订单行
工程模块(ENG) ECO审批
车间模块(WIP) WIP发运和接收外协装配件、WIP更改PO需要日期
质量模块(QA) QA自助采购员通知、QA自助事务处理通知
计划模块(MRP) 计划例外消息
……

下面的SQL可以查当前系统中所有的工作流:

SELECT b.NAME, t.display_name, t.description


FROM wf_item_types b, wf_item_types_tl t
WHERE b.NAME = t.NAME
AND t.LANGUAGE = 'ZHS'
ORDER BY 1

具体实例

1、 GL日记帐审批流程

Workflow Oracle Workflow基础 4 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
2、 COGS销售成本帐户生成

公司 成本中心 会计科目 产品 备注

订单类型 销售员 物料 订单类型

3、 OM周期活动的控制

订单输入

预订

挑选发放

发货确认

库存接口 应收接口

完成

工作流的演进

R10.7 Flex Field builder 流程组织型

R11 Workflow 2.03 流程组织型

R11i Workflow 2.6 流程组织型 + 事件驱动型

Workflow的体系结构

简单的体系结构图:

Workflow Oracle Workflow基础 5 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

Email通知
Workflow
Loader
工作流引擎

工作流监控器

Workflow
Builder
内置通知
Notification
Mailer

应用服务器
Web 浏览器

Oracle 7.3.2 or higher

复杂的体系结构图:

A A
Directory Services
A

Users Roles
A A AQ
Workflow
Web
Builder
XML
Notification

Business Event Notificatio Workflow


Workflow
System n Services Engine
Builder
Web Send Send Execution
M it iAS
Receive Respond Definition
Workflow
Raise Forward Administration
Loader
Web Listen Cancel Monitoring
Analysis
Query Query Query
Workflow
Definition

Mail Files
Notificatio
Applications Oracle Workflow Enabled Application

Browser Application
Oracle server
Client Server

Workflow Oracle Workflow基础 6 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.2. 必要设置

下载

http://www.oracle.com/technology/software/products/workflow/index.html。

这里有Workflow Builder和独立版本的Workflow Server。

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中添加的路径移到最后

Workflow Oracle Workflow基础 7 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
如果要看httpd为何无法启动,查看Log是没用的;应该先运行CMD,然后cd到需要的目
录,输入apache.exe,这个时候就会有错误出现

2、Notification默认的配置是html email,这个时候易遇到Notification就报错,因为我们自己一般
没有配置Mail服务器,所以需要在Global Workflow Preferences里面把Send me electronic mail
notifications设置为Do not send me mail

3、开始我没有配好Business Event System,在执行Approve等动作的时候老是No Data Found;后


来我根据Error Stack找到wf_xml包,把里面的RemoveNotification的Raise语句注释掉就可以了。嘿
嘿,反正我是自己研究工作流,无所谓了

4、我的系统是XP Home SP1,没有JVM,无法View Diagram;装了JDK,不太好用,卸掉装


msjavx86.exe一切正常。

1.3. 先睹为快:一个简单例子.Start to End

新建一个WFT文件

N: Workflow Builder/File/New

在开发阶段Workflow源代码一般保存在本地,扩展名是wft。我们新建一个工作流文
件,然后保存,假定文件名为:CUX_WF_DEMO.wft。

新建一个Item Type

N: Workflow Builder/Edit/New/Item Type

Workflow Oracle Workflow基础 8 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

Item Type是个抽象的概念,为方便理解,可以看作就是一个工作流。

Internal Name相当于Code,在程序中经常用它来标志一个工作流;Display Name相


当于User Name。

引用标准Workflow

N: Workflow Builder/File/Open

我们选择从数据库打开,输入APPS用户名和密码及TNSNAME。找到Standard,点击
<<移入Visible区,OK打开。

Workflow Oracle Workflow基础 9 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

打开后把Standard这个Item Type拖到我们创建的文件下面。

然后赶紧关闭刚才打开的Standard工作流,以免误操作。N: Workflow
Builder/File/Close Store,在弹出的保存确认界面选择No。

*顺便看下,本地Workflow文件的图标和从数据打开的不一样。

*实际开发中,我们有必要再建立一个自己的Standard。

以后在我们的工作流中就可以很方便的使用一些标准的工作流对象了。现在结果如
下:

Workflow Oracle Workflow基础 10 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
创建一个Top Process

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:

双击Demo Top Process,可以看到,里面什么都没有。需要加入一些元素。

从下面的Standard下的Function中,把Start和End拖到打开的Demo Top Process中,


结果如下:

Workflow Oracle Workflow基础 11 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

这个时候,要在这里修改一下属性。选中Start节点,右键,选择Property,把
Start/End从Normal改为Start:

同样,把End节点的Start/End从Normal改为End。

然后,右键Start节点,不要放开鼠标,拖到End节点,这样就把这两个点连起来了。

这样,一个最简单的工作流就做好了。结果如下:

Workflow Oracle Workflow基础 12 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.4. 先睹为快:一个简单例子.Save to Database

方式一:直接通过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

WFLOAD apps/apps 0 Y UPLOAD $CUX_TOP/install/CUX_WF_DEMO.wft

Workflow Oracle Workflow基础 13 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
如果有问题,可以查看.log文件。

方式三:请求Workflow Definitions Loader

N: System Administrator/View/Request/Submit

首先用FTP工具把CUX_WF_DEMO.wft上传到应用服务器,同上。

然后到系统管理员职责提交请求:

嘿嘿,Mode选Upload,File要写绝对路径,上面的画面用环境变量是有问题的哦!
Item Type放空。

上线安装的时候用这种模式。

1.5. 先睹为快:一个简单例子.运行

方式一:Workflow管理界面

N: System Administrator/Workflow/Administrator Workflow/Home

Workflow Oracle Workflow基础 14 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

实际上可以从很多地方进,而且不同版本不一样。这里是11.5.9以上的版本,之前的版
本直接就有Find Process菜单。

切换到“Developer Studio”Tab页,输入查询条件,这里输入Internal Name:


CUX_DEMO,查询结果如下:

注意,只有Workflow的管理员用户进来后面才有Run列!

SELECT wfr.text FROM wf_resources wfr WHERE NAME = 'WF_ADMIN_ROLE'


AND wfr.LANGUAGE = 'US'可以查看当前的Workflow管理员,用其登陆EBS即可。
*代表所有人。

也可以从上面的画面的“Administrator”Tab页查看和设置。

接下来,点击 ,出来:

Workflow Oracle Workflow基础 15 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

按照上图内容输入。Item Key是本工作流运行实例的标志;相对的保存在数据库中
Item Type可理解为一个定义或者一个Template。User Key是用户看到的实例标志。

点击Run Workflow。

运行情况查看

N: System Administrator/Workflow/Administrator Workflow/Home

选择“Status Monitor”Tab页。输入查询条件查询,出来刚才运行的CUX_DEMO实
例:

点击Status Diagram,可以看到,由于例子太简单已经运行到终点,且都是“绿
线”,说明没有错误:

Workflow Oracle Workflow基础 16 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

方式二: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页查看了。

Workflow Oracle Workflow基础 17 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

2. 其他特性和功能实例

上面的例子虽然极其简单,但演示了整个过程,至少可以初学者迈出第一步;接下来
我们看看一些其他重要的功能,至于基本操作,就不再详细说明了。

2.1. 第2个例子:Notification

准备

N: Copy and Paste

我们把上面的例子中的WF_DEMO这个Item Type拷贝一份;新的Internal Name为


WF_0002。

新建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,用来保存提交者和审批者的信息。

Internal Name Display Name Type Length


APPROVER_ID Approver ID Number
APPROVER_NAME Approver Name Role
APPROVER_DSP_NAME Approver Display Name Text 360
SUBMITER_ID Submiter ID Number
SUBMITER_NAME Submiter Name Role
SUBMITER_DSP_NAME Submiter Display Name Text 360

Tips: Attribute相当于全局变量,供整个Item Type里面的元素使用,可以作为Message的


附加属性,Send给用户看或者存储用户的Response内容比如Note和Forward To;
Attribute另一个常用的地方是作为Notification的Performer。当然我们的PL/SQL代码是
离不开Attribute,几乎任何PL/SQL函数都需要通过取得Attribute变量--判断Attribute变
量--设置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

Internal Name Display Name Text Body


Just for testing.
APPROVAL_REQ Approval Requisition
Message from &SUBMITER_DSP_NAME

注意上面对变量的引用方式;实际上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

Internal Name Display Name Message


REQ_APPROVAL Requisition Approval Approval Requisition

修改CUX_TOP

N: 把上面建的Notification拖到CUX_TOP(Demo Top Process)中。

这个时候,再右键这里的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。为使测试顺利,我验
证了一下:

SELECT r.NAME, r.display_name, r.orig_system, r.orig_system_id


FROM wf_roles r
WHERE r.NAME = 'HUAJHUA';

结果是:HUAJHUA Jianhua, Huang PER 6987

说明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_submiter_id NUMBER := 6987;


l_approver_id NUMBER := 6987;
l_orig_system VARCHAR2(30) := 'PER';

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);

wf_engine.setitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'SUBMITER_ID',
avalue => l_submiter_id);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'SUBMITER_NAME',
avalue => l_user_name);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'SUBMITER_DSP_NAME',
avalue => l_display_name);

wf_directory.getusername(p_orig_system => l_orig_system,


p_orig_system_id => l_approver_id,
p_name => l_user_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);

wf_engine.setitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'APPROVER_ID',
avalue => l_approver_id);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'APPROVER_NAME',
avalue => l_user_name);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'APPROVER_DSP_NAME',
avalue => 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。

2.2. 第3个例子:Lookup Types和分支处理Function

准备

N: Copy and Paste

我们把上面的例子中的CUX_0002这个Item Type拷贝一份;新的Internal Name为


CUX_0003。

新建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,用来代表审批者的审批选项。

Type Internal Name Display Name


Lookup Types CUX_APPROVAL Approved or Rejected result
Lookup Codes CANCEL Cancel

新建2个Item Type级别的Attribute

N:

Internal Name Display Name Type Length


NOTE Note Text 480
DOCUMENT_ID Document ID Number
DOCUMENT_NUMBER Document Number Text 30
DOCUMENT_AMOUNT Document Amount Number

修改Message的属性

N:

首先把上面新建的Attribute统统拉下来;其中关键要改一下 Note属性的Source为
Response,这个用来保留审批者输入的备注信息。

接下来,在Message Approval Requisition属性的Result标签页,增加上面新建的


Lookup Type

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

内容如下

Display Name Lookup Type Default Value


Approval Action Demo Approval Approve

再修改Subject为:

Document : &DOCUMENT_NUMBER Requires Your Approval

修改Text Body,内容为:

Please Approve The Following Document.

From &SUBMITER_DSP_NAME

Document Number: &DOCUMENT_NUMBER

Document Amount: &DOCUMENT_AMOUNT

修改HTML Body,内容为:

Your Note: &NOTE

Please Approve The Following Document.

<br>

From &SUBMITER_DSP_NAME

<br>

Document Number: &DOCUMENT_NUMBER

<br>

Document Amount: &DOCUMENT_AMOUNT

&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:

在Notification Requisition Approval属性的Activity标签页,补充Result Type为Demo


Approval。

修改Process的流程

N: 双击Demo Top Process打开

再从Standard中拖两个End Function过来,并从Requisition Approval拉线过来,最终


结果如下(别忘了,修改他们的Start/End属性为End)。

现在测试

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的参数是固定的,不能多也不能少;而且里面的代码块基本上也是相同的。

代码如下:

CREATE OR REPLACE PACKAGE cux_wf_demo_pkg AUTHID CURRENT_USER AS

--初始化代码
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;

CREATE OR REPLACE PACKAGE BODY cux_wf_demo_pkg AS

--取得下一个审批者,可以通过各种方式取得
--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_orig_system wf_roles.orig_system%TYPE := 'PER';

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

IF (funcmode <> wf_engine.eng_run) THEN

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);

wf_engine.setitemattrtext(itemtype => itemtype,


itemkey => itemkey,
aname => 'SUBMITER_NAME',
avalue => l_submiter_user_name);

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);

wf_engine.setitemattrtext(itemtype => itemtype,


itemkey => itemkey,
aname => 'DOCUMENT_AMOUNT',
avalue => l_document_amount);

--获得审批者
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);

wf_engine.setitemattrtext(itemtype => itemtype,


itemkey => itemkey,
aname => 'APPROVER_NAME',
avalue => l_approver_user_name);

wf_engine.setitemattrtext(itemtype => itemtype,


itemkey => itemkey,
aname => 'APPROVER_DSP_NAME',
avalue => l_approver_display_name);

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

WHEN OTHERS THEN

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

IF (funcmode <> wf_engine.eng_run) THEN

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

WHEN OTHERS THEN

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

IF (funcmode <> wf_engine.eng_run) THEN

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

WHEN OTHERS THEN

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

IF (funcmode <> wf_engine.eng_run) THEN

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

WHEN OTHERS THEN

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

具体设置如下:

Internal Name Display Name Function Name


INITIALIZE Initialize cux_wf_demo_pkg.initialize
DOC_APPROVE Document Approved cux_wf_demo_pkg.approve_result
DOC_CANCEL Document Cancelled cux_wf_demo_pkg.cancel_result
DOC_REJECT Document Rejected cux_wf_demo_pkg.reject_result

第一个Function相当于我们例子2种的初始化作用,后面3个Function分别对应审批者
的3种审批结果。

修改Process的流程

N: 双击Demo Top 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,我做这个文档的时候是在不同环境做的。

SELECT r.NAME, r.display_name, r.orig_system, r.orig_system_id


FROM wf_roles r
WHERE r.NAME = 'HUAJHUA';

结果是:HUAJHUA Jianhua, Huang PER 6987

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;

INSERT INTO cux_wf_demo_documents


(document_id,
document_number,
document_amount,
authorization_status,

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);

wf_engine.setitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'SUBMITER_ID',
avalue => l_submiter_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

Note输入:OK, I agree it.

点击Approve按钮

测试:验证表数据

N:

SELECT *
FROM cux_wf_demo_documents doc
WHERE doc.document_number = DOC00000006;

结果如下:

6 DOC00000006 30644.58 APPROVED 6987 6987 OK, I agree it

测试:看工作流程图

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

2.3. 第4个例子:Loop、Timeout、Defer和Workflow Background Process

准备:建立一个新的Standard Item Type

N:

这个工作在这里做有点晚了:建立自己的标准Item Type。内容如下:

Internal Name Display Name


CUX_STDD Oracle EBS 11i Workflow Standard

同时把例子3中的Lookup Type拖到CUX_STDD中(不要按CTRL)。

准备:拷贝CUX_0003成CUX_0004

N: Copy/Paste

我们把上面的例子中的CUX_0003这个Item Type拷贝一份;新的Internal Name为


CUX_0004。

修改Notification: Requisition Approval的Timeout属性

N: Copy/Paste

查看Process中Requisition Approval的属性,并设置Timeout属性,这里设置1分钟是
为了方便测试。

超时一般是针对Notification的,意思是多长时间之后不处理该消息就算超时,超时也
是一种返回结果。

增加一个标准Function: Loop Counter

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。

增加一个标准Function: Defer Thread

N:

从Standard中把Defer Thread拖过来,不用设置属性,不过可以注意一下Function是
WF_STANDARD.DEFER,我们也可以新建这样的Defer Function。实际上,标准功
能中的大部分Item,我们都可以参照着自己创建。

Defer的意思相当于Pause,意思是工作流到这个地方暂停,需要外力(可用程序、可
用下面讲的请求)来推动。

增加一个标准Function: End

N:

注意,这次比较特殊,不设置其Start/End属性为End,而是保留默认的Normal。

重新调整Demo Top Process

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,我做这个文档的时候是在不同环境做的。

SELECT r.NAME, r.display_name, r.orig_system, r.orig_system_id


FROM wf_roles r
WHERE r.NAME = 'HUAJHUA';

结果是:HUAJHUA Jianhua, Huang PER 6187

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;

INSERT INTO cux_wf_demo_documents


(document_id,
document_number,
document_amount,
authorization_status,
submiter_id)
VALUES

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);

wf_engine.setitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'SUBMITER_ID',
avalue => l_submiter_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

结果如下:

104156 CUX_0004 HUAJHUA OPEN Document : DOC00000022 Requires Your


Approval 2005-12-13 9:47:34 (空)

说明目前只有一条消息,并且是Open的,注意due_date。

用Huajhua登录上去看Notification,确实有一条:

测试:运行Workflow Background Process处理Timeout

N: System Administrator职责

不要审批,一分钟之后该通知会超时,但状态还是Open的,其实还可以审批。

这个时候到系统管理员职责提交Workflow Background Process,参数如下:

处理Timeout类型活动。运行完再到数据库查询,结果如下:

104157 CUX_0004 HUAJHUA OPEN Document : DOC00000022 Requires Your


Approval 2005-12-13 9:54:10

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。

测试:运行Workflow Background Process处理Defer

N: System Administrator职责

这个时候到系统管理员职责提交Workflow Background Process,参数如下:

注意上面参数变化。再去看运行状态图:

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的属性。

测试:运行Workflow Background Process处理Stuck

N: System Administrator职责

这个时候到系统管理员职责提交Workflow Background Process,参数如下:

注意上面参数变化。结果如下:

下面的处理可以是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

2.4. 第5个例子:Wait、Wait/Continue Process

准备:拷贝CUX_0004成CUX_0005

N: Copy/Paste

我们把上面的例子中的CUX_0004这个Item Type拷贝一份;新的Internal Name为


CUX_0005。

添加Function:Wait

N: 从Standard中拖到Demo Top Process

设置属性如下:

Wait Mode: Relative Time

Relative Time: 0.0007,这个单位是天,所以0.0007相当于1分钟。

布局如下:

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

Relative Time: 0.0007,这个单位是天,所以0.0007相当于1分钟。

Wait的节点如果超时了,用Workflow Background Process的Defer=Yes来处理。测试


略。

添加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:

添加Wait For Flow节点。

着重看下Wait For Flow

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';

l_submiter_id NUMBER := 6187;


l_document_id NUMBER;
BEGIN

--00 业务数据录入
SELECT cux_wf_demo_documents_s.NEXTVAL INTO l_document_id FROM dual;

INSERT INTO cux_wf_demo_documents


(document_id,
document_number,
document_amount,
authorization_status,
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');

l_child_item_key := 'CHILD' || l_document_id;


l_child_user_item_key := l_user_item_key;

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);

wf_engine.createprocess(itemtype => l_child_item_type,


itemkey => l_child_item_key,
process => l_child_process,
user_key => l_child_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);

wf_engine.setitemattrnumber(itemtype => l_item_type,


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:

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

可以看到,停在了Wait For Flow节点。

测试:看下子工作流状态图

N:

停在我们安排的Defer Thread。

测试:运行Workflow Background Process处理Defer

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

已经自动过了Wait For Flow节点。

测试:再看下子工作流状态图

N:

已经结束。

2.5. 第6个例子:Document、Forms、Function Result、隐藏标准按钮

准备:拷贝CUX_0005成CUX_0006

N: Copy/Paste

我们把上面的例子中的CUX_0005这个Item Type拷贝一份;新的Internal Name为


CUX_0006。

添加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

修改Message: Approval Requisition

N:

首先把Document Details和Open Document拉过来。

其次添加两个Attribute:

#HIDE_REASSIGN,可以隐藏标准的Reassign按钮

#HIDE_MOREINFO,可以隐藏标准的Request Information按钮

最后修改Message的Text Body和Html Body,加入:

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

IF (funcmode <> wf_engine.eng_run) THEN

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);

resultout := wf_engine.eng_completed || ':' || 'Y';

EXCEPTION

WHEN OTHERS THEN

resultout := wf_engine.eng_completed || ':' || 'N';

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;

l_document VARCHAR2(32000) := '';


l_clob_document CLOB;

BEGIN

l_item_type := substr(document_id, 1, instr(document_id, ':') - 1);


l_item_key := substr(document_id,
instr(document_id, ':') + 1,
length(document_id) - 2);

l_document_id := wf_engine.getitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'DOCUMENT_ID');

l_org_id := wf_engine.getitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'ORG_ID');

fnd_client_info.set_org_context(to_char(l_org_id));

l_document := '<table border=1><tr><td>This table shows the details of the


document. You can put anything here.</td></tr></table>';

--方法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';

l_submiter_id NUMBER := 6187;


l_document_id NUMBER;
BEGIN

--00 业务数据录入
SELECT cux_wf_demo_documents_s.NEXTVAL INTO l_document_id FROM dual;

INSERT INTO cux_wf_demo_documents


Workflow 其他特性和功能实例 59 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_id,
document_number,
document_amount,
authorization_status,
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');

l_child_item_key := 'CHILD' || l_document_id;


l_child_user_item_key := l_user_item_key;

wf_engine.createprocess(itemtype => l_item_type,


itemkey => l_item_key,
process => l_process,
user_key => l_user_item_key);

wf_engine.createprocess(itemtype => l_child_item_type,


itemkey => l_child_item_key,
process => l_child_process,
user_key => l_child_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);

wf_engine.setitemattrnumber(itemtype => l_item_type,

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:

/*SELECT r.NAME, r.display_name, r.orig_system, r.orig_system_id


FROM wf_roles r
WHERE r.NAME = 'HUAJHUA';*/
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_submiter_id NUMBER := 6987;


l_approver_id NUMBER := 6987;
l_orig_system VARCHAR2(30) := 'PER';

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);

wf_engine.setitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'SUBMITER_ID',
avalue => l_submiter_id);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,

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);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'SUBMITER_DSP_NAME',
avalue => l_display_name);

wf_directory.getusername(p_orig_system => l_orig_system,


p_orig_system_id => l_approver_id,
p_name => l_user_name,
p_display_name => l_display_name);

wf_engine.setitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'APPROVER_ID',
avalue => l_approver_id);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'APPROVER_NAME',
avalue => l_user_name);

wf_engine.setitemattrtext(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'APPROVER_DSP_NAME',
avalue => l_display_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

代码实例

相当于Workflow Background Process(wf_engine.BackgroundConcurrent)的功


能。

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

IF (funcmode <> wf_engine.eng_run) THEN

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);

resultout := wf_engine.eng_completed || ':' || 'Y';

EXCEPTION

WHEN OTHERS THEN

resultout := wf_engine.eng_completed || ':' || 'N';

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;

l_document VARCHAR2(32000) := '';


l_clob_document CLOB;

BEGIN

l_item_type := substr(document_id, 1, instr(document_id, ':') - 1);


l_item_key := substr(document_id,
instr(document_id, ':') + 1,
length(document_id) - 2);

l_document_id := wf_engine.getitemattrnumber(itemtype => l_item_type,

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');

l_org_id := wf_engine.getitemattrnumber(itemtype => l_item_type,


itemkey => l_item_key,
aname => 'ORG_ID');

fnd_client_info.set_org_context(to_char(l_org_id));

l_document := '<table border=1><tr><td>This table shows the details of the


document. You can put anything here.</td></tr></table>';

--方法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';

-- Call the procedure


oe_reprice_wf.start_repricing(itemtype => 'OEOL',
itemkey => 2558365,
actid => l_actid,
funcmode => 'RUN',
resultout => x_resultout);

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天后自动删除。

如果item type的Persistence 设置为Permanent时,需要调用WF_PURGE.TotalPerm。

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

代码实例

SELECT notification_id, status, mail_status, begin_date


FROM wf_notifications
WHERE status = 'OPEN'
AND mail_status = 'MAIL'

注意:status = 'SENT'的记录说明已经成功发送。

外发Mail通常在如下Queue中:

SELECT *
FROM wf_notification_out wno
WHERE wno.state = 0
AND wno.corrid LIKE 'APPS%'

3.14. Queue相关

Queue的有效性

SELECT owner, object_name, object_type, status


FROM dba_objects
WHERE object_name LIKE 'WF_%'
AND object_type = 'QUEUE';

如果有使用的Queue处于无效状态,请依照Metalink 275571.1处理。

Queue的订阅Rule

SELECT rule_name, to_char(rule_condition) rule_condition


FROM dba_rules
WHERE rule_name LIKE 'WF%'

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

说明

使用Oracle Approval Manager来定义审批权限和审批路径。具体看


AME_Dev_guide.pdf和AME_Imp_guide.pdf。这里提供一个简单实例。

创建客户化表和对象

N:

drop table CUX_AME_TEST_HEADERS_ALL;


create table CUX_AME_TEST_HEADERS_ALL
(
HEADER_ID NUMBER not null,
AMOUNT NUMBER not null,
LAST_UPDATED_BY NUMBER not null,
APPROVAL_STATUS varchar2(30) not null
);
Workflow 审批路径 73 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

drop table CUX_AME_TEST_LINES_ALL;


create table CUX_AME_TEST_LINES_ALL
(
HEADER_ID NUMBER,
LINE_ID NUMBER,
AMOUNT NUMBER not null
);

DROP sequence CUX_AME_TEST_HEADERS_S;


create sequence CUX_AME_TEST_HEADERS_S;

DROP sequence CUX_AME_TEST_LINES_S;


create sequence CUX_AME_TEST_LINES_S;

插入业务数据

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';

INSERT INTO cux_ame_test_headers_all VALUES l_header_rec;

SELECT cux_ame_test_lines_s.NEXTVAL INTO l_line_rec.line_id FROM dual;


l_line_rec.header_id := l_header_rec.header_id;
l_line_rec.amount := 123000;
INSERT INTO cux_ame_test_lines_all VALUES l_line_rec;

SELECT cux_ame_test_lines_s.NEXTVAL INTO l_line_rec.line_id FROM dual;


l_line_rec.amount := 456;
INSERT INTO cux_ame_test_lines_all VALUES l_line_rec;

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

N:AME Application Administrator职责

名字:CUX_AME_TEST_DESC

参数:

Line-Item-ID Query String

SELECT to_char(line_id)
FROM cux_ame_test_lines_all
WHERE header_id = :transactionid
ORDER BY line_id

增加标准Attribute到客户化Transaction Type

N:AME Application Administrator职责

增加标准Attribute:OW_EMPTY_APPROVAL_GROUPS

增加自定义Attribute到客户化Transaction Type

N:AME Application Administrator职责

名字:CUX_AME_TEST_AMOUNT

参数:

动态Usage

SELECT amount
FROM cux_ame_test_headers_all
WHERE header_id = :transactionId

增加自定义Group

N:AME Application Administrator职责

名字:Approval Group Static

并添加User类型的Member若干

增加自定义Condition

N:AME Application Administrator职责

条件:0 <= CUX_AME_TEST_AMOUNT <= 10000

增加自定义Rule

N:AME Application Administrator职责

名字:CUX AME Test Rule

参数:

Approval选Require approval from Approval Group Static


Workflow 审批路径 75 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:数据库

以下脚本实际上可以用在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';

INSERT INTO cux_ame_test_headers_all VALUES l_header_rec;

SELECT cux_ame_test_lines_s.NEXTVAL INTO l_line_rec.line_id FROM dual;


l_line_rec.header_id := l_header_rec.header_id;
l_line_rec.amount := 123000;
INSERT INTO cux_ame_test_lines_all VALUES l_line_rec;

SELECT cux_ame_test_lines_s.NEXTVAL INTO l_line_rec.line_id FROM dual;


l_line_rec.amount := 456;
INSERT INTO cux_ame_test_lines_all VALUES l_line_rec;

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);

EXIT WHEN l_next_approver.user_id IS NULL; --测试用的Group是基于User的

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);

IF l_result = 'APPROVED' THEN


ame_api.updateapprovalstatus2(applicationidin => l_app_id,
transactionidin => l_header_id,
approvalstatusin => ame_util.approvedstatus,
approverpersonidin => NULL,
approveruseridin => l_next_approver.user_id,
transactiontypein => l_transaction_type);

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。举几个例子:

Type of Role Orig_System User_Flag


ERP用户,未和HR中的员工建立关联 FND_USR Y
ERP用户,和HR中的员工建立关联 PER Y
不是ERP用户,而是HR中的员工 PER_ROLE N
客户/员工 HZ_PARTY Y
直接插入WF_LOCAL_USERS的记录 WF_LOCAL_USERS Y
直接插入WF_LOCAL_ROLES的记录 WF_LOCAL_ROLES N
职责 FND_RESP<ID> N
职位Position POS N

更详细的说明请看Oracle Workflow Administrator's Guide。

所以,总的来说,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

5.2. Database Layer

Table Partition

随着业务的增长和历史数据的增多,有几个工作流的表会越来越大,如果不进行分
区,其性能(DML和Export/Import)是比较糟糕的。默认情况下,只有目录服务的
几个表是按来源分区过的;其他的表,需要运

Workflow Workflow Notification Mailer Configuration 79 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
行%FND_TOP%/admin/sql/wfupartb.sql来分区。值得一提的是,wfupartb.sql本身
是学习Oracle Partition的最好材料。我的11.5.10没有打补丁,wfupartb.sql是空的;我
是从客户那里看wfupartb.sql的,它们是11.5.9。

需要分区的表和索引为:目录服务表、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

5.3. Application Layer

Directory Service

在System Administrator下,跑Synchronize Workflow LOCAL tables即可。该请求集


建议计划运行。

如果我们加了个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

Workflow Background Process请求用来处理Timeout、Defer、Stuck的工作流;通常


情况下我们需要分别为处理超时、阻塞、挂起各Schedule一个Workflow Background
Process。

如果我们Schedule了该请求,但有时候等不及,也可手工提交;下面的例子是最常见
的处理销售订单行Defer的请求:

Workflow Workflow Notification Mailer Configuration 80 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

5.4. System Layer

Global Preferences

定义Workflow全局参数。仅需关注两个参数。

Workflow System Administrator默认是sysadmin,说明只有sysadmin可以查看、管


理任何workflow和实例;*表示任何人都可以。

Notification Style,默认是Do not send me mail,说明通知只能通过登录EBS后查看,


不能通过Email。

N: SYS/Workflow/Global Preferences

参考SQL: SELECT * FROM wf_resources WHERE NAME = 'WF_ADMIN_ROLE'。

Parameter Value
Workflow Administrator *

Workflow Workflow Notification Mailer Configuration 81 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
1、 MAILTEXT/Plain text mail,纯文本邮件,没有附件
2、 MAILHTML/HTML mail with attachments,HTML邮件,
有个链接到Notification Details页面的附件
3、 MAILHTM2/HTML mail,HTML邮件,没有附件
4、 MAILATTH/Plain text mail with HTML attachments,纯
文本邮件,有个链接到Notification Details页面的附件,还
有个HTML格式的通知作为附件
Notification Style
5、 SUMMARY/ Plain text summary mail,纯文本邮件,所有
Open状态的通知的汇总
6、 SUMHTML/ HTML summary mail , HTML 邮 件 , 并 有
Link
7、 QUERY/ Do not send me mail,不会发邮件
8、 DISABLED/ Disabled,当要发邮件给没有设置邮件地址的
用户,Workflow会自动设置该用户的Style为Disabled

WF_RESOUCE环境变量

WF_RESOURCE环境变量用于存储指向Workflow资源文件,EBS的资源文件
为%FND_TOP%/%APPLRSC%/wf<language>.res,不需要设置该变量。

5.5. Notification Mailer


目前,Oracle Workflow支持SMTP协议(默认端口是25)处理出站消息、IMAP4协议
(默认端口是143)处理进站消息,这也是Oracle Workflow对Mail服务器的要求。可
以使用Microsoft Exchange作为Mail服务器,简单点,我们使用Imail。

IMAP4是Oracle Workflow Server对Mail Server的要求,对于用户,其客户端可以使


用不支持IMAP4的Foxmail。

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职责:

2. Navigate to Workflow Manager

Workflow Workflow Notification Mailer Configuration 82 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. 进入Service Components管理界面

启动两个Container服务

从Container选择Workflow Mailer Service,进入该容器服务控制界面。然后先后启动


Workflow Mailer Service和Workflow Agent Listener Service。

* 这两个玩意儿其实是Concurrent Manager的两个Administer。启动这两个服务后,
到系统中去看,这两个Administer也起来了。

回到Service Components管理界面,发现需要的服务只有Workflow Notification


Mailer由于没有配置过而没有起来。

Workflow Workflow Notification Mailer Configuration 83 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

配置Workflow Notification Mailer

选择Workflow Notification Mailer,点击下面的Edit按钮,有8个步骤,跳过1、5、


6。

参考设置:

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。

第8步完成后,回到Service Components管理界面,发现Workflow Notification


Mailer也起来了。

Test Address: 如果设置了,所有外发邮件均发到该地址!!.9环境

测试

用客户端收test@huajhua的信,看ID号就可以知道是第7步测试步骤发来的;最直接就
是在Imail的管理器里面看相应用户的邮箱是否有东西。

Workflow Workflow Notification Mailer Configuration 85 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

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。

1. Go the the directory $FND_TOP/patch/115/sql and make a copy of file


wfmlrb.pls (back it up)
2. Edit the file and change
wf_core.token('ERROR','sqlerrm');
to
wf_core.token('ERROR',sqlerrm);
Note: Remove the quotes around sqlerrm; there are two places in the file where the
change is required.
3. Save the file and recompile the object as follows:
sqlplus APPS/<passwd> @wfmlrb.pls
4. Reproduce the problem and check the error again.

配置保存在哪里

旧版保存在$FND_TOP/resource/wfmail.cfg,新版在哪里?

SELECT * FROM wf_mailer_parameters

SELECT * FROM fnd_user_preferences

日志保存在哪里

$APPLCSF/log and check the latest WFMAILER<n>.txt

启用调式模式

启动Debug后,所有邮件将发给Test Address!

Workflow Manager/Notification Mailer/Workflow Mailer'

点击View Status,点击Set Debug On

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

7. Open and Closed Issues for this Deliverable

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

ID Issue Resolution Responsibility Target Date Impact


Date

Closed Issues

ID Issue Resolution Responsibility Target Date Impact


Date

Workflow Open and Closed Issues for this Deliverable 87 of 90


File Ref: 深入浅出Oracle EBS之Workflow实例详解.docx (v. DRAFT 1A )
Company Confidential - For internal use only

You might also like