Tuesday, December 29, 2009

Flexible Contact query for all entities in your application


as we published the first version of the contact object group that can be added to any form in your application and register your entities that you want to have contact , here we will publish the query process of this component

the screen is base on two blocks :
1- search block ( field for selecting the master database file i.e users , customers , operating units ..... etc another field for selecting the contact entity i.e the specified person or the specified customers )

2- the contact block that based on the contacts table to display the data according to the search criteria in the above block


the Implementation :


1- on your when new form instance trigger or your program unit that called in when new form instance trigger write the following code:
--- FILL THE MASTER FILE SEARCH WITH THE DATA
u_program_pkg.P_POPULATE_LIST('SERACH_BLK.MASTER_FILE','SELECT ARABIC_DESC,TABLE_NAME FROM GN_TABLE
WHERE ENABLE_CONTACT=1');

where the gn_Table is the table that keep the names of the tables of the system that designed to have contact , also this table contain the select statement for the id and the name of the entity to be used in the list of value to get the specified entity ( person , user , custoemr , supplier ,.... etc)
2- on when list changed of the above list item
vREG_ID RECORDGROUP;
vEXECUTE NUMBER;
BEGIN
vREG_ID := FIND_GROUP('flex_group');
IF NOT ID_NULL(vREG_ID) THEN
DELETE_GROUP(vREG_ID);
END IF;
vEXECUTE := POPULATE_GROUP_with_query(vREG_ID,:p_query);
set_lov_property('flex_lov',group_name,'flex_group'); to assign the used select statement for the selected master table in the list iem

3- now the list of values now assigned with the id and the name of the entity that you will select form to display the contacts assigned to this specified entity

Thursday, November 5, 2009

Get Online Currency Exchange Rates


here we will explain how to use a java bean in the forms to get the currecny exchange rates from webservice provided by a website on the internet

first step for implementing this java bean is
1- put the jar file CurrencyExchange.jar in the path form
2- add the path of this jar file with the full name in the archivjinit paramter in your working section in the Fromsweb.cfg file
3-add the full path in step 2 also in classpath parameter in Default.env file

4- create new form and create a bean item and set its implementation class to
oracle.forms.jvr.CurrencyExchange

5- create items that hold from currency and to currency with the values of standard currency symbol

6- call the following code

fbean.invoke('yourblock.yourbean',1,'setFrom',:fromcurrencybindvariable);
fbean.invoke('yourblock.yourbean',1,'setTo',:tocurrencybindvariable);
:bindvariableforresult:=fbean.invoke_char('yourblock.bean',1,'change','');

the jar file link
http://www.4shared.com/file/146643242/9c8e15e6/CurrencyExchange.html

Sunday, September 6, 2009

Dynamic Import using sqlldr



Here i provide a form that can be used to import dynamically data from a specified file to selected table and columns
- this version run in the environment that the database and application server is on the same server , other environment needs extra code adding to the provided code.
- you can add new feature or functionality to the code provided , or enhance the existing code according to your requirements




-- You choose the table that you want to upload data into from the provided list of the tables in your schema.

-- you will choose the columns form the table column list populated
-- write the file name with extension that you want to upload data from

-- choose if truncte the table or append the data to the existing data



------ the explaination of the mechanism
-- the main idea is to dynamically create the control file , and the batch file that will change the running oracle home and run the Sql loader command using the control file created
an audit piece of code is issued at the end of the program unit to audit the importing process.
-- the user will only choose the table and column and write the file name with extenstion .
--- Code Sample -----
PROCEDURE Import_process IS
v_load_directory varchar2(30);
V_FILE_TYPE UTL_FILE.FILE_TYPE;
v_directory_path varchar2(200) ;
v_file_name varchar2(50);
v_ext varchar2(3);
V_COL_LIST VARCHAR2(500);
V_SEP_POS NUMBER(3);
V_ORA_HOME VARCHAR2(500);
v_bat_file_name varchar2(500);
v_control_file varchar2(50);
BEGIN

if :table_name is null then
message('You Must Choose Table For Importing Process'); message('You Must Choose Table For Importing Process');
raise form_trigger_failure ;
end if ;
if :file_name is null then
message('You Must Specify File Name You Want to Upload'); message('You Must Specify File Name You Want to Upload');
raise form_trigger_failure ;
end if ;
if Get_List_Element_Count('SELECTED_COLS')=0 then
message('No Column Selected For Importing Process');message('No Column Selected For Importing Process');
raise form_trigger_failure ;
end if ;
--- start collecting information and parameters for the process
v_load_directory:=sm_check_pkg.check_application_setting('LOAD_DATA_DIR');
v_directory_path :=sm_get_pkg.get_directory_path(v_load_directory);
v_file_name:=substr(:file_name,1,instr(:file_name,'.')-1) ;
v_ext:=substr (:file_name,-3) ;
V_ORA_HOME:=SM_CHECK_PKG.CHECK_APPLICATION_SETTING('DB_ORA_HOME');


V_COL_LIST:='';
For i IN 1 .. Get_List_Element_Count('SELECTED_COLS') Loop
V_COL_LIST:=V_COL_LIST','Get_List_Element_Value( 'SELECTED_COLS', i );
End loop ;
---V_SEP_POS:=INSTR(V_COL_LIST,',',-1);
V_COL_LIST:=SUBSTR(V_COL_LIST,2);

-- CREATE TEH CONTROL FILE
v_control_file:=dbms_random.STRING('b',8)'.''ctl';
v_file_type:=utl_file.fopen(v_load_directory,v_control_file,'W');
UTL_FILE.putf(V_FILE_TYPE,'LOAD DATA'); -- first line
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'INFILE ''''' v_directory_path'\':file_name''''); -- second line
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'BADFILE ''''' v_directory_path'\'v_file_name'.''bad'''''); -- third line
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'DISCARDFILE ''''' v_directory_path'\'v_file_name'.''dsc'''''); -- fourth line
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,:PREDATA_02);
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'INTO TABLE ''"TMS"''.''"':TABLE_NAME'"');
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'FIELDS TERMINATED BY '''''';''''');
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'('V_COL_LIST')');
UTL_FILE.fclose(V_FILE_TYPE);
synchronize;

---- CREATE THE BATCH FILE
v_bat_file_name:=dbms_random.STRING('b',8)'.''bat';
v_file_type:=utl_file.fopen(v_load_directory,v_bat_file_name,'W');
UTL_FILE.putf(V_FILE_TYPE,'@echo on ');
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'set oracle_home='v_ora_home);
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,'cd\');
UTL_FILE.new_line(V_FILE_TYPE); ------------------------------------------
UTL_FILE.putf(V_FILE_TYPE,v_ora_home'\bin\sqlldr.exe '
'userid=tms/tms@hdb control='v_directory_path'\'v_control_file);
UTL_FILE.fclose(V_FILE_TYPE);
synchronize;
host('start 'v_directory_path'\'v_bat_file_name);
if Form_success then
paragma_pkg.p_import_audit(info_pkg.get_current_user_id,v_control_file,v_bat_file_name);
end if ;
END;

Tuesday, August 25, 2009

Forms Dynamic Audit Program


For sure that auditing the insert , update , delete transaction is ver cretical issue for some customers although the auditing may little preformance reduction , but they are still interested in monitoring the DML transactions of the application user ,


OF Course we know that there are two main options about auditing


First is the Database audit it self ( you can enable this feature for selected or all tables of your application )

Second is the Forms side audit and this is the option which we provide dynamic solution

you need dynamic and effective design to implement this auditing with minumum coding
at first you need two tables ( gn _audit_master , gn_audit_detail ) two table instead of one to reduce the storage required by this program.
- Note that all column names and table names are related to your environment i.e. you can choose any name you want

after that you will make a procedure to insert the master record detail ( like the current form , the current user , the current date , .... )

- then you can start to code the procedure that will implement this functionality

- in your form create Post_insert-trigger in the block you want to audit and
call your procedure and pass the operation type 'I' means insert


- in your form create Post- upate in the block you want to audit and call your procedure and pass the operation type 'U' means update


- in your form create Pre-delete ................................


-- usage note :

1- if your primary key item get its value from before insert trigger on the database , so you must change the block property DML_return_value to 'Yes'


2- the code contains ' substr , 'string' these literals are related to My environment and you can customize your code according to yours


3- the program enable you to track all operation with all values even the record is deleted and the ability to restore the deleted row with the same values exactly
4- after you understand the functionality of the program you can adjust it to add new functionaliyt , edit existing functionality, or delete exisiting feature.



the code and scripts available on this link :
http://www.4shared.com/file/127826208/fabb5f2d/Audit_program.html

Thursday, August 13, 2009

Before Starting ( Application Development and Desgin Standards)

- Here in this post we will provide sample of guides that Any Development and Design team should keep and apply .






1- You Should Comment your Tables and database objects to facilitate the understanding of the database design and reduce the cost of any future modification and facilitates the knowledge requested by any developer or desginer





2- You should comment your columns if needed to be cleared what is this column functionality is . ( if columns are commented , the developer will know in very easy way what this column is designed to , and whic values allowed & which symbol means )







3- Naming Convention for database objects and its attributes should be kept to facilitate the work process and make any common adjustments can be done.( suppose that you keep the naming convention of your tables to be prefixed by 2 letter_ and the table primary key column is composed of your table name without the prefeix and suffixed by _id, you can create a stored procedure that create a sequence and trigger for any new table , so you can save the time and effort by keeping database objects naming conventions )





4- Documentation of the database design is very important for understanding, updating , and maintaining the database design , this document should describe the details of the database design and its functionality and break down ERDs .







5- The development environment must have maintained Templates for any developed business unit ( form – report - process - menue , ... etc) by having templates with subclassing you can adjust the code of specified triggers ( subclassed one ) of 1000 form module for example in 1 menutes after compiling the 1000 if you use object classing , or only one minute without compiling if you call the code stored in pll library ,


also templates are very critical issue in the development process or the interface changing .





6- Commenting the code should include the name of author



, the date of creation, the date of adjustment, the reason,



simple description of the functionality of the code. ,and hints on every line important to know







7- Testing Procedures must be set , starting with the unit test , transaction test to improve the quality of the product the process can be as the following :





- Test the business unit against (insert , update, delete, and query functions)



- Test the business unit against the required validation of the form or the report



- Test the functionality of the form or report against the functionality in the whole system cycle.


- Maintain more than one test scenario for the business unit .





8- Performance considerations must be taken to improve the quality of the product according to your frame work and your requirements , forexample





- Any SQL statement must be written on the database side not in the forms side to avoide the network traffic caused by the database roundtrips



- Any business unit must be developed from the designed template ( Form module from the from module template , report from the report template, parameter form from the parameter form template ,….. etc) to centeralize the performance tunning issues







- Packages Should be maintained and used in the Development process to get their benefits in performance and organizing the work






- Naming Conventions of the forms , reports ,PLL libraries , OLB libraries , Object groups , Program units , canvases, blocks, …. Etc must be maintained to easily develop and maintain (easy and fast )





- Any common Pl/sql code must be packaged in the PLL libraries to ensure that the right code is used for the issue arised



- Any common interface items packaging should be packaged in Object group (for example approval process , contact object group )





- Primary keys must be numbers only and auto filled not user filled other unique columns like code can have unique constraint and can maintained by the user




- No composite primary keys are allowed





- Use the appropriate way to get block non related data ( Join – view – database function ) according to the situation rather than using the post – query trigger







- Any in ordinary way of coding must be discussed between team member before using it in the development process ( discussion among the team member is very important and very usefull process )





- Any object group, templates, Should be documented and has its read me file to guide the developer how to use it in the development process.





- The basic triggers of the form or the report mustn’t be used by the developer ( instead write the code in the called procedures in the original triggers for example design your when-new-form-instance to call the following procedure - p_before_init ;


Fram_work_code;


p_after_init ;
p_before_init ; is module program unit that the user can write his code when he want to execute his own code in the when new form instance trigger , and so on .....




- Messaging to the end user must be done through defined package in the system to facilitate any future modification or enhancements ( like multilingual messaging)




- Any interface item ( text item , display item , list item , Button , ….. etc) must be sub classed from the appropriate object ( smart class shoul be maintained to easily do this process)





- Any tabular Block should have indicator item to improve the interface looking and current record visual attribute



- Any huge number of columns to be displayed on the form should be set its canvas to stack canvas style to expand horizontally.







9- “ Know How “ documentation must be maintained to facilitate the work process and exchange the experience between team members





10- The implementation of the work to the production Environment must have documented procedures and flow chart ( this is very important issue )





11- Documentation of how to develop Form Module, how to develop Report module, how to develop parameter form Must be read before any development starts for the first time , to avoid the violation of develompment standrds













Read Client machine Information ( Get benefit of using the java beans in Forms)



Using java beans in your forms is very usefull action to increase your application performance , functionality , and interface attraction .





fore example


1- a java bean that restrict the input of text item to number will decrease network traffic if the user enter character.


2- a java bean that customize the shape of forms buttons will make your interface more attractive


3- a java bean that read client machine information , increase your forms functinality





in this post we will explain a java bean that can read client machine information ( webutil can do this also ) and pass it to the form

- consider that you want to know which Ip address currenty use this form

first step is to make the deployment steps of using java bean

1- pur the jar file in your java path
2- edit Archive_jinit parameter in your formsweb.cfg in your section to add this jar name
3- create a bean area in your forms
4- set the implementation class property of your bean item to
oracle.forms.fd.ClientInfos ( case sensitive)
5- write your code to get the information you want as follow :

- to get the Ip address and pass it to bind variable
:your bind variable:= Get_Custom_Property('your bean item', 1, 'IP' ) ;

- to get the operating system
:your bind variable : =get_custom_property('your bean item',1,'operating');

- to get the operating system user name
:your bind variable : =get_custome_property('your bean item',1,'username');


very important note :

-- if you want to get this information in "when new form instance "

you have to write your code in " when timer expired " to ensure that the form interface included the bean area is built

you can download the jar file from http://sheikyerbouti.developpez.com/forms-pjc-bean/menu/

Tuesday, August 11, 2009

PRAGMA autonmous_transaction

If you want to create a procedure to perform some dml operations and commit this transactions regardless or without affect the transactions control of the calling environment you should use PRAGMA autonmous_transaction
in the declaration section of your pl/sql code

pragma autonmous_transaction instruct oracle server to do the dml operations and commit or rollback independently of the calling environment

sample code :

create or replace procedure xx as

pragma autonmous_Transaction ;
begin
......
end;

Avoid Post - query code round trip (Block on join - Function based column sourc)

getting the value of a column that not related to your database block have many various methods , ( post query code - block on joing - function based column source )

consider a asituation that you want to display the the dept name in your employees block , the old fashion and not efficient way is to write a select statemnt in Post-query trigger of your block using the value of the emp.deptid bind variable in your form , this way in this situation is not effecient as it make round tirp to the database to get the dept name , also you can suppose that the business requirement arisen to not display the deptname only , it needs to display 'deptname-deptlocation' , in this situation you will change all modules that display this field !!!!!!!

the most effecient way to display the dept name is to make a database function that have argument deptid and return the deptname ,
after that you can create a field in your emp block and change its property database to yes and its column source name to "your function name " , this will erase any roundtrip to the database in your post query trigger , also you can change the output of the function according any new business requirement , also you will write the code once and use it many times

--- block on join

suppose that you want to display 9 or more columns from the dept table with your emp table ( block on join will be the effecient way )

implementation of the block on join
- create your emp block
- create your other columns you need
- change the column source name of the emp block to 'emp,dept'
- change the source column property for your added column to the corresponding database column name ( don't forget prefex with table name)
- change the property of your emp blcok primary key to primary key - yes
- change the property query only , update allowed , insert allowed to yes, no , no respectively of your added columns
- change the properry " dml target name " of your block to 'emp'

run your form to show the result

Monday, August 10, 2009

Sending Email With Attachment

sending email message from Oracle database ( note that we can send mail form the Forms by using javamail ) is very simple , specially starting form the 10 g release UTL_Mail package that make the issue very simple , but have limitation in the size of the attachment , so we can customize the old demo_mail package that supplied with oracle to send mail with attachment by changing some code in Attach_base64 procedure to be like the following :

PROCEDURE ATTACH_BASE64
(P_CONN IN OUT NOCOPY UTL_SMTP.connection
,P_DATA IN BLOB
,P_MIME_TYPE IN VARCHAR2 := 'application/octet'
,P_INLINE IN BOOLEAN := TRUE
,P_FILENAME IN VARCHAR2 := NULL
,P_LAST IN BOOLEAN := FALSE
)
IS

i PLS_INTEGER;
len PLS_INTEGER;
BEGIN
attach_demo_mail.BEGIN_ATTACHMENT(p_conn, p_mime_type, p_inline, p_filename, 'base64');

-- Split the Base64-encoded attachment into multiple lines
i := 1;
len := DBMS_LOB.getLength(p_data);

WHILE (i < len) LOOP
IF(i + MAX_BASE64_LINE_WIDTH < len)THEN
UTL_SMTP.Write_Raw_Data (p_conn
, UTL_ENCODE.Base64_Encode(
DBMS_LOB.Substr(p_data, MAX_BASE64_LINE_WIDTH, i)
)
);
ELSE
UTL_SMTP.Write_Raw_Data (p_conn
, UTL_ENCODE.Base64_Encode(
DBMS_LOB.Substr(p_data, (len - i), i)
)
);
END IF;

UTL_SMTP.Write_Data(p_conn, UTL_TCP.CRLF);
i := i + MAX_BASE64_LINE_WIDTH;
END LOOP;
END_ATTACHMENT(p_conn, p_last);
END;
------------------------------------------------------------------------

After that you can make your private pkg the use the supplied package to sned your email with different type of attachment ( you can customize the code below according to your requirement)

Pre - requisities -- create your own table to load the blob files to it
CREATE TABLE GN_BLOB
(
BLOB_RECID NUMBER,
TEMP_FILE BLOB
)

CREATE OR REPLACE PACKAGE TMS.mail_Attach_pkg AS
/******************************************************************************
NAME: mail_Attach_pkg
PURPOSE:

REVISIONS:
Ver Date Author Description
--------- ---------- --------------- ------------------------------------
1.0 10/08/2009 1. Created this package.
******************************************************************************/

procedure p_load_file_to_db(p_file_name varchar2,p_recid out number);
PROCEDURE p_MAIL_WITH_ATTACHMENT(p_attach_type number,p_file_name varchar2,p_sender varchar2,p_receipients varchar2 ,p_subject varchar2,p_message varchar2);


END mail_Attach_pkg;
/


CREATE OR REPLACE PACKAGE BODY TMS.mail_attach_pkg AS
/******************************************************************************
NAME: mail_attach_pkg
PURPOSE:

REVISIONS:
Ver Date Author Description
--------- ---------- --------------- ------------------------------------
1.0 10/08/2009 1. Created this package body.
******************************************************************************/
procedure p_load_file_to_db(p_file_name varchar2,p_recid out number)is
LOBD BLOB;
FILS BFILE;
AMT INT;
v_Recid number(16);
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN

-- get the record id for the blob

select seq_GN_blob.nextval into v_Recid from dual;

-- load html file to database

INSERT INTO GN_blob(temp_file,blob_recid) -- this your table that you will save the blob file to use it after that
VALUES(EMPTY_BLOB(),v_Recid)
RETURNING Temp_FILE INTO LOBD;

FILS:=BFILENAME('TEST_DIR', p_file_name);
DBMS_LOB.FILEOPEN(FILS, DBMS_LOB.FILE_READONLY);
AMT:= DBMS_LOB.GETLENGTH(FILS);
DBMS_LOB.LOADFROMFILE(LOBD, FILS, AMT); -- LOAD THE FILE directy to the data base
DBMS_LOB.FILECLOSE(FILS);
COMMIT;

p_Recid:=v_recid ;

end ;
--****************************************************************************************************************
PROCEDURE p_MAIL_WITH_ATTACHMENT(p_attach_type number ,p_file_name varchar2,p_sender varchar2,p_receipients varchar2 ,p_subject varchar2,p_message varchar2) is
t_conn UTL_SMTP.Connection;
t_blob BLOB;
-- cCRLF ; --VarChar2(2) := CHR(13) CHR(10);

v_Recid number(16);
BEGIN


--- load the file to the database
P_LOAD_FILE_TO_DB(p_file_name,v_recid);


-- load BLOB
DBMS_LOB.CREATETEMPORARY(t_blob, FALSE);
SELECT gn_blob.TEMP_FILE INTO t_blob FROM GN_blob WHERE blob_recid = v_recid;

-- start mail
t_conn := Attach_DEMO_MAIL.Begin_Mail(p_sender,
p_receipients,
p_subject,
attach_DEMO_MAIL.MULTIPART_MIME_TYPE);

-- some inline html text first line
attach_DEMO_MAIL.Attach_Text(t_conn, 'Dear sirs 'UTL_TCP.CRLF
' Good Day kindly find our attached report haythem mousa 'UTL_TCP.CRLF, 'text/plain');

--- second line
---attach_DEMO_MAIL.Attach_Text(t_conn, 'second line 'UTL_TCP.CRLF
---- ' 22222t 'UTL_TCP.CRLF, 'text/plain');

-- attachment
-- 'application/pdf' for PDF files
-- DEMO_MAIL.Attach_Base64(t_conn, t_blob, 'application/x-zip-compressed', TRUE, 'file.zip');
if p_attach_type=1 then
Attach_DEMO_MAIL.Attach_Base64(t_conn, t_blob, 'text/txt', TRUE, 'test.txt');
elsif p_attach_type=2 then
Attach_DEMO_MAIL.Attach_Base64(t_conn, t_blob, 'image/jpg', TRUE, 'sample.jpg');
elsif p_attach_type=3 then
Attach_DEMO_MAIL.Attach_Base64(t_conn, t_blob, 'application/pdf', TRUE, 'sample.pdf');
end if ;

-- some html attachment
---html attachment
--c_DEMO_MAIL.Attach_Text(t_conn, 'This is a HTML report.'
--cCRLF' good morning ', 'text/plain', FALSE,null);

-- end connection
attach_DEMO_MAIL.End_Mail(t_conn);

--DBMS_LOB.FREETEMPORARY(t_blob);
COMMIT;
END;


END mail_attach_pkg;
/


you can customize the code above to add,edit, delete features

Tuesday, August 4, 2009

KEY Flexfield generation on your application


- in this post we will know the basics of how to make your own key flexfield mechnaism in your application , after knowing these basics you can add new features , edit existed one , and enhance the functionality of the mechanism provided

- you can enhance the code provided and change it according to your environment of development ( as the code contains some specified piece of codes that related to my own development standards and environment )

at first we will explain the bussiness functionality and desgin of this process,

-the first step is to define value sets and value set details table to store the data about value set you want to use

- after that you can define the key flex field and define its detail information ( number of segment , prompt of each segment , sequqnece of each segment , .....) and assign a value set to each segment in the key flex field detail

- next step is to define a table to store the data combination of the different flex fields

here are sample scripts for these tabl creation ( note that the naming convention and some columns related to current environment)



-----------------------------------------
CREATE TABLE GN_VALUE_SET
(
VALUE_SET_RECID NUMBER NOT NULL,
VALUE_SET_NAME VARCHAR2(50 BYTE) NOT NULL,
VALUE_SET_DESC VARCHAR2(50 BYTE) NOT NULL,
SYSTEM_DATA NUMBER(2) DEFAULT 0,
CODE_LEN NUMBER(2) DEFAULT 3
)
TABLESPACE SYSTEM
PCTUSED 40
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
FREELISTS 1
FREELIST GROUPS 1
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


CREATE TABLE GN_VALUE_SET_DTL
(
VALUE_SET_DTL_RECID NUMBER NOT NULL,
VALUE_SET_RECID NUMBER,
VALUE_SET_CODE VARCHAR2(10 BYTE) NOT NULL,
VALUE_STATUS NUMBER(2) DEFAULT 1,
VALUE_SET_DESC VARCHAR2(50 BYTE),
VALUE_SET_EDESC VARCHAR2(50 BYTE)
)
TABLESPACE SYSTEM
PCTUSED 40
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
FREELISTS 1
FREELIST GROUPS 1
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


CREATE TABLE GN_FLEXFIELD_DET
(
FLEXFIELD_DET_RECID NUMBER(16),
FLEXFIELD_RECID NUMBER(16) NOT NULL,
SEGMENT_SERIAL NUMBER(2),
VALUE_SET_RECID NUMBER(16),
SEGMENT_ARABIC_PROMPT VARCHAR2(50 BYTE),
SEGMENT_ENGLISH_PROMPT VARCHAR2(50 BYTE),
SEGMENT_LEN NUMBER(5)
)
TABLESPACE USERS
PCTUSED 0
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


CREATE TABLE GN_FLEXFIELD_COMB
(
FLEXFIELD_COMB_RECID NUMBER(16),
FLEXFIELD_RECID NUMBER(16),
SEGMENT_COMB_VALUE VARCHAR2(200 BYTE),
SEGMENT_COMB_DESC VARCHAR2(500 BYTE)
)
TABLESPACE USERS
PCTUSED 0
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


CREATE TABLE GN_FLEXFIELD
(
FLEXFIELD_RECID NUMBER(16),
FLEXFIELD_NAME VARCHAR2(50 BYTE),
SEPARATOR VARCHAR2(1 BYTE),
SEGMENT_NUMBER NUMBER(2),
ALLOW_DYNAMIC_INSERT NUMBER(1) DEFAULT 1 NOT NULL,
ARABIC_WINDOW_PROMPT VARCHAR2(50 BYTE),
ENGLISH_WINDOW_PROMPT VARCHAR2(50 BYTE)
)
TABLESPACE USERS
PCTUSED 0
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;


CREATE UNIQUE INDEX GN_FLEXFIELD_PK ON GN_FLEXFIELD
(FLEXFIELD_RECID)
LOGGING
TABLESPACE USERS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
NOPARALLEL;


CREATE UNIQUE INDEX GN_FLEXFIELD_COMB_PK ON GN_FLEXFIELD_COMB
(FLEXFIELD_COMB_RECID)
LOGGING
TABLESPACE USERS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
NOPARALLEL;


CREATE UNIQUE INDEX GN_FLEXFIELD_DET_PK ON GN_FLEXFIELD_DET
(FLEXFIELD_DET_RECID)
LOGGING
TABLESPACE USERS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT
)
NOPARALLEL;


CREATE UNIQUE INDEX PK_GN_VALUE_SET ON GN_VALUE_SET
(VALUE_SET_RECID)
LOGGING
TABLESPACE SYSTEM
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
FREELISTS 1
FREELIST GROUPS 1
BUFFER_POOL DEFAULT
)
NOPARALLEL;


CREATE UNIQUE INDEX PK_GN_VALUE_SET_DTL ON GN_VALUE_SET_DTL
(VALUE_SET_DTL_RECID)
LOGGING
TABLESPACE SYSTEM
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
FREELISTS 1
FREELIST GROUPS 1
BUFFER_POOL DEFAULT
)
NOPARALLEL;


CREATE OR REPLACE TRIGGER TRG_GN_VALUE_SET BEFORE INSERT ON GN_VALUE_SET REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE V_RECID NUMBER ;
BEGIN
SELECT SEQ_GN_VALUE_SET.NEXTVAL INTO V_RECID FROM DUAL ;
:NEW.VALUE_SET_RECID := V_RECID ;
END TRG_GN_VALUE_SET;
/
SHOW ERRORS;



CREATE OR REPLACE TRIGGER TRG_GN_VALUE_SET_DTL BEFORE INSERT ON GN_VALUE_SET_DTL REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE V_RECID NUMBER ;
BEGIN
SELECT SEQ_GN_VALUE_SET_DTL.NEXTVAL INTO V_RECID FROM DUAL ;
:NEW.VALUE_SET_DTL_RECID := V_RECID ;
END TRG_GN_VALUE_SET_DTL;
/
SHOW ERRORS;



CREATE OR REPLACE TRIGGER TRG_GN_FLEXFIELD_DET BEFORE INSERT ON GN_FLEXFIELD_DET REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE V_RECID NUMBER ;
BEGIN
SELECT SEQ_GN_FLEXFIELD_DET.NEXTVAL INTO V_RECID FROM DUAL ;
:NEW.FLEXFIELD_DET_RECID := V_RECID ;
END TRG_GN_FLEXFIELD_DET;
/
SHOW ERRORS;



CREATE OR REPLACE TRIGGER TRG_GN_FLEXFIELD_COMB BEFORE INSERT ON GN_FLEXFIELD_COMB REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE V_RECID NUMBER ;
BEGIN
SELECT SEQ_GN_FLEXFIELD_COMB.NEXTVAL INTO V_RECID FROM DUAL ;
:NEW.FLEXFIELD_COMB_RECID := V_RECID ;
END TRG_GN_FLEXFIELD_COMB;
/
SHOW ERRORS;



CREATE OR REPLACE TRIGGER TRG_GN_FLEXFIELD BEFORE INSERT ON GN_FLEXFIELD REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE V_RECID NUMBER ;
BEGIN
SELECT SEQ_GN_FLEXFIELD.NEXTVAL INTO V_RECID FROM DUAL ;
:NEW.FLEXFIELD_RECID := V_RECID ;
END TRG_GN_FLEXFIELD;
/
SHOW ERRORS;



ALTER TABLE GN_VALUE_SET ADD (
CONSTRAINT PK_GN_VALUE_SET
PRIMARY KEY
(VALUE_SET_RECID)
USING INDEX
TABLESPACE SYSTEM
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
FREELISTS 1
FREELIST GROUPS 1
));


ALTER TABLE GN_VALUE_SET_DTL ADD (
CONSTRAINT PK_GN_VALUE_SET_DTL
PRIMARY KEY
(VALUE_SET_DTL_RECID)
USING INDEX
TABLESPACE SYSTEM
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
FREELISTS 1
FREELIST GROUPS 1
));


ALTER TABLE GN_FLEXFIELD_DET ADD (
CONSTRAINT GN_FLEXFIELD_DET_PK
PRIMARY KEY
(FLEXFIELD_DET_RECID)
USING INDEX
TABLESPACE USERS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
));


ALTER TABLE GN_FLEXFIELD_COMB ADD (
CONSTRAINT GN_FLEXFIELD_COMB_PK
PRIMARY KEY
(FLEXFIELD_COMB_RECID)
USING INDEX
TABLESPACE USERS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
));


ALTER TABLE GN_FLEXFIELD ADD (
CONSTRAINT GN_FLEXFIELD_PK
PRIMARY KEY
(FLEXFIELD_RECID)
USING INDEX
TABLESPACE USERS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
MINEXTENTS 1
MAXEXTENTS 2147483645
PCTINCREASE 0
));


ALTER TABLE GN_VALUE_SET_DTL ADD (
CONSTRAINT FK_GN_VALUE_REFERENCE_GN_VALUE
FOREIGN KEY (VALUE_SET_RECID)
REFERENCES GN_VALUE_SET (VALUE_SET_RECID));
-----------------------------------------------------


- Next step is to make your forms moudules that define value set and key flexfield and make the required functions and procedure to get information about value set or key flexfield it sefl


- after that you can make your object group that will contains the items , blocks, canvases,.... that will be used to implement this functionality

the object group should contain the following :

1- stack canvas 2- window 3- control block 4- two list of values one of them is dummy lov to be attached to the item in your form that will invoke the key flex field

5-one parameter with number data type to hold the value of the value set that will displayed for the current segment

6- pl/sql package that will contain all procedures and functions that will be implement that funcationality

7- the items in the block ( segment_1 , .... segment_6 ) this segments that will be displayed to the user according to the number of the segments defined in the choosed flexfield , i.e. if the flex field has 4 segments so the items ( segment_1,segment_2,....,segment_4) will be displayed to the user the same rule applied for the display items ( desc_1, ...,desc_6)
but the items value_set_1 ,..... value_set_6 will not displayed they are only for holding the value set record id that attach to corresponding segment , these items can be deleted and package variables used instead )

8- two display item to hold the selected value and describtion selected form the list of value from each segment

9- two display item to hold the combined value and combined desc , ( these two items can be replaced and package variables can be used )

here the code of the forms package included
-------------------------------------------------------------------

PACKAGE init_flexfield IS

flex_item_name varchar2(200); ---- to hold the item name that invoked the key flex field and waiting for the combination
flex_item_name_desc varchar2(200); -- to hold the item name that will hold the description of the combined value
flex_block_name varchar2(100);--- the block of the item that invoked the flex field
flex_recid number(16); -- the applied felx field --- hard coded ----
flex_window_prompt varchar2(50); --- hold the window prompt
flex_separator varchar2(1); ---flex_separator
flex_segment_number number(2); ---flex_segment_numbe
flex_dynamic_status boolean ; -- if the flex field allow to insert the non existed combination into the combination table


procedure invoke_flex_field(target_item varchar2, target_item_desc varchar2);
procedure invoke_lov ;
Procedure validate_segment_value;
procedure ensure_right_lov ;
Procedure combine_segments ;
procedure validate_combination ;



END;

-------------------------------------------------------------------------------


PACKAGE BODY init_flexfield IS
----------------------------------------------------------------
----------------------------------------------------------------

Procedure combine_segments is

begin

--- clear any old combination
:combined_value:='';
:combined_desc:='';

-- loop the segments to catch the values and concat between each value with the flex field separator
for i in 1..init_flexfield.flex_segment_number loop
:combined_value:=:combined_valueinit_flexfield.flex_separatorname_in('segment_'i);
:combined_desc:=:combined_descinit_flexfield.flex_separatorname_in('desc_'i);
end loop;
--- omit extra separator
:combined_value:=substr(:combined_value,2);
:combined_desc:=substr(:combined_desc,2);

end ;
---------------------------------------------------------------
procedure ensure_right_lov is

v_cursor_segment varchar2(50);
v_segment_number number(2);
begin

--- this code get the current item and get the value of the value set id assigned to this segment and pass this value to the
---- parameter init_valu_set that is used in calling the list of values accross all segments
v_cursor_segment:=:system.trigger_item;
v_segment_number:=to_number(substr(v_cursor_segment,-1));
:parameter.INIT_VALUE_SET:=name_in('value_set_'v_segment_number);
end ;
--------------------------------------------------------------------------
Procedure validate_segment_value is
v_cursor_segment varchar2(50);
v_segment_number number(2);
v_valid number(2);
v_segment_desc varchar2(50);
begin

INIT_FLEXFIELD.ensure_right_lov ;
v_cursor_segment:=:system.trigger_item;
v_segment_number:=to_number(substr(v_cursor_segment,-1));

--- check if this value existed or not using the database package flexfield_pkg
v_valid:=flexfield_pkg.validate_sement_value(name_in(v_cursor_segment),name_in('value_set_'v_segment_number)) ;


if v_valid = 0 then
message('Invalid Value for the segment');
message('Invalid Value for the segment');
raise form_trigger_failure;
else
--- get the right desc for semgnet
v_segment_desc:=value_set_pkg.get_value_set_desc(:parameter.INIT_VALUE_SET,
value_set_pkg.get_detail_Recid(name_in('value_set_'v_segment_number),name_in('segment_'v_segment_number)
),translation_pkg.get_user_lang_id);
copy(v_segment_desc,'desc_'v_segment_number);
end if ;

end;

--------------------------------------------------------------------------

procedure invoke_lov is

v_cursor_segment varchar2(50);
v_segment_number number(2);
begin

v_cursor_segment:=:system.trigger_item;
v_segment_number:=to_number(substr(v_cursor_segment,-1));

:parameter.INIT_VALUE_SET:=name_in('value_set_'v_segment_number);


if show_lov('LOV_VALUE') then

copy(:lov_value,name_in('system.trigger_item'));
--copy(:lov_desc,'desc_'v_segment_number);
else

message('you must choose value from list');message('');
raise form_trigger_failure ;
end if ;



end ;


---------------------------------------------------------------------------------------------------------------

procedure invoke_flex_field(target_item varchar2, target_item_desc varchar2) is

cursor c_cur is select GN_FLEXFIELD_DET.flexfield_det_recid,value_set_recid from GN_FLEXFIELD_DET where GN_FLEXFIELD_DET.flexfield_recid=init_flexfield.flex_recid
order by segment_serial ;

v_segment_prompt varchar2(50);
v_counter number(16);
begin
---- initialize package variables
init_flexfield.flex_item_name:=target_item;
init_flexfield.flex_item_name_desc:=target_item_desc ;
init_flexfield.flex_recid:=flexfield_pkg.get_account_flexfield(1);
init_flexfield.flex_window_prompt:=flexfield_pkg.get_flexfield_window_prompt(init_flexfield.flex_recid,translation_pkg.get_user_lang_id);
init_flexfield.flex_separator:=flexfield_pkg.get_flexfield_separator(init_flexfield.flex_recid);
init_flexfield.flex_segment_number:=flexfield_pkg.get_flexfield_segment_number(init_flexfield.flex_recid);
init_flexfield.flex_dynamic_status:=flexfield_pkg.get_dynamic_insert_flag(init_flexfield.flex_recid) ;
init_flexfield.flex_block_name:=:system.trigger_block;

---- set the width of the cnavas and the window ----------
set_canvas_property('flex_can',width,(init_flexfield.flex_segment_number*100)+24);
set_window_property('flex_window',width,(init_flexfield.flex_segment_number*100)+24);
--- center the button
set_item_property('flex_block.flex_ok',x_pos,((((init_flexfield.flex_segment_number*100)+24)-100)/2));
set_item_property('flex_block.flex_cancel',x_pos,((((init_flexfield.flex_segment_number*100)+24)-100)/2)+60);

-------- set the specified number of segment---

for i in 1..init_flexfield.flex_segment_number loop
set_item_property('segment_'i,visible,property_true);
set_item_property('segment_'i,enabled,property_true);
set_item_property('segment_'i,navigable,property_true);

set_item_property('segment_'i,required,property_true);
set_item_property('desc_'i,visible,property_true);

end loop;

--- clear the combined value and desc

:combined_value:='';
:combined_desc:='';

v_counter:=1;
---- set prompt of the segment -- and assign the value set of each segment to the corresponding item
for rec in c_cur loop
copy('','segment_'v_counter);
copy('','desc_'v_counter);
copy(rec.value_set_recid,'value_set_'v_counter);
v_segment_prompt:=flexfield_pkg.get_segment_prompt(rec.flexfield_det_recid,translation_pkg.get_user_lang_id);
set_item_property('segment_'v_counter,prompt_text,v_segment_prompt);
v_counter:=v_counter+1;
end loop;


--- BEFORE GO TO THE FLEXFIELD BLOCK YOU SHOULD CHANGE THE VALIDATION SCOPE

SET_FORM_PROPERTY(GET_APPLICATION_PROPERTY (CURRENT_FORM_NAME),VALIDATION_UNIT,FORM_SCOPE);

-- show the flex field cnavas and window
go_block('FLEX_BLOCK');

SET_FORM_PROPERTY(GET_APPLICATION_PROPERTY (CURRENT_FORM_NAME),VALIDATION_UNIT,ITEM_SCOPE);

end ; --- invoke flex field

--****************************************************************************

procedure validate_combination is

begin


init_flexfield.combine_Segments;

--- check if the combination exists
if flexfield_pkg.check_combination_exist(init_flexfield.flex_recid,:combined_value)=0 then --- the combination not existed before
--- check if the current flexfiedl allow dynamic insertion of non existed combination
if init_flexfield.flex_dynamic_status =true then
--- insert the combination
flexfield_pkg.generate_combination(init_flexfield.flex_recid,:combined_value,:combined_desc);
else
message ('This combination not existed ');message ('This combination not existed ');
raise form_trigger_failure ;
end if ;
end if;

copy(:combined_value,init_flexfield.flex_item_name);
copy(:combined_DESC,init_flexfield.flex_item_name_desc);

go_block(init_flexfield.flex_block_name);
go_item(init_flexfield.flex_item_name);


end ;

--#########################################################################3
END;


---------------------------- Some Data base packages Used ---------------------


CREATE OR REPLACE PACKAGE BODY TMS.flexfield_pkg AS
/******************************************************************************
NAME: flexfield_pkg
PURPOSE:


REVISIONS:
Ver Date Author Description
--------- ---------- --------------- ------------------------------------
1.0 28/07/2009 1. Created this package body.
******************************************************************************/



Function get_dynamic_insert_flag(p_flexfield_recid number) return boolean is



v_result number(2);


cursor c_cur is (select gn_flexfield.ALLOW_DYNAMIC_INSERT from gn_flexfield where gn_flexfield.FLEXFIELD_RECID = p_flexfield_recid) ;


begin


open c_cur ;
fetch c_cur into v_result;
if c_cur%notfound then
close c_cur ;
return false ;
end if ;
close c_cur ;


if v_result =1 then
return true;
elsif v_result =0 then
return false ;
else
return false ;
end if ;



end;
--**********************************************************************************************


Function check_combination_exist(p_flexfield_recid number , p_combination varchar2) return number is


cursor c_cur is (select gn_flexfield_comb.FLEXFIELD_COMB_RECID from gn_flexfield_comb where gn_flexfield_comb.FLEXFIELD_RECID=p_flexfield_Recid
and gn_flexfield_comb.SEGMENT_COMB_VALUE= p_combination);


v_return number(16);
begin


if p_flexfield_Recid is null or p_combination is null then
return null;
end if ;


open c_cur ;
fetch c_cur into v_Return;
if c_cur%notfound then
v_return:=0;
end if ;
close c_cur ;


if v_return>0 then
v_return:=1;
end if ;


return v_return ;



end ;


--****************************************************************************************


Procedure generate_combination(p_flexfield_recid number , p_combination varchar2,p_combination_desc varchar2) is


PRAGMA AUTONOMOUS_TRANSACTION;
begin


insert into gn_flexfield_comb (gn_flexfield_comb.FLEXFIELD_RECID,gn_flexfield_comb.SEGMENT_COMB_VALUE,gn_flexfield_comb.SEGMENT_COMB_DESC)
values (p_flexfield_recid,p_combination,p_combination_desc);
commit;



end ;


----*********************************************************************************************
function validate_sement_value(p_seg_value varchar2, p_value_set_Recid number) return number is



cursor c_cur is (select count(*) from gn_value_set_dtL where (gn_value_set_dtl.VALUE_SET_CODE =p_seg_value and
gn_value_set_dtl.VALUE_SET_RECID=p_value_set_Recid) AND gn_value_set_dtL.VALUE_STATUS=1 );


v_return number(16);
begin



open c_cur ;
fetch c_cur into v_return ;
close c_cur ;



return v_return;
end ;


--*******************************************************************************************



Function get_account_flexfield(p_sob_recid number) return number is


begin


return 1;
end ;
--******************************************************************************/
function get_segment_value_set_Recid ( p_segment_recid number) return number is
cursor c_cur is (select gn_flexfield_det.VALUE_SET_RECID from gn_flexfield_det where gn_flexfield_det.flexfield_det_Recid= p_segment_recid );


v_return number(16);


begin
if p_segment_recid is null then
return null;
end if ;



open c_cur ;
fetch c_cur into v_Return ;
if c_cur%notfound then
close c_Cur ;
return null;
end if ;
close c_cur ;



return v_return;


end ;



---******************************************************************************************
function get_segment_prompt(p_segment_recid number,v_lang_recid number) return varchar2 is


cursor c_cur is (select gn_flexfield_det.SEGMENT_ARABIC_PROMPT from gn_flexfield_det where gn_flexfield_det.flexfield_det_Recid= p_segment_recid);

cursor c_cur_e is (select gn_flexfield_det.segment_english_prompt from gn_flexfield_det where gn_flexfield_det.flexfield_det_Recid= p_segment_recid );

v_return varchar2(50);
begin


if p_segment_recid is null or v_lang_recid is null then
return null;
end if ;



if v_lang_recid =1 then
open c_cur ;
fetch c_cur into v_Return ;
if c_cur%notfound then
close c_Cur ;
return null;
end if ;
close c_cur ;


else


open c_cur_e ;
fetch c_cur_e into v_Return ;
if c_cur_e%notfound then
close c_Cur_e ;
return null;
end if ;
close c_cur_e;


end if ;


return v_return;




end ;
---**************************************************************************************************


Function get_flexfield_segment_number(p_flexfield_Recid number) return number is
cursor c_cur is (select gn_flexfield.SEGMENT_NUMBER from gn_flexfield where gn_flexfield.flexfield_Recid= p_flexfield_recid);


v_return number(2);


begin
if p_flexfield_recid is null then
return null;
end if ;



open c_cur ;
fetch c_cur into v_Return ;
if c_cur%notfound then
close c_Cur ;
return null;
end if ;
close c_cur ;



return v_return;


end ;



---*********************************************************************************


Function get_flexfield_separator(p_flexfield_recid number)return varchar2 is
cursor c_cur is (select gn_flexfield.SEPARATOR from gn_flexfield where gn_flexfield.flexfield_Recid= p_flexfield_recid);


v_return varchar2(1);


begin
if p_flexfield_recid is null then
return null;
end if ;



open c_cur ;
fetch c_cur into v_Return ;
if c_cur%notfound then
close c_Cur ;
return null;
end if ;
close c_cur ;



return v_return;


end ;



---************************************************************************************************
Function get_flexfield_window_prompt(p_flexfield_recid number,v_lang_id number ) return varchar2 is


cursor c_cur is (select gn_flexfield.arabic_window_prompt from gn_flexfield where gn_flexfield.flexfield_Recid= p_flexfield_recid);

cursor c_cur_e is (select gn_flexfield.english_window_prompt from gn_flexfield where gn_flexfield.flexfield_Recid= p_flexfield_recid );

v_return varchar2(50);
begin


if p_flexfield_recid is null then
return null;
end if ;



if v_lang_id =1 then
open c_cur ;
fetch c_cur into v_Return ;
if c_cur%notfound then
close c_Cur ;
return null;
end if ;
close c_cur ;


else


open c_cur_e ;
fetch c_cur_e into v_Return ;
if c_cur_e%notfound then
close c_Cur_e ;
return null;
end if ;
close c_cur_e;


end if ;


return v_return;




end ;
--################################################################################3

END flexfield_pkg;
/


---------------------------------------------------------------------------------


the code in the segments item triggers

1- key list value init_flexfield.invoke_lov;


2- pre-text init_flexfield.ensure_right_lov ;


3-When - validate item init_flexfield.validate_segment_value ;


the code that you will write it to invoke the flexfield from your form


init_flexfield.invoke_flex_field('TARGET_ITEM','target_item_desc');



--------------------------------------------------------------------------------------


Finally you can this FMB that contains this object group from the following URL









Sunday, August 2, 2009

DML Error Log Feature

if you want to merge or insert too many rows , and want if the insertion or updating failed for some records a log error process to know wich the error in each row failed , so you should use the DML logging error feature of 10 release 2

-- first step is to make the database know which table you want to log by running the followin procedure

dbms.errorlog.create_error_log('your table name','error_log_yourtablename');

- a table will be created fo you with some built in columns and the coluns of your table

-- the second step is to add the procedure that run the error loggin process into your DML plsql code

-- LOG ERRORS INTO ERROR_LOG_TABLENAME REJECT LIMIT 1;

-- you can use this clause in the merge statement like this

merge into (table)
using (table,view)
on (condition)
when matched then
(update st)
when not matchec then ()
[log errors into .......... reject limit 1]

Thursday, July 30, 2009

Internet Explorer 7 or 8 not work with oracle forms

this problem related to two things :


-- some add ons is enabled on the internet explorer make conflict

-- jvm.dll version of the jinitiator


the solution simply is to disable these add ons that cause conflict , after that replace the file jvm.dll located in the installation path of the jinitiator with the new one from sun


internet explorer will work successfully