14.01.2014

Описательные гибкие поля (DF) и OAF

Descriptive Flex Fields (описательные ГП) - инструмент в среде OeBS для универсализации использования одних и тех же полей таблиц для хранения свойств разных сущностей. Обычно это набор полей ATTRIBUTE1..ATTRIBUTE15 varchar2(150) для хранения свойств и поле ATTRIBUTE_CATEGORY для хранения контекста. В зависимости от контекста одно и то же поле может иметь разный бизнес-смысл.



Реализуем следующий пример. Имеется таблица транспортных средств. Создадим описательное ГП с двумя контекстами: легковые автомобили (CARS) и грузовые (TRUCKS). В зависимости от контекста, будем заполнять атрибуты следующими данными:

Поле таблицы CARS TRUCKS
ATTRIBUTE1 Тип Тип
ATTRIBUTE2 Объем багажника Грузоподъемность
ATTRIBUTE3 - Крытый/не крытый

В контекстах может участвовать различное количество атрибутов. В нашем примере ATTRIBUTE3 в контексте CARS не задействован.
Поехали. 1) Создаем таблицу и представление (пригодится на следующем этапе)
create table xxmy.car_flex_test(
       id                      number not null,
       name                    varchar2(50),
       car_number              varchar2(9),
       attribute_category      varchar2(30),
       attribute1              varchar2(150),
       attribute2              varchar2(150),
       attribute3              varchar2(150),
       attribute4              varchar2(150),
       attribute5              varchar2(150),
       attribute6              varchar2(150),
       attribute7              varchar2(150),
       attribute8              varchar2(150),
       attribute9              varchar2(150),
       attribute10             varchar2(150),
       attribute11             varchar2(150),
       attribute12             varchar2(150),
       attribute13             varchar2(150),
       attribute14             varchar2(150),
       attribute15             varchar2(150),
       created_by              number not null,
       creation_date           date   not null,
       last_updated_by         number not null,
       last_update_date        date   not null,
       last_update_login       number not null,
       object_version_number   number not null)
/
create or replace view car_flex_test_dfv as
select rowid row_id,
       fts.attribute_category,
       fts.attribute1,
       fts.attribute2,
       fts.attribute3,
       fts.attribute1 || '.' || fts.attribute2 || '.' ||
       fts.attribute3 concatenated_segments
       from xxmy.car_flex_test fts; 
Для того, чтобы на таблице можно было построить ГП, её необходимо зарегистрировать:
 declare
 l_table_id number;
 p_table_name varchar2(30) := 'CAR_FLEX_TEST';
    cursor c_data is
      select column_name,
             column_id,
             data_type,
             data_length,
             nullable,
             'N' translatable
        from all_tab_columns
       where owner = 'XXMY'
         and upper(table_name) = p_table_name
       order by column_id;
  BEGIN
    --Проверка регистрировалась ли таблица ранее
    begin
     select table_id
      into l_table_id
      from fnd_tables ft, fnd_application fa
     where fa.application_short_name = 'XXMY'
       and ft.application_id = fa.application_id
       and upper(ft.table_name) = p_table_name;
    exception 
      when NO_DATA_FOUND then
        l_table_id := null;
    end;   

    if l_table_id is not null then
      return;
    end if;
    --Регистрируем таблицу
    ad_dd.register_table(p_appl_short_name => 'XXMY',
                         p_tab_name        => p_table_name,
                         p_tab_type        => 'T');
    --Регистрируем столбцы таблицы
    for v_data in c_data loop
      ad_dd.register_column(p_appl_short_name => 'XXMY',
                            p_tab_name        => p_table_name,
                            p_col_name        => v_data.column_name,
                            p_col_seq         => v_data.column_id,
                            p_col_type        => v_data.data_type,
                            p_col_width       => v_data.data_length,
                            p_nullable        => v_data.nullable,
                            p_translate       => v_data.translatable);
    end loop;
  commit;
end;
На всякий случай, скрипт отмены регистрации:
declare
    p_table_name varchar2(30) := 'CAR_FLEX_TEST';
begin
    ad_dd.delete_table(p_appl_short_name => 'XXMY',
                       p_tab_name        => p_table_name);
end;
Разделители в представлении должны быть такими же, как в будущем ГП. В данном случае это точка (.).
2) Создаем описательное ГП.
CAR_FLEX_TEST_DFV - имя нашего представления.

Набор значений для поля TYPE легковых автомобилей

Набор значений для поля TYPE грузовых автомобилей

В окне сегментов описательного ГП и определяем 2 контекста.
Сегменты контекста CARS. FLEX_TEST_CAR_VS - набор значений на основе набора значений FLEX_TEST_CAR.

Сегменты контекста TRUCKS.
Для использования созданного ГП необходимо его "заморозить" ("freeze"), иначе при использовании получим ошибку The descriptive flexfield with application name is not frozen. 
 3) Встраиваем созданное ГП в страницу. Для этого создадим страницу поиска DFTestPG с кнопками "Поиск" и "Создать" и страницу редактирования записи DFTestCreatePG. Пакет server содержит Entity Object на основе нашей созданной таблицы и View Object на основе EO. Для редактирования записи одно из полей сделаем ссылочным. Встроенный бин flex на странице DFTestCreatePG будет иметь вид:
Больше ничего не требуется. Свойство Display Context Field=true указывает, что будет отображаться отдельный переключатель для выбора контекста. Если свойство Segment List не задано, подгружаются все имеющиеся в контексте сегменты. Чтобы задать это свойство вручную в зависимости от переданного контекста, можно воспользоваться следующим кодом:
with segments as(
select rownum rn, fcu.form_above_prompt segname
       from FND_DESCRIPTIVE_FLEXS dfx,
            FND_DESCR_FLEX_CONTEXTS dfc,
            FND_DESCR_FLEX_COL_USAGE_TL fcu
       where dfx.descriptive_flexfield_name = 'CAR_FLEX_TEST'
       and   dfx.application_table_name = dfc.descriptive_flexfield_name
       and   fcu.descriptive_flexfield_name = dfx.descriptive_flexfield_name
       and   fcu.descriptive_flex_context_code = dfc.descriptive_flex_context_code
       and   fcu.source_lang = 'RU'
       and   fcu.language = 'RU'
       and   dfc.descriptive_flex_context_code = 'CARS'
) select substr(sys_connect_by_path(segname, '|'), 2)
         from segments
      where connect_by_isleaf = 1
      connect by prior rn = rn - 1
      start with rn = 1
Результатом будет строка сегментов с разделителем '|', это условие OAF.
Все сегменты с описаниями и наборами значений подгружаются автоматически.
Добавим раз.

Добавим два.

Результат.
Всё работает.




Комментариев нет :