Query to retrieve forms personalization from database:
SELECT FP.ENABLED,FP.DESCRIPTION PERSONALIZATION_DESC,FP.condition,FP.TRIGGER_OBJECT,FP.SEQUENCE,FP.FORM_NAME,FM.USER_FORM_NAME,F.FUNCTION_NAME,FT.USER_FUNCTION_NAME,F
.TYPE FROM FND_FORM_CUSTOM_RULES FP,FND_FORM_FUNCTIONS F,FND_FORM_FUNCTIONS_TL FT,FND_FORM_TL FM
WHERE F.FUNCTION_ID = FT.FUNCTION_IDAND FM.FORM_ID = F.FORM_IDAND FP.FUNCTION_NAME = F.FUNCTION_NAME--AND F.FUNCTION_NAME like '%'--AND UPPER (condition) LIKE '%%'AND FP.FUNCTION_NAME like 'ONT_OEXOEORD%'ORDER
What is called first? Forms Personalization or CUSTOM.pll
First your form personalization is called, and then CUSTOM.pll is called.
Commonly used events that are trapped using CUSTOM.pll are:- ZOOM
WHEN-NEW-FORM-INSTANCE
WHEN-NEW-BLOCK-INSTANCE
WHEN-NEW-RECORD-INSTANCE
WHEN-NEW-ITEM-INSTANCE
WHEN-VALIDATE-RECORD
However, for example in HRMS, you can also write code in CUSTOM.pll to trap below listed events :-PRE-DELETE and POST-DELETE
PRE-UPDATE and POST-UPDATE
PRE-INSERT and POST-INSERT
POST-FORMS-COMMIT
WHEN-CREATE-RECORD
KEY-DELREC
How and why does CUSTOM.pll work?
Every form in Oracle Apps is created using something called as TEMPLATE.fmb. But some of the modules like HRMS have their own HR Specific Templates[HRTEMPLT.fmb]. These template files have form level triggers that make call to CUSTOM.pll. The triggers that can be trapped using CUSTOM.pll in HRMS screen can be different than those which can be trapped for other modules.
Custom.pll scenarios
1. Change the label of a fieldapp_item_property2.set_property ('BLOCK.FIELD',label,'New Label');
2. Default a value
copy (TO_CHAR (n_person_id),'PERSON_BLOCK.PERSON_ID' );
3. Alter the SQL for LOV Query
PROCEDURE filter_customers_in_lov IS
v_customer_group_id recordgroup;
n_temp_id NUMBER;
v_customer_lov lov;
BEGIN
v_customer_group_id := create_group_from_query('XX_CUSTOMER_GROUP'
,'select ... from hz_cust_accounts where ..your custom criteria here..');
n_temp_id := populate_group(v_customer_group_id);
v_customer_lov := find_lov('EXISTING_LOV_NAME_HERE');
IF get_lov_property(v_customer_lov,group_name) = 'EXISTING_GROUP_NAME_HERE'
THEN
set_lov_property(v_customer_lov,group_name,'XX_CUSTOMER_GROUP');
END IF;
END filter_customers_in_lov;
4. Make a field mandatory
app_item_property2.set_property ('XXBLOCK_NAME.XXFIELD_NAME',required,property_true);
Similarly you can enable or disable the fields too.
5. You can display messages, for example
FND_MESSAGE.CLEAR;
fnd_message.set_name('APPL_SHORT_NAME_HERE', 'MSG_NAME_HERE'); or fnd_message.set_string('message text');
fnd_message.warn or fnd_message.error or fnd_message.
6. Enable or Disable Special Menu
PROCEDURE manage_special_menu IS
mi_id menuitem;
BEGIN
mi_id := find_menu_item('SPECIAL.SPECIAL15');
IF name_in('system.cursor_block') = 'INVOICE_HEADER' THEN
app_special2.instantiate('SPECIAL15', 'Print Invoice');
set_menu_item_property(mi_id, displayed, property_true);
set_menu_item_property(mi_id, enabled, property_true);
ELSE
set_menu_item_property(mi_id, displayed, property_false);
END IF;
END manage_special_menu;
7. Handle the click on Special Menu
IF event_name = 'SPECIAL15' THEN
IF form_name = 'INVOICE_FORM' THEN
xx_invoice_form.process_printing;
END IF;
IF form_name = 'SUPPLIER_FORM' THEN
xx_supplier_form.email_supplier;
END IF;
END IF;
8. Ask user a question, and take appropriate action v_token_value VARCHAR2(1000);
n_button_selection INTEGER;
BEGIN
fnd_message.set_name('APPL', 'MESSAGE');
fnd_message.set_token('XXTOKEN1', v_token_value);
n_button_selection := fnd_message.question('Email Invoice', 'Fax Invoice', '', 1, 2, 'question');
IF n_button_selection = 1 THEN
xx_call_invoice_print;
ELSE
xx_fax_invoice;
END IF;
9. Call Another form functionfnd_function.EXECUTE(
function_name => 'XX_FORM_FUNCTION_NAME_HERE'
,open_flag => 'Y'
,session_flag => 'SESSION'
,other_params => 'P_INVOICE_ID = "' || n_invoice_header_id || '"'
,activate_flag => 'Y');
10. Make some segments of a KeyFlexfield Display-Only depending upon some conditionFor example to make 1st segment of a KFF display-only, we can use
IF v_check_result='xyz' THEN
FND_KEY_FLEX.UPDATE_DEFINITION(
BLOCK => 'BLOCKNAMEHERE'
,FIELD => 'FLEXFIELDNAME'
,ENABLED => 'Y'
,DISPLAYABLE => 1);
END IF ;
BY FP.FORM_NAME, FP.SEQUENCE, F.FUNCTION_NAME
SELECT FP.ENABLED,FP.DESCRIPTION PERSONALIZATION_DESC,FP.condition,FP.TRIGGER_OBJECT,FP.SEQUENCE,FP.FORM_NAME,FM.USER_FORM_NAME,F.FUNCTION_NAME,FT.USER_FUNCTION_NAME,F
.TYPE FROM FND_FORM_CUSTOM_RULES FP,FND_FORM_FUNCTIONS F,FND_FORM_FUNCTIONS_TL FT,FND_FORM_TL FM
WHERE F.FUNCTION_ID = FT.FUNCTION_IDAND FM.FORM_ID = F.FORM_IDAND FP.FUNCTION_NAME = F.FUNCTION_NAME--AND F.FUNCTION_NAME like '%'--AND UPPER (condition) LIKE '%%'AND FP.FUNCTION_NAME like 'ONT_OEXOEORD%'ORDER
What is called first? Forms Personalization or CUSTOM.pll
First your form personalization is called, and then CUSTOM.pll is called.
Commonly used events that are trapped using CUSTOM.pll are:- ZOOM
WHEN-NEW-FORM-INSTANCE
WHEN-NEW-BLOCK-INSTANCE
WHEN-NEW-RECORD-INSTANCE
WHEN-NEW-ITEM-INSTANCE
WHEN-VALIDATE-RECORD
However, for example in HRMS, you can also write code in CUSTOM.pll to trap below listed events :-PRE-DELETE and POST-DELETE
PRE-UPDATE and POST-UPDATE
PRE-INSERT and POST-INSERT
POST-FORMS-COMMIT
WHEN-CREATE-RECORD
KEY-DELREC
How and why does CUSTOM.pll work?
Every form in Oracle Apps is created using something called as TEMPLATE.fmb. But some of the modules like HRMS have their own HR Specific Templates[HRTEMPLT.fmb]. These template files have form level triggers that make call to CUSTOM.pll. The triggers that can be trapped using CUSTOM.pll in HRMS screen can be different than those which can be trapped for other modules.
Custom.pll scenarios
1. Change the label of a fieldapp_item_property2.set_property ('BLOCK.FIELD',label,'New Label');
2. Default a value
copy (TO_CHAR (n_person_id),'PERSON_BLOCK.PERSON_ID' );
3. Alter the SQL for LOV Query
PROCEDURE filter_customers_in_lov IS
v_customer_group_id recordgroup;
n_temp_id NUMBER;
v_customer_lov lov;
BEGIN
v_customer_group_id := create_group_from_query('XX_CUSTOMER_GROUP'
,'select ... from hz_cust_accounts where ..your custom criteria here..');
n_temp_id := populate_group(v_customer_group_id);
v_customer_lov := find_lov('EXISTING_LOV_NAME_HERE');
IF get_lov_property(v_customer_lov,group_name) = 'EXISTING_GROUP_NAME_HERE'
THEN
set_lov_property(v_customer_lov,group_name,'XX_CUSTOMER_GROUP');
END IF;
END filter_customers_in_lov;
4. Make a field mandatory
app_item_property2.set_property ('XXBLOCK_NAME.XXFIELD_NAME',required,property_true);
Similarly you can enable or disable the fields too.
5. You can display messages, for example
FND_MESSAGE.CLEAR;
fnd_message.set_name('APPL_SHORT_NAME_HERE', 'MSG_NAME_HERE'); or fnd_message.set_string('message text');
fnd_message.warn or fnd_message.error or fnd_message.
6. Enable or Disable Special Menu
PROCEDURE manage_special_menu IS
mi_id menuitem;
BEGIN
mi_id := find_menu_item('SPECIAL.SPECIAL15');
IF name_in('system.cursor_block') = 'INVOICE_HEADER' THEN
app_special2.instantiate('SPECIAL15', 'Print Invoice');
set_menu_item_property(mi_id, displayed, property_true);
set_menu_item_property(mi_id, enabled, property_true);
ELSE
set_menu_item_property(mi_id, displayed, property_false);
END IF;
END manage_special_menu;
7. Handle the click on Special Menu
IF event_name = 'SPECIAL15' THEN
IF form_name = 'INVOICE_FORM' THEN
xx_invoice_form.process_printing;
END IF;
IF form_name = 'SUPPLIER_FORM' THEN
xx_supplier_form.email_supplier;
END IF;
END IF;
8. Ask user a question, and take appropriate action v_token_value VARCHAR2(1000);
n_button_selection INTEGER;
BEGIN
fnd_message.set_name('APPL', 'MESSAGE');
fnd_message.set_token('XXTOKEN1', v_token_value);
n_button_selection := fnd_message.question('Email Invoice', 'Fax Invoice', '', 1, 2, 'question');
IF n_button_selection = 1 THEN
xx_call_invoice_print;
ELSE
xx_fax_invoice;
END IF;
9. Call Another form functionfnd_function.EXECUTE(
function_name => 'XX_FORM_FUNCTION_NAME_HERE'
,open_flag => 'Y'
,session_flag => 'SESSION'
,other_params => 'P_INVOICE_ID = "' || n_invoice_header_id || '"'
,activate_flag => 'Y');
10. Make some segments of a KeyFlexfield Display-Only depending upon some conditionFor example to make 1st segment of a KFF display-only, we can use
IF v_check_result='xyz' THEN
FND_KEY_FLEX.UPDATE_DEFINITION(
BLOCK => 'BLOCKNAMEHERE'
,FIELD => 'FLEXFIELDNAME'
,ENABLED => 'Y'
,DISPLAYABLE => 1);
END IF ;
BY FP.FORM_NAME, FP.SEQUENCE, F.FUNCTION_NAME