Define a KFF step by step
Contents
Define a KFF step by step
BaseTable 表增加一个外键列
在Base Table 中定义一个字段 XXX_ID ,这个用于保存 KFF表记录的主键(对于 Base Table 就是外键列),比如对于本例,如果要增加一个 Account 的KFF ,需要在 Base Table 上增加一个 XXX_ID外键字段用于保存捕获的 CODE_COMBINATION_ID
Block 中创建一个 Flexfield的隐藏 item
Block中定义一个隐藏字段用于保存上边一步创建的 FK 字段,设置 canvas为 NULL ,TEXT_ITEM property class
Block 中创建一个 Flexfield显示字段
创建了隐藏字段,当然要创建一个显示的字段让用户来输入,这里我们需要创建一个 non-database 字段用来展示合并的科目值, subclass Information 继续使用TEXT_ITEM, 设置合适 canvas 来显示,LOV 设置为 'ENABLE_LIST_LAMP', 'Validate from list' is set to No
When-New-Form-Instance 中加入FlexField 的定义
在When-New-Form-Instance 中加入 FlexField的定义,当然好的戏,代码类似于
SELECT CHART_OF_ACCOUNTS_ID INTO :PARAMETER.CHART_OF_ACCOUNTS_ID FROM ORG_ORGANIZATION_DEFINITIONS WHERE ORGANIZATION_ID = :PARAMETER.ORG_ID; FND_KEY_FLEX.DEFINE( BLOCK => 'TOMAI_MAIN_HEADER_BLK', FIELD => 'TO_ACCOUNT_PT', CODE => 'GL#', APPL_SHORT_NAME =>'SQLGL', NUM => ':PARAMETER.CHART_OF_ACCOUNTS_ID', ID => 'TO_ACCOUNT_PT_id', VRULE => '\\nSUMMARY_FLAG\\nI\\nAPPL=SQLGL;NAME=GL_NO_PARENT_SEGMENT_ALLOWED\\nN\\0GL_GLOBAL\\nDETAIL_POSTING_ALLOWED\\nE\\nAPPL=INV;NAME=INV_VRULE_POSTING\\nN', REQUIRED => 'N', DINSERT => 'Y', VALIDATE => 'FULL', USEDBFLDS => 'N');
FND_KEY_FLEX.DEFINE 的用法
FND_KEY_FLEX.DEFINE( block => 'Custom block', Field => 'BTL_KFF',-- 第三步创建的显示 item ID => 'XXX_ID',-- 第二步创建的隐藏 item Appl_short_name => 'SQLGL', Code => 'GL#',--ID_FLEX_CODE Num => '101',--Chart of account Vrule => 'GL_GLOBAL\nDETAIL_POSTING_ALLOWED \nE\nAPPL=''SQLGL''; name=Parent Values are not allowed\nN' );
Trigger 中调用FlexField 标准的方法
Trigger包括
PRE-QUERY
POST-QUERY
PRE-INSERT
PRE-UPDATE
WHEN-VALIDATE-RECORD
WHEN-NEW-ITEM-INSTANCE
WHEN-VALIDATE-ITEM
代码类似于:
if ( :system.mode = 'NORMAL' ) then fnd_flex.event( 'WHEN-VALIDATE-ITEM' ); end if;
app_standard.event('WHEN-NEW-ITEM-INSTANCE'); fnd_flex.event('WHEN-NEW-ITEM-INSTANCE' );
--Loads the flexfields (in our case, it populates --the concatenated field on execute query). FND_FLEX.EVENT('POST-QUERY');
--If you don't do this, whatever query criteria you may enter in -- the concatenated flex field, it is not taken into account. FND_FLEX.EVENT('PRE-QUERY' );
APP_STANDARD.EVENT('KEY-LISTVAL'); FND_FLEX.EVENT('KEY-LISTVAL' );
一般情况下,我们会把 fnd_flex.event这样的代码放在 Form 级别,这样我们新加的 Trigger只要不是 Override 模式, 那么 fnd_flex.event都会被执行到,当然如果你的 trigger 为override 模式或者需要比较复杂的 Flexfield 的业务逻辑,那么你就必须手工添加 fnd_flex.event 代码到你的 Trigger中。对于本例 Account 的KFF 来说,因为要校验 Account ID 是否有效,所以需要在 When-Validate-Item中加入一些其他校验
FND_FLEX.EVENT('WHEN-VALIDATE-ITEM'); IF :BLOCK.XXX_ID = -1 THEN FND_MESSAGE.SET_STRING('You Have Selected An Undefined Code Combination !'); FND_MESSAGE.SHOW; RAISE FORM_TRIGGER_FAILURE; END IF;
Flexfield 相关的API
fnd_flex.event的代码位于 FNDSQF.pll
procedure event(event_name varchar2) is begin fnd_flex_private.flex_debug('BEGIN FND_FLEX.EVENT('||event_name||')'); if ((event_name = 'WHEN-VALIDATE-ITEM') AND (name_in('system.mode') = 'ENTER-QUERY')) then GOTO lbl_return; end if; -- -- Synchronize call seems to solve some problems in -- event handling in Forms side. -- According to Peter this call does nothing, but let's -- call it. G.Olgun -- -- Per Peter's request commenting out the code. -- --IF (event_name = 'WHEN-NEW-ITEM-INSTANCE') THEN -- synchronize; --END IF; -- user_exit('FND FFLEX ' || event_name); if (NOT Form_Success) then fnd_flex_private.flex_failure('user_exit(FND FFLEX ' || event_name || ') is failed.'); copy(NULL, 'GLOBAL.FND_FLEX_NAVIGATE'); copy(NULL, 'GLOBAL.FND_FLEX_NAVIGATE_PUBLIC'); copy(NULL, 'GLOBAL.FND_FLEX_READONLY'); copy(NULL, 'GLOBAL.FND_FLEX_ENABLELOV'); raise FORM_TRIGGER_FAILURE; end if; -- if (event_name = 'POST-QUERY') then -- set_record_property(name_in('SYSTEM.TRIGGER_RECORD'), -- name_in('SYSTEM.TRIGGER_BLOCK'), -- STATUS, QUERY_STATUS); -- end if; fnd_flex_private.navigate_from_flex; if (event_name = 'WHEN-NEW-ITEM-INSTANCE') then fnd_flex_private.set_flex_item_properties; end if; -- -- This step was asked for by Peter Wallack to enable localizations -- This would eventually be moved to APPCORE. -- if (event_name = 'WHEN-VALIDATE-RECORD') then copy('Y', 'GLOBAL.APPCORE_WVR_ZOOM'); execute_trigger('ZOOM'); if not form_success then raise form_trigger_failure; end if; end if; <<lbl_return>> fnd_flex_private.flex_debug('END FND_FLEX.EVENT('||event_name||')'); RETURN; EXCEPTION WHEN OTHERS THEN fnd_flex_private.flex_exception('FND_FLEX.EVENT'); RAISE; end event;
FlexField 的相关表
This table captures the information of all the Key FlexFields. The main columns in this table are:
APPLICATION_ID ‐ Column consists of Application ID
ID_FLEX_CODE ‐ Column KFF Code (like ‘ GL#’ , ‘AR# ’ etc.)
ID_FLEX_NAME - KFF Name (like ‘Accounting Flexfield’, ‘Category Flexfield’..etc.)
APPLICATION_TABLE_NAME – Name of combination table (like ‘GL_CODE_COMBINATIONS’ , ‘FA_LOCATIONS’ etc.)
This table stores structure information about key Flexfields. Each Structure is uniquely identified by
APPLICATION_ID – Module Code
ID_FLEX_CODE – Code of KFF
ID_FLEX_NUM – Number of a Structure
It captures the information of Segments. Each Segment is Uniquely identified by
APPLICATION_ID – Module Code
ID_FLEX_CODE – Key Flexfield code
ID_FLEX_NUM – Key flexfield structure number
SEG_NUM – Segment number
FLEX_VALUE_SET_ID – Flexfield value set identifier
This table captures the information of each Segment’s Value Set. Each Value Set is Uniquely identified by FLEX_VALUE_SET_ID as Foreign Key of FND_ID_FLEX_SEGMENTS Table.
This table captures the information each Value codes of a Value Set of a Segment. Each Value Code is uniquely identified by
FLEX_VALUE_SET_ID
FLEX_VALUE_ID
This table captures the information of each Value Description of a Value Set of a Segment. Each Value Description is uniquely identified by FLEX_VALUE_ID.