EBS FORM开发全过程
基于EBS的FORM开发全过程(1)
FORM开发过程化中使用的用户和工具
区分三类用户:
1、 OS用户:包括超级用户root,应用OS用户如applprod,数据库OS用户如oraprod。后两个用户具体由dba安装环境时创建,名字不定。
2、 数据库用户:包括内置管理用户sys、system,EBS用户apps,EBS各模块用户applsys、gl、inv、po、ar、ap等等,EBS网关用户applsyspub。
3、 EBS用户:也叫OA用户、应用用户、ERP用户,包括默认超级用户sysadmin,其他内置用户,企业实施、使用过程中创建的用户。
Form开发使用的用户和工具:
1、 应用OS用户:用telnet工具如putty登录服务器,获得各$XXX_TOP的具体路径、编译form和pll;用FTP如Filezilla连接服务器,下载必要文件、上传开发的form
步骤:
1.使用putty登录到服务器,使用ROOT账号登录成功之后,切换到ORACLE
#su - oracle
2.进入文件夹之后查看目录
$cd $***_TOP/forms/ZHS
3.获得具体路径
$pwd
4.使用Filezilla新建站点,输入主机号,用户,密码,端口默认为空,协议选择SFTP模式,登录类型选择正常
5.登录成功之后选择步骤3获得的路径进行下载和上传
2、数据库用户:包括内置管理用户sys、system,EBS用户apps,EBS各模块用户applsys、gl、inv、po、ar、ap等等,EBS网关用户applsyspub。
3、EBS用户:也叫OA用户、应用用户、ERP用户,包括默认超级用户sysadmin,其他内置用户(参见《深入浅出Oracle EBS之安全机制探索》),企业实施、使用过程中创建的用户。
AOL开发框架:EBS功能安全性基本原理
为了方便管理,分类维护,EBS在"用户"和"Forms"之间加了几个层次。考察如下过程:
1、 "用户"如sysadmin登录,系统验证其用户名/密码
2、 如果OK,系统列出其拥有的所有角色,在EBS中叫"职责"(Responsibility),而每个职责,都对应一个定义好的"菜单"
3、 当用户选择相应的职责进入"Navigator"后,显示的就是此菜单的内容
4、 每个底层菜单项,还不是直接对应Forms,而是先对应一个"功能(Function),由功能再去对应一个具体的"Forms"。这里的好处是,在功能上可以定义参数比如查询条件、控制码等,然后传递给Forms,当然大部分情况是不定义参数,所以功能和Forms基本上是一一对应关系
5、 用户点击菜单项,到定义Forms时指定的应用的TOP下,找到"fmx文件"执行之
所以,反过来,如果我们开发好一个Forms,要在EBS中跑起来,完整的过程就是为该"Forms"定义"功能",定义"菜单"调用该功能,定义"职责"使用该菜单,最后把职责分配给"用户"等一系列无Coding的定义工作。
Template.fmb
专业的软件系统,其操作方式、界面风格总是非常统一,即便是后来收购集成进来的模块,经过调整优化后,风格也基本一致。那么如何才能做到统一呢?一是依赖于规范文档,大家老老实实照标准开发;二是采用更加直接有效的办法--模版。
Oracle EBS的Forms,基本上都是从Template.fmb开始,该模版预先定义了:
1、 各种界面元素的属性集--子类
2、 常用的控件--日历、进度条
3、 一系列Form级触发器,统一处理各种未被明确处理的事件
4、 丰富的PLL库函数,大大超越了Forms Builder内置的函数
所以,我们基于EBS的开发,当然也是从Template.fmb开始
EBS文件系统

上面<应用简称>,如INV、GL、AP、AR等等,在System Administrator职责下的Application/Register中定义
通常各个企业都会创建一个客户化应用来管理二次开发的所有代码和设置,比如CUX、HAND等,下面以CUX(客户化的意思)为例。
总之我们需要的模版及相关文件在AU_TOP下;我们开发的fmb文件呢,也应根据上述规则传到
AU_TOP/forms的相关语言路径下,不过为管理、备份方便,实际开发中可能故意违反EBS的规则,
与fmx一起放在CUX_TOP/forms的相关语言路径下。
基于EBS的Forms开发过程
FORM 文件类型
.fmb:源文件,目前是二进制格式,也可以转成早期版本的ASCII格式
.fmx:可执行文件,类似VB的.exe文件,其也需要在Forms Runtime环境中运行
.pll:库函数源文件,类似所有开发语言的库函数,如VC的.cpp文件
.plx:库函数可执行文件
调用关系:fmb文件可以引用其他fmb文件、pll文件,pll文件可以进一步引用其他pll文件,引用是可以嵌套的。所以要成功打开一个forms源文件,必须保证其直接引用、间接引用的fmb、pll文件均存在。
怎样才叫"存在"呢?类似各种语言如C的Include Path或Java的Class Path,Forms也有一个参数--注册表FORMS60_PATH来指示引用的路径,只要需要的文件在该路径下即可。
配置TNSNAME
从DBA或他人索要SQLNET.ORA和TNSNAMES.ORA,直接覆盖到安装目录的NET80\ADMIN下。
SQLNET.ORA是Oracle SQL*Net协议配置文件,样例如下:
SQLNET.AUTHENTICATION_SERVICES= NONE
NAMES.DIRECTORY_PATH= (TNSNAMES, ONAMES, HOSTNAME)
SQLNET.EXPIRE_TIME=1
TNSNAMES.ORA是Oracle SQL*Net数据库服务解析文件,样例如下:
PROD=
(DESCRIPTION=
(ADDRESS=(PROTOCOL=tcp)(HOST=HUAJHUA.leiko.com)(PORT=1521))
(CONNECT_DATA=
(SERVICE_NAME=PROD)
(INSTANCE_NAME=PROD)
)
)
配置NLS_LANG
修改注册表:Local Machine/Software/Oracle/NLS_LANG

配置FORMS60_PATH
基于EBS的Forms开发,需要从服务器上下载必要的fmb和pll文件到本地,比如两类文件都放在d:\oracle\resource,那么需要添加注册表的字符串值FORMS60_PATH,类似C语言的Include Directory或者Java的Class Path:

配置FORMS_PATH
在注册表的ORACLE_HOME下 编辑字符串 FORMS_PATH 值为引用资源的路径,例如:
E:\DevSuiteHome_1\cgenf61\admin;E:\DevSuiteHome_1\forms;D:\form;D:\form\files

路径下放pll和fmb(引用的)文件,将文件全部放在这个目录下。
文件分别在服务器$AU_TOP/resource目录下AU_TOP/forms/US 目录下获取。
注意:E:\DevSuiteHome_1\cgenf61\admin;E:\DevSuiteHome_1\forms; 这部分是自带的内容,不要删掉。
创建数据库对象
要求:表、序列、索引建在应用数据库用户下,表放在数据表空间中,索引放在索引表空间中;视图、包建在APPS下,表和序列需要在APPS下创建别名。
约束前缀:SECOM
以下脚本在PL/SQL Developer中,用APPS登录,在Command Window中运行。
其他说明:本文档使用"SECOM"客户化应用做开发,不过数据库对象仍然沿用"CUX"前缀;没有建立专门的索引表空间。
创建数据库对象
这里仅创建"头信息"表,并遵循如下规范:
1、 1个表关键字ID,通常与表名一致,并用Sequence为每条记录获得一个唯一值。
2、 1个组织ID,根据不同的开发选用不同层次的组织ID,这里的销售订单跑在OU层,所以基表命名为_ALL表,并创建一个过滤组织的View作为"基表"。
3、 5个Who字段,记录由谁在何时创建,并由谁在何时修改,登录ID是多少。
4、 4个请求字段,处理的请求ID、请求日期、并发程序ID及其应用ID,如果有的话。
5、 16个描述性弹性域字段,1个上下文字段,15个弹性域字段。
6、 另外,根据以往开发经验,加个描述字段可解决不少难缠的问题。
点击查看代码
-- Create table
create table SECOM.CUX_ORDER_HEADERS_ALL
(
HEADER_ID NUMBER not null,
ORG_ID NUMBER not null,
ORDER_NUMBER NUMBER not null,
ORDERED_DATE DATE not null,
ORDER_TYPE VARCHAR2(1) not null,
CUSTOMER_ID NUMBER not null,
SALESREP_ID NUMBER(15),
PRICE_LIST_ID NUMBER,
CURRENCY_CODE VARCHAR2(15) not null,
FLOW_STATUS_CODE VARCHAR2(30) not null,
DESCRIPTION VARCHAR2(240),
CREATION_DATE DATE not null,
CREATED_BY NUMBER not null,
LAST_UPDATED_BY NUMBER not null,
LAST_UPDATE_DATE DATE not null,
LAST_UPDATE_LOGIN NUMBER,
PROGRAM_APPLICATION_ID NUMBER,
PROGRAM_ID NUMBER,
PROGRAM_UPDATE_DATE DATE,
REQUEST_ID NUMBER,
ATTRIBUTE_CATEGORY VARCHAR2(30),
ATTRIBUTE1 VARCHAR2(240),
ATTRIBUTE2 VARCHAR2(240),
ATTRIBUTE3 VARCHAR2(240),
ATTRIBUTE4 VARCHAR2(240),
ATTRIBUTE5 VARCHAR2(240),
ATTRIBUTE6 VARCHAR2(240),
ATTRIBUTE7 VARCHAR2(240),
ATTRIBUTE8 VARCHAR2(240),
ATTRIBUTE9 VARCHAR2(240),
ATTRIBUTE10 VARCHAR2(240),
ATTRIBUTE11 VARCHAR2(240),
ATTRIBUTE12 VARCHAR2(240),
ATTRIBUTE13 VARCHAR2(240),
ATTRIBUTE14 VARCHAR2(240),
ATTRIBUTE15 VARCHAR2(240)
)
--不指定会选择默认的表空间
tablespace SECOM;
-- Create/Recreate indexes
create unique index SECOM.CUX_ORDER_HEADERS_U1 on SECOM.CUX_ORDER_HEADERS_ALL (HEADER_ID);
create unique index SECOM.CUX_ORDER_HEADERS_U2 on SECOM.CUX_ORDER_HEADERS_ALL (ORG_ID, ORDER_NUMBER);
create index SECOM.CUX_ORDER_HEADERS_N1 on SECOM.CUX_ORDER_HEADERS_ALL (CUSTOMER_ID);
create index SECOM.CUX_ORDER_HEADERS_N2 on SECOM.CUX_ORDER_HEADERS_ALL (SALESREP_ID);
create index SECOM.CUX_ORDER_HEADERS_N3 on SECOM.CUX_ORDER_HEADERS_ALL (FLOW_STATUS_CODE);
-- Create/Recreate sequence
-- 作用:在多用户环境下产生唯一整数的数据库对象
CREATE SEQUENCE SECOM.CUX_ORDER_HEADERS_S;
-- Create/Recreate synonum
CREATE SYNONYM CUX_ORDER_HEADERS_S FOR SECOM.CUX_ORDER_HEADERS_S;
CREATE SYNONYM CUX_ORDER_HEADERS_ALL FOR SECOM.CUX_ORDER_HEADERS_ALL;
--insert
--insert
insert into SECOM.CUX_ORDER_HEADERS_ALL (HEADER_ID, ORG_ID, ORDER_NUMBER, ORDERED_DATE,
ORDER_TYPE,CUSTOMER_ID,CURRENCY_CODE,FLOW_STATUS_CODE,CREATION_DATE,CREATED_BY,LAST_UPDATED_BY,LAST_UPDATE_DATE)
values (1,90,1, sysdate,'I',1,'CNY','Y',sysdate,1,1,sysdate);
insert into SECOM.CUX_ORDER_HEADERS_ALL (HEADER_ID, ORG_ID, ORDER_NUMBER, ORDERED_DATE,
ORDER_TYPE,CUSTOMER_ID,CURRENCY_CODE,FLOW_STATUS_CODE,CREATION_DATE,CREATED_BY,LAST_UPDATED_BY,LAST_UPDATE_DATE)
values (2,90,2, sysdate,'I',2,'CNY','Y',sysdate,2,2,sysdate);
insert into SECOM.CUX_ORDER_HEADERS_ALL (HEADER_ID, ORG_ID, ORDER_NUMBER, ORDERED_DATE,
ORDER_TYPE,CUSTOMER_ID,CURRENCY_CODE,FLOW_STATUS_CODE,CREATION_DATE,CREATED_BY,LAST_UPDATED_BY,LAST_UPDATE_DATE)
values (3,90,3, sysdate,'I',3,'CNY','Y',sysdate,3,3,sysdate);
insert into SECOM.CUX_ORDER_HEADERS_ALL (HEADER_ID, ORG_ID, ORDER_NUMBER, ORDERED_DATE,
ORDER_TYPE,CUSTOMER_ID,CURRENCY_CODE,FLOW_STATUS_CODE,CREATION_DATE,CREATED_BY,LAST_UPDATED_BY,LAST_UPDATE_DATE)
values (4,90,4, sysdate,'I',4,'CNY','Y',sysdate,4,4,sysdate);
insert into SECOM.CUX_ORDER_HEADERS_ALL (HEADER_ID, ORG_ID, ORDER_NUMBER, ORDERED_DATE,
ORDER_TYPE,CUSTOMER_ID,CURRENCY_CODE,FLOW_STATUS_CODE,CREATION_DATE,CREATED_BY,LAST_UPDATED_BY,LAST_UPDATE_DATE)
values (5,90,5, sysdate,'I',5,'CNY','Y',sysdate,5,5,sysdate);
commit;
-- Create/Recreate View
-- 过滤组织的VIEW基表
CREATE OR REPLACE VIEW CUX_ORDER_HEADERS AS
SELECT header_id,
org_id,
order_number,
ordered_date,
order_type,
customer_id,
salesrep_id,
price_list_id,
currency_code,
flow_status_code,
description,
creation_date,
created_by,
last_updated_by,
last_update_date,
last_update_login,
program_application_id,
program_id,
program_update_date,
request_id,
attribute_category,
attribute1,
attribute2,
attribute3,
attribute4,
attribute5,
attribute6,
attribute7,
attribute8,
attribute9,
attribute10,
attribute11,
attribute12,
attribute13,
attribute14,
attribute15
FROM cux_order_headers_all
WHERE nvl(org_id,
nvl(to_number(decode(substrb(userenv('CLIENT_INFO'), 1, 1),
' ',
NULL,
substrb(userenv('CLIENT_INFO'), 1, 10))),
-99)) =
nvl(to_number(decode(substrb(userenv('CLIENT_INFO'), 1, 1),
' ',
NULL,
substrb(userenv('CLIENT_INFO'), 1, 10))),
-99);
-- 模拟初始化才能查到视图里面的数据
begin
FND_GLOBAL.APPS_INITIALIZE(USER_ID => 0,
RESP_ID => 50484,
RESP_APPL_ID => 200);
end;
/
select * from CUX_ORDER_HEADERS;
注册表和字段
需要向EBS注册表和字段,这样以后就可通过标准功能设置弹性域、监控表操作。
EXECUTE AD_DD.REGISTER_TABLE('SECOM','CUX_ORDER_HEADERS_ALL','T',2,10,40);
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','HEADER_ID',1,'NUMBER',38,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ORG_ID',2,'NUMBER',38,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ORDER_NUMBER',3,'NUMBER',38,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ORDERED_DATE',4,'DATE',9,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ORDER_TYPE',5,'VARCHAR2',1,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','CUSTOMER_ID',6,'NUMBER',38,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','SALESREP_ID',7,'NUMBER',38,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','PRICE_LIST_ID',8,'NUMBER',38,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','CURRENCY_CODE',9,'VARCHAR2',15,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','FLOW_STATUS_CODE',10,'VARCHAR2',30,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','DESCRIPTION',11,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','CREATION_DATE',12,'DATE',9,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','CREATED_BY',13,'NUMBER',38,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','LAST_UPDATED_BY',14,'NUMBER',38,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','LAST_UPDATE_DATE',15,'DATE',9,'N','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','LAST_UPDATE_LOGIN',16,'NUMBER',38,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','PROGRAM_APPLICATION_ID',17,'NUMBER',38,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','PROGRAM_ID',18,'NUMBER',38,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','PROGRAM_UPDATE_DATE',19,'DATE',9,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','REQUEST_ID',20,'NUMBER',38,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE_CATEGORY',21,'VARCHAR2',30,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE1',22,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE2',23,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE3',24,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE4',25,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE5',26,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE6',27,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE7',28,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE8',29,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE9',30,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE10',31,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE11',32,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE12',33,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE13',34,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE14',35,'VARCHAR2',240,'Y','N');
EXECUTE AD_DD.REGISTER_COLUMN('SECOM','CUX_ORDER_HEADERS_ALL','ATTRIBUTE15',36,'VARCHAR2',240,'Y','N');
创建用于Form的View
Form可以直接基于基表,但对于复杂的表,则必需使用View,将各个ID转换为有意义的编码或者描述。
CREATE OR REPLACE VIEW CUX_ORDER_HEADERS_V AS
SELECT coh.ROWID row_id,
coh.header_id,
coh.org_id,
coh.order_number,
coh.ordered_date,
coh.order_type,
coh.customer_id,
rac.customer_name,
coh.salesrep_id,
jrs.NAME salesrep_name,
coh.price_list_id,
qlh.NAME price_list_name,
coh.currency_code,
coh.flow_status_code,
coh.description,
coh.creation_date,
coh.created_by,
coh.last_updated_by,
coh.last_update_date,
coh.last_update_login,
coh.program_application_id,
coh.program_id,
coh.program_update_date,
coh.request_id,
coh.attribute_category,
coh.attribute1,
coh.attribute2,
coh.attribute3,
coh.attribute4,
coh.attribute5,
coh.attribute6,
coh.attribute7,
coh.attribute8,
coh.attribute9,
coh.attribute10,
coh.attribute11,
coh.attribute12,
coh.attribute13,
coh.attribute14,
coh.attribute15
FROM cux_order_headers coh,
ra_customers rac,
jtf_rs_salesreps jrs,
qp_list_headers_vl qlh
WHERE coh.customer_id = rac.customer_id
AND coh.salesrep_id = jrs.salesrep_id(+)
AND coh.price_list_id = qlh.list_header_id(+);
--更新数据
--2510 ~ 2515
select customer_id from ra_customers rac where rac;
--100013151 ~ 100013155
select jrs.salesrep_id from jtf_rs_salesreps jrs;
select qlh.list_header_id from qp_list_headers_vl qlh;
select * from SECOM.CUX_ORDER_HEADERS_ALL for update;
commit;
--初始化
BEGIN
FND_GLOBAL.APPS_INITIALIZE(USER_ID => 0,
RESP_ID => 50484,
RESP_APPL_ID => 200);
END;
select * from CUX_ORDER_HEADERS_V;
创建表操作API
不管是基于基表还是基于视图的Block,都建议编写ON-UPDATE、ON-INSERT、ON-DELETE、ON-LOCK触发器,并且,把具体的DML和锁记录代码放入数据库Package中,然后在Form中调用,该Package以后还可以在其他地方调用。这些设计,都是基于以往开发经验所归纳出来的,有利于模块化开发、有利于扩展。以下脚本在APPS下运行,源文件为cux_order_headers_pkg.pck:
CREATE OR REPLACE PACKAGE CUX_ORDER_HEADERS_PKG AS
/*=====================================
** PROCEDURE: insert_row()
**=====================================*/
PROCEDURE insert_row(
x_row_id IN OUT VARCHAR2,
x_header_id IN OUT NUMBER,
p_org_id IN NUMBER,
p_order_number IN NUMBER,
p_ordered_date IN DATE,
p_order_type IN VARCHAR2,
p_customer_id IN NUMBER,
p_salesrep_id IN NUMBER DEFAULT NULL,
p_price_list_id IN NUMBER DEFAULT NULL,
p_currency_code IN VARCHAR2,
p_flow_status_code IN VARCHAR2,
p_description IN VARCHAR2 DEFAULT NULL,
p_creation_date IN DATE,
p_created_by IN NUMBER,
p_last_updated_by IN NUMBER,
p_last_update_date IN DATE,
p_last_update_login IN NUMBER DEFAULT NULL,
p_program_application_id IN NUMBER DEFAULT NULL,
p_program_id IN NUMBER DEFAULT NULL,
p_program_update_date IN DATE DEFAULT NULL,
p_request_id IN NUMBER DEFAULT NULL,
p_attribute_category IN VARCHAR2 DEFAULT NULL,
p_attribute1 IN VARCHAR2 DEFAULT NULL,
p_attribute2 IN VARCHAR2 DEFAULT NULL,
p_attribute3 IN VARCHAR2 DEFAULT NULL,
p_attribute4 IN VARCHAR2 DEFAULT NULL,
p_attribute5 IN VARCHAR2 DEFAULT NULL,
p_attribute6 IN VARCHAR2 DEFAULT NULL,
p_attribute7 IN VARCHAR2 DEFAULT NULL,
p_attribute8 IN VARCHAR2 DEFAULT NULL,
p_attribute9 IN VARCHAR2 DEFAULT NULL,
p_attribute10 IN VARCHAR2 DEFAULT NULL,
p_attribute11 IN VARCHAR2 DEFAULT NULL,
p_attribute12 IN VARCHAR2 DEFAULT NULL,
p_attribute13 IN VARCHAR2 DEFAULT NULL,
p_attribute14 IN VARCHAR2 DEFAULT NULL,
p_attribute15 IN VARCHAR2 DEFAULT NULL);
/*=====================================
** PROCEDURE: lock_row()
**=====================================*/
PROCEDURE lock_row(
p_header_id IN NUMBER,
p_org_id IN NUMBER,
p_order_number IN NUMBER,
p_ordered_date IN DATE,
p_order_type IN VARCHAR2,
p_customer_id IN NUMBER,
p_salesrep_id IN NUMBER,
p_price_list_id IN NUMBER,
p_currency_code IN VARCHAR2,
p_flow_status_code IN VARCHAR2,
p_description IN VARCHAR2,
p_creation_date IN DATE,
p_created_by IN NUMBER,
p_last_updated_by IN NUMBER,
p_last_update_date IN DATE,
p_last_update_login IN NUMBER,
p_program_application_id IN NUMBER,
p_program_id IN NUMBER,
p_program_update_date IN DATE,
p_request_id IN NUMBER,
p_attribute_category IN VARCHAR2,
p_attribute1 IN VARCHAR2,
p_attribute2 IN VARCHAR2,
p_attribute3 IN VARCHAR2,
p_attribute4 IN VARCHAR2,
p_attribute5 IN VARCHAR2,
p_attribute6 IN VARCHAR2,
p_attribute7 IN VARCHAR2,
p_attribute8 IN VARCHAR2,
p_attribute9 IN VARCHAR2,
p_attribute10 IN VARCHAR2,
p_attribute11 IN VARCHAR2,
p_attribute12 IN VARCHAR2,
p_attribute13 IN VARCHAR2,
p_attribute14 IN VARCHAR2,
p_attribute15 IN VARCHAR2);
/*=====================================
** PROCEDURE: update_row()
**=====================================*/
PROCEDURE update_row(
p_header_id IN NUMBER,
p_org_id IN NUMBER,
p_order_number IN NUMBER,
p_ordered_date IN DATE,
p_order_type IN VARCHAR2,
p_customer_id IN NUMBER,
p_salesrep_id IN NUMBER DEFAULT NULL,
p_price_list_id IN NUMBER DEFAULT NULL,
p_currency_code IN VARCHAR2,
p_flow_status_code IN VARCHAR2,
p_description IN VARCHAR2 DEFAULT NULL,
p_last_updated_by IN NUMBER,
p_last_update_date IN DATE,
p_last_update_login IN NUMBER DEFAULT NULL,
p_program_application_id IN NUMBER DEFAULT NULL,
p_program_id IN NUMBER DEFAULT NULL,
p_program_update_date IN DATE DEFAULT NULL,
p_request_id IN NUMBER DEFAULT NULL,
p_attribute_category IN VARCHAR2 DEFAULT NULL,
p_attribute1 IN VARCHAR2 DEFAULT NULL,
p_attribute2 IN VARCHAR2 DEFAULT NULL,
p_attribute3 IN VARCHAR2 DEFAULT NULL,
p_attribute4 IN VARCHAR2 DEFAULT NULL,
p_attribute5 IN VARCHAR2 DEFAULT NULL,
p_attribute6 IN VARCHAR2 DEFAULT NULL,
p_attribute7 IN VARCHAR2 DEFAULT NULL,
p_attribute8 IN VARCHAR2 DEFAULT NULL,
p_attribute9 IN VARCHAR2 DEFAULT NULL,
p_attribute10 IN VARCHAR2 DEFAULT NULL,
p_attribute11 IN VARCHAR2 DEFAULT NULL,
p_attribute12 IN VARCHAR2 DEFAULT NULL,
p_attribute13 IN VARCHAR2 DEFAULT NULL,
p_attribute14 IN VARCHAR2 DEFAULT NULL,
p_attribute15 IN VARCHAR2 DEFAULT NULL);
/*=====================================
** PROCEDURE: delete_row()
**=====================================*/
PROCEDURE delete_row(
p_header_id IN NUMBER);
END CUX_ORDER_HEADERS_PKG;
/
CREATE OR REPLACE PACKAGE BODY CUX_ORDER_HEADERS_PKG AS
/*=====================================
** PROCEDURE: insert_row()
**=====================================*/
PROCEDURE insert_row(
x_row_id IN OUT VARCHAR2,
x_header_id IN OUT NUMBER,
p_org_id IN NUMBER,
p_order_number IN NUMBER,
p_ordered_date IN DATE,
p_order_type IN VARCHAR2,
p_customer_id IN NUMBER,
p_salesrep_id IN NUMBER DEFAULT NULL,
p_price_list_id IN NUMBER DEFAULT NULL,
p_currency_code IN VARCHAR2,
p_flow_status_code IN VARCHAR2,
p_description IN VARCHAR2 DEFAULT NULL,
p_creation_date IN DATE,
p_created_by IN NUMBER,
p_last_updated_by IN NUMBER,
p_last_update_date IN DATE,
p_last_update_login IN NUMBER DEFAULT NULL,
p_program_application_id IN NUMBER DEFAULT NULL,
p_program_id IN NUMBER DEFAULT NULL,
p_program_update_date IN DATE DEFAULT NULL,
p_request_id IN NUMBER DEFAULT NULL,
p_attribute_category IN VARCHAR2 DEFAULT NULL,
p_attribute1 IN VARCHAR2 DEFAULT NULL,
p_attribute2 IN VARCHAR2 DEFAULT NULL,
p_attribute3 IN VARCHAR2 DEFAULT NULL,
p_attribute4 IN VARCHAR2 DEFAULT NULL,
p_attribute5 IN VARCHAR2 DEFAULT NULL,
p_attribute6 IN VARCHAR2 DEFAULT NULL,
p_attribute7 IN VARCHAR2 DEFAULT NULL,
p_attribute8 IN VARCHAR2 DEFAULT NULL,
p_attribute9 IN VARCHAR2 DEFAULT NULL,
p_attribute10 IN VARCHAR2 DEFAULT NULL,
p_attribute11 IN VARCHAR2 DEFAULT NULL,
p_attribute12 IN VARCHAR2 DEFAULT NULL,
p_attribute13 IN VARCHAR2 DEFAULT NULL,
p_attribute14 IN VARCHAR2 DEFAULT NULL,
p_attribute15 IN VARCHAR2 DEFAULT NULL)
IS
CURSOR c
IS SELECT rowid
FROM SECOM.CUX_ORDER_HEADERS_ALL
WHERE HEADER_ID = x_header_id;
BEGIN
IF x_header_id IS NULL THEN
SELECT SECOM.CUX_ORDER_HEADERS_S.NEXTVAL
INTO x_header_id
FROM DUAL;
END IF;
INSERT INTO SECOM.cux_order_headers_all (
header_id,
org_id,
order_number,
ordered_date,
order_type,
customer_id,
salesrep_id,
price_list_id,
currency_code,
flow_status_code,
description,
creation_date,
created_by,
last_updated_by,
last_update_date,
last_update_login,
program_application_id,
program_id,
program_update_date,
request_id,
attribute_category,
attribute1,
attribute2,
attribute3,
attribute4,
attribute5,
attribute6,
attribute7,
attribute8,
attribute9,
attribute10,
attribute11,
attribute12,
attribute13,
attribute14,
attribute15)
VALUES (
x_header_id,
p_org_id,
p_order_number,
p_ordered_date,
p_order_type,
p_customer_id,
p_salesrep_id,
p_price_list_id,
p_currency_code,
p_flow_status_code,
p_description,
p_creation_date,
p_created_by,
p_last_updated_by,
p_last_update_date,
p_last_update_login,
p_program_application_id,
p_program_id,
p_program_update_date,
p_request_id,
p_attribute_category,
p_attribute1,
p_attribute2,
p_attribute3,
p_attribute4,
p_attribute5,
p_attribute6,
p_attribute7,
p_attribute8,
p_attribute9,
p_attribute10,
p_attribute11,
p_attribute12,
p_attribute13,
p_attribute14,
p_attribute15);
OPEN c;
FETCH c INTO x_row_id;
IF (c%NOTFOUND) THEN
CLOSE c;
RAISE NO_DATA_FOUND;
END IF;
CLOSE c;
END insert_row;
/*=====================================
** PROCEDURE: lock_row()
**=====================================*/
PROCEDURE lock_row(
p_header_id IN NUMBER,
p_org_id IN NUMBER,
p_order_number IN NUMBER,
p_ordered_date IN DATE,
p_order_type IN VARCHAR2,
p_customer_id IN NUMBER,
p_salesrep_id IN NUMBER,
p_price_list_id IN NUMBER,
p_currency_code IN VARCHAR2,
p_flow_status_code IN VARCHAR2,
p_description IN VARCHAR2,
p_creation_date IN DATE,
p_created_by IN NUMBER,
p_last_updated_by IN NUMBER,
p_last_update_date IN DATE,
p_last_update_login IN NUMBER,
p_program_application_id IN NUMBER,
p_program_id IN NUMBER,
p_program_update_date IN DATE,
p_request_id IN NUMBER,
p_attribute_category IN VARCHAR2,
p_attribute1 IN VARCHAR2,
p_attribute2 IN VARCHAR2,
p_attribute3 IN VARCHAR2,
p_attribute4 IN VARCHAR2,
p_attribute5 IN VARCHAR2,
p_attribute6 IN VARCHAR2,
p_attribute7 IN VARCHAR2,
p_attribute8 IN VARCHAR2,
p_attribute9 IN VARCHAR2,
p_attribute10 IN VARCHAR2,
p_attribute11 IN VARCHAR2,
p_attribute12 IN VARCHAR2,
p_attribute13 IN VARCHAR2,
p_attribute14 IN VARCHAR2,
p_attribute15 IN VARCHAR2)
IS
CURSOR c
IS SELECT
header_id,
org_id,
order_number,
ordered_date,
order_type,
customer_id,
salesrep_id,
price_list_id,
currency_code,
flow_status_code,
description,
creation_date,
created_by,
last_updated_by,
last_update_date,
last_update_login,
program_application_id,
program_id,
program_update_date,
request_id,
attribute_category,
attribute1,
attribute2,
attribute3,
attribute4,
attribute5,
attribute6,
attribute7,
attribute8,
attribute9,
attribute10,
attribute11,
attribute12,
attribute13,
attribute14,
attribute15
FROM SECOM.cux_order_headers_all
WHERE header_id = p_header_id
FOR UPDATE OF header_id NOWAIT;
rec c%rowtype;
BEGIN
OPEN c;
FETCH c INTO rec;
IF (c%NOTFOUND) THEN
CLOSE c;
fnd_message.set_name('FND','FORM_RECORD_DELETED');
app_exception.raise_exception;
END IF;
CLOSE c;
IF (
(rec.header_id = p_header_id)
AND ((rec.org_id = p_org_id) OR
((rec.org_id IS NULL) AND (p_org_id IS NULL)))
AND ((rec.order_number = p_order_number) OR
((rec.order_number IS NULL) AND (p_order_number IS NULL)))
AND ((rec.ordered_date = p_ordered_date) OR
((rec.ordered_date IS NULL) AND (p_ordered_date IS NULL)))
AND ((rec.order_type = p_order_type) OR
((rec.order_type IS NULL) AND (p_order_type IS NULL)))
AND ((rec.customer_id = p_customer_id) OR
((rec.customer_id IS NULL) AND (p_customer_id IS NULL)))
AND ((rec.salesrep_id = p_salesrep_id) OR
((rec.salesrep_id IS NULL) AND (p_salesrep_id IS NULL)))
AND ((rec.price_list_id = p_price_list_id) OR
((rec.price_list_id IS NULL) AND (p_price_list_id IS NULL)))
AND ((rec.currency_code = p_currency_code) OR
((rec.currency_code IS NULL) AND (p_currency_code IS NULL)))
AND ((rec.flow_status_code = p_flow_status_code) OR
((rec.flow_status_code IS NULL) AND (p_flow_status_code IS NULL)))
AND ((rec.description = p_description) OR
((rec.description IS NULL) AND (p_description IS NULL)))
AND ((rec.creation_date = p_creation_date) OR
((rec.creation_date IS NULL) AND (p_creation_date IS NULL)))
AND ((rec.created_by = p_created_by) OR
((rec.created_by IS NULL) AND (p_created_by IS NULL)))
AND ((rec.last_updated_by = p_last_updated_by) OR
((rec.last_updated_by IS NULL) AND (p_last_updated_by IS NULL)))
AND ((rec.last_update_date = p_last_update_date) OR
((rec.last_update_date IS NULL) AND (p_last_update_date IS NULL)))
AND ((rec.last_update_login = p_last_update_login) OR
((rec.last_update_login IS NULL) AND (p_last_update_login IS NULL)))
AND ((rec.program_application_id = p_program_application_id) OR
((rec.program_application_id IS NULL) AND (p_program_application_id IS NULL)))
AND ((rec.program_id = p_program_id) OR
((rec.program_id IS NULL) AND (p_program_id IS NULL)))
AND ((rec.program_update_date = p_program_update_date) OR
((rec.program_update_date IS NULL) AND (p_program_update_date IS NULL)))
AND ((rec.request_id = p_request_id) OR
((rec.request_id IS NULL) AND (p_request_id IS NULL)))
AND ((rec.attribute_category = p_attribute_category) OR
((rec.attribute_category IS NULL) AND (p_attribute_category IS NULL)))
AND ((rec.attribute1 = p_attribute1) OR
((rec.attribute1 IS NULL) AND (p_attribute1 IS NULL)))
AND ((rec.attribute2 = p_attribute2) OR
((rec.attribute2 IS NULL) AND (p_attribute2 IS NULL)))
AND ((rec.attribute3 = p_attribute3) OR
((rec.attribute3 IS NULL) AND (p_attribute3 IS NULL)))
AND ((rec.attribute4 = p_attribute4) OR
((rec.attribute4 IS NULL) AND (p_attribute4 IS NULL)))
AND ((rec.attribute5 = p_attribute5) OR
((rec.attribute5 IS NULL) AND (p_attribute5 IS NULL)))
AND ((rec.attribute6 = p_attribute6) OR
((rec.attribute6 IS NULL) AND (p_attribute6 IS NULL)))
AND ((rec.attribute7 = p_attribute7) OR
((rec.attribute7 IS NULL) AND (p_attribute7 IS NULL)))
AND ((rec.attribute8 = p_attribute8) OR
((rec.attribute8 IS NULL) AND (p_attribute8 IS NULL)))
AND ((rec.attribute9 = p_attribute9) OR
((rec.attribute9 IS NULL) AND (p_attribute9 IS NULL)))
AND ((rec.attribute10 = p_attribute10) OR
((rec.attribute10 IS NULL) AND (p_attribute10 IS NULL)))
AND ((rec.attribute11 = p_attribute11) OR
((rec.attribute11 IS NULL) AND (p_attribute11 IS NULL)))
AND ((rec.attribute12 = p_attribute12) OR
((rec.attribute12 IS NULL) AND (p_attribute12 IS NULL)))
AND ((rec.attribute13 = p_attribute13) OR
((rec.attribute13 IS NULL) AND (p_attribute13 IS NULL)))
AND ((rec.attribute14 = p_attribute14) OR
((rec.attribute14 IS NULL) AND (p_attribute14 IS NULL)))
AND ((rec.attribute15 = p_attribute15) OR
((rec.attribute15 IS NULL) AND (p_attribute15 IS NULL)))
) THEN
NULL;
ELSE
fnd_message.set_name('FND', 'FORM_RECORD_CHANGED');
app_exception.raise_exception;
END IF;
END lock_row;
/*=====================================
** PROCEDURE: update_row()
**=====================================*/
PROCEDURE update_row(
p_header_id IN NUMBER,
p_org_id IN NUMBER,
p_order_number IN NUMBER,
p_ordered_date IN DATE,
p_order_type IN VARCHAR2,
p_customer_id IN NUMBER,
p_salesrep_id IN NUMBER DEFAULT NULL,
p_price_list_id IN NUMBER DEFAULT NULL,
p_currency_code IN VARCHAR2,
p_flow_status_code IN VARCHAR2,
p_description IN VARCHAR2 DEFAULT NULL,
p_last_updated_by IN NUMBER,
p_last_update_date IN DATE,
p_last_update_login IN NUMBER DEFAULT NULL,
p_program_application_id IN NUMBER DEFAULT NULL,
p_program_id IN NUMBER DEFAULT NULL,
p_program_update_date IN DATE DEFAULT NULL,
p_request_id IN NUMBER DEFAULT NULL,
p_attribute_category IN VARCHAR2 DEFAULT NULL,
p_attribute1 IN VARCHAR2 DEFAULT NULL,
p_attribute2 IN VARCHAR2 DEFAULT NULL,
p_attribute3 IN VARCHAR2 DEFAULT NULL,
p_attribute4 IN VARCHAR2 DEFAULT NULL,
p_attribute5 IN VARCHAR2 DEFAULT NULL,
p_attribute6 IN VARCHAR2 DEFAULT NULL,
p_attribute7 IN VARCHAR2 DEFAULT NULL,
p_attribute8 IN VARCHAR2 DEFAULT NULL,
p_attribute9 IN VARCHAR2 DEFAULT NULL,
p_attribute10 IN VARCHAR2 DEFAULT NULL,
p_attribute11 IN VARCHAR2 DEFAULT NULL,
p_attribute12 IN VARCHAR2 DEFAULT NULL,
p_attribute13 IN VARCHAR2 DEFAULT NULL,
p_attribute14 IN VARCHAR2 DEFAULT NULL,
p_attribute15 IN VARCHAR2 DEFAULT NULL)
IS
BEGIN
UPDATE SECOM.CUX_ORDER_HEADERS_ALL SET
header_id = p_header_id,
org_id = p_org_id,
order_number = p_order_number,
ordered_date = p_ordered_date,
order_type = p_order_type,
customer_id = p_customer_id,
salesrep_id = p_salesrep_id,
price_list_id = p_price_list_id,
currency_code = p_currency_code,
flow_status_code = p_flow_status_code,
description = p_description,
last_updated_by = p_last_updated_by,
last_update_date = p_last_update_date,
last_update_login = p_last_update_login,
program_application_id = p_program_application_id,
program_id = p_program_id,
program_update_date = p_program_update_date,
request_id = p_request_id,
attribute_category = p_attribute_category,
attribute1 = p_attribute1,
attribute2 = p_attribute2,
attribute3 = p_attribute3,
attribute4 = p_attribute4,
attribute5 = p_attribute5,
attribute6 = p_attribute6,
attribute7 = p_attribute7,
attribute8 = p_attribute8,
attribute9 = p_attribute9,
attribute10 = p_attribute10,
attribute11 = p_attribute11,
attribute12 = p_attribute12,
attribute13 = p_attribute13,
attribute14 = p_attribute14,
attribute15 = p_attribute15
WHERE header_id = p_header_id;
IF (SQL%NOTFOUND) THEN
RAISE NO_DATA_FOUND;
END IF;
END update_row;
/*=====================================
** PROCEDURE: delete_row()
**=====================================*/
PROCEDURE delete_row(
p_header_id IN NUMBER)
IS
BEGIN
DELETE FROM SECOM.cux_order_headers_all
WHERE header_id = p_header_id;
IF (SQL%NOTFOUND) THEN
RAISE NO_DATA_FOUND;
END IF;
END delete_row;
END CUX_ORDER_HEADERS_PKG;
/
创建Forms块操作API
PACKAGE ORDER_HEADERS_PRIVATE IS
PROCEDURE insert_row;
PROCEDURE lock_row;
PROCEDURE update_row;
PROCEDURE delete_row;
END ORDER_HEADERS_PRIVATE;
PACKAGE BODY ORDER_HEADERS_PRIVATE IS
/*=====================================
** PROCEDURE: insert_row()
**=====================================*/
PROCEDURE insert_row IS
BEGIN
fnd_standard.set_who;
IF :order_headers.header_id IS NULL THEN
SELECT SECOM.CUX_ORDER_HEADERS_S.NEXTVAL
INTO :order_headers.header_id
FROM DUAL;
END IF;
cux_order_headers_pkg.insert_row (
x_row_id => :order_headers.row_id
,x_header_id => :order_headers.header_id
,p_org_id => :order_headers.org_id
,p_order_number => :order_headers.order_number
,p_ordered_date => :order_headers.ordered_date
,p_order_type => :order_headers.order_type
,p_customer_id => :order_headers.customer_id
,p_salesrep_id => :order_headers.salesrep_id
,p_price_list_id => :order_headers.price_list_id
,p_currency_code => :order_headers.currency_code
,p_flow_status_code => :order_headers.flow_status_code
,p_description => :order_headers.description
,p_creation_date => :order_headers.creation_date
,p_created_by => :order_headers.created_by
,p_last_updated_by => :order_headers.last_updated_by
,p_last_update_date => :order_headers.last_update_date
,p_last_update_login => :order_headers.last_update_login
,p_program_application_id => :order_headers.program_application_id
,p_program_id => :order_headers.program_id
,p_program_update_date => :order_headers.program_update_date
,p_request_id => :order_headers.request_id
,p_attribute_category => :order_headers.attribute_category
,p_attribute1 => :order_headers.attribute1
,p_attribute2 => :order_headers.attribute2
,p_attribute3 => :order_headers.attribute3
,p_attribute4 => :order_headers.attribute4
,p_attribute5 => :order_headers.attribute5
,p_attribute6 => :order_headers.attribute6
,p_attribute7 => :order_headers.attribute7
,p_attribute8 => :order_headers.attribute8
,p_attribute9 => :order_headers.attribute9
,p_attribute10 => :order_headers.attribute10
,p_attribute11 => :order_headers.attribute11
,p_attribute12 => :order_headers.attribute12
,p_attribute13 => :order_headers.attribute13
,p_attribute14 => :order_headers.attribute14
,p_attribute15 => :order_headers.attribute15
);
END insert_row;
/*=====================================
** PROCEDURE: lock_row()
**=====================================*/
PROCEDURE lock_row IS
i NUMBER := 0;
BEGIN
LOOP
BEGIN
i := i + 1;
cux_order_headers_pkg.lock_row(
p_header_id => :order_headers.header_id
,p_org_id => :order_headers.org_id
,p_order_number => :order_headers.order_number
,p_ordered_date => :order_headers.ordered_date
,p_order_type => :order_headers.order_type
,p_customer_id => :order_headers.customer_id
,p_salesrep_id => :order_headers.salesrep_id
,p_price_list_id => :order_headers.price_list_id
,p_currency_code => :order_headers.currency_code
,p_flow_status_code => :order_headers.flow_status_code
,p_description => :order_headers.description
,p_creation_date => :order_headers.creation_date
,p_created_by => :order_headers.created_by
,p_last_updated_by => :order_headers.last_updated_by
,p_last_update_date => :order_headers.last_update_date
,p_last_update_login => :order_headers.last_update_login
,p_program_application_id => :order_headers.program_application_id
,p_program_id => :order_headers.program_id
,p_program_update_date => :order_headers.program_update_date
,p_request_id => :order_headers.request_id
,p_attribute_category => :order_headers.attribute_category
,p_attribute1 => :order_headers.attribute1
,p_attribute2 => :order_headers.attribute2
,p_attribute3 => :order_headers.attribute3
,p_attribute4 => :order_headers.attribute4
,p_attribute5 => :order_headers.attribute5
,p_attribute6 => :order_headers.attribute6
,p_attribute7 => :order_headers.attribute7
,p_attribute8 => :order_headers.attribute8
,p_attribute9 => :order_headers.attribute9
,p_attribute10 => :order_headers.attribute10
,p_attribute11 => :order_headers.attribute11
,p_attribute12 => :order_headers.attribute12
,p_attribute13 => :order_headers.attribute13
,p_attribute14 => :order_headers.attribute14
,p_attribute15 => :order_headers.attribute15
);
RETURN;
EXCEPTION
WHEN app_exception.record_lock_exception THEN
app_exception.record_lock_error(i);
END;
END LOOP;
END lock_row;
/*=====================================
** PROCEDURE: update_row()
**=====================================*/
PROCEDURE update_row IS
BEGIN
fnd_standard.set_who;
cux_order_headers_pkg.update_row(
p_header_id => :order_headers.header_id
,p_org_id => :order_headers.org_id
,p_order_number => :order_headers.order_number
,p_ordered_date => :order_headers.ordered_date
,p_order_type => :order_headers.order_type
,p_customer_id => :order_headers.customer_id
,p_salesrep_id => :order_headers.salesrep_id
,p_price_list_id => :order_headers.price_list_id
,p_currency_code => :order_headers.currency_code
,p_flow_status_code => :order_headers.flow_status_code
,p_description => :order_headers.description
,p_last_updated_by => :order_headers.last_updated_by
,p_last_update_date => :order_headers.last_update_date
,p_last_update_login => :order_headers.last_update_login
,p_program_application_id => :order_headers.program_application_id
,p_program_id => :order_headers.program_id
,p_program_update_date => :order_headers.program_update_date
,p_request_id => :order_headers.request_id
,p_attribute_category => :order_headers.attribute_category
,p_attribute1 => :order_headers.attribute1
,p_attribute2 => :order_headers.attribute2
,p_attribute3 => :order_headers.attribute3
,p_attribute4 => :order_headers.attribute4
,p_attribute5 => :order_headers.attribute5
,p_attribute6 => :order_headers.attribute6
,p_attribute7 => :order_headers.attribute7
,p_attribute8 => :order_headers.attribute8
,p_attribute9 => :order_headers.attribute9
,p_attribute10 => :order_headers.attribute10
,p_attribute11 => :order_headers.attribute11
,p_attribute12 => :order_headers.attribute12
,p_attribute13 => :order_headers.attribute13
,p_attribute14 => :order_headers.attribute14
,p_attribute15 => :order_headers.attribute15
);
END update_row;
/*=====================================
** PROCEDURE: delete_row()
**=====================================*/
PROCEDURE delete_row IS
BEGIN
cux_order_headers_pkg.delete_row(
p_header_id => :order_headers.header_id
);
END delete_row;
END ORDER_HEADERS_PRIVATE;
基于模板的开发
快速认识Forms Builder开发环境
1、Object Navigator,分层次的对象管理,常用的有:Triggers触发器、Data Blocks数据块(其下有Items字段、Triggers触发器)、Canvases画布、LOVs下拉列表、Parameters参数、Program Units程序单元、Record Group记录组、Windows窗体。
这些对象可以通过左边红框标记的按钮进行添加、删除。
2、Property Palette,分类别的属性设置
3、Canvases,设计各字段在画布上的布局。
快捷键F4:选中Object Navigator中的某个对象,F4可以调出Property Palette。
4、Code Editor代码编辑器:编写PL/SQL代码的地方。
拷贝TEMPLATE.fmb
拷贝TEMPLATE.fmb,改名为CUXORDENT.fmb,打开之后把Form Name也改为CUXORDENT,一定要保持一致性。
删除多余对象
删除Data Blocks下的两个块——BLOCKNAME、DETAILBLOCK,它们是模版自带的示例主从块。
删除Canvases下的一个画布——BLOCKNAME。
修改Windows名称
修改Windows下的BLOCKNAME这个Window,在Property Palette中将Name改为"SALES_ORDER",将Title改为"Sales Order"。

修改2个触发器、1个程序单元
因为一个Forms有多个Window,所以需要明确指出哪个Window是主Window,这样在关闭主Window的时候将退出整个Forms;此外,我们也须要在源代码中记录作者、开发时间、版本等备注信息。这些是通过代码而非属性来控制的。
1、 修改Forms级触发器PRE-FORM
将其中的app_window.set_window_position('BLOCKNAME', 'FIRST_WINDOW');改为app_window.set_window_position('SALES_ORDER', 'FIRST_WINDOW');
同时修改上面几行代码中的作者、时间、版本、Form描述、应用简称,示例如下:
FND_STANDARD.FORM_INFO('$Revision: 1.0$', 'CUXFLODER Form', 'FND',
'$Date: 2023/03/07 23:25 $', '$Author: Chuck_Deng $');

2、 修改Forms级触发器WHEN-NEW-FORM-INSTANCE
主要修改Form名字、版本和日期。

3、 修改Program Unit下app_custom中的close_window过程
将if (wnd = 'your first window') then app_window.close_first_window;改为 if (wnd = 'SALES_ORDER') then app_window.close_first_window;

创建Block数据块
数据块,定义Form上的字段与数据库中的字段是如何对应的,同时定义块和字段的各种操作特性--字段类型、长度、默认值、可否增删改查等等。
N: 在Data Blocks上右键,选择数据块创建向导:
之后第一步跳过,第二步保持默认的选择"Table or View"
第三步输入View名字CUX_ORDER_HEADERS_V,如果没有登录过,则会弹出登录框:
登录后Available Column将显示所有视图字段,点击>>全部选过来。
第四步跳过,第五步选择"Just create the data block"后Finish。
Forms Builder将自动将表字段的名称、类型、长度、是否必须等信息带到Block下的Items中。

设置Block属性及其Subclass
默认Block名字为视图名字,需要"精简",此例改为"ORDER_HEADERS",同时需要设置块属性中的Subclass为Block:

此外,需要设置块的前后导航属性,本例目前仅有一个有意义的数据块,这里将Previous和Next Navigation Data Block均设置为自身,这样在运行时,使用快捷键Shift+Pageup和Shift+Pagedown时,均不会跳离本块。
子类:类似Java中的子类,用来继承Item类型和各种属性,在开发过程中,要严格设置各种Item的子类,不得手工随意修改对象的属性,从而保持界面有一致的风格;设置过子类的对象,图标上有个红色的箭头。
设置Item属性及其Subclass
设置需要显示Item和特殊Item的子类,同时设置部分Item的默认值:
| Item | Subclass | Required | Initial Value | 说明 |
|---|---|---|---|---|
| ROW_ID | ROW_ID | 不显示 | ||
| ORDER_NUMBER | TEXT_ITEM | Yes | ||
| ORDERED_DATE | TEXT_ITEM | Yes | $$DBDATE$$ | 系统日期 |
| ORDER_TYPE | TEXT_ITEM | Yes | I | |
| CUSTOMER_NAME | TEXT_ITEM | Yes | ||
| SALESREP_NAME | TEXT_ITEM | No | ||
| PRICE_LIST_NAME | TEXT_ITEM | No | ||
| CURRENCY_CODE | TEXT_ITEM | Yes | ||
| FLOW_STATUS_CODE | TEXT_ITEM | Yes | ENTERED | |
| DESCRIPTION | TEXT_ITEM | No |
此外,为测试和学习方便,这里先把ORG_ID和CUSTOMER_ID的默认值设置为0。
创建Canvas画布
画布,用来设计各字段的布局,画布必需放置在Window上后才真正对用户"可见"。最基本的画布为Content画布,一个Window必需有且仅有一个Content画布。
N: 在Data Blocks上右键,选择布局创建向导:
第一步选择New Canvas,Type选择Content:
第二步选择要显示的字段:
第三步修改各字段的提示和显示长度:
后面两步跳过直至Finish。
在打开的画布设计界面,删除自动生成的Frame。
设置画布属性和子类
1、设置画布名字为SALES_ORDER,放置的Window为SALES_ORDER,子类为Canvas:

2、调整View和Canvas大小,Content画布这两者设置为一样大,即拉到重叠为止。

Canvas与View:Canvas是整个画布的大小,Item是放置在Canvas上的;View是这个画布的可见部分,如果View小于Canvas,那么通常需要借助滚动条来查看整个Canvas中的内容;可以通过菜单View中的Show View、Show Canvas来确定哪个框是Canvas哪个框是View。
调整布局
调整默认的布局,这里通过属性直接将Sales Person和Price List的宽度设置为1.8:
调整Prompt提示
Oracle标准的Form中,Form形式的布局,提示放置在字段左边,居中对齐,并且距离字段0.073;而Table形式的布局,提示放置在第一行字段上边,数字靠右,其他靠左,并分别距离字段边缘0.05。以ORDER_NUMBER为例设置如下:

设置Windows属性
设置Window"SALES_ORDER"的Primary Canvas为"SALES_ORDER",该Window的大小将自动调整为Content Canvas的大小:

设置Form属性
设置Form的第一个导航块为ORDER_HEADERS,这样运行时,一进入Form,光标将停在该块的第一个字段上:

编写数据操作触发器
编写数据操作Program Unit
该Program Unit主要用来调用之前步骤创建的数据库API。
1、 选中对象管理器中的Program Unit,点击左边的+,选择Package Spec,在Name中输入ORDER_HEADERS_PRIVATE:
2、 OK后,输入如下包头代码:(详细代码可参考上面的form块操作API)

3、 同1,选择Package Body,OK后输入如下包体代码,注意块字段的值的引用格式":块名.字段名":
点击查看代码
PACKAGE BODY ORDER_HEADERS_PRIVATE IS
/*=====================================
** PROCEDURE: insert_row()
**=====================================*/
PROCEDURE insert_row IS
BEGIN
fnd_standard.set_who;
IF :order_headers.header_id IS NULL THEN
SELECT SECOM.CUX_ORDER_HEADERS_S.NEXTVAL
INTO :order_headers.header_id
FROM DUAL;
END IF;
cux_order_headers_pkg.insert_row (
x_row_id => :order_headers.row_id
,x_header_id => :order_headers.header_id
,p_org_id => :order_headers.org_id
,p_order_number => :order_headers.order_number
,p_ordered_date => :order_headers.ordered_date
,p_order_type => :order_headers.order_type
,p_customer_id => :order_headers.customer_id
,p_salesrep_id => :order_headers.salesrep_id
,p_price_list_id => :order_headers.price_list_id
,p_currency_code => :order_headers.currency_code
,p_flow_status_code => :order_headers.flow_status_code
,p_description => :order_headers.description
,p_creation_date => :order_headers.creation_date
,p_created_by => :order_headers.created_by
,p_last_updated_by => :order_headers.last_updated_by
,p_last_update_date => :order_headers.last_update_date
,p_last_update_login => :order_headers.last_update_login
,p_program_application_id => :order_headers.program_application_id
,p_program_id => :order_headers.program_id
,p_program_update_date => :order_headers.program_update_date
,p_request_id => :order_headers.request_id
,p_attribute_category => :order_headers.attribute_category
,p_attribute1 => :order_headers.attribute1
,p_attribute2 => :order_headers.attribute2
,p_attribute3 => :order_headers.attribute3
,p_attribute4 => :order_headers.attribute4
,p_attribute5 => :order_headers.attribute5
,p_attribute6 => :order_headers.attribute6
,p_attribute7 => :order_headers.attribute7
,p_attribute8 => :order_headers.attribute8
,p_attribute9 => :order_headers.attribute9
,p_attribute10 => :order_headers.attribute10
,p_attribute11 => :order_headers.attribute11
,p_attribute12 => :order_headers.attribute12
,p_attribute13 => :order_headers.attribute13
,p_attribute14 => :order_headers.attribute14
,p_attribute15 => :order_headers.attribute15
);
END insert_row;
/*=====================================
** PROCEDURE: lock_row()
**=====================================*/
PROCEDURE lock_row IS
i NUMBER := 0;
BEGIN
LOOP
BEGIN
i := i + 1;
cux_order_headers_pkg.lock_row(
p_header_id => :order_headers.header_id
,p_org_id => :order_headers.org_id
,p_order_number => :order_headers.order_number
,p_ordered_date => :order_headers.ordered_date
,p_order_type => :order_headers.order_type
,p_customer_id => :order_headers.customer_id
,p_salesrep_id => :order_headers.salesrep_id
,p_price_list_id => :order_headers.price_list_id
,p_currency_code => :order_headers.currency_code
,p_flow_status_code => :order_headers.flow_status_code
,p_description => :order_headers.description
,p_creation_date => :order_headers.creation_date
,p_created_by => :order_headers.created_by
,p_last_updated_by => :order_headers.last_updated_by
,p_last_update_date => :order_headers.last_update_date
,p_last_update_login => :order_headers.last_update_login
,p_program_application_id => :order_headers.program_application_id
,p_program_id => :order_headers.program_id
,p_program_update_date => :order_headers.program_update_date
,p_request_id => :order_headers.request_id
,p_attribute_category => :order_headers.attribute_category
,p_attribute1 => :order_headers.attribute1
,p_attribute2 => :order_headers.attribute2
,p_attribute3 => :order_headers.attribute3
,p_attribute4 => :order_headers.attribute4
,p_attribute5 => :order_headers.attribute5
,p_attribute6 => :order_headers.attribute6
,p_attribute7 => :order_headers.attribute7
,p_attribute8 => :order_headers.attribute8
,p_attribute9 => :order_headers.attribute9
,p_attribute10 => :order_headers.attribute10
,p_attribute11 => :order_headers.attribute11
,p_attribute12 => :order_headers.attribute12
,p_attribute13 => :order_headers.attribute13
,p_attribute14 => :order_headers.attribute14
,p_attribute15 => :order_headers.attribute15
);
RETURN;
EXCEPTION
WHEN app_exception.record_lock_exception THEN
app_exception.record_lock_error(i);
END;
END LOOP;
END lock_row;
/*=====================================
** PROCEDURE: update_row()
**=====================================*/
PROCEDURE update_row IS
BEGIN
fnd_standard.set_who;
cux_order_headers_pkg.update_row(
p_header_id => :order_headers.header_id
,p_org_id => :order_headers.org_id
,p_order_number => :order_headers.order_number
,p_ordered_date => :order_headers.ordered_date
,p_order_type => :order_headers.order_type
,p_customer_id => :order_headers.customer_id
,p_salesrep_id => :order_headers.salesrep_id
,p_price_list_id => :order_headers.price_list_id
,p_currency_code => :order_headers.currency_code
,p_flow_status_code => :order_headers.flow_status_code
,p_description => :order_headers.description
,p_last_updated_by => :order_headers.last_updated_by
,p_last_update_date => :order_headers.last_update_date
,p_last_update_login => :order_headers.last_update_login
,p_program_application_id => :order_headers.program_application_id
,p_program_id => :order_headers.program_id
,p_program_update_date => :order_headers.program_update_date
,p_request_id => :order_headers.request_id
,p_attribute_category => :order_headers.attribute_category
,p_attribute1 => :order_headers.attribute1
,p_attribute2 => :order_headers.attribute2
,p_attribute3 => :order_headers.attribute3
,p_attribute4 => :order_headers.attribute4
,p_attribute5 => :order_headers.attribute5
,p_attribute6 => :order_headers.attribute6
,p_attribute7 => :order_headers.attribute7
,p_attribute8 => :order_headers.attribute8
,p_attribute9 => :order_headers.attribute9
,p_attribute10 => :order_headers.attribute10
,p_attribute11 => :order_headers.attribute11
,p_attribute12 => :order_headers.attribute12
,p_attribute13 => :order_headers.attribute13
,p_attribute14 => :order_headers.attribute14
,p_attribute15 => :order_headers.attribute15
);
END update_row;
/*=====================================
** PROCEDURE: delete_row()
**=====================================*/
PROCEDURE delete_row IS
BEGIN
cux_order_headers_pkg.delete_row(
p_header_id => :order_headers.header_id
);
END delete_row;
END;
4、 点击PL/SQL Editor窗口顶上的Compile按钮,必须保证没有错误:(编译之前确保已经登录了ORACLE (可通过'文件'->'连接' 查看登录))
编写块的On触发器
1、 选中Block"ORDER_HEADERS"下的Triggers,点击左边的+,选择ON-INSERT触发器:
2、 OK后输入如下代码:
ORDER_HEADERS_PRIVATE.insert_row;
3、 同1,选择ON-LOCK后输入如下代码:
ORDER_HEADERS_PRIVATE.lock_row;
4、 同1,选择ON-UPDATE后输入如下代码:
ORDER_HEADERS_PRIVATE.update_row;
5、 同1,选择ON-DELETE后输入如下代码:
ORDER_HEADERS_PRIVATE.delete_row;

理解:对于基于非单表视图的Block来说,这里的4个触发器是必须要写的,具体代码可以直接写在触发器内,但为了模块化管理和今后维护方便,这里分为三层调用,触发器中调用Program Unit中的过程,Program Unit中调用数据库Package中的过程。
上传&编译
步骤
1、以应用OS用户用telnet工具putty登录服务器,使用如下命令获得要上传的路径:
su - oracle
echo $SECOM_TOP/forms/US
假如得到(/sekorm/prodappl/secom/11.5.0/forms/ZHS)

2、以应用OS用户用FTP工具FileSilla登录服务器,使用如下命令获得要上传的路径,将CUXORDENT.fmb以二进制方式上传到(/sekorm/prodappl/secom/11.5.0/forms/ZHS)

3、回到telnet工具,使用如下命令,必须进入Forms源文件目录:
$cd $AU_TOP/forms/US
4、 编译Form的命令如下:
f60gen /sekorm/prodappl/secom/11.5.0/forms/ZHS/SECCWAYBILL apps/apps output_file=/sekorm/prodappl/secom/11.5.0/forms/ZHS/SECCWAYBILL
成功编译的话,最后一行将显示:
Created form file /sekorm/prodappl/secom/11.5.0/forms/US/CUXORDENT.fmx

另注:Window版本的EBS,直接在客户端Forms Builder中按CTRL+R,当然肯定无法直接运行,需要我们不断按Esc键取消运行时错误信息(非编译错误!),不过可以生成fmx文件,将其直接拷贝到服务器的 %SECOM_TOP%/forms/US目录下。


在EBS中注册运行
登录EBS
用至少需要有Application Developer职责的用户登录,比如Sysadmin用户,然后选择Application Developer职责。
注册Form
N: DEV/Application/Form
2、切换到Form标签页,选择刚才定义的Form后按Ctrl+S保存。
加入Menu
N: DEV/Application/Menu

运行Form
切换到"**"职责,选择Sales Order菜单,可以看到做好的Form:


注意事项:
因为2个隐藏的必需字段我们暂时没有赋值,而是给了无意义的默认值0,其他可见字段也未做任何有效性控制,所以目前该Form还不能进行实际数据录入操作,不过还是可以测试下打开、字段导航、录入记录、保存记录、关闭等正常操作;但查询记录、修改记录则没法做,暂时只能用SQL直接从表cux_order_headers_all中查看。
字段导航:
运行时用Tab或Shift+Tab键可以在字段间导航,默认情况下,导航的顺序与我们开发时块中Item的排列顺序一致(并非和布局中的顺序一致);
我们可以设置Item的属性Keyboard Navigable为No来禁止键盘导航,也可以设置Previous/Next Navigation Item来强制改变前后导航顺序。
基于EBS的Forms开发全过程(2)
FORM的Parameter参数
关于Parameter
Parameter是Form级参数,外部程序在调用Form时,也可传递具体的参数值,从而达到对Form的某种控制;如果不考虑外部程序传递,完全可以创建一个不基于数据库、字段不显示的特殊块来替代Parameter,实际工作中也经常如此。不过这里仍然采用Parameter。
创建Parameter
N: 选中对象浏览器中的Parameters,然后点击左边工具栏上的"+"新增Parameter,并改名为ORG_ID,类型改为Number,子类不用设置:

初始化Parameter
通常对Parameter的初始化需要在Form级触发器Pre-Form中完成。这里我们根据当前用户的Profile来取得其对应的OU。追加的Pre-Form代码如下:
:parameter.org_id := fnd_profile.value('ORG_ID');

什么是Profile?Profile翻译为预制文件,它是特殊的系统参数,说它特殊,是因为其可以设置在不同的层面上,优先级从高到低主要为:用户、职责、应用、系统。
使用Parameter
来给ORDER_HEADERS块的ORG_ID字段赋初始值:

查询数据之后通过诊断->检查 查看ORG_ID 字段

结果可以看到ORG_ID字段已经被赋上了初始值90
FORM的List值列表
关于List
List是一种特殊的Item,可限制字段的值在某一范围内,通常这个范围是固定的,而且数量通常少于10个。
List值包含两部分:后台存储的Value + 前台显示的含义。
List字段会直接显示一个下拉框,用户必须使用下拉框来选择该字段的值,不能自己输入。
创建List
N: 选中Item,这里是ORDER_HEADERS块的ORDER_TYPE,把子类改为 List,点击Elements in List输入值列表:
| 后台存储的Value | 前台显示的含义 |
|---|---|
| I | Internal |
| R | External |

Mapping of Other Values(其他值的映射)这个属性要特别注意,它的意思是,如果从数据库中读出来的数据,不在这个列表内(这里是I和E),那么要映射为I还是E,如果不映射,那么该条记录将无法在Form中显示出来,表现出来的现象就是数据库和View中明明有,界面却看不到。
对ORDER_HEADERS块的FLOW_STATUS_CODE字段,我们也用List,值列表为:
| 后台存储的Value | 前台显示的含义 |
|---|---|
| ENTERED | Entered |
| BOOKED | Booked |
| PARTIAL | Partial |
| COMPLETE | Complete |
结果显示如下图:

出现一个问题:F11检索不到任何的数据
FORM的LOV窗口式值列表
关于LOV
LOV(List of Value)是窗口式值列表,也是用来限制字段的值在某一范围内,这个范围在Form中用"记录组"来表示,而记录组通常来源于数据库的表。
LOV不是特殊的Item,Item本身通常还是Text Item,LOV仅是Item的一个属性,设有LOV的Item,光标进入到该Item后才会显示一个"..."的按钮。
LOV的值与List不同了,其可以有多列,而List在用户看来只有1列。
List的值直接就是Item的值,而Lov不同,它的每一列都可以指定一个目标,也就是每一列都可以返回给任何一个Item,未必要返回给设有LOV属性的Item。
LOV的验证采用"可见"的第一列,也就是用户可以自己输入,只要输入的值在第一列中即可;如果用户输入的值可匹配到多个值,那么将自动弹出LOV供用户选择,如果只匹配到一个,就不再弹出LOV,达到自动选择了。
LOV也可以不验证,用户可以随便输入,这个一般用在特殊用途比如日期、弹性域、或者其他特殊业务需求。
不管是自动选择还是手工选择,只有"选择"了,才会触发LOV中各列的值返回给对应的目标Item;而不验证的LOV就要注意了,因为其可能没有经过"选择"这一步。
LOV还有个麻烦的问题,如果清空了Item的值,因为空值不触发验证,这样之前返回到各个目标Item上的值并没有自动被清空,需要写代码处理。
创建LOV
N: 在对象浏览器中(最好是在要设置LOV的Item上,这里是CUSTOMER_NAME)右键,选择LOV Wizard。
第1步选择New Record Group based on a query。
第2步输入查询SQL:
SELECT cust.customer_id, cust.customer_name, cust.customer_type,cust.customer_number
FROM ra_customers cust
注意:sql不能有冒号
第3步选择所有列。
第4步设置显示的列名、列框、返回值:
| 数据库字段 | 列名 | 宽 | Return Value |
|---|---|---|---|
| customer_id | 0 | ORDER_HEADERS.CUSTOMER_ID | |
| customer_name | Customer Name | ORDER_HEADERS.CUSTOMER_NAME | |
| customer_number | Customer Number | ||
| customer_type | Type | ORDER_HEADERS.ORDER_TYPE |
第5步输入整个LOV的窗口标题:CUSTOMER_NAME。
第6步跳过。
第7步的意思是,这个LOV要挂在哪个Item上,我们希望是Customer Name

改进LOV
向导创建的LOV没有子类,命名也是乱七八糟,需要修改:
1、 把生成的记录组和LOV都改名为Customers
2、 设置LOV的子类为LOV
我们可以看看Assigned Item的LOV属性:

注意Validate from List(从列表验证),意思是用户输入的值必须在LOV第一可见列的值范围内。
前端FORM显示:

FORM字段和记录控制
字段属性
字段的控制,最常见的就是默认值、是否必需、是否可以更新、是否可以F11查询。其他的都可以顾名思义,可直接看各个属性。本例主要设置Order Number、Ordered Date、Order Type、Currency、Status字段的不可更新属性:

前端FORM显示:

对于Status字段,用户是不可干预的,输入时状态必须是Entered,所以还需要设置其为不可插入:

前端FORM显示:

字段控制
Customer、Sales Person、Price List在状态为非“Entered”的情况下,才不可更新的,这需要用代码实现。在Block的WHEN-NEW-RECORD-INSTANCE触发器中写入下代码,最好写成program unit:
if :ORDER_HEADERS.FLOW_STATUS_CODE = 'ENTERED' then
app_item_property.set_property('ORDER_HEADERS.CUSTOMER_NAME',UPDATE_ALLOWED,PROPERTY_TRUE);
app_item_property.set_property('ORDER_HEADERS.SALESREP_NAME',UPDATE_ALLOWED,PROPERTY_TRUE);
app_item_property.set_property('ORDER_HEADERS.PRICE_LIST_NAME',UPDATE_ALLOWED,PROPERTY_TRUE);
else
app_item_property.set_property('ORDER_HEADERS.CUSTOMER_NAME',UPDATE_ALLOWED,PROPERTY_FALSE);
app_item_property.set_property('ORDER_HEADERS.SALESREP_NAME',UPDATE_ALLOWED,PROPERTY_FALSE);
app_item_property.set_property('ORDER_HEADERS.PRICE_LIST_NAME',UPDATE_ALLOWED,PROPERTY_FALSE);
end if;
注:WHEN-NEW-RECORD-INSTANCE的执行层次要改为Before,为什么?
记录控制
记录的控制,最常见就是显示条数、是否可增/删/改/查、是否可以F11查询、是否显示滚动条。本例需要实现,在状态为非“Entered”的情况下,记录不可删除,这样需要在Block的WHEN-NEW-RECORD-INSTANCE触发器中追加代码,最好写成program unit:
if :ORDER_HEADERS.FLOW_STATUS_CODE = 'ENTERED' then
app_item_property.set_property('ORDER_HEADERS.CUSTOMER_NAME',UPDATE_ALLOWED,PROPERTY_TRUE);
app_item_property.set_property('ORDER_HEADERS.SALESREP_NAME',UPDATE_ALLOWED,PROPERTY_TRUE);
app_item_property.set_property('ORDER_HEADERS.PRICE_LIST_NAME',UPDATE_ALLOWED,PROPERTY_TRUE);
set_block_property('ORDER_HEADERS',DELETE_ALLOWED,PROPERTY_TRUE);
else
app_item_property.set_property('ORDER_HEADERS.CUSTOMER_NAME',UPDATE_ALLOWED,PROPERTY_FALSE);
app_item_property.set_property('ORDER_HEADERS.SALESREP_NAME',UPDATE_ALLOWED,PROPERTY_FALSE);
app_item_property.set_property('ORDER_HEADERS.PRICE_LIST_NAME',UPDATE_ALLOWED,PROPERTY_FALSE);
set_block_property('ORDER_HEADERS',DELETE_ALLOWED,PROPERTY_FALSE);
end if;
Tips:如何通过代码控制字段和块的属性,可直接查这两个过程的在线帮助。
FORM日历
Form中没有日历控件,日期的选择是通过一个特殊的Windows实现的,因为系统封装的比较好,我们需要按照如下三个步骤实现日期的选择:
1、 编写Item的KEY-LISTVAL触发器:calendar.show;

2、 设置Item的List of Values属性:ENABLE_LIST_LAMP
3、 设置Item的Validate from List属性:No


前端FORM显示:


浙公网安备 33010602011771号